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

Should wasm code be able to extract the externref from exceptions thrown from js? #202

Open
Ms2ger opened this issue Feb 14, 2022 · 6 comments

Comments

@Ms2ger
Copy link
Contributor

Ms2ger commented Feb 14, 2022

It seems like we would need to expose the "JavaScript exception tag" to JS (as a WebAssembly.Tag object, presumably?), so it can be passed as one of the imports when instantiating a wasm module.

I'll try to take a look at defining this after #201.

CC @aheejin

@dschuff
Copy link
Member

dschuff commented May 2, 2022

Based on our previous discussions, I think the conclusion was that we do want to do this. As you said, I think that it would be a WebAssembly.Tag object, and when you import it and catch it, you'd get an externref on the stack which corresponds to the object thrown from JS.

@bakkot
Copy link

bakkot commented Jan 24, 2023

I would like to be able to do this. Specifically, I have some wasm code which calls a JS function inside a (wasm) try/catch, and the JS function throws an arbitrary JS exception (or indeed any value, since JS exceptions are not restricted), and inside the (wasm) catch I want to be able to pass that exception as an externref to a different JS function.

Was there ever progress on this?

I see a comment at #218 (comment) which seems to imply it's "could be deferred to a future version of wasm". Is that right? Is that tracked somewhere?

@aheejin
Copy link
Member

aheejin commented Feb 3, 2023

#218 (comment) is about preserving exception identities and not about being able to extract JS exceptions from Wasm side. #218 (comment) basically says, if JS throws an exception and it passes through Wasm (either by not being caught or being caught and rethrown) the exception object you will get is the same as the one you threw.

I think you can define your own WebAssembly.Tag in the JS side using the JS API and specify parameters as [externref], create an WebAssembly.Exception using the JS API and pass your JS object, import the tag you defined from Wasm, and create a catch instruction that can catch the imported tag and extract the externref thrown. I don't think there's a toolchain yet that enables this process automatically though.

@michaelficarra
Copy link
Contributor

@aheejin The exceptions I am interested in catching are not thrown by code that I control. They are not WebAssembly.Exception instances. They are any JavaScript value. I want to catch them and pass the externref to a JavaScript FFI that I've defined for processing.

The current strategy I have to take is wrapping the body of any JS FFI that may throw (due to transitively calling something that may throw) in a try/catch and then in the catch block setting a wasm global with the caught value. Then after every call to one of these FFIs from wasm, I check to see if the global has been set and, if so, process it. This works, but it is much less convenient than having a catch in wasm for JS exceptions.

@aheejin
Copy link
Member

aheejin commented Feb 3, 2023

The current strategy I have to take is wrapping the body of any JS FFI that may throw (due to transitively calling something that may throw) in a try/catch and then in the catch block setting a wasm global with the caught value.

How do you catch a JS exception and extract it, given that you don't have a tag for that imported in wasm?

@michaelficarra
Copy link
Contributor

function someJSFFI() {
  try {
    // do some stuff
  } catch (e) {
    wasmInstance.exports.storedError.value = e;
  }
}

dschuff added a commit that referenced this issue Apr 26, 2024
As discussed in #202

The JS tag was added to the JS API spec in #301, but it is not observable. This change
exposes it on the WebAssembly namespace, allowing it to be imported into wasm modules.
This allows wasm modules to explicitly extract the thrown JS objects as externrefs from the
caught exrefs, and also to throw fresh exceptions with externref payloads that will propagate 
into JS and can be caught as bare JS objects not wrapped in a WebAssembly.Exception.

It also places the restriction that WebAssembly.Exception objects cannot be created with
the JS tag, because it would result in ambiguity or asymmetry when such objects unwind
from JS into wasm and back out.
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

5 participants