-
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
Unintended Functionality: Trap Catching in Wasm #22
Comments
Unfortunately, the strategy for polyfilling JSPI with core stack-switching that was presented yesterday was unsound; it would cause non-trapping JSPI programs to trap. The key issue lies in the export wrapper:
This wrapper is introduced to address the issue I identified here. In particular, it essentially has the export wrapper install a JS-frame to catch the trap. However, the export wrapper is itself supposed to be "suspendable", since the idea was that export wrappers would eventually be implementable in WebAssembly and would consequently be suspendable. Unfortunately, installing this JS-frame would make this polyfilling of the export wrapper not suspendable, which could cause previously-non-trapping JSPI programs to trap. So the issue identified above remains unresolved. |
I do not follow this argument. There is no requirement that the wrapper be suspendable. The requirement is to polyfill the API. |
The spec says "A function is suspendable if it was ... returned by |
Is there a problem with the simple fix of not catching a trap before suspending? If someone really wants a rejected promise when that occurs, they can wrap the promising export with the simple JS code that does so. |
If we change the spec so that the wrapped export always returns a promise, as seems to be the resolution in #11, then this problem is resolved: the wrapped export creates a promise with resolves (i.e. |
Issue: This proposal was designed with the intention that eventually the "suspending" and "promising" functions it produces would be implementable using just WebAssembly extended with some core stack-switching design (and some JS imports or manipulating JS Suspender objects and testing for and adding listeners to JS Promises). However, as an unintended consequence of semantic corner cases, the current semantics makes this impossible without also adding support for catching traps in wasm. In particular, given a wasm function "foo", you can use simple wasm modules and WebAssembly.Function with "suspending" and "promising" options (and no JS code beyond simple linking) to build a WebAssembly.Function that behaves just like "foo" except it throws a wasm exception (with your choice of tag of type
externref
) instead of trapping.Cause: The issue is caused by the fact that a "promising" function both calls the wrapped function immediately and returns a rejected promise immediately if that call traps before suspending.
Fix: The simplest and most flexible way to resolve the issue is to have the "promising" function also trap if that call traps before suspending. (We might also consider taking the change a step further to make "promising" symmetric with "suspending" and have the "promising" function return a promise only if a corresponding suspend occurs, and have it otherwise simply return the tuple of values coerced into an
externref
.)The text was updated successfully, but these errors were encountered: