diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index c464d4f1e1..cda89b4c87 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -443,6 +443,17 @@ result (if (empty? result) txt/default-text-attrs result)] result)) +(defn- v2-editor-live? + "False for a missing or disposed v2 editor. A component can still hold + the instance for one render after closing the editor disposed it, and + reading its style then throws." + [editor] + (and (some? editor) + (try + (.-currentStyle ^js editor) + true + (catch :default _ false)))) + (defn- styled-runs "The text runs of `content` with their styles, without node ids or the style keys set to nil." @@ -475,7 +486,7 @@ [{:keys [editor-styles editor-state editor-instance attrs shape] :as options}] (cond (some? editor-styles) (v3-current-text-values options) - (some? editor-instance) (v2-current-text-values options) + (v2-editor-live? editor-instance) (v2-current-text-values options) (some? editor-state) (v1-current-paragraph-values options) :else (shape-current-values shape txt/is-paragraph-node? attrs))) @@ -492,7 +503,7 @@ [{:keys [editor-styles editor-state editor-instance attrs shape] :as options}] (cond (some? editor-styles) (v3-current-text-values options) - (some? editor-instance) (v2-current-text-values options) + (v2-editor-live? editor-instance) (v2-current-text-values options) (some? editor-state) (v1-current-text-values options) :else (shape-current-values shape txt/is-text-node? attrs))) diff --git a/frontend/test/frontend_tests/data/workspace_texts_test.cljs b/frontend/test/frontend_tests/data/workspace_texts_test.cljs index 2280456eb4..52280e43e1 100644 --- a/frontend/test/frontend_tests/data/workspace_texts_test.cljs +++ b/frontend/test/frontend_tests/data/workspace_texts_test.cljs @@ -643,6 +643,33 @@ (t/is (= 50 (:width result))) (t/is (= 25 (:height result)))))) +;; --------------------------------------------------------------------------- +;; Tests: values read from a disposed v2 editor +;; --------------------------------------------------------------------------- + +(defn- disposed-v2-editor + "A v2 editor after `dispose!`: reading its style throws." + [] + (let [editor #js {}] + (js/Object.defineProperty editor "currentStyle" + #js {:get (fn [] (throw (js/TypeError. "Cannot read properties of null (reading 'currentStyle')")))}) + editor)) + +;; Scenario: the sidebar renders once more with the editor it saw last, +;; after closing the text editor disposed it. Proves: the values come from +;; the shape instead of crashing the workspace. +(t/deftest current-values-of-a-disposed-v2-editor-come-from-the-shape + (let [shape (make-text-shape) + editor (disposed-v2-editor)] + (t/is (= (dwt/current-text-values {:shape shape :attrs txt/text-node-attrs}) + (dwt/current-text-values {:editor-instance editor + :shape shape + :attrs txt/text-node-attrs}))) + (t/is (= (dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs}) + (dwt/current-paragraph-values {:editor-instance editor + :shape shape + :attrs txt/paragraph-attrs}))))) + ;; --------------------------------------------------------------------------- ;; same-styled-text? ;; ---------------------------------------------------------------------------