-
Notifications
You must be signed in to change notification settings - Fork 22
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
Don't use IsPromise
#56
Comments
The issue is that (a) we are only looking for 'branded' Promises and (b) we definitely do NOT want to await if a non-Promise is returned. |
Why? That is not something literally any other JS or web API does, as far as I'm aware.
Say more? Why not? What are the scenarios you're concerned about here? My understanding is that this bit of logic only applies when calling specially-marked JS functions, which means that it only applies to functions which return Promises at least some of the time, and in JS it is extremely unusual to have a function which sometimes returns a Promise and sometimes does not. |
If you're concerned about ensuring that applications can avoid the microtask tick when calling a function whose result happens to be immediately ready, they can achieve that with something like function possiblyAsync() {
if (isReady) {
return { async: false, value: foo };
} else {
return { async: true, value: new Promise(resolve => /*...*/) };
}
}
function isAsync(box) {
return val.async;
}
function unwrap(box) {
return box.value;
}
let imports = {
possiblyAsync,
isAsync,
unwrapAsync: new WebAssembly.Suspending(unwrap),
unwrapSync: unwrap,
}; and then (local.set $wrapped (call $possiblyAsync))
(if (call $isAsync (local.get $wrapped))
(then (local.set $unwrapped (call $unwrapAsync (local.get $wrapped))))
(else (local.set $unwrapped (call $unwrapSync (local.get $wrapped))))
) The |
The approach described in the spec has been adopted after a fair amount of discussion within the Wasm CG. Note that we are not specifically covered by this. Or, more accurately, we are partly covered by it: when a module function is exported via WebAssembly.promising, that function will always return a Promise. In the case of suspending, JSPI acts as a consumer of the Promise-returning API call; as such we have the same latitude that JS callers do. Furthermore, the Promise (if it is actually there) is not seen by any user code: it is 'consumed' by the JSPI and transmuted into a suspension of the WebAssembly code. I.e., as far as user code is concerned, from a normal data flow perspective, the caller from user code does not see whether or not a Promise was returned. (There is a back-door route by which a wasm client can potentially tell if they had been suspended but the caller of the suspending function is not directly aware of having been suspended. The principle is the same as for a stopped machine: a stopped machine can only infer indirectly -- after the fact -- that it had been stopped.) |
Is that discussion available anywhere? If not, can you summarize it? Since this contradicts specific guidance from the TAG (as well as being different from every other web spec) I think it's important to capture the reasoning here. I can also come to a Wasm CG meeting if that would be helpful.
I don't know what that means. I gave an example of how to consume an API like Atomics.awaitAsync; just replace
Consuming the result of a developer-supplied Promise-returning function is covered in this document and it says the same thing I did: "you should also allow it to return a thenable or non-promise value, or even throw an exception, and treat all these cases as if they had returned an analogous promise". What do you mean by "we are not covered"?
JS callers do not have access to
Right, but it is produced by user code, yes? So it matters whether only branded promises are accepted. |
Following on from the discussion in the stacks sub-group, and some off-line discussions with other stakeholders:
This counts as a call to those who feel that option 3 does not meet their needs: i.e., that the performance implications of using Promise.resolve are not acceptable. Otherwise, we are leaning to option 3. |
IsPromise
is an ECMAScript-internal thing. Web specs don't use it, and ECMA-262 only uses it inside ofPromise.resolve
andPromise.prototype.then
. It's not intended for use by host APIs like this.The more conventional thing would be to either do an actual
await
unconditionally (which would be my preference), or to check that the result is an object and onlyawait
it in that case (if you're really concerned about not having a microtask tick fornull
, or something).I can help update the spec text to do the conventional thing if you'd like.
The text was updated successfully, but these errors were encountered: