Skip to content

Commit

Permalink
Enforce a clean stack for onFulfilled and onRejected.
Browse files Browse the repository at this point in the history
Closes #139. See also discussions in #70, #84, and #100.
  • Loading branch information
domenic committed Aug 14, 2013
1 parent 15410d4 commit afd105b
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ promise.then(onFulfilled, onRejected)
1. it must be called after `promise` is rejected, with `promise`'s reason as its first argument.
1. it must not be called before `promise` is rejected.
1. it must not be called more than once.
1. `then` must return before `onFulfilled` or `onRejected` is called [[4.1](#notes)].
1. `onFulfilled` or `onRejected` must not be called until the execution context stack contains only platform code. [[4.1](#notes)].
1. `onFulfilled` and `onRejected` must be called as functions (i.e. with no `this` value). [[4.2](#notes)]
1. `then` may be called multiple times on the same promise.
1. If/when `promise` is fulfilled, all respective `onFulfilled` callbacks must execute in the order of their originating calls to `then`.
Expand Down Expand Up @@ -102,7 +102,7 @@ If a promise is resolved with a thenable that participates in a circular thenabl

## Notes

1. In practical terms, an implementation must use a mechanism such as `setTimeout`, `setImmediate`, or `process.nextTick` to ensure that `onFulfilled` and `onRejected` are not invoked in the same turn of the event loop as the call to `then` to which they are passed.
1. Here "platform code" means engine, environment, and promise implementation code. In practice, this requirement ensures that `onFulfilled` and `onRejected` execute asynchronously, after the event loop turn in which `then` is called, and with a fresh stack. This can be implemented with either a "macro-turn" mechanism such as `setTimeout` or `setImmediate`, or with a "micro-turn" mechanism such as `Object.observe` or `process.nextTick`. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or "trampoline" in which the handlers are called.

This comment has been minimized.

Copy link
@briancavalier

briancavalier Aug 18, 2013

Member

Does it make sense to provide a definition of "platform code" in the definitions section? On one hand, I can see it, since we are defining it. On the other, however, it isn't a term that is central to the foundation of promises (although it is necessary for our particular specification). It's also quite a long paragraph, and would look weird if we moved the whole thing up--would probably have to split it up, providing a short definition up top, and retain the rest of the note at the bottom. Hrm, thoughts?

This comment has been minimized.

Copy link
@domenic

domenic Aug 18, 2013

Author Member

That could work, actually. We'd just move the first sentence up and leave the rest down here.

Although, maybe it doesn't fit, since we're specifically doing promise-specific "terminology" instead of a more general "definitions." Hmm.

This comment has been minimized.

Copy link
@briancavalier

briancavalier Aug 18, 2013

Member

Yeah, that's what I got stuck on as well. It feels like describing machinery rather than defining foundational terminology. I'm leaning toward leaving it as is.


1. That is, in strict mode `this` will be `undefined` inside of them; in sloppy mode, it will be the global object.

Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ These changes help clarify and improve the specification, but should not affect
These changes impose new requirements on implementations, either to specify a previously-undefined behavior, or to fix something incorrect that the spec allowed in version 1.0.

- Specified that `onFulfilled` and `onRejected` must be called as functions, with no `this` value.
- Changed the way in which asynchronicity was mandated for `onFulfilled` and `onRejected`, to enforce the important invariant that the stack be clear. In particular, the new wording prevents fulfilling or rejecting a promise from ever synchronously calling the handlers.
- Prohibited implementations from calling `onFulfilled` or `onRejected` before the corresponding promise was respectively fulfilled or rejected.
- Specified the Promise Resolution Procedure, instead of leaving the mechanism for adopting a thenable's state unspecified.
- The recursive nature of the now-specified procedure improves upon the naïve non-recursive suggestion given in version 1.0.
Expand Down

0 comments on commit afd105b

Please sign in to comment.