> > Taking a quick look at rethrow_exception, it looks like it calls `terminate` > if the `ptr` is NULL: > > https://github.com/emscripten-core/emscripten/blob/097290ded2746c6ba703d556fd53b23e5aef760a/system/lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp#L66-L71 > > Can you trace the value of the `std::exception_ptr` you are trying to rethrow > to confirm?
That was spot on Sam! The error is thrown in JS, so calling `std::current_exception()` in C++ returns a null ptr. What I do now is to forward the thrown exception from JS (which is one of the C++ exceptions) and call std::make_exception_ptr to convert it to an exception pointer (to create a nested exception). > > Regarding handling C++ exceptions in JS, I think you will always need to do > things like getExceptionMessage to unpack information if all you have is a > thrown object from C++. Well, the thrown error has its name set to the C++ exception, so what I do now is: private isCancellationException(e: Error): boolean { return e.name === "std::__nested<antlr4::ParseCancellationException>"; } Not really elegant, nor type safe, but it works. > > Can you explain what you mean by "if I throw a C++ exception in its JS > incarnation".. what is a JS incarnation? Sure. There are 4 ways you can throw an exception/error with wasm: - throw JSError in JS - throw C++ exception in C++ - throw C++ exception in JS - throw a JS error in C++ (I believe, never tried that) To throw a C++ exception in JS that exception must be bound as usual with embind (and that thrown JS error is the JS incarnation of the C++ exception). When you get an instance of a normal C++ class in JS, it represents such an embind/emval object (class handle). Not so for a C++ exception thrown in C++ but catched in JS. Check this out: This is the JS object of the C++ exception thrown in C++: std::__nested<antlr4::ParseCancellationException>\n at ___resumeException (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:1328:25)\n at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) (wasm://wasm/0507610a:wasm-function[2254]:0x414cb)\n at invoke_viii (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7667:29)\n at antlr4::BailErrorStrategy::recover(antlr4::Parser*, antlr4::RecognitionException*) (wasm://wasm/0507610a:wasm-function[2257]:0x4161d)\n at emscripten::internal::MethodInvoker<void (antlr4::BailErrorStrategy::*)(antlr4::Parser*, antlr4::RecognitionException*), void, antlr4::BailErrorStrategy*, antlr4::Parser*, antlr4::RecognitionException*>::invoke(void (antlr4::BailErrorStrategy::* const&)(antlr4::Parser*, antlr4::RecognitionException*), antlr4::BailErrorStrategy*, antlr4::Parser*, antlr4::RecognitionException*) (wasm://wasm/0507610a:wasm-function[205]:0xb1a1)\n at ClassHandle.BailE… … excPtr: 4098424 name: 'std::__nested<antlr4::ParseCancellationException>' message: '' stack: 'std::__nested<antlr4::ParseCancellationException>\n at ___resumeException (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:1328:25)\n <> at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) (wasm://wasm/0507610a:wasm-function[2254]:0x414cb)\n <> at invoke_viii (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7667:29)\n <> at antlr4::BailErrorStrategy::recover(antlr4::Parser*, antlr4::RecognitionException*) (wasm://wasm…r4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:12448:40)\n <> at MySQLParser.selectStatement (file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:12222:30)\n <> at MySQLParser.simpleStatement (file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:3283:30)\n <> at MySQLParser.query (file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:3140:46 <>)' [[Prototype]]: EmscriptenEH while the C++ exception, thrown in JS looks like this: ClassHandle {$$: {…}} $$: {ptrType: RegisteredPointer, ptr: 4069744, count: {…}} [[Prototype]]: ClassHandle The call stack for the first case is: std::__nested<antlr4::ParseCancellationException> at ___resumeException (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:1328:25) at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) (wasm://wasm/0507610a:wasm-function[2254]:0x414cb) at invoke_viii (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7667:29) at antlr4::BailErrorStrategy::recover(antlr4::Parser*, antlr4::RecognitionException*) (wasm://wasm/0507610a:wasm-function[2257]:0x4161d) at emscripten::internal::MethodInvoker<void (antlr4::BailErrorStrategy::*)(antlr4::Parser*, antlr4::RecognitionException*), void, antlr4::BailErrorStrategy*, antlr4::Parser*, antlr4::RecognitionException*>::invoke(void (antlr4::BailErrorStrategy::* const&)(antlr4::Parser*, antlr4::RecognitionException*), antlr4::BailErrorStrategy*, antlr4::Parser*, antlr4::RecognitionException*) (wasm://wasm/0507610a:wasm-function[205]:0xb1a1) at ClassHandle.BailErrorStrategy$recover [as recover] (eval at newFunc (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:5544:27), <anonymous>:11:1) at MySQLParser.queryExpression (file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:12448:40) at MySQLParser.selectStatement (file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:12222:30) at MySQLParser.simpleStatement (file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:3283:30) at MySQLParser.query (file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:3140:46) {excPtr: 4098424'} The class MySQLParser is a JS file (TS actually, but anyway). During a parse run it creates an error (which is a bound C++ exception) and throws it. It also catches it and forwards it to C++ (the call to `recover`). This function now throws a nested C++ exception, which is then catched in the outer code that started the parser run. > > When you talk of ` $$` and `class handle` and you talking about embind/emval > objects? The JS operator `instanceof` only works for the second form (embind/emval object), not the first one, which must be some special object type I have not seen before in normal execution. Mike -- www.soft-gems.net -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/FC886282-090A-4B9B-9EDD-9D09D82BF6E3%40googlemail.com.