-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Normative: provide default prototype and realm values for CreateBuiltinFunction #1044
Conversation
I like the idea of this change. I agree with you that the spec text is a little bit vague in this respect. However, I have some small suggestions for improvements in the way you've phrased things, all minor editorial nits:
|
@littledan My motivation is to understand what to do in step 2 of https://tc39.github.io/ecma262/#sec-proxy.revocable. In that call to this abstract algorithm, there is no prototype nor realm defined. An alternate fix is to find all the calls to the abstract algorithm and make sure they always specify the prototype and realm. Regarding "the current realm record", it is defined here https://tc39.github.io/ecma262/#current-realm: it's the realm of the running execution context. |
Oh, I misunderstood and was trying to explain how to clarify a different step, where I thought the current realm was more vague, in CreateIntrinsics. However, it seems that CreateIntrinsics does have a direct call to CreateBuiltinFunction, and the line at the end of CreateBuiltinFunction describing that it's called in this case doesn't serve a normative function. For the case in Proxy.revokable, could this be handled by replacing step 2 with a direct call to CreateBuiltinFunction with the appropriate arguments? Otherwise, the semantics make sense to me with respect to Proxy.revocable. cc @verwaest @domenic , is this how you interpreted the realm for Proxy.revocable? |
@littledan Using |
@brabalan I'd amend the current PR. |
Done. I also seized the occasion to make clear the internal slot we need. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great fix--I think it makes the specification much more clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM pending comment
spec.html
Outdated
1. Let _realm_ be the current Realm Record. | ||
1. Let _steps_ be the algorithm steps defined in <emu-xref href="#sec-proxy-revocation-functions"></emu-xref>. | ||
1. Let _prototype_ be the intrinsic object %FunctionPrototype%. | ||
1. Let _revoker_ be CreateBuiltinFunction(_realm_,_steps_,_prototype_,« [[RevocableProxy]] »). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each argument comma needs a space after it.
@ljharb fixed |
spec.html
Outdated
1. Let _realm_ be the current Realm Record. | ||
1. Let _steps_ be the algorithm steps defined in <emu-xref href="#sec-proxy-revocation-functions"></emu-xref>. | ||
1. Let _prototype_ be the intrinsic object %FunctionPrototype%. | ||
1. Let _revoker_ be CreateBuiltinFunction(_realm_, _steps_, _prototype_, « [[RevocableProxy]] »). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd inline %FunctionPrototype%
in the call to CreateBuiltinFunction
, cf. MakeArgGetter and MakeArgSetter.
What is special about |
The root problem here is in clause 17 where it says:
The intent of that line was to eliminate the need to have to explicitly show the determination of the CreateBuildinFunction arguments every place we need to create one. But the text has too much ambiguity WRT the arguments passed to CreateBuildinFunction. I'd restate it as:
Note that "current realm" is defined in https://tc39.github.io/ecma262/#sec-execution-contexts With the above addition the current language in step 2 of Proxy.revoke and all other similar built-in function creation steps should be fine. |
@allenwb I agree, this is very similar to what I initially proposed (in English instead of providing default values in the steps). I like that solution because it fixes everything once and for all. Should I amend the pull request to reflect this? (I'm new to this, I don't know what the process should be.) |
Sorry for getting things off-track here with that suggestion! I missed the call in section 17. Is that section normative text? I don't really understand what that spec text is doing--aren't the same built-in function objects provided by 8.2.2 CreateIntrinsics (which is already explicit about its realm argument, though maybe it could use some more clarity for the prototype)? Minor: Do we prefer to use functional notation or general sentences when calling abstract algorithms like CreateBuiltinFunction from paragraphs? I'm not against using sentences (it seems to work just fine for web specs) but was suggesting functional notation above since it seems to be used most of the time in this document. |
8.2.2 CreateIntrinsics covers the built-in functions that are in or reachable from Table 7: 'Well-Known Intrinsic Objects', but that isn't (quite) every built-in function defined in the spec. Of that remainder, some are created by explicit calls to CreateBuiltinFunction (in MakeArgGetter and MakeArgSetter), and the rest are created by wording such as (If we converted the latter to explicit calls to CreateBuiltinFunction (see old bug 4080), I don't think we'd need the wording in 17 or 9.3.3, though we could say something similar in a note. I should maybe submit a PR.) |
To answer @anba 's question about what makes Proxy.revocable different from those other cases--nothing, just that I didn't remember those cases and so didn't bring them up. The current logic was a little hard for me to trace, especially with a lot of places that create built-in function objects somehow just linking to "function object". If these aren't changed to call CreateBuiltinFunction directly, maybe they should at least each link to either section 17 or 9.3.3. |
+100 for this change |
The reason for the paragraph in clause 17 (and all of clause 17 is indeed normative) the need to repetitively use a 4 step sequence such as that proposed in #1044 (review) The primary purpose of all of clause 17 is to define such short cuts. |
@allenwb I see. Would it be acceptable to somehow link from the places where it applies to the relevant part of section 17? Or, as a maybe-too-explicit alternative, what if we used a "spec macro" the way @domenic is refactoring Await in the async iteration spec ? |
well, the macro is essentially "a new built-in function object as defined in". Clause 17 is the definition of that macro. Note that clause 17 applies to every function defined in clauses 18-26, unless otherwise specified. |
As @anba pointed out above, the prototype can be specified inline, so it'd only be a 3-step sequence. And we could arrange that realm is an optional arg, defaulting to the current Realm Record, reducing it to a 2-step sequence. (We could also arrange that prototype is optional, defaulting to %FunctionPrototype%.) We could get get it down to 1 step, but only by introducing some new notation, which probably isn't worth it. |
Yes, except almost all of them are otherwise specified, in CreateIntrinsics. |
To summarize, if I understand correctly, we have two options:
The former is more precise and formal, but requires much more work to find out all the places that require the change. How do we choose which option to take? |
The only algorithm steps that require the change are those using the phrase "a new built-in function object as defined in". There are 8 such occurrences, and @anba has already listed where they occur. Are there any built-in functions defined in the spec that are not created by some algorithm step? I've scanned through the spec and I don't think so. How else could they be created? |
@jmdyck Well, seems like ES5.1 didn't have all this explicit CreateBuiltinFunction/CreateIntrinsics logic, so that's a way. Hats off to @allenwb for making things more concrete in ES2015. In this bug, we're just discussing a minor tweak on something that was already significantly improved in that iteration. |
When I said "How else could they be created?", I didn't mean "How could the spec be (re)organized to create built-in functions differently?", but rather "Is there any other wording/mechanism that the current spec is using to create built-in functions?" (I.e., basically just rephrasing the first sentence of that para.) (This question is important to determining, after certain changes, whether the para in clause 17 is needed any more. We could make the changes and yet retain the clause 17 para "just in case", but that would be unsatisfying.) |
I changed all the occurrences listed by @anba to explicitly call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bterlson What do you think of this patch?
Is there anything I can do to help move this forward? |
You missed a case in CreateResolvingFunctions ("Let reject be a new built-in function object ..."). You need to resolve conflicts (rebase against ecma262's current master). You may need to wait a while for this to be merged. I gather @bterlson is focusing on the stage 4 normative PRs (I think there are two left: #1048 and #1066) so that they can get into the 2018 snapshot. After that, he'll have time to look at editorial PRs (which have a later snapshot-deadline). |
@jmdyck Thank you for the feedback. I merged the changes from master and added the missed cases. |
The fact that you merged from master (rather than rebasing to it) confused my limited git-fu (when I tried to pull your changes onto one of my branches, for checking). But I eventually got it via some cherry-picks. The net effect looks good to me. (@bterlson, I recommend pulling it in as a single commit.) |
@jmdyck Sorry for the merge, I thought one should never rebase a published branch. Is it different for pull requests? |
Hm, yes, there is that injunction. But as you suggest, I think it is different for pull requests, since it's unlikely that anyone would use a PR branch as a base for subsequent work. For my PR branches, I rebase-to-master all the time (have done for years), and nobody's complained. But we should ask the editors (@bterlson, @ljharb): when a PR's submitter resolves conflicts with master, do you have a preference between rebasing or merging? CONTRIBUTING.md doesn't say. |
Merge commits should be avoided; always rebase and force push a PR branch. |
…inFunction To address tc39#1030
895a221
to
cdcd8df
Compare
Rebased and squashed. |
Good to have this guidance; I've been debating for myself about this. Let's make sure to document this as our team's practice in CONTRIBUTING.md or someplace similar. |
See #1099. |
This looks good, thanks everyone for the detailed review! Sorry for being delinquent. |
... now that they're all created by CreateBuiltinFunction (since tc39#1044). (Suggested in tc39#1044 (comment))
... move them to the end of the parameter list, and make them optional. (Almost all calls to CreateBuiltinFunction get shorter, and don't need a step to set up _realm_.) (Suggested in tc39#1044 (comment))
To address #1030
This is my first pull request to the spec, please let me know if I'm doing it wrong.