-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Closed
Description
#17064 made it possible to access thrown values in Wasm EH and print messages, but it is still hard to use because the user needs to export several functions manually, which is illustrated in the test code in test_exception_message:
Lines 1636 to 1713 in 2a3bb65
| @no_wasm64('MEMORY64 does not yet support exceptions') | |
| @with_both_eh_sjlj | |
| def test_exception_message(self): | |
| self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$getExceptionMessage', '$incrementExceptionRefcount', '$decrementExceptionRefcount']) | |
| self.set_setting('EXPORTED_FUNCTIONS', ['_main', 'getExceptionMessage', '___get_exception_message']) | |
| if '-fwasm-exceptions' in self.emcc_args: | |
| exports = self.get_setting('EXPORTED_FUNCTIONS') | |
| self.set_setting('EXPORTED_FUNCTIONS', exports + ['___cpp_exception', '___increment_wasm_exception_refcount', '___decrement_wasm_exception_refcount']) | |
| # FIXME Temporary workaround. See 'FIXME' in the test source code below for | |
| # details. | |
| if self.get_setting('DISABLE_EXCEPTION_CATCHING') == 0: | |
| self.emcc_args.append('-D__USING_EMSCRIPTEN_EXCEPTION__') | |
| self.maybe_closure() | |
| src = ''' | |
| #include <emscripten.h> | |
| #include <exception> | |
| #include <stdexcept> | |
| using namespace std; | |
| class myexception : public exception { | |
| virtual const char* what() const throw() { return "My exception happened"; } | |
| } myex; | |
| EMSCRIPTEN_KEEPALIVE extern "C" void throw_exc(int x) { | |
| if (x == 1) { | |
| throw 1000; | |
| } | |
| if (x == 2) { | |
| throw 'c'; | |
| } | |
| if (x == 3) { | |
| throw runtime_error("abc"); | |
| } | |
| if (x == 4) { | |
| throw myex; | |
| } | |
| if (x == 5) { | |
| throw "abc"; | |
| } | |
| } | |
| int main() { | |
| EM_ASM({ | |
| for (let i = 1; i < 6; i++){ | |
| try { | |
| _throw_exc(i); | |
| } catch(p) { | |
| // Because we are catching and handling the exception in JS, the normal | |
| // exception catching C++ code doesn't kick in, so we need to make sure we free | |
| // the exception, if necessary. By incrementing and decrementing the refcount | |
| // we trigger the free'ing of the exception if its refcount was zero. | |
| #ifdef __USING_EMSCRIPTEN_EXCEPTION__ | |
| // FIXME Currently Wasm EH and Emscripten EH increases | |
| // refcounts in different places. Wasm EH sets the refcount to | |
| // 1 when throwing, and decrease it in __cxa_end_catch. | |
| // Emscripten EH sets the refcount to 0 when throwing, and | |
| // increase it in __cxa_begin_catch, and decrease it in | |
| // __cxa_end_catch. Fix this inconsistency later. | |
| incrementExceptionRefcount(p); | |
| #endif | |
| console.log(getExceptionMessage(p)); | |
| decrementExceptionRefcount(p); | |
| } | |
| } | |
| }); | |
| } | |
| ''' | |
| expected = '''\ | |
| exception of type int | |
| exception of type char | |
| exception of type std::runtime_error: abc | |
| exception of type myexception: My exception happened | |
| exception of type char const* | |
| ''' | |
| self.do_run(src, expected) |
It'd be good to make this easier to use by creating a single option that adds all necessary imports and exports the tag.
Metadata
Metadata
Assignees
Labels
No labels