Luke Lau 6846afd08c
⚡ Send objects-map pages to the worker without a second encode (#12811)
* ⚡ Send objects-map pages to the worker without a second encode

When switching between pages on a large file e.g Material Design Icons, there's
some UI freeze from :index/initialize encoding object map shapes to send to the
worker. An objects map already stores the encoded JSON for each shape, and
`encode-str` was wrapping those strings in a second layer of JSON on the main
thread.

We can just transmit the already encoded JSON in a js/Map alongisde the
payload, similar to :blob, so structured clone just copies the strings verbaitm
without re-encoding. To do this this PR adds two functions to ObjectsMap that
converts to and from a js/Map.

The "Main components" page of the Material Design Icons has ~30k objects, so
this reduces the freeze when switching pages from 306ms -> 189ms (1.63x) on a
release build.

AI-assisted-by: claude-sonnet-5-5

* Split property tests out into new deftest

---------

Signed-off-by: Luke Lau <luke_lau@icloud.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2026-11-09 17:35:20 +01:00

33 lines
1.2 KiB
Clojure

;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS SUBSIDIARY SL
(ns frontend-tests.worker.messages-test
(:require
[app.common.files.builder :as fb]
[app.common.types.objects-map :as omap]
[app.common.uuid :as uuid]
[app.util.object :as obj]
[app.worker.messages :as wm]
[cljs.test :as t :include-macros true]
[clojure.string :as str]))
(defn- make-page
[]
(-> (fb/create-state)
(fb/add-file {:name "Test"})
(fb/add-page {:name "Page 1"})
(fb/add-shape {:type :rect :name "unique-shape-name" :x 0 :y 0 :width 100 :height 100})
(fb/get-current-page)))
(t/deftest objects-map-shapes-skip-transit
(let [page (update (make-page) :objects omap/wrap)
encoded (wm/encode {:sender-id (uuid/next)
:payload {:cmd :index/initialize :page page}})]
(t/is (not (str/includes? (obj/get encoded "payload") "unique-shape-name")))
(t/is (instance? js/Map (obj/get encoded "pageObjects")))
(t/is (= (count (:objects page))
(.-size (obj/get encoded "pageObjects"))))))