mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
🐛 Realize library pointers with each library's own loader
Fragment rows are keyed by file id, and every caller binds the fragment loader of the file it works on. get-resolved-file-libraries returned libraries with their pages still as pointers, so the first read of a library page under fdata/pointer-map asked the consuming file for the fragment and failed with :fragment-not-found. That broke migrations and file validation for every file using a pointer-mapped library. The weak-map loader now realizes each library's pointers with the library's own id. The test fails without the change. AI-assisted-by: claude-opus-5-5 Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
This commit is contained in:
parent
42a2e33ffe
commit
a6c20b3e95
@ -949,7 +949,12 @@
|
||||
(let [library-ids (->> (get-file-libraries conn (:id file))
|
||||
(map :id)
|
||||
(cons (:id file)))
|
||||
load-fn #(get-file cfg % :migrate? false)]
|
||||
;; Fragment rows are file-local and callers bind the loader of
|
||||
;; the file they work on, so each library realizes its pointers
|
||||
;; here, with its own id, before anything walks its data.
|
||||
load-fn (fn [library-id]
|
||||
(->> (get-file cfg library-id :migrate? false)
|
||||
(fdata/realize-pointers cfg)))]
|
||||
(weak/loadable-weak-value-map library-ids load-fn {id file})))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
(:require
|
||||
[app.binfile.common :as bfc]
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.files.changes-builder :as pcb]
|
||||
[app.common.files.migrations :as fmg]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.objects-map :as omap]
|
||||
@ -917,3 +918,39 @@
|
||||
(t/is (seq (th/db-query :file-migration
|
||||
{:file-id file-id
|
||||
:name "0031-migrate-stroke-width-token-attr"}))))))
|
||||
|
||||
(t/deftest libraries-load-their-pages-with-their-own-loader
|
||||
;; Fragment rows are keyed by (file_id, id), and every caller binds the
|
||||
;; loader of the file it works on. A library's pages must therefore come
|
||||
;; back from the library loader already readable, or the first deref
|
||||
;; under the consumer's loader asks the wrong file for the fragment.
|
||||
(let [profile (th/create-profile* 1)
|
||||
library (th/create-file* 1 {:profile-id (:id profile)
|
||||
:project-id (:default-project-id profile)
|
||||
:is-shared true})
|
||||
file (th/create-file* 2 {:profile-id (:id profile)
|
||||
:project-id (:default-project-id profile)
|
||||
:is-shared false})
|
||||
lib-page (uuid/random)]
|
||||
|
||||
(th/link-file-to-library* {:file-id (:id file) :library-id (:id library)})
|
||||
(update-file! :profile-id (:id profile)
|
||||
:file-id (:id library)
|
||||
:changes (-> (pcb/empty-changes nil)
|
||||
(pcb/with-library-data (:data library))
|
||||
(pcb/add-empty-page lib-page "library page")
|
||||
(:redo-changes)))
|
||||
|
||||
;; Precondition: the library stores the page as a fragment pointer.
|
||||
(t/is (contains? (page-pointer-ids (:id library)) lib-page))
|
||||
|
||||
(let [page (db/tx-run! th/*system*
|
||||
(fn [cfg]
|
||||
(fdata/with-pointers cfg (:id file)
|
||||
(let [consumer (bfc/get-file cfg (:id file))
|
||||
libs (bfc/get-resolved-file-libraries cfg consumer)]
|
||||
(-> (get libs (:id library))
|
||||
(get-in [:data :pages-index lib-page])
|
||||
(fdata/realize-entry))))))]
|
||||
(t/is (= lib-page (:id page)))
|
||||
(t/is (contains? (:objects page) uuid/zero)))))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user