-
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
Editorial: remove implicit wrapping/unwrapping of completion records #2547
Conversation
The PR introduces a term |
ba9380a
to
69d0904
Compare
d9cedf7
to
ac7a242
Compare
e4aa02d
to
77dc5da
Compare
d4b1dce
to
dce5d78
Compare
a509120
to
bbc3c4b
Compare
7c5f301
to
72f7102
Compare
5dac806
to
8c5a8ec
Compare
ea69c47
to
1897937
Compare
(You should probably also update the PR description where it says "Not ready for review".) |
Why? |
@jmdyck No reason, we just thought it was stylistically neater and semantically it's equivalent. |
In particular, we already have lots of |
Okay. Given those choices, I'd vote for
I might agree that
As for "clearer", I strongly disagree. To me,
Also, in a lot of cases of |
It's true that if you think about what the spec looks like after applying the rewrite rules, that thing ends up being a fairly awkward sequence of steps. But most readers are not thinking about what the spec looks like after applying rewrite rules, and they already encounter I stand by "clearer" here. |
As part of the tc39/ecma262#2547 the JavaScript specification has reformed how it deals with Completion Records, and thus what abstract operations can return. See tc39/ecma262#253 (comment) for a brief description of when to use ? vs. ! vs. nothing at all. Additional minor fixes: * Replace uses of ObjectCreate (which no longer exists) with OrdinaryObjectCreate. * Replace "Rethrow any exceptions" with the ? syntax. * Use ? with GetFunctionRealm, which can throw due to revoked proxies.
As part of the tc39/ecma262#2547 ecma262 has reformed how it deals with Completion Records. See tc39/ecma262#253 (comment) for a brief description of when to use ? vs. ! vs. nothing at all.
Specifically, change occurrences of: ``` 1. Let _ref_ be Completion(Evaluation of X). 1. ... ? GetValue(_ref_) ... 1. (later references to _ref_) ``` to: ``` 1. Let _ref_ be ? Evaluation of X. 1. ... ? GetValue(_ref_) ... 1. (later references to _ref_) ``` In the following case analysis, let "CR" denote the value returned by `Evaluation of X` (always a Completion Record), and, if it's a normal completion, let "V" denote the value in its [[Value]] field. Before the change: If CR is an abrupt completion: it is bound to _ref_, then passed to GetValue, which executes ReturnIfAbrupt on it, i.e. returns it from GetValue, and the `?` before GetValue returns it from the algorithm. If CR is a normal completion: _ref_ is bound to it, then passed to GetValue, which would execute ReturnIfAbrupt on it, which would unwrap it to V. The rest of GetValue then operates on V, and then, in any event, returns some completion record, not necessarily the same as CR. (Note that _ref_ remains bound to CR.) After the change: If CR is an abrupt completion: the `?` before Evaluation returns it from the algorithm. (So, the same net effect as before.) If CR is a normal completion: the `?` before Evaluation unwraps it to V, _ref_ is bound to V, then passed to GetValue. GetValue's ReturnIfAbrupt has no effect on V, and the rest of GetValue operates on V, and returns some completion record, not necessaily the same as CR. (So, the same effect as before, *except* that _ref_ is bound to V, not CR. This difference is important because of the later references to _ref_.) To summarize: if the result of `Evaluation of X` is a normal completion, then in the status quo, the later references to _ref_ are references to that Completion Record, but with this commit, they would be references to the [[Value]] of that Completion Record. However, I believe that in every case, that difference either doesn't matter, or it fixes an editorial bug. Example of "doesn't matter": In some cases, the only later reference is where _ref_ is passed to the first parameter of PutValue, which immediately calls ReturnIfAbrupt on it, so it doesn't matter if _ref_ refers to the Completion Record or its [[Value]]. Example of "fixes an editorial bug": In the Evaluation rule for `CallExpression : CoverCallExpressionAndAsyncArrowHead` the next step says: ```If _ref_ is a Reference Record, ...``` In the "Before" world, where _ref_ is bound to a Completion Record, this test is never true. Another example: In many cases, the value of _ref_ is passed (directly or indirectly) to the second parameter of EvaluateCall, which requires "an ECMAScript language value or a Reference Record". In the "Before" world, _ref_ is bound to a Completion Record, which is not what's required. Prior to the merge of PR tc39#2547, these cases would have caused an implicit unwrapping from the Completion Record to its [[Value]], but tc39#2547 removed the idea of implicit unwrapping, so these references have been editorial bugs since then.
Specifically, change occurrences of: ``` 1. Let _ref_ be Completion(Evaluation of X). 1. ... ? GetValue(_ref_) ... 1. (later references to _ref_) ``` to: ``` 1. Let _ref_ be ? Evaluation of X. 1. ... ? GetValue(_ref_) ... 1. (later references to _ref_) ``` In the following case analysis, let "CR" denote the value returned by `Evaluation of X` (always a Completion Record), and, if it's a normal completion, let "V" denote the value in its [[Value]] field. Before the change: If CR is an abrupt completion: it is bound to _ref_, then passed to GetValue, which executes ReturnIfAbrupt on it, i.e. returns it from GetValue, and the `?` before GetValue returns it from the algorithm. If CR is a normal completion: _ref_ is bound to it, then passed to GetValue, which would execute ReturnIfAbrupt on it, which would unwrap it to V. The rest of GetValue then operates on V, and then, in any event, returns some completion record, not necessarily the same as CR. (Note that _ref_ remains bound to CR.) After the change: If CR is an abrupt completion: the `?` before Evaluation returns it from the algorithm. (So, the same net effect as before.) If CR is a normal completion: the `?` before Evaluation unwraps it to V, _ref_ is bound to V, then passed to GetValue. GetValue's ReturnIfAbrupt has no effect on V, and the rest of GetValue operates on V, and returns some completion record, not necessaily the same as CR. (So, the same effect as before, *except* that _ref_ is bound to V, not CR. This difference is important because of the later references to _ref_.) To summarize: if the result of `Evaluation of X` is a normal completion, then in the status quo, the later references to _ref_ are references to that Completion Record, but with this commit, they would be references to the [[Value]] of that Completion Record. However, I believe that in every case, that difference either doesn't matter, or it fixes an editorial bug. Example of "doesn't matter": In some cases, the only later reference is where _ref_ is passed to the first parameter of PutValue, which immediately calls ReturnIfAbrupt on it, so it doesn't matter if _ref_ refers to the Completion Record or its [[Value]]. Example of "fixes an editorial bug": In the Evaluation rule for `CallExpression : CoverCallExpressionAndAsyncArrowHead` the next step says: ```If _ref_ is a Reference Record, ...``` In the "Before" world, where _ref_ is bound to a Completion Record, this test is never true. Another example: In many cases, the value of _ref_ is passed (directly or indirectly) to the second parameter of EvaluateCall, which requires "an ECMAScript language value or a Reference Record". In the "Before" world, _ref_ is bound to a Completion Record, which is not what's required. Prior to the merge of PR tc39#2547, these cases would have caused an implicit unwrapping from the Completion Record to its [[Value]], but tc39#2547 removed the idea of implicit unwrapping, so these references have been editorial bugs since then.
As part of the tc39/ecma262#2547 the JavaScript specification has reformed how it deals with Completion Records, and thus what abstract operations can return. See tc39/ecma262#253 (comment) for a brief description of when to use ? vs. ! vs. nothing at all. Additional minor fixes: * Replace uses of ObjectCreate (which no longer exists) with OrdinaryObjectCreate. * Replace "Rethrow any exceptions" with the ? syntax. * Use ? with GetFunctionRealm, which can throw due to revoked proxies.
Specifically, change occurrences of: ``` 1. Let _ref_ be Completion(Evaluation of X). 1. ... ? GetValue(_ref_) ... 1. (later references to _ref_) ``` to: ``` 1. Let _ref_ be ? Evaluation of X. 1. ... ? GetValue(_ref_) ... 1. (later references to _ref_) ``` In the following case analysis, let "CR" denote the value returned by `Evaluation of X` (always a Completion Record), and, if it's a normal completion, let "V" denote the value in its [[Value]] field. Before the change: If CR is an abrupt completion: it is bound to _ref_, then passed to GetValue, which executes ReturnIfAbrupt on it, i.e. returns it from GetValue, and the `?` before GetValue returns it from the algorithm. If CR is a normal completion: _ref_ is bound to it, then passed to GetValue, which would execute ReturnIfAbrupt on it, which would unwrap it to V. The rest of GetValue then operates on V, and then, in any event, returns some completion record, not necessarily the same as CR. (Note that _ref_ remains bound to CR.) After the change: If CR is an abrupt completion: the `?` before Evaluation returns it from the algorithm. (So, the same net effect as before.) If CR is a normal completion: the `?` before Evaluation unwraps it to V, _ref_ is bound to V, then passed to GetValue. GetValue's ReturnIfAbrupt has no effect on V, and the rest of GetValue operates on V, and returns some completion record, not necessaily the same as CR. (So, the same effect as before, *except* that _ref_ is bound to V, not CR. This difference is important because of the later references to _ref_.) To summarize: if the result of `Evaluation of X` is a normal completion, then in the status quo, the later references to _ref_ are references to that Completion Record, but with this commit, they would be references to the [[Value]] of that Completion Record. However, I believe that in every case, that difference either doesn't matter, or it fixes an editorial bug. Example of "doesn't matter": In some cases, the only later reference is where _ref_ is passed to the first parameter of PutValue, which immediately calls ReturnIfAbrupt on it, so it doesn't matter if _ref_ refers to the Completion Record or its [[Value]]. Example of "fixes an editorial bug": In the Evaluation rule for `CallExpression : CoverCallExpressionAndAsyncArrowHead` the next step says: ```If _ref_ is a Reference Record, ...``` In the "Before" world, where _ref_ is bound to a Completion Record, this test is never true. Another example: In many cases, the value of _ref_ is passed (directly or indirectly) to the second parameter of EvaluateCall, which requires "an ECMAScript language value or a Reference Record". In the "Before" world, _ref_ is bound to a Completion Record, which is not what's required. Prior to the merge of PR tc39#2547, these cases would have caused an implicit unwrapping from the Completion Record to its [[Value]], but tc39#2547 removed the idea of implicit unwrapping, so these references have been editorial bugs since then.
Ready for review. Based on #2546. Fixes #1796. Fixes #497. Fixes #496. Closes #1916. Fixes #253. Fixes #1572. Closes #486. Closes #2612. Fixes #2645.
~empty~
returns with~unused~
?
/!
/Completion()
; call sites for AOs that do not return completion records should not use!
/?
/Completion()
ReturnIfAbrupt
/?
/throw
?
orthrow
orReturnIfAbrupt
or returns a completion explicitly~unused~
are always invoked using "Perform". if it's a completion record that normally contains~unused~
, make sure only its[[Type]]
is relied upon.~unused~
or a completion record that normally contains~unused~
!
and make them not return completion recordsNormalCompletion
in AOs that return completion records; exceptCompletion
orThrowCompletion
orNormalCompletion
return Completion(X)
withreturn ? X
in AOs that return a completion recordCompletion()
are on the call of an AO that returns a completion, field accesses, or some other opaque sourceCompletion(...)
orCompletion Record { ... }
orNormalCompletion(...)
orThrowCompletion(...)
in algorithms that don't return completion records