-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ambiguity/identity loss when (re)throwing external exceptions #207
Comments
I'm not sure I'm clear on what exactly the use case is here. Doing one of those things will allow a toolchain to track exception identity explicitly either internally to the language (e.g. as C++ has an exception object allocated in linear memory), or externally via an externref which corresponds to a JS exception object (or externally via importing some other language or module's definition of an exception). In emscripten the current plan is to actually do both; this is because we use the C++ standard way of allocating exception objects, but also because we want to have the option of preserving exception identity via a JS object so that we can attach a JS stack trace to it. The idea is that we can call to JS to allocate a |
The use case I am currently thinking about is ~ the following: When a (local $exception i32)
;; code before
block $try
try
;; code of try block
br $try
catch $SomeTag
local.set $exception
catch_all
;; make substitute
local.set $exception
end
;; code of catch
end
;; code after so that any kind of exception can be handled according to the expectation that a source level // code before
try {
// code of try block
} catch (Exception exception) {
// code of catch
}
// code after is guaranteed to handle any exception, known or not, where Now, #202 addresses the case where the unknown exception is a JS exception, which can be modeled by importing JS's exception tag as envisioned and providing, say, an immutable As such, what I am particularly interested in is the general case, for example when modules are (re-)composed post-compilation. Modules can be moved between hosts for example, or various languages can be involved that are not necessarily aware of each other at compilation time so there are no tags to import, yet there may be the need to defensively handle any exception, leading to either a) loss of identity via substitute or b) the need for a non-portable, non-standard workaround, which both seem desirable to avoid - for example by providing a usable reference in the general case. |
OK, I think I understand what you're getting at. I think what you've shown is what you'd do if you want to actually handle an unknown exception (as opposed to, say, running some local cleanup and then rethrowing it). |
It's true that the identity does not necessarily matter for the cleanup code in an intermediary module (i.e. a substitute might be fine), but preserving identity might nonetheless matter for the original caller that does not expect that a substitute became necessary half-way. What I imagine is that, depending on how complex the cleanup code is, and where or when within the cleanup code the original exception is thrown for the caller again (say cleanup code is async [e.g. goes through a callback] and/or the rethrow happens in another function, which is fine in any language that assumes that any exception is referenceable), there might not be the option to use a As a reference point, I guess an incomplete solution mid-way between a virtual reference and a properly typed reference (e.g. imported JS exception tag) can be imagined as a generalization of #202 that works for any kind of exception that can be represented by an |
To handle an external exception, for example originating in JavaScript, one would naturally use a
catch_all
clause iiuc. The caught exception can (only) berethrow
n unmodified as long as it does not escape the scope of the catch clause, implying some limitations. To give an example of what I mean, imagine the following pseudocode in Wasm with EH:where
ex
cannot refer to the original exception since there is no such reference available when using acatch_all
clause, so a compiler will likely utilize a substitute, say anExternalException
instance to represent the exception. When raising the exception again, this leads to an ambiguity within the catch clause if a language does not itself have an expression-lessthrow;
instruction (JS for example considers this a syntax error) or likewise to indicate the intent to rethrow:Furthermore, if the exception escapes the catch clause, the only available option becomes to throw the substitute, with the exception losing identity and being unable to refer to the original exception due the unavailable reference:
Now I know that
exnref
has been removed for reasons, yet being able to reference an (external) exception incatch_all
seems useful. Externally in JS this is not a problem because there is such a reference, aWebAssembly.Exception
. Could there perhaps be a similar reference in Wasm when using/limited to acatch_all
clause? Or are there clever tricks to emulate the desired behavior in a portable way?Related: #202
The text was updated successfully, but these errors were encountered: