On Tue, Aug 22, 2023 at 1:56 AM 'Mike Lischke' via emscripten-discuss <
[email protected]> wrote:

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

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 <[email protected]> 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)`.

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 [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/emscripten-discuss/FC886282-090A-4B9B-9EDD-9D09D82BF6E3%40googlemail.com
> <https://groups.google.com/d/msgid/emscripten-discuss/FC886282-090A-4B9B-9EDD-9D09D82BF6E3%40googlemail.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/CAL_va28LoU_7vRRJBNRPUyFxsCSC0X20ZDBfo2c4LfLpOgZ0qg%40mail.gmail.com.

Reply via email to