diff --git a/frontend/src/app/main/errors.cljs b/frontend/src/app/main/errors.cljs index 3c769d0375..973163b3fc 100644 --- a/frontend/src/app/main/errors.cljs +++ b/frontend/src/app/main/errors.cljs @@ -127,24 +127,15 @@ (ex/print-throwable cause :prefix "Unexpected Error") (flash :cause cause :type :unhandled)))) -(defmethod ptk/handle-error :wasm-non-blocking +(defmethod ptk/handle-error :wasm-error [error] (when-let [cause (::instance error)] - (flash :cause cause))) - -(defmethod ptk/handle-error :wasm-critical - [error] - (when-let [cause (::instance error)] - (ex/print-throwable cause :prefix "WASM critical error")) - - (st/emit! (rt/assign-exception error))) - -(defmethod ptk/handle-error :wasm-exception - [error] - (when-let [cause (::instance error)] - (let [prefix (or (:prefix error) "Exception")] - (ex/print-throwable cause :prefix prefix))) - (st/emit! (rt/assign-exception error))) + (ex/print-throwable cause) + (let [code (get error :code)] + (if (or (= code :panic) + (= code :webgl-context-lost)) + (st/emit! (rt/assign-exception error)) + (flash :type :handled :cause cause))))) ;; We receive a explicit authentication error; If the uri is for ;; workspace, dashboard, viewer or settings, then assign the exception @@ -376,19 +367,24 @@ (let [data (ex-data cause) type (get data :type)] (set! last-exception cause) - (if (#{:wasm-critical :wasm-non-blocking :wasm-exception} type) + (if (= :wasm-error type) (on-error cause) (do (ex/print-throwable cause :prefix "Uncaught Exception") - (ts/schedule #(flash :cause cause :type :unhandled)))))))) + (ts/asap #(flash :cause cause :type :unhandled)))))))) (on-unhandled-rejection [event] (.preventDefault ^js event) (when-let [cause (unchecked-get event "reason")] (when-not (is-ignorable-exception? cause) - (set! last-exception cause) - (ex/print-throwable cause :prefix "Uncaught Rejection") - (ts/schedule #(flash :cause cause :type :unhandled)))))] + (let [data (ex-data cause) + type (get data :type)] + (set! last-exception cause) + (if (= :wasm-error type) + (on-error cause) + (do + (ex/print-throwable cause :prefix "Uncaught Rejection") + (ts/asap #(flash :cause cause :type :unhandled))))))))] (.addEventListener g/window "error" on-unhandled-error) (.addEventListener g/window "unhandledrejection" on-unhandled-rejection) diff --git a/frontend/src/app/main/ui/error_boundary.cljs b/frontend/src/app/main/ui/error_boundary.cljs index c3e9ec18b6..91e09920cf 100644 --- a/frontend/src/app/main/ui/error_boundary.cljs +++ b/frontend/src/app/main/ui/error_boundary.cljs @@ -15,12 +15,10 @@ [rumext.v2 :as mf])) (mf/defc error-boundary* - {::mf/props :obj} [{:keys [fallback children]}] (let [fallback-wrapper (mf/with-memo [fallback] (mf/fnc fallback-wrapper* - {::mf/props :obj} [{:keys [error reset-error-boundary]}] (let [route (mf/deref refs/route) data (errors/exception->error-data error)] diff --git a/frontend/src/app/main/ui/static.cljs b/frontend/src/app/main/ui/static.cljs index a32b0aca7f..3eb44668d0 100644 --- a/frontend/src/app/main/ui/static.cljs +++ b/frontend/src/app/main/ui/static.cljs @@ -477,8 +477,8 @@ :service-unavailable [:> service-unavailable*] - :wasm-exception - (case (get data :exception-type) + :wasm-error + (case (get data :code) :webgl-context-lost [:> webgl-context-lost*] diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index 52255eac22..89fe0459fe 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -57,6 +57,7 @@ [app.render-wasm.api :as wasm.api] [app.util.debug :as dbg] [app.util.text-editor :as ted] + [app.util.timers :as ts] [beicon.v2.core :as rx] [promesa.core :as p] [rumext.v2 :as mf])) @@ -361,9 +362,9 @@ (mf/with-effect [focus] (when (and @canvas-init? @initialized?) - (if (empty? focus) - (wasm.api/clear-focus-mode) - (wasm.api/set-focus-mode focus)))) + (ts/asap #(if (empty? focus) + (wasm.api/clear-focus-mode) + (wasm.api/set-focus-mode focus))))) (mf/with-effect [vbox zoom] (when (and @canvas-init? initialized?) diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 82fb16ebaa..1a60b27979 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -1420,11 +1420,9 @@ [event] (dom/prevent-default event) (reset! wasm/context-lost? true) - (log/warn :hint "WebGL context lost") - (ex/raise :type :wasm-exception - :exception-type :webgl-context-lost - :prefix "WebGL context lost" - :hint "WebGL context lost")) + (ex/raise :type :wasm-error + :code :webgl-context-lost + :hint "WASM Error: WebGL context lost")) (defn init-canvas-context [canvas] diff --git a/frontend/src/app/render_wasm/helpers.cljc b/frontend/src/app/render_wasm/helpers.cljc index 5b973cd837..0ce16bd955 100644 --- a/frontend/src/app/render_wasm/helpers.cljc +++ b/frontend/src/app/render_wasm/helpers.cljc @@ -5,11 +5,13 @@ ;; Copyright (c) KALEIDOS INC (ns app.render-wasm.helpers - #?(:cljs (:require-macros [app.render-wasm.helpers]))) + #?(:cljs (:require-macros [app.render-wasm.helpers])) + (:require [app.common.data :as d])) -(def ^:export error-code +(def error-code "WASM error code constants (must match render-wasm/src/error.rs and mem.rs)." - {0x01 :wasm-non-blocking 0x02 :wasm-critical}) + {0x01 :non-blocking + 0x02 :panic}) (defmacro call "A helper for calling a wasm function. @@ -18,19 +20,19 @@ - :wasm-non-blocking: call app.main.errors/on-error (eventually, shows a toast and logs the error) - :wasm-critical or unknown: throws an exception to be handled by the global error handler (eventually, shows the internal error page)" [module name & params] - (let [fn-sym (with-meta (gensym "fn-") {:tag 'function}) - e-sym (gensym "e") - code-sym (gensym "code")] + (let [fn-sym (with-meta (gensym "fn-") {:tag 'function}) + cause-sym (gensym "cause")] `(let [~fn-sym (cljs.core/unchecked-get ~module ~name)] (try (~fn-sym ~@params) - (catch :default ~e-sym - (let [read-code# (cljs.core/unchecked-get ~module "_read_error_code") - ~code-sym (when read-code# (read-code#)) - type# (or (get app.render-wasm.helpers/error-code ~code-sym) :wasm-critical) - ex# (ex-info (str "WASM error (type: " type# ")") - {:fn ~name :type type# :message (.-message ~e-sym) :error-code ~code-sym} - ~e-sym)] - (if (= type# :wasm-non-blocking) - (@~'app.main.store/on-error ex#) - (throw ex#)))))))) + (catch :default ~cause-sym + (let [read-code-fn# (cljs.core/unchecked-get ~module "_read_error_code") + code-num# (when read-code-fn# (read-code-fn#)) + code# (get error-code code-num# :wasm-critical) + hint# (str "WASM Error (" (d/name code#) ")") + context# {:type :wasm-error + :code code# + :hint hint# + :fn ~name} + cause# (ex-info hint# context# ~cause-sym)] + (throw cause#)))))))