It is possible for WebAssembly modules to throw an exception in order to unblock the event loop so that events can be handled by otherwise synchronous code. The only example I can find of this at the moment is in Rust's winit crate. Note that throw
is just implemented as follows:
pub fn throw(msg: &str) {
wasm_bindgen::throw_str(msg);
}
I would expect that throwing such an exception would unwind the WebAssembly stack. Moreover, even if the stack was not unwound, how could the be stack rewound once events (if any) have been handled?
Throwing a WASM exception is not "yielding". It does not "rewind the stack". It's more akin to panic
- it's going to terminate the current execution up to the point where something (usually the browser) catches it. There are no facilities to resume execution of your code at the point at which it threw.
Now, the browser may call into your code again, by executing other handlers and events, but the stack at the point that you threw is gone - akin to resuming execution after catching a panic with catch_unwind
.
For your specific question of why winit's run
function does this:
The contract of the EventLoop::run
function is that it starts up the event loop and runs forever without ever returning (hence the !
return type). For desktop platforms, that's fairly straightforward to do, since the EventLoop
type is in charge of actually setting up and running the event loop.
But in the browser, it's more complicated. The actual event loop is ran by the browser, not by winit, and EventLoop::run
needs to return control to that event loop so that it can "start", but without actually returning to the Rust code.
The easiest way is to throw a dummy exception. The exception will break out of the WASM code into the browser, which will then start executing all the events and callbacks that winit and other things have set up.