Skip to content
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

spec question; should <dfn>ToWebAssemblyValue</dfn> be updated to include exceptions? #328

Open
fgmccabe opened this issue Sep 10, 2024 · 5 comments

Comments

@fgmccabe
Copy link

From a potentially inadequate reading of the spec, there seems to be a gap in ToWebAssemblyValue: it does not seem to allow for a JavaScript exception value to be translated into a WebAssembly exception.

Something like this occurs in JSPI when the reject handler is called if the underlying Promise is rejected: it must be mapped (eventually) to a WebAssembly throw.

@dschuff
Copy link
Member

dschuff commented Sep 10, 2024

The way to translate JS exceptions into wasm exceptions is to import the JavaScript exception tag. Then you can create a wasm catch with that tag, and when a JS function throws/propagates an exception, the thrown object is passed to wasm as a payload (see step 3.10.3 of create a host function). The reverse happens in step 11.3 of call an exported function. What you can't do though is get an exnref that corresponds to an exception originally thrown from JS. Nor can exnrefs go to or from JS via ToJSValue or ToWebAssemblyValue. There was some brief discussion of that here and previous discussion linked there.

@fgmccabe
Copy link
Author

This does not appear to address my concern.
In particular, I believe that it should be possible to pass a JS exception value to wasm, and have the wasm throw it. I.e., we don't throw it into wasm directly.

@dschuff
Copy link
Member

dschuff commented Sep 10, 2024

You can pass any JS value as an externref into wasm (either by passing/returning it from a function, or catching it in wasm), and then you can throw it from wasm as a JS exception (using a throw with the JS tag as its tag, and that externref value as its payload). Once it propagates out to JS, IIUC it will behave the same as any other thrown JS value (i.e it will not be wrapped in a WebAssembly.Exception object).

@sjrd
Copy link

sjrd commented Sep 11, 2024

What you can't do though is get an exnref that corresponds to an exception originally thrown from JS.

Hum, I'm confused by that statement. A catch_ref $JSTag or catch_all_ref clause can definitely catch an exception originally thrown in JavaScript. That gives you a perfectly valid exnref representing the exception thrown by JavaScript. If you rethrow it with throw_ref you'll rethrow the original JavaScript-emitted exception.

Granted, you cannot directly manipulate an exnref in JavaScript code. But that applies regardless of whether the underlying exception was a JavaScript exception of a Wasm exception.

In fact, a JavaScript exception is not special at all. It's just like any other Wasm exception that happens to have the tag WA.JSTag.

@dschuff
Copy link
Member

dschuff commented Sep 11, 2024

Yes, all of that is true. I probably should have said that you can't get a unique exnref that corresponds to the original JS throw. Because the exnref is actually created not at the time of the original JS throw, but when the exception propagates into wasm (3.10.3.3 of "create a host function"). Also, in the "sandwich" scenario with interleaved JS and wasm frames, if that same exception propagates back and forth between JS and wasm multiple times in a single unwind, a fresh exnref is actually created each time it goes from JS to wasm (rather than reusing the original one). I don't know of any case where that distinction actually matters though (and it's not observable in JS, and I guess not even in wasm; exnrefs are not eqrefs and you can't really do anything with them other than storing and throwing).

When we discussed this before where I suggested that we could also allow passing exnrefs out of wasm by means other than throwing and catching; @rossberg noted the complications around throwing vs just allocating a WA.Exception, but if we need to do more interesting things witn exnrefs e.g. for JSPI, then we could easily relax that restriction as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants