From d851f82678cf77c61c269762985bf8910c621803 Mon Sep 17 00:00:00 2001 From: Alonso Torres Date: Thu, 1 Oct 2026 09:21:05 +0200 Subject: [PATCH] :bug: Fix crashing happening on hot reloads (#12005) --- frontend/src/app/main.cljs | 9 ++++++++- frontend/src/app/render_wasm/api.cljs | 15 +++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main.cljs b/frontend/src/app/main.cljs index b6fbfb3ca5..c7d87ba8ba 100644 --- a/frontend/src/app/main.cljs +++ b/frontend/src/app/main.cljs @@ -54,8 +54,12 @@ (let [el (dom/get-element "app")] (mf/create-root el))) +;; Root component of the last render; a hot reload of `app.main.ui` replaces it +(defonce ^:private rendered-app (atom nil)) + (defn init-ui [] + (reset! rendered-app ui/app) (mf/render! app-root (mf/element ui/app))) (defn- initialize-rasterizer @@ -146,7 +150,10 @@ (init-ui))) (defn ^:dev/after-load after-load + "Rerender the UI after a hot reload. When the reload replaced the root + component, unmount the whole tree first so its cleanups run before + the new tree mounts." [] - (reinit)) + (reinit (not (identical? @rendered-app ui/app)))) (set! (.-stackTraceLimit js/Error) 50) diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 0c5a4c3d0b..78623aa43e 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -2492,6 +2492,13 @@ :cause cause) nil))))) +;; Stable listener identities, so `removeEventListener` matches across hot reloads +(defonce ^:private webgl-context-lost-listener + (fn [event] (on-webgl-context-lost event))) + +(defonce ^:private webgl-context-restored-listener + (fn [event] (on-webgl-context-restored event))) + (defn init-canvas-context [canvas] (if-not (wasm/module-ready?) @@ -2536,8 +2543,8 @@ ;; Add event listeners for WebGL context lost (set! wasm/canvas canvas) (when can-listen? - (.addEventListener canvas "webglcontextlost" on-webgl-context-lost) - (.addEventListener canvas "webglcontextrestored" on-webgl-context-restored)) + (.addEventListener canvas "webglcontextlost" webgl-context-lost-listener) + (.addEventListener canvas "webglcontextrestored" webgl-context-restored-listener)) (start-canvas-snapshot-listener!) (reset! wasm/context-lost? false) (set! wasm/context-initialized? true) @@ -2571,8 +2578,8 @@ ;; Remove listener before losing/deleting context. (when wasm/canvas - (.removeEventListener wasm/canvas "webglcontextlost" on-webgl-context-lost) - (.removeEventListener wasm/canvas "webglcontextrestored" on-webgl-context-restored)) + (.removeEventListener wasm/canvas "webglcontextlost" webgl-context-lost-listener) + (.removeEventListener wasm/canvas "webglcontextrestored" webgl-context-restored-listener)) (stop-canvas-snapshot-listener!) (when (wasm/module-ready?)