v8.dev icon indicating copy to clipboard operation
v8.dev copied to clipboard

Add exception paragraph to JSPI article

Open tomayac opened this issue 1 year ago • 11 comments

This came up as a developer question.

tomayac avatar Jul 18 '23 17:07 tomayac

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.

tlively avatar Jul 18 '23 21:07 tlively

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).

aheejin avatar Jul 18 '23 22:07 aheejin

I haven't experimented with JSPI and exceptions. Maybe @SPY knows the status in V8?

brendandahl avatar Jul 18 '23 22:07 brendandahl

But does that work out of the box with Emscripten, @aheejin?

tlively avatar Jul 19 '23 20:07 tlively

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.

aheejin avatar Jul 19 '23 23:07 aheejin

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.

tlively avatar Jul 20 '23 00:07 tlively

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 :(

fgmccabe avatar Jul 21 '23 16:07 fgmccabe

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'.

fgmccabe avatar Jul 21 '23 17:07 fgmccabe

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.

tlively avatar Jul 21 '23 17:07 tlively

Or we can not change the blog post at all; given that the issues are not actually JSPI-related.

fgmccabe avatar Jul 24 '23 19:07 fgmccabe

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.

tlively avatar Jul 24 '23 20:07 tlively