🐛 Fix let scoping bugs in modifiers.cljs

Two let forms in set-wasm-modifiers and apply-wasm-modifiers
had their bindings vectors closed prematurely, causing undeclared
var warnings for snap-pixel?, translation?, ids, update-shape,
options, bool-ids, undo-id, and other bindings.

In set-wasm-modifiers: removed premature ) after ] on the let
bindings so the let body wraps snap-pixel? and translation?.

In apply-wasm-modifiers: the cond form was not explicitly closed,
so all subsequent bindings (ignore-tree, options, modif-tree, ids,
update-shape, bool-ids, undo-id) were parsed as cond clauses
instead of let bindings. Added ) to close cond after :else, and
moved ] to close the bindings vector after undo-id.

AI-assisted-by: mimo-v2.5-pro
This commit is contained in:
Andrey Antukh 2026-08-18 16:59:45 +00:00
parent 371b333495
commit 8a703f54d0

View File

@ -727,46 +727,46 @@
;; `clear-local-transform`. ;; `clear-local-transform`.
(ensure-interactive-transform-start!) (ensure-interactive-transform-start!)
(let [snap-pixel? (and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid)) (let [snap-pixel? (and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
translation? (every? #(ctm/only-move? (:modifiers %)) (vals modif-tree))]) translation? (every? #(ctm/only-move? (:modifiers %)) (vals modif-tree))]
(if translation? (if translation?
;; Pure translation: no structure changes needed. If structure ;; Pure translation: no structure changes needed. If structure
;; modifiers were active from a previous non-translation frame ;; modifiers were active from a previous non-translation frame
;; (e.g. shape hovered over a frame then dragged back out), ;; (e.g. shape hovered over a frame then dragged back out),
;; clear them now so the shape is not clipped by the old frame. ;; clear them now so the shape is not clipped by the old frame.
(when @wasm-structure-modifiers-active? (when @wasm-structure-modifiers-active?
(wasm.api/clean-modifiers) (wasm.api/clean-modifiers)
(vreset! wasm-structure-modifiers-active? false)) (vreset! wasm-structure-modifiers-active? false))
(let [objects (dsh/lookup-page-objects state)] (let [objects (dsh/lookup-page-objects state)]
(set-wasm-props! objects (:prev-wasm-props state) (:wasm-props state)) (set-wasm-props! objects (:prev-wasm-props state) (:wasm-props state))
(wasm.api/clean-modifiers) (wasm.api/clean-modifiers)
(wasm.api/set-structure-modifiers (parse-structure-modifiers modif-tree)) (wasm.api/set-structure-modifiers (parse-structure-modifiers modif-tree))
(vreset! wasm-structure-modifiers-active? true))) (vreset! wasm-structure-modifiers-active? true)))
(let [geometry-entries (parse-geometry-modifiers modif-tree) (let [geometry-entries (parse-geometry-modifiers modif-tree)
root-modifiers (into [] (map (fn [[id data]] [id (:transform data)])) geometry-entries) root-modifiers (into [] (map (fn [[id data]] [id (:transform data)])) geometry-entries)
wasm-ready? (wasm.api/initialized?) wasm-ready? (wasm.api/initialized?)
;; While the GL context is down (lost / mid-reload), keep the ;; While the GL context is down (lost / mid-reload), keep the
;; root transforms so SVG selection/preview can still move. ;; root transforms so SVG selection/preview can still move.
;; `propagate-modifiers` returns [] when not ready, do not ;; `propagate-modifiers` returns [] when not ready, do not
;; treat that as "no modifiers". ;; treat that as "no modifiers".
modifiers modifiers
(cond (cond
(or (not wasm-ready?) (or (not wasm-ready?)
(and translation? (not snap-pixel?))) (and translation? (not snap-pixel?)))
root-modifiers root-modifiers
:else :else
(let [propagated (wasm.api/propagate-modifiers geometry-entries snap-pixel?)] (let [propagated (wasm.api/propagate-modifiers geometry-entries snap-pixel?)]
(if (seq propagated) propagated root-modifiers)))] (if (seq propagated) propagated root-modifiers)))]
(when wasm-ready? (when wasm-ready?
(wasm.api/set-modifiers modifiers)) (wasm.api/set-modifiers modifiers))
(let [ids (into [] xf:map-key geometry-entries) (let [ids (into [] xf:map-key geometry-entries)
selrect (when wasm-ready? selrect (when wasm-ready?
(if (and translation? (not snap-pixel?) selection-rect-cache (seq modifiers)) (if (and translation? (not snap-pixel?) selection-rect-cache (seq modifiers))
(cached-translation-selrect ids (second (first modifiers)) selection-rect-cache) (cached-translation-selrect ids (second (first modifiers)) selection-rect-cache)
(wasm.api/get-selection-rect ids)))] (wasm.api/get-selection-rect ids)))]
(rx/of (set-temporary-selrect selrect) (rx/of (set-temporary-selrect selrect)
(set-temporary-modifiers modifiers)))))))) (set-temporary-modifiers modifiers)))))))))
(defn propagate-structure-modifiers (defn propagate-structure-modifiers
[modif-tree objects] [modif-tree objects]
@ -820,88 +820,89 @@
(parse-geometry-modifiers modif-tree) (parse-geometry-modifiers modif-tree)
snap-pixel? snap-pixel?
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))] (and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
transforms transforms
(cond (cond
(and translation? (not snap-pixel?)) (and translation? (not snap-pixel?))
;; Mirror WASM `propagate_modifiers` in CLJS: splat the ;; Mirror WASM `propagate_modifiers` in CLJS: splat the
;; translation matrix onto every descendant. Without ;; translation matrix onto every descendant. Without
;; this step the commit would only touch the dragged ;; this step the commit would only touch the dragged
;; primaries and descendants would snap back to their ;; primaries and descendants would snap back to their
;; pre-drag positions on drop. ;; pre-drag positions on drop.
;; ;;
;; Skipped when `snap-pixel?` is on: WASM applies ;; Skipped when `snap-pixel?` is on: WASM applies
;; per-shape pixel correction (different scale/translate ;; per-shape pixel correction (different scale/translate
;; per descendant) which we can't replicate cheaply on ;; per descendant) which we can't replicate cheaply on
;; the CLJS side. ;; the CLJS side.
(reduce (reduce
(fn [acc [id data]] (fn [acc [id data]]
(let [t (:transform data) (let [t (:transform data)
subtree-ids subtree-ids
(or (get subtree-ids-by-id id) (or (get subtree-ids-by-id id)
(cfh/get-children-ids-with-self objects id))] (cfh/get-children-ids-with-self objects id))]
(reduce (fn [a sid] (assoc a sid t)) acc subtree-ids))) (reduce (fn [a sid] (assoc a sid t)) acc subtree-ids)))
{} {}
geometry-entries) geometry-entries)
;; Context lost / mid-reload: do not call into WASM. Use ;; Context lost / mid-reload: do not call into WASM. Use
;; root transforms (and splat translation onto descendants ;; root transforms (and splat translation onto descendants
;; when we can) so the commit still lands in file data. ;; when we can) so the commit still lands in file data.
(not (wasm.api/initialized?)) (not (wasm.api/initialized?))
(if translation? (if translation?
(reduce (reduce
(fn [acc [id data]] (fn [acc [id data]]
(let [t (:transform data) (let [t (:transform data)
subtree-ids subtree-ids
(or (get subtree-ids-by-id id) (or (get subtree-ids-by-id id)
(cfh/get-children-ids-with-self objects id))] (cfh/get-children-ids-with-self objects id))]
(reduce (fn [a sid] (assoc a sid t)) acc subtree-ids))) (reduce (fn [a sid] (assoc a sid t)) acc subtree-ids)))
{} {}
geometry-entries) geometry-entries)
(into {} (into {}
(map (fn [[id data]] [id (:transform data)])) (map (fn [[id data]] [id (:transform data)]))
geometry-entries)) geometry-entries))
:else :else
(into {} (wasm.api/propagate-modifiers geometry-entries snap-pixel?)) (into {} (wasm.api/propagate-modifiers geometry-entries snap-pixel?)))
ignore-tree ignore-tree
(calculate-ignore-tree-wasm transforms objects) (calculate-ignore-tree-wasm transforms objects)
options options
(-> params (-> params
(assoc :reg-objects? true) (assoc :reg-objects? true)
(assoc :ignore-tree ignore-tree) (assoc :ignore-tree ignore-tree)
(assoc :translation? translation?) (assoc :translation? translation?)
;; Attributes that can change in the transform. This ;; Attributes that can change in the transform. This
;; way we don't have to check all the attributes ;; way we don't have to check all the attributes
(assoc :attrs transform-attrs)) (assoc :attrs transform-attrs))
modif-tree modif-tree
(propagate-structure-modifiers modif-tree (dsh/lookup-page-objects state)) (propagate-structure-modifiers modif-tree (dsh/lookup-page-objects state))
ids ids
(into (set (keys modif-tree)) xf:without-uuid-zero (keys transforms)) (into (set (keys modif-tree)) xf:without-uuid-zero (keys transforms))
update-shape update-shape
(fn [shape] (fn [shape]
(let [shape-id (dm/get-prop shape :id) (let [shape-id (dm/get-prop shape :id)
transform (get transforms shape-id) transform (get transforms shape-id)
modifiers (dm/get-in modif-tree [shape-id :modifiers])] modifiers (dm/get-in modif-tree [shape-id :modifiers])]
(-> shape (-> shape
(gsh/apply-transform transform) (gsh/apply-transform transform)
(ctm/apply-structure-modifiers modifiers)))) (ctm/apply-structure-modifiers modifiers))))
bool-ids bool-ids
(into #{} (into #{}
(comp (comp
(mapcat (partial cfh/get-parents-with-self objects)) (mapcat (partial cfh/get-parents-with-self objects))
(filter cfh/bool-shape?) (filter cfh/bool-shape?)
(map :id)) (map :id))
ids) ids)
undo-id (js/Symbol)]
undo-id (js/Symbol))
(rx/concat (rx/concat
(if undo-transation? (if undo-transation?
(rx/of (dwu/start-undo-transaction undo-id)) (rx/of (dwu/start-undo-transaction undo-id))