A call to std::rethrow_exception prints Abort() error

152 views
Skip to first unread message

Mike Lischke

unread,
Aug 19, 2023, 8:05:38 AM8/19/23
to emscripte...@googlegroups.com
Hi,

In my library I have to catch errors in JS and let C++ do something with them. A typical catch block in JS looks like this:

catch (re) {
if (re instanceof RecognitionException) {
this.getErrorHandler().reportError(this, re);
this.getErrorHandler().recover(this);
} else {
throw re;
}
}

The call to `recover` prints this message, however (-s ASSERTION used with -O3):

Aborted(native code called abort())

The native code is:

void BailErrorStrategy::recover(Parser *recognizer, std::exception_ptr e) {
ParserRuleContext *context = recognizer->getContext();
do {
context->exception = e;
if (context->parent == nullptr)
break;
context = static_cast<ParserRuleContext *>(context->parent);
} while (true);

try {
std::rethrow_exception(e); // Throw the exception to be able to catch and rethrow nested.
} catch (RecognitionException & /*inner*/) {
std::throw_with_nested(ParseCancellationException());
}
}

I traced the execution to the `std::rethrow_exception` line, which ends this call prematurely with the above error. To see if it is just a different exception I added a catch(...) clause, but that is never executed, so to me it looks as if `std::rethrow_exception` is something that cannot be used in WebAssembly. Is that assumption correct and what can I do to overcome that problem?


Sam Clegg

unread,
Aug 20, 2023, 6:24:14 PM8/20/23
to emscripte...@googlegroups.com
Hi Mike,

Can you share the link flags you are are using for your project?    We know this works in at least some cases because we have a test for it:

See:


and:


I imagine there is some issue with the settings you are using.

Do you get any kind of backtrace when you see the `Aborted(native code called abort())` message?  Normally I would expect to see a backtrace?  Does happens with you build with `-O0` vs `-O3`?  Any more information?

cheers,
sam

--
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-disc...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/3E0EEA6F-D458-4771-8443-FD4E242808D4%40googlemail.com.

Mike Lischke

unread,
Aug 21, 2023, 3:45:13 AM8/21/23
to emscripte...@googlegroups.com
Hey Sam,



Can you share the link flags you are are using for your project?    We know this works in at least some cases because we have a test for it:

See:


and:


I imagine there is some issue with the settings you are using.

Do you get any kind of backtrace when you see the `Aborted(native code called abort())` message?  Normally I would expect to see a backtrace?  Does happens with you build with `-O0` vs `-O3`?  Any more information?

Sure, here's the stack:

Aborted(native code called abort())
antlr4-runtime-wasm.js:677
RuntimeError: Aborted(native code called abort())
    at abort (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:696:11)
    at _abort (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:6770:7)
    at invoke_v (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7777:29)
    at std::__terminate(void (*)()) (wasm://wasm/0503c22a:wasm-function[5703]:0xdaa23)
    at std::terminate() (wasm://wasm/0503c22a:wasm-function[5701]:0xdaa06)
    at std::rethrow_exception(std::exception_ptr) (wasm://wasm/0503c22a:wasm-function[3857]:0xb19ca)
    at invoke_vi (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7645:29)
    at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) (wasm://wasm/0503c22a:wasm-function[2218]:0x405c6)
    at invoke_viii (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7667:29)
    at antlr4::BailErrorStrategy::recover(antlr4::Parser*) (wasm://wasm/0503c22a:wasm-function[2223]:0x40bc1)

And this is the build call:

em++ \
wasm/antlr4-runtime-wrapper.cpp \
antlr4-cpp-runtime/*.cpp\
antlr4-cpp-runtime/atn/*.cpp\
antlr4-cpp-runtime/dfa/*.cpp\
antlr4-cpp-runtime/internal/*.cpp\
antlr4-cpp-runtime/misc/*.cpp\
antlr4-cpp-runtime/support/*.cpp\
antlr4-cpp-runtime/tree/*.cpp\
antlr4-cpp-runtime/tree/pattern/*.cpp\
antlr4-cpp-runtime/tree/xpath/*.cpp\
-O3\
-std=c++17 -lembind -Iantlr4-cpp-runtime/ \
-o wasm/antlr4-runtime-wasm.js\
-s EXPORT_ES6=1\
-s WASM=1\
-s WASM_BIGINT=1\
-s ALLOW_MEMORY_GROWTH=1\
-s ASSERTIONS\
-fexceptions\
-g


I wonder why std::rethrow_exception calls std::__terminate in my code...

Btw. I saw that JS objects from exceptions thrown in C++ are different compared to all the other objects (no $$, no class handle etc). That makes it impossible to use `instanceof` to check for a particular exception type. I now have to check the exception name, which is a bit awkward. As you see I'm using JS exception support, not wasm exceptions, as the latter are a bit inconvenient with those tags to get details (I know there's getExceptionMessage, but that's not better than checking the JS exception object name).

On the other hand, if I throw a C++ exception in its JS incarnation, I get the normal object structure and `instanceof` works. Is this different behaviour intended?

For completeness I also tested with -swasm-exception and got this stack trace:

libc++abi: terminating
antlr4-runtime-wasm.js:1660
Aborted(native code called abort())
antlr4-runtime-wasm.js:677
RuntimeError: unreachable
    at __trap (wasm://wasm/04f49f3e:wasm-function[5811]:0xb7307)
    at ___trap (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7407:54)
    at abort (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:706:5)
    at _abort (file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:6599:7)
    at abort_message (wasm://wasm/04f49f3e:wasm-function[5680]:0xb53bd)
    at demangling_terminate_handler() (wasm://wasm/04f49f3e:wasm-function[5681]:0xb54ed)
    at std::__terminate(void (*)()) (wasm://wasm/04f49f3e:wasm-function[5703]:0xb56b9)
    at std::terminate() (wasm://wasm/04f49f3e:wasm-function[5701]:0xb5692)
    at std::rethrow_exception(std::exception_ptr) (wasm://wasm/04f49f3e:wasm-function[3815]:0x92fd7)
    at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) (wasm://wasm/04f49f3e:wasm-function[2178]:0x386ed)






Sam Clegg

unread,
Aug 21, 2023, 12:02:19 PM8/21/23
to emscripte...@googlegroups.com
Taking a quick look at rethrow_exception, it looks like it calls `terminate` if the `ptr` is NULL:


Can you trace the value of the `std::exception_ptr` you are trying to rethrow to confirm?

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

Can you explain what you mean by "if I throw a C++ exception in its JS incarnation".. what is a JS incarnation?

When you talk of ` $$` and `class handle` and you talking about embind/emval objects?

cheers,
sam

--
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-disc...@googlegroups.com.

Mike Lischke

unread,
Aug 22, 2023, 4:56:11 AM8/22/23
to emscripte...@googlegroups.com

Taking a quick look at rethrow_exception, it looks like it calls `terminate` if the `ptr` is NULL:


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

          while the C++ exception, thrown in JS looks like this:

          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.

          Sam Clegg

          unread,
          Aug 22, 2023, 12:26:01 PM8/22/23
          to emscripte...@googlegroups.com, Heejin Ahn
          On Tue, Aug 22, 2023 at 1:56 AM 'Mike Lischke' via emscripten-discuss <emscripte...@googlegroups.com> wrote:

          Taking a quick look at rethrow_exception, it looks like it calls `terminate` if the `ptr` is NULL:


          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

          My JSError do you mean something that is the result of calling `new Error` in JS?   I don't think that can or should interact at all with the C++ exception handling mechanism.   I see them as two orthogonal systems and trying to mix them or conflate them is likely to lead to trouble.
           
          - throw C++ exception in C++

          This should clearly work. 
           
          - throw C++ exception in JS

          I don't think it possible (or should be possible) to use a JS `throw` statement to throw C++ exception.. C++ exceptions must be thrown by the native `__cxa_throw` mechanism.  In order words even if you have a handle to C++ object you want to throw, I believe the only way to throw is to call back into native code to perform a C++ throw.

          I could be wrong about this though.. @Heejin Ahn can probably say more on this.

          - throw a JS error in C++ (I believe, never tried that)

          IIRC would just be throwing C++ object that happened to be a val that pointed to JS object.. which I think should work fine.



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

          I don't see why embind would need to be involved necessarily.  Not all programs use embind, and its possible to refer to C++ object via simple pointers in JS.   If you have a simple pointer to C++ object I don't think there is anything stopping you from just doing `throw ptr` in JS.  However, as I say above that is not that same as throwing in C++.. and what you would really want to do is callback into native code. e.g. `_throw_in_cpp(ptr)`.

          --
          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-disc...@googlegroups.com.

          Heejin Ahn

          unread,
          Aug 22, 2023, 8:08:10 PM8/22/23
          to emscripte...@googlegroups.com, Heejin Ahn
          I'm not sure if I understand the whole thread. For starters, BailErrorStrategy::recover in the first post takes two arguments and it looks you only provided one, making the second argument null automatically? Also I don't understand what you mean by "JS incarnation of C++ exceptions" either... Anyway, my comments for the last email are inline.

          On Tue, Aug 22, 2023 at 9:26 AM 'Sam Clegg' via emscripten-discuss <emscripte...@googlegroups.com> wrote:


          On Tue, Aug 22, 2023 at 1:56 AM 'Mike Lischke' via emscripten-discuss <emscripte...@googlegroups.com> wrote:

          Taking a quick look at rethrow_exception, it looks like it calls `terminate` if the `ptr` is NULL:


          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

          My JSError do you mean something that is the result of calling `new Error` in JS?   I don't think that can or should interact at all with the C++ exception handling mechanism.   I see them as two orthogonal systems and trying to mix them or conflate them is likely to lead to trouble.
           
          - throw C++ exception in C++

          This should clearly work. 
           
          - throw C++ exception in JS

          I don't think it possible (or should be possible) to use a JS `throw` statement to throw C++ exception.. C++ exceptions must be thrown by the native `__cxa_throw` mechanism.  In order words even if you have a handle to C++ object you want to throw, I believe the only way to throw is to call back into native code to perform a C++ throw.

          I could be wrong about this though.. @Heejin Ahn can probably say more on this.

          You can do that for Wasm exceptions by using the JS API.

          This code does some string manipulation to make the stack trace tidy, but what you need for creating an exception and throwing is just these lines:
          ```
          var e = new WebAssembly.Exception(getCppExceptionTag(), [ex], {traceStack: true});
          throw e;
          ```
          I'm not sure you can do that for the old way of Emscripten exceptions. 


          - throw a JS error in C++ (I believe, never tried that)

          IIRC would just be throwing C++ object that happened to be a val that pointed to JS object.. which I think should work fine.



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

          I don't see why embind would need to be involved necessarily.  Not all programs use embind, and its possible to refer to C++ object via simple pointers in JS.   If you have a simple pointer to C++ object I don't think there is anything stopping you from just doing `throw ptr` in JS.  However, as I say above that is not that same as throwing in C++.. and what you would really want to do is callback into native code. e.g. `_throw_in_cpp(ptr)`.

          I'm also not sure why embind should be involved. By the way, Wasm exceptions will not be represented as simple integer pointers in the JS world. They are WebAssembly.Exception objects.

          Mike Lischke

          unread,
          Aug 23, 2023, 3:47:52 AM8/23/23
          to emscripte...@googlegroups.com, Heejin Ahn

          - throw JSError in JS

          My JSError do you mean something that is the result of calling `new Error` in JS?   I don't think that can or should interact at all with the C++ exception handling mechanism.   I see them as two orthogonal systems and trying to mix them or conflate them is likely to lead to trouble.

          Right, right, this was just the initial step to find a common ground from which to go up in our discussion.


          - throw C++ exception in JS

          I don't think it possible (or should be possible) to use a JS `throw` statement to throw C++ exception.. C++ exceptions must be thrown by the native `__cxa_throw` mechanism.  In order words even if you have a handle to C++ object you want to throw, I believe the only way to throw is to call back into native code to perform a C++ throw.

          I could be wrong about this though.. @Heejin Ahn can probably say more on this.

          For me it works. I have bound the RecognitionException (and many others, including std::exception) with embind and throw that in my JS code. It is catched in the catch() clause in JS and I can work with the exception, including sending it to C++ where it can be used to wrap it with `std::make_exception_ptr` and `std::rethrow_exception`. Great integration, I must say!

          The only little thing that is missing is the wrapping of the exception class as "normal class handle", as it is done for the other C++ classes in JS, to allow things like checking the type using `instanceof`.



          I don't see why embind would need to be involved necessarily.  Not all programs use embind, and its possible to refer to C++ object via simple pointers in JS. 

          That's certainly true, but my confusion with all the things required to make this work with embind is already huge. Please don't add to that with more options :-D

          Thanks, 

          Mike Lischke

          unread,
          Aug 23, 2023, 4:15:32 AM8/23/23
          to emscripte...@googlegroups.com, Heejin Ahn
          Hey Heejin,


          I'm not sure if I understand the whole thread. For starters, BailErrorStrategy::recover in the first post takes two arguments and it looks you only provided one, making the second argument null automatically?

          During the time this e-mail thread ran I tried a number of changes, to find a solution. The original code tried to get the exception ptr from C++ in JS and forwarded that to the recover() method. That didn't work, so I changed the code and passed no exception in, while on C++ side `std::current_exception()` was used to get this exception pointer. Also that failed, but a hint from Sam gave me the right idea (there can't be a current exception in C++, if no C++ exception was thrown **in C++**). That's why I ended up with passing the C++ exception that was thrown in JS to C++, where I could then do all the processing successfully.

          Also I don't understand what you mean by "JS incarnation of C++ exceptions" either... 

          In one of my mails I explained what I meant. It's about the JS object for a C++ exception class (or any C++ class, for that matter).


           
          - throw C++ exception in JS

          I don't think it possible (or should be possible) to use a JS `throw` statement to throw C++ exception.. C++ exceptions must be thrown by the native `__cxa_throw` mechanism.  In order words even if you have a handle to C++ object you want to throw, I believe the only way to throw is to call back into native code to perform a C++ throw.

          I could be wrong about this though.. @Heejin Ahn can probably say more on this.

          You can do that for Wasm exceptions by using the JS API.

          This code does some string manipulation to make the stack trace tidy, but what you need for creating an exception and throwing is just these lines:
          ```
          var e = new WebAssembly.Exception(getCppExceptionTag(), [ex], {traceStack: true});
          throw e;
          ```
          I'm not sure you can do that for the old way of Emscripten exceptions. 

          Well, I guess we have to make sure we talk about the same use cases. In my case I throw these exceptions in JS only to interrupt JS code, not C++ code. However, I have to know which exception was thrown from JS code in C++, as further handling depends on that (hence that call to `recover()` with the catched exception in JS). To recap, this is how it looks (and works) now:

          catch (re) {
          if (re instanceof RecognitionException) {
          this.getErrorHandler().reportError(this, re);
          this.getErrorHandler().recover(this, re);
          } else {
          throw re;
          }
          }

          `re` is a sub class of the wrapped C++ `RecognitionException` and recover() will throw a nested exception in C++ as the final action, which is catched somewhere else.


          I'm also not sure why embind should be involved. By the way, Wasm exceptions will not be represented as simple integer pointers in the JS world. They are WebAssembly.Exceptionobjects.

          Yes, I experimented with both variants (-fexceptions and -fwasm-exceptions), but I have no clear picture which one is better. However, the WebAssembly exceptions seem to require more work (getting information and manually delete them) and the documentation is pretty thin for either way.

          Anyway, the discussion here is rather about how to make the `instanceof` operator work on a catched exception that was thrown in C++.

          Thanks for all the insight!
          Reply all
          Reply to author
          Forward
          0 new messages