1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

eframe web: Better panic handling (#2942)

* Refactor: remove extra store of events

* Remove unnecessary extra function

* Refactor: simplify event registering

* Store panic summary

* egui_demo_app: move web-part to own module

* index.html: await

* Properly unsubscribe from events on panic

* Better error handling

* Demo app html: hide the wasm canvas and show an error message on panic

* egui_demo_app: add panic button to test panic response on web

* fix typo

* Use a constructor to create WebHandle

* Refactor: less use of locks in the interfaces

* More consistent naming
This commit is contained in:
Emil Ernerfeldt
2023-04-21 08:33:01 +02:00
committed by GitHub
parent 7f2de426d2
commit ac50fa0d94
10 changed files with 703 additions and 650 deletions

View File

@@ -91,6 +91,7 @@
transform: rotate(360deg);
}
}
</style>
</head>
@@ -124,27 +125,58 @@
// We'll defer our execution until the wasm is ready to go.
// Here we tell bindgen the path to the wasm file so it can start
// initialization and return to us a promise when it's done.
console.debug("loading wasm…");
console.debug("Loading wasm…");
wasm_bindgen("./egui_demo_app_bg.wasm")
.then(on_wasm_loaded)
.catch(on_wasm_error);
.catch(on_error);
function on_wasm_loaded() {
console.debug("wasm loaded. starting app…");
console.debug("Wasm loaded. Starting app…");
// This call installs a bunch of callbacks and then returns:
const handle = wasm_bindgen.start("the_canvas_id");
// call `handle.stop_web()` to stop
// uncomment to quick result
// setTimeout(() => {handle.stop_web(); handle.free())}, 2000)
console.debug("app started.");
document.getElementById("center_text").remove();
let handle = new wasm_bindgen.WebHandle("the_canvas_id");
handle.then(on_app_started).catch(on_error);
}
function on_wasm_error(error) {
function on_app_started(handle) {
// Call `handle.destroy()` to stop. Uncomment to quick result:
// setTimeout(() => { handle.destroy(); handle.free()) }, 2000)
console.debug("App started.");
document.getElementById("center_text").innerHTML = '';
function check_for_panic() {
if (handle.has_panicked()) {
console.error("The egui app has crashed");
// The demo app already logs the panic message and callstack, but you
// can access them like this if you want to show them in the html:
// console.error(`${handle.panic_message()}`);
// console.error(`${handle.panic_callstack()}`);
document.getElementById("the_canvas_id").remove();
document.getElementById("center_text").innerHTML = `
<p>
The egui app has crashed.
</p>
<p style="font-size:14px">
See the console for details.
</p>
<p style="font-size:14px">
Reload the page to try again.
</p>`;
} else {
let delay_ms = 1000;
setTimeout(check_for_panic, delay_ms);
}
}
check_for_panic();
}
function on_error(error) {
console.error("Failed to start: " + error);
document.getElementById("the_canvas_id").remove();
document.getElementById("center_text").innerHTML = `
<p>
An error occurred during loading:

View File

@@ -1,3 +1,4 @@
<!-- TODO(emilk): make this example nicer. The layout is HORRIBLE -->
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
@@ -17,10 +18,10 @@
/* Light mode background color for what is not covered by the egui canvas,
or where the egui canvas is translucent. */
background: #909090;
display:flex;
display: flex;
}
.canvas_wrap{
.canvas_wrap {
/* height: 200px; */
width: 400px;
}
@@ -52,8 +53,8 @@
top: 0%;
left: 50%;
transform: translate(-50%, 0%); */
width:90%;
height:90%;
width: 45%;
height: 90%;
}
.centered {
@@ -99,6 +100,7 @@
transform: rotate(360deg);
}
}
</style>
</head>
@@ -108,19 +110,17 @@
<div>controls</div>
<button class="stop_one">
stop
stop
</button>
<div class="canvas_wrap one">
<canvas id="the_canvas_id_one"></canvas>
<canvas id="canvas_id_one"></canvas>
</div>
<div class="canvas_wrap two">
<canvas id="the_canvas_id_two"></canvas>
<div class="canvas_wrap two">
<canvas id="canvas_id_two"></canvas>
</div>
<div class="centered" id="center_text">
<p style="font-size:16px">
Loading…
@@ -148,38 +148,41 @@
// We'll defer our execution until the wasm is ready to go.
// Here we tell bindgen the path to the wasm file so it can start
// initialization and return to us a promise when it's done.
console.debug("loading wasm…");
console.debug("Loading wasm…");
wasm_bindgen("./egui_demo_app_bg.wasm")
.then(on_wasm_loaded)
.catch(on_wasm_error);
.catch(on_error);
function on_wasm_loaded() {
console.debug("wasm loaded. starting app…");
console.debug("Wasm loaded. Starting apps…");
// This call installs a bunch of callbacks and then returns:
wasm_bindgen.init_wasm_hooks()
const handle_one = new wasm_bindgen.WebHandle("canvas_id_one");
const handle_two = new wasm_bindgen.WebHandle("canvas_id_two");
const handle_one = wasm_bindgen.start_separate("the_canvas_id_one");
const handle_two = wasm_bindgen.start_separate("the_canvas_id_two");
Promise.all([handle_one, handle_two]).then((handles) => {
on_apps_started(handles[0], handles[1])
}).catch(on_error);
}
function on_apps_started(handle_one, handle_two) {
const button = document.getElementsByClassName("stop_one")[0]
button.addEventListener("click", ()=>{
handle_one.stop_web()
button.addEventListener("click", () => {
document.getElementById("canvas_id_one").remove()
handle_one.destroy()
handle_one.free()
});
// call `handle.stop_web()` to stop
// uncomment to quick result
// setTimeout(() => {handle.stop_web()}, 2000)
// Call `handle.destroy()` to stop. Uncomment to quick result:
// setTimeout(() => { handle.destroy() }, 2000)
console.debug("app started.");
console.debug("Apps started.");
document.getElementById("center_text").remove();
}
function on_wasm_error(error) {
function on_error(error) {
console.error("Failed to start: " + error);
document.getElementById("center_text").innerHTML = `
<p>