It looks like it is, actually, but it's a bit complicated. Here's the scheme: am I requiring anything that doesn't exist?
I have a great big math library that I want to make available in WebAssembly form, as a commercial product. It is written in C and C++, and runs on Android, iOS, Linux, macOS and Windows. Its heritage is from 1980s and 1990s technical computing, but it is still going strong as a commercial product. The immediate customers for it want to call it from C/C++ code that they already use on other platforms (mostly Linux and Windows), rather than from JavaScript.
This math library has a test harness, also written in C and C++. The test cases are not written in C/C++, but in interpreted LISP, because that's quite suitable for handling the data that the library works with, plus it was easy to write our own portable implementation of the language.
When you run the test harness, it looks for a LISP file to run and starts interpreting it, which usually starts by reading a lot more LISP files to set up a working environment. It then starts reading test scripts and making the calls to the math library that they request. The test harness does not exit until it has finished running everything it was given, or it hits an unrecoverable error. On its existing platforms, it can recover from SIGSEGV, SIGPFE, and other run-time errors, aborting the test that caused them and continuing with the subsequent test(s).
That last part is the problem with a naive WebAssembly implementation, where the library and the test harness are statically linked together. That means there's no opportunity for a JavaScript error handler to get involved before exceptions caused by access violations come flying out of the top of the test harness. By then, the call stack is gone, and there's no way to recover from the exception and continue with the next test.
That's where I'd got to when I wrote " . . . what I want to do isn't possible in Emscripten." I've had what seem like better ideas since then.
WebAssembly "modules" are, as far as I understand, kind of like Windows DLLs or Linux shared libraries. There's a difference in that you can't link a module against other modules: inter-module calls have to go via JavaScript. Is that correct?
I was slow to realise that I can put JavaScript error handlers into any JavaScript layer. To take advantage of that, I would link my math library as a module, and its test harness as the main program. The test harness would call JavaScript code, which would call the library from within a try/catch block, catch exceptions, call the library's "tidy up" functions, and return an error code to the test harness. That lets the test harness recover from exceptions and move on to the next test. It also means I need to create a JavaScript wrapper for the whole of the library's API, which is a bit of a big job, but makes the library more generally usable in WebAssembly code.
While writing this mail,I realised a possible short-cut to let me get the test harness running more quickly, without having to generate a wrapper for hundreds of different functions, with thousands of associated data types and constants. It goes like this:
The calls to the library from the test harness are generated by C macros, and I can add code to those for the WebAssembly build. So it appears I could use EM_ASM() to create JavaScript error handlers at each of those call sites, as part of the test harness source. I could then statically link the library and the test harness for running tests. Is that plausible?
Thanks in advance,
John