-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Normative: PromiseResolve check proto instead of constructor #3689
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
base: main
Are you sure you want to change the base?
Changes from 2 commits
da0dd08
53b2ab1
ed27ba3
02dc66b
23f3711
0de5715
ed3e660
74c0260
5c666fe
d1e26b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3890,6 +3890,16 @@ <h1>Well-Known Intrinsic Objects</h1> | |
| The Promise constructor (<emu-xref href="#sec-promise-constructor"></emu-xref>) | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td> | ||
| %PromiseThenAction% | ||
| </td> | ||
| <td> | ||
| </td> | ||
| <td> | ||
| An internal function object for PerformPromiseThen | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td> | ||
| %Proxy% | ||
|
|
@@ -48472,21 +48482,42 @@ <h1>Promise Resolve Functions</h1> | |
| 1. If _resolution_ is not an Object, then | ||
| 1. Perform FulfillPromise(_promise_, _resolution_). | ||
| 1. Return *undefined*. | ||
| 1. Let _then_ be Completion(Get(_resolution_, *"then"*)). | ||
| 1. If _then_ is an abrupt completion, then | ||
| 1. Perform RejectPromise(_promise_, _then_.[[Value]]). | ||
| 1. Return *undefined*. | ||
| 1. Let _thenAction_ be _then_.[[Value]]. | ||
| 1. If IsCallable(_thenAction_) is *false*, then | ||
| 1. Perform FulfillPromise(_promise_, _resolution_). | ||
| 1. Return *undefined*. | ||
| 1. Let _thenAction_ be *null*. | ||
| 1. If IsPromise(_resolution_) is *true*, then | ||
| 1. Let _proto_ be ! _resolution_.[[GetPrototypeOf]](). | ||
| 1. If SameValue(_proto_, %Promise.prototype%) is *true*, set _thenAction_ to %PromiseThenAction%. | ||
bakkot marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 1. If _thenAction_ is *null*, then | ||
| 1. Let _then_ be Completion(Get(_resolution_, *"then"*)). | ||
| 1. If _then_ is an abrupt completion, then | ||
| 1. Perform RejectPromise(_promise_, _then_.[[Value]]). | ||
| 1. Return *undefined*. | ||
| 1. Set _thenAction_ to _then_.[[Value]]. | ||
| 1. If IsCallable(_thenAction_) is *false*, then | ||
| 1. Perform FulfillPromise(_promise_, _resolution_). | ||
| 1. Return *undefined*. | ||
| 1. Let _thenJobCallback_ be HostMakeJobCallback(_thenAction_). | ||
| 1. Let _job_ be NewPromiseResolveThenableJob(_promise_, _resolution_, _thenJobCallback_). | ||
| 1. Perform HostEnqueuePromiseJob(_job_.[[Job]], _job_.[[Realm]]). | ||
| 1. Return *undefined*. | ||
| </emu-alg> | ||
| <p>The *"length"* property of a promise resolve function is *1*<sub>𝔽</sub>.</p> | ||
| </emu-clause> | ||
|
|
||
| <emu-clause id="sec-%promisethenaction%"> | ||
| <h1>%PromiseThenAction% ( _onFulfilled_, _onRejected_ )</h1> | ||
| <p>The <dfn>%PromiseThenAction%</dfn> intrinsic function:</p> | ||
| <ul> | ||
| <li>is an anonymous built-in function object that is defined once for each realm.</li> | ||
| <li>is never directly accessible to ECMAScript code.</li> | ||
mhofman marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| <li>is used by the promise resolve functions to adopt the state of the promise passed as the receiver.</li> | ||
| <li>performs the following steps when called:</li> | ||
| </ul> | ||
| <emu-alg> | ||
| 1. Let _promise_ be the *this* value. | ||
| 1. Assert: IsPromise(_promise_) is *true*. | ||
| 1. Return PerformPromiseThen(_promise_, _onFulfilled_, _onRejected_). | ||
| </emu-alg> | ||
| </emu-clause> | ||
| </emu-clause> | ||
|
|
||
| <emu-clause id="sec-fulfillpromise" type="abstract operation"> | ||
|
|
@@ -49141,8 +49172,9 @@ <h1> | |
| </dl> | ||
| <emu-alg> | ||
| 1. If IsPromise(_x_) is *true*, then | ||
| 1. Let _xConstructor_ be ? Get(_x_, *"constructor"*). | ||
| 1. If SameValue(_xConstructor_, _C_) is *true*, return _x_. | ||
| 1. Let _xProto_ be ! _x_.[[GetPrototypeOf]](). | ||
| 1. Let _CPrototype_ be ? Get(_C_, *"prototype"*). | ||
mhofman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 1. If SameValue(_xProto_, _CPrototype_) is *true*, return _x_. | ||
|
Check warning on line 49177 in spec.html
|
||
|
Comment on lines
49549
to
49553
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, consider This is basically inverting the loophole that already exists, where instead of a real promise being able to fake association with an arbitrary constructor (and getting the chance to run code in the process), an arbitrary constructor can fake association with any real promise. But since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we wanted to be really prescriptive about this, we could check if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some functions don't have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it’s not a constructor, then we can’t I’m kinda ambivalent on whether we need to support proxies of the promise constructor. Up to you. |
||
| 1. Let _promiseCapability_ be ? NewPromiseCapability(_C_). | ||
mhofman marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 1. Perform ? Call(_promiseCapability_.[[Resolve]], *undefined*, « _x_ »). | ||
| 1. Return _promiseCapability_.[[Promise]]. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.