-
Notifications
You must be signed in to change notification settings - Fork 461
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
Promise.all() will have unexpected behavior if Array.prototype.then exists and is callable (?) #105
Comments
Nope, this is working as intended. You should never be able to fulfill with a thenable; that's why resolving with a thenable triggers its |
An analogous situation: if you remove |
Although I see your point, I believe this behavior will be surprising to many -- similar to Promise.race([]) returning a never-fulfilled promise; it makes sense, but it isn't expected. In particular, the difference between deleting Symbol.iterator and adding Array.prototype.then is that deleting Symbol.iterator is obviously bad, and will visibly break lots of syntax; while adding a 'then' to a object prototype will only affect Promise.all. Psychology plays into this as well. It's easier to understand that removing something causes damage than adding something seemingly innocuous which happens to have a magic name. Consider:
Or how about this:
I think that's pretty surprising. Especially if the definition of This behavior is visible in Chrome 38.0.2125.104 m |
i thought of two more: O.p.then = function (a, b) { b(new SyntaxError("illegal character")); } O.p.then = function () {} // all promises fulfilled with an object will pend forever And another: O.p.then = function (a) { console.log(JSON.stringify(this)); a(this); } // log all promise fulfillment args |
Shrug. This is just how promises work. |
OK. I will add tests to cover this behavior. |
Consider the case where Promise.all([p1, p2]) is called, and p1 and p2 are both unsettled (non-foreign) promises. Then Promise.all installs an
onFulfilled
handler on p1, p2 which is a Promise.all Resolve Element FunctionAssuming both p1, p2 eventually are fulfilled, whichever one fulfills second triggers the final steps of that algorithm, specifically:
CreateArrayFromList
creates an Array object. IfArray.prototype.then
exists and is callable, then instead of fulfilling the Promise with the array, the "foreign thenable" code path in promiseCapability.[[Resolve]] will be exercised, and the Promise returned from Promise.all will be "locked in" to whatever thenable Array.prototype.then looks like.It's hard for me to think of a good design reason that I would want to add a method
then
to Array.prototype or Object.prototype, so this is not something most people will encounter in normal development.Now this is all obviously insane, and possibly just a minor nuisance, but there may be a security risk here in that an attacker who can modify Array.prototype (which is already quite bad, I understand!) would be able to break any Promise.all resolutions in the same ... Realm? Vat? execution context, maybe./cc @domenic
Edited above to clarify meaning.
The text was updated successfully, but these errors were encountered: