1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00

Fix crash on request_animation_frame when destroying web runner (#4169)

Previously, any frames in flight (`requestAnimationFrame`) on web were
not being cancelled (`cancelAnimationFrame`) when `WebRunner::destroy`
was called. If a user called `destroy`, then immediately removed the
canvas from the DOM, eframe could panic with a "failed to find (canvas)
element by id" error message.

This PR changes two things:
- The canvas element is directly referenced everywhere it's needed
instead of being looked up by `canvas_id`[^1]
- The RAF handle is stored in `WebRunner` and `cancelAnimationFrame` is
called on it inside of `WebRunner::destroy`[^2]

[^1]: The WebGL/WGPU backends were already holding onto the canvas (and
associated GPU context), so the change is just converting all the
`get_element_by_id` lookups to retrieve the canvas from the web runner
handle.

[^2]: There is only ever one frame in flight, so we store it directly as
a scalar field.
This commit is contained in:
Jan Procházka
2024-03-14 10:26:34 +01:00
committed by GitHub
parent 00e8ce6d7e
commit c5eaba43cd
9 changed files with 73 additions and 61 deletions

View File

@@ -41,7 +41,6 @@ impl HasDisplayHandle for EguiWebWindow {
pub(crate) struct WebPainterWgpu {
canvas: HtmlCanvasElement,
canvas_id: String,
surface: wgpu::Surface<'static>,
surface_configuration: wgpu::SurfaceConfiguration,
render_state: Option<RenderState>,
@@ -163,7 +162,7 @@ impl WebPainterWgpu {
}
}
let canvas = super::canvas_element_or_die(canvas_id);
let canvas = super::get_canvas_element_by_id_or_die(canvas_id);
let surface = instance
.create_surface(wgpu::SurfaceTarget::Canvas(canvas.clone()))
.map_err(|err| format!("failed to create wgpu surface: {err}"))?;
@@ -188,7 +187,6 @@ impl WebPainterWgpu {
Ok(Self {
canvas,
canvas_id: canvas_id.to_owned(),
render_state: Some(render_state),
surface,
surface_configuration,
@@ -200,8 +198,8 @@ impl WebPainterWgpu {
}
impl WebPainter for WebPainterWgpu {
fn canvas_id(&self) -> &str {
&self.canvas_id
fn canvas(&self) -> &HtmlCanvasElement {
&self.canvas
}
fn max_texture_side(&self) -> usize {