-
Notifications
You must be signed in to change notification settings - Fork 108
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
2.2.2.2 fails when resolving synchronously outside of .then's event-loop-turn #68
Comments
The spec seems pretty clear that no matter what causes |
That's the interpretation issue I was referring to. I think it would have been clearer if the spec said "after the event loop turn which triggered the call, be it |
The spec doesn't real with resolve or reject though. But it does deal with every onFulfilled passed to then. |
True that... |
Hi all, This is also related to the interpretation of "after the event loop turn in which then is called, and with a fresh stack" as well so thought I'd pop it in here rather than new issue. My promise implementation uses an internal trampoline queue (to cover the fresh stack/platform code aspect) & passes all current compliance tests but I'm concerned that I did not correctly implement the after event loop turn requirement...there doesn't seem to be any actual coverage of that requirement when dealing with adding a fulfilment handler to the same promise within a fulfillment handler to that promise. I've modified a test from 2.2.4 to illustrate: describe("Clean-stack execution ordering tests (fulfillment case)", function () {
....
specify("when one `onFulfilled` is added inside another `onFulfilled`", function (done) {
var promise = resolved();
var firstOnFulfilledFinished = false;
promise.then(function () {
var x
;
process.nextTick(function () {
x = 1;
});
promise.then(function () {
assert.strictEqual(firstOnFulfilledFinished, true);
assert.strictEqual(x, 1);
done();
});
firstOnFulfilledFinished = true;
});
}); Am I correct in assuming that A+ implementation would pass this test: I.e. then called in a fulfillment handler is fulfilled in the next event loop turn? |
@sterpe I believe this being left unspecified is intentional |
@stefanpenner nope. @sterpe that test is a bit tricky because it's interleaving two "async queues": process.nextTick and the promise queue. The test of You can picture it this way:
At this point a bunch of stuff has been enqueued, but no other code is ready to run, so our stack is empty. Now it's time to start dequeing stuff. Let's say that things have worked out so that the promise queue comes before the nextTick queue. Then we have:
So this shows how an implementation can be conforming but still fail the x === 1 test. |
I must be missing something because you followed this up with an explanation as to why this is left unspecified. |
Well, I guess it depends on perspective. But this is not an unspecified loophole. This is a very well-specified issue. |
@domenic ah ok. I then believe my wording was incorrect. |
@domenic, thanks for the clarification. I suppose then there's an unnecessary resolution speed penalty that an implementation would have to take in this situation waiting for the next tick queue to unwind in order to pass the 'x' test. |
Or rather potential performance impact since you are ceding the thread back between the on fulfillment handler resolution. |
This is the test for 2.2.2.2:
I think the spec says that
onFulfilled
should be called with a clean stack with regards to thethen
, but not necessarily WRTresolve
. Spec 2.2.4 says:Where note 3.1 clarifies:
Depending on interpretation, specifically of "and with a fresh stack" but mostly because
then
's context is mentioned explicitly whileresolve
/reject
are not, ifd.resolve(dummy)
executesonFulfilled
synchronously, which at this test is not at the same execution context wherethen
was called, then I think the spec says it's OK, but this test will fail because it expectsonFulfilled
to be at a different context toresolve
(i.e. thatisFulfilled = true;
runs beforeonFulfilled
)Personally I think that the spec should enforce fully async of
resolve
/reject
as well (like the test expects), and even further that twoonFulfilled
/onRejected
should also not be called at the same execution context, but if an implementer tries to squeeze every ounce of speed by using synchronous executions where the spec allows, then I think this test should pass ifresolve
executesonFulfilled
synchronously (same for the equivalentreject
and possibly other tests).The text was updated successfully, but these errors were encountered: