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 <
[email protected]> wrote:

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

You can do that for Wasm exceptions by using the JS API
<https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Exception>
.

An example of such code is in our JS library:
https://github.com/emscripten-core/emscripten/blob/9bb02c0182bcfc32450ea15d5be69eab494042df/src/library_exceptions.js#L328-L344
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
<https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Exception>
objects.


> 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
> <https://groups.google.com/d/msgid/emscripten-discuss/CAL_va28LoU_7vRRJBNRPUyFxsCSC0X20ZDBfo2c4LfLpOgZ0qg%40mail.gmail.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/CALJpS1PE2s_D52y7AvyqTK-p6J%3DZOXPOcKss_5_-o18NYwmeAw%40mail.gmail.com.

Reply via email to