-
Notifications
You must be signed in to change notification settings - Fork 165
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
Small clarification on what is a legal value #44
Comments
Actually, since conforming implementations must be able to detect whether an object is or is not a promise created by another implementation (correct me if I'm wrong), the test for "a value" would need to be implementable, and thus should probably be something like "not an object with a |
Hmm, it seems like the spec says exactly that:
and
So, by definition a value is anything that is not an object or function, or is an object or function, but does not define a method (i.e. a callable property) named Although, one nit may be that the phrase "which accepts the following two arguments" is not something we intend to enforce and is not something that is checked in practice. It's possible some may take it to mean, as I think @awwx is hinting, that an object or function with a callable In practice, the check for a promise used by most Promises/A compliant libs is: x && typeof x.then === 'function' I'm not aware of any libs that check |
The problem is that |
No, actually, the question is more what happens to Suppose "a promise" is defined as "an object with a Ok, but
so now if I return Conversely, the spec as it is currently written says "A promise is an object or function that defines a then method that accepts [onFulfilled and onRejected]" and further specifies how onFulfilled and onRejected must work... which could be interpreted to say that if the How to say that One suggestion is that "a promise" could mean "an object fully compliant with the Promises/A+" spec and that "a value" is "a legal language value for which Or, you might prefer to say that "a promise" is a value for which Either way you avoid the ambiguity around |
Hmm. I think this is a good point to bring up, and some interesting clarifications have been made. Notably, when I talked with @lukehoban (T39 member) about standardizing promises, he brought up that one of the things he thought was missing from Promises/A+ was a more precise definition of "promise." Partially this was regarding the duck-typing versus canonical-constructor question that standardizing promises at a language level would bring up, but it also is telling about a potential hole in the spec. Perhaps clarifying with a line item specifically saying that promises are objects or functions with a Let's recall the overall goal of such exercises, though: we need to find the edge cases and specify them so users know how promise libraries will behave. In particular, solutions that make the spec more airtight by walling of large chunks of reality into "noncomformant land" are not great, so I dislike introducing concepts like "valid promise." My first reaction was that this was the situation compliance branding (see #2) was meant to solve: we could specify precisely what an A+ promise is in that way. But that doesn't really help. We want to have users be able to return crap-promises and still a Promises/A+ library does its best to do the right thing. For example, var p = aplusPromise.then(function () {
return $.when(5);
}); should result in Libraries essentially accomplish this by saying if the return value has a I suppose we could spec this. We could modify the main text to more precisely state what "place in the same state" means, along the lines of:
This is pretty icky-sounding and I hesitate to type it because now nobody will try and think of a better phrasing, but there it is. Alternately we could expand upon this in a footnote, saying something like
|
Yes, if it works to have 2.2.6.5 specify what an implementation should do instead of what the result should be, that also fixes the issue for an implementation that wants to be compliant. |
o i c what you are asking, I misunderstood your original question, @awwx. So yeah, I think we could use a note along the lines of what @domenic suggested, to provide guidance for implementors there. It's worth noting though, that
Or something along those lines. That sort of implies that to use promises, you need to make sure your code isn't returning something like |
Yeah, issue one is that for the end-user, they should know that returning Issue two is the wording of 2.2.6.5 could be interpreted to mean the promises implementer was supposed to get it to work, when of course they can't :) So I think if you say that a promise is a value that satisfies |
More comments later, but just wanted to point out one interesting thing:
I don't think this is what you want, given that such a test will fail the (admittedly silly) var x = { valueOf: function () { return false; }, then: function () { } }; Instead it should probably be typeof x === "object" && x !== null && typeof x.then === "function" or in ES-spec language (for fun)
|
@domenic mind that in some of the already existing implementations promises are functions, so I was thinking about it recently, and I think that aside of x && (typeof x.then === 'function') && (x.isPromise === true) Looking at ways of how we identify native EcmaScript objects, the best solution would be following: Object.prototype.toString.call(promise) === '[object Promise]' but we're unable to implement such behavior, so it's good to come up with some workaround. |
@medikoo Good point! My ES-spec language version is correct but not my JS version. Not sure what that says about me. New version: (typeof x === "object" || typeof x === "function") && x !== null && typeof x.then === "function"
See #2!! But then, see my above argument: we still want to be able to support returning crappy not-even-Promises/A promises. Everyone: another possible problem to specify. What do we do in this new spec-addition for the case of
? We should probably cover this case. Unfortunately it seems like we're having to spec an entire assimilation protocol (i.e. a |
@domenic nice, |
Perhaps we could say that an implementation must do the magic with promises/A+ promises and should make a best effort attempt with other promises. Perhaps we could agree to have a canonical |
I dunno guys. Any duck-type test can be thwarted. Simply adding more checks makes it less likely someone will accidentally do it, but until we have a language-level check, it can't be foolproof.
I would rather provide guidance, or even specify (see upthread) what Codifying the test that should separate promises from values does seem like a good addition. We could tighten this test slightly to something like x != null && typeof x.then === 'function' Or something like the very narrow version that @domenic suggested, which exactly matches the current spec language "A promise is an object or function that defines a then method": (typeof x === "object" || typeof x === "function") && x !== null && typeof x.then === "function") |
Just to be clear, you're saying that the behavior for a handler returning this should be implementation-defined? :-/ |
@domenic It's not clear to me how Promises/A+ could account for all possible busted promise doppelgangers. We could suggest/specify what a Promises/A+ It seems like the simplest thing is for the spec to assume that handler-returned promises are well-behaved enough, and we can use their |
Where do we stand on this one? Is @domenic's latest addition of defining the term "promise" enough, or do we still need to go further? Specifically:
I think 1 could be helpful, but I'm not sure about 2. Thoughts? |
I think 1 is not necessary given that it would just be restating the definition in code. We could add it as a footnote if we wanted, I guess. I think 2 is very necessary. |
Wording 2 might be a bit tricky since we're staying away from fulfill/reject APIs. We may be able to say something generic like calling the handler-returned promise's |
Yeah. It might be the place for a non-normative note explaining all the subtleties. Maybe
Alternately, we could be more normative about it:
Maybe there "attempt" could have a footnote explaining why it's an attempt. |
I like those. Perhaps we combine them, as you suggested. Normative:
Footnote for "attempt [3]"
|
What about things that are even less like promises, e.g. an event emitter which might have two events |
@briancavalier Looks pretty good. Only remaining questions:
@ForbesLindesay Those fall under 2.2.6.3: "If either |
I think this can be closed in favor of #52. |
The spec says
and specifies that a callback has different behavior depending on whether a value or a promise is returned.
I might attempt to construct what I think would be a legal value:
which I think is not a promise because it doesn't meet the requirements to make it a conforming promise; and since it's not a promise then it should be a legal value.
Of course one couldn't expect an implementation to inspect my object to see that it wasn't a conforming promise... so for clarity it would be useful to say something like a value is "any legal language value... that is not an object with a
then
property which is callable."The text was updated successfully, but these errors were encountered: