v8.dev
v8.dev copied to clipboard
Add exception paragraph to JSPI article
This came up as a developer question.
Are there any toolchains that actually handle the exceptions thrown by JSPI properly? @aheejin or @brendandahl, do you know if Emscripten supports this?
If so, it would be good to add an example of this to the docs, otherwise I think the current recommendation in this PR makes sense.
As long as they are JS exceptions, Wasm EH instructions will treat that as such, meaning, catch_all
will catch it and tagged catch
can also catch it if a module imports the JS tag (https://github.com/WebAssembly/exception-handling/pull/269).
I haven't experimented with JSPI and exceptions. Maybe @SPY knows the status in V8?
But does that work out of the box with Emscripten, @aheejin?
For catch_all
catching JS exceptions, it has been supported for long time now.
For catch
catching JS exceptions with the imported JS tag, it was recently added in V8 and I haven't tested it myself, but if you use Emscripten's Wasm EH support and fix the js files manually and run it with V8, I think you should be able run them. V8's test code has an example:
https://github.com/v8/v8/blob/8f6ab4d613bcdb498aac91235694ac0d478ef5d4/test/mjsunit/wasm/exceptions-api.js#L269-L305
But this JS tag spec has not landed yet in the EH repo. I think we shouldn't assume this feature as finished at this point.
Thanks. Since Emscripten does not support smooth interop with JSPI exceptions (or any JS exceptions) at the moment, I think this PR should be good to land as-is.
I am drafting some text to more fully explain this. However, it turns out that returning multiple values (result+errorcode) from JS into wasm/C is completely non-trivial :(
I propose the following wording re exceptions:
Some programming languages, such as C, do not have explicit mechanisms for handling exceptions. In addition, dealing with foreign exceptions in languages that do support exceptions is always likely to be difficult and not very portable. So, while JSPI does support exceptions -- in the sense that a rejected Promise
associated with a wrapped import results in an exception being thrown -- you may need to avoid dealing with exceptions in your code.
One way of dealing with this is to map the result of an operation into a combination of a result value and an error code. In this strategy, you would need to modify the JS of the function you are calling to catch all exceptions and map them into the result code/result value pair. For example, one might write:
function suspFun(args...){
try{
return [ok,realFun(args)];
} catch (E){
return [bad,E];
}
}
On the WebAssembly side, you would need to have code that checked the result code to ensure that the results are as expected. In this case, though, it is unfortunately very awkward to deal with arrays coming from JS in C. What we actually have to write is closer to:
const ok = 0;
const bad = 1;
function suspFun(ptr,args...){
try{
setValue(ptr,ok,i32);
setValue(ptr+4,realFun(args),i32)); // depending on the return type of realFun
return ptr;
} catch (E){
setValue(ptr,bad,i32);
setValue(ptr+4,E,*); // We can't really handle exceptions in C
return ptr;
}
}
On the C/WebAssembly side, the call to the suspFun
import would look something like:
struct{
enum{ok,bad} code;
void *result
} RetSpec;
suspFun(&RetSpec,arg0,..,argn);
This code is understandably fairly ugly, but this complexity is not specifically due to JSPI but rather because C and JavaScript are very different languages; and the boundaries between them have not been fully 'smoothed out'.
Perhaps we can simplify things by having an example where the suspended function just returns 0 on success and -1 on failure. The problem of returning multiple values into Wasm is a real problem, but not directly related to JSPI.
Or we can not change the blog post at all; given that the issues are not actually JSPI-related.
I think saying something about how to handle errors would be useful. This PR was motivated by a partner asking us about error handling with JSPI, and I'm sure other developers would wonder the same thing. The current content of this PR is the best advice we can give that works today with existing toolchains (i.e. Emscripten), so perhaps we can add "In the future, toolchains may make it easier to handle JS exceptions directly" and land this.