Demos and examples: show alert on webgl init failure - #12771
Conversation
|
Hm, I also observe a different issue here. Looking closer at specifically the gallery example, the alert is not appearing because of webGL failure, it appears regardless, because the index.html seems to expect subdirectories for different styles, fluent, material, etc, which are not present. I believe heard something about support for some styles being dropped so I will not touch that for now. |
41e887a to
0ed32d4
Compare
2ea49ad to
4d91f88
Compare
4d91f88 to
a884621
Compare
tronical
left a comment
There was a problem hiding this comment.
Using Rust panic to propagate an error seems counter-intuitive. Why can't we propagate the error via Result to JavaScript?
|
|
||
| #[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))] | ||
| pub fn main() -> Result<(), slint::PlatformError> { | ||
| pub fn main() { |
There was a problem hiding this comment.
This seems counter-intuitive. If wasm-bindgen doesn't support Result<> for main, maybe that's what needs fixing - but at least I think it's worth investigating.
There was a problem hiding this comment.
As I understand it, it is fundamental to the way doing an event driven browser app works, because the browser controls the event loop we have to yield from main in some way or another before the app can even start, since main's job is just to set up the callbacks for the browser to call, not to actually drive things. So failure while the app is running will happen in a place where our main() isn't even in the call stack.
So to be clear, wasm-bindgen does support returning result from main, its just that the webgl error specifically will not be propagated this way.
Now that I look closer, I should probably have kept this result return for the examples, because that would work as intended for errors that occur before the event loop starts, specifically MainWindow::new(). But it would not help the WebGL error since that happens inside of an event handler.
I think in order for us to use Result to propagate this error, winit would have to support returning Result from the trait functions of ApplicationHandler and have those be converted to js exceptions, as returning a result from main() currently does.
Another option which would be similar but leave more rust error handling control flow intact would be to throw the exception in exiting() handler, since that gets called when the browser is closing down the event loop anyways. But then there would (probably?) need to be a mechanism to decide whether a given error warrants an alert popup to the user.
There was a problem hiding this comment.
Now that I look closer, I should probably have kept this result return for the examples, because that would work as intended for errors that occur before the event loop starts, specifically MainWindow::new(). But it would not help the WebGL error since that happens inside of an event handler.
I agree.
I think in order for us to use Result to propagate this error, winit would have to support returning Result from the trait functions of ApplicationHandler and have those be converted to js exceptions, as returning a result from main() currently does.
Right, this isn't possible. Even if we used spawn.
Fundamentally we should try to detect WebGL compatibility problems as early as possible to fit better into our flow of error handling. But any errors after that will either way leave the page useless and the best we can probably do is show an alert or so (we can trigger that).
|
Maybe a different way of looking at this: If we want to detect that the browser doesn't support the absolute minimum requirements we need, then we should do that check as early as possible so that if its into our |
|
I see, I will return Result from everything and then see about detecting this error earlier. |
This improves error messages on wasm for errors that occur before the event loop starts (ie. before we yield out of main).
If the example returns an error from main, this will display a popup with the error's message. If the module panics it will also display a popup but the error message will not be helpful, refer to the console in debug mode (thanks to console_error_panic_hook) in that case. This was already the case for the slide puzzle example and has just been copied to other examples and demos.
a884621 to
d5abbc8
Compare
We don't have a way to return errors out of event handlers in wasm besides panics and exceptions, but we want to display an error message on the event of webgl initialization failure. To get around this, we can create the webgl context when initializing the window, and recognize failures there.
d5abbc8 to
590a550
Compare
|
@tronical AFAICT, there is not really any check for webgl support as conclusive as actually trying to create the context, so I've changed things to do that early, in But this solution isn't perfect since normally we let femtovg decide the parameters for the context creation, we have to replicate those on our end and potentially keep them in sync if they were to change (though I doubt that will happen to any meaningful extent). Additionally, returning an error from So only femtovg is considered and then the webgl error gets returned and displayed as an alert. |
This PR addresses #896 and makes it so that all examples have an obvious error popup if a platform error (such as webgl not loading) happens at startup.
Previously, only the slide puzzle example had this feature. However, it was only able to observe that the main wasm module had panicked and could not get its error message (on panic, the error displayed said something like "unreachable executed"). There was also some unused stuff to return any error from
MainWindow::run()out ofmain(). While that would successfully be converted to an exception and be displayed in an alert, it would never happen on web becauserun()just throws a js exception and never returns: https://docs.rs/winit/latest/winit/event_loop/struct.EventLoop.html#method.run_app (called here). The documentation onrun_app()suggests usingEventLoopExtWebSys::spawn_app()instead but I do not see an easy way to migrate to that.I considered making it so that any exit of the event loop would throw an exception + display an error, but I am not certain that every error should be displayed to the user in that way, so I just kept it in the scope of the issue and just made errors returned from
create_inactive_windows()be propagated into exceptions + alerts.I also reverted the changes related to returning
PlatformErrorfrom main since unwrapping those is fine/consistent with other examples and it was unused on web anyways.Opening a demo in a browser with webgl disabled:

After pressing OK:

I also made a slight change to how the "Slint requires WebGL to be enabled in your browser" warning text appears in the canvas window, since it was getting cut off for me when viewing things like the home automation demo. Previously it looked like this: