fix(render): refresh inherited styles for mixed paint updates
Some checks are pending
CI / test (29.1) (push) Waiting to run
CI / test (30.2) (push) Waiting to run
CI / native-build (macos-latest) (push) Waiting to run
CI / native-build (ubuntu-latest) (push) Waiting to run
CI / native-build (windows-latest) (push) Waiting to run
CI / native-msrv (macos-latest) (push) Waiting to run
CI / native-msrv (ubuntu-latest) (push) Waiting to run
CI / native-msrv (windows-latest) (push) Waiting to run
Some checks are pending
CI / test (29.1) (push) Waiting to run
CI / test (30.2) (push) Waiting to run
CI / native-build (macos-latest) (push) Waiting to run
CI / native-build (ubuntu-latest) (push) Waiting to run
CI / native-build (windows-latest) (push) Waiting to run
CI / native-msrv (macos-latest) (push) Waiting to run
CI / native-msrv (ubuntu-latest) (push) Waiting to run
CI / native-msrv (windows-latest) (push) Waiting to run
This commit is contained in:
parent
8da2fe68cc
commit
23bf6052ab
@ -7305,9 +7305,27 @@ certificate."
|
||||
candidate-source-index 'type))))
|
||||
(candidate-region-box-table
|
||||
(plist-get candidate-index :region-box-table))
|
||||
(source-dirty-set
|
||||
(if local-preparation
|
||||
(plist-get local-preparation :dirty-set)
|
||||
(ebox-incremental--declarative-dirty-set
|
||||
old-state candidate-root candidate-index)))
|
||||
(style-node-ids
|
||||
(or (plist-get local-preparation :touched-node-ids)
|
||||
(and prepare-all-styles-p
|
||||
(and (or prepare-all-styles-p
|
||||
;; A fully copied region batch has no touched-node
|
||||
;; index. Mixed projection retains the style tree,
|
||||
;; so prepare inherited consumers before proving or
|
||||
;; rendering either its paint or geometry owners.
|
||||
(and (cl-some
|
||||
(lambda (entry)
|
||||
(eq (plist-get entry :dirty-kind) 'paint))
|
||||
source-dirty-set)
|
||||
(cl-some
|
||||
(lambda (entry)
|
||||
(memq (plist-get entry :dirty-kind)
|
||||
'(geometry structure)))
|
||||
source-dirty-set)))
|
||||
(ebox-incremental--hash-keys
|
||||
(plist-get candidate-index :node-table)))))
|
||||
(candidate-subject-table
|
||||
@ -7315,11 +7333,6 @@ certificate."
|
||||
(ebox-incremental--prepare-inline-candidate-styles
|
||||
old-state candidate-index style-node-ids)))
|
||||
(styles-prepared-p (hash-table-p candidate-subject-table))
|
||||
(source-dirty-set
|
||||
(if local-preparation
|
||||
(plist-get local-preparation :dirty-set)
|
||||
(ebox-incremental--declarative-dirty-set
|
||||
old-state candidate-root candidate-index)))
|
||||
(axis-node-ids
|
||||
(unless (ebox-style-cascade-active-p)
|
||||
(cl-loop for entry in source-dirty-set
|
||||
@ -7374,7 +7387,13 @@ certificate."
|
||||
buffer (plist-get old-root :node-id))))
|
||||
(let* ((structural-caches
|
||||
(ebox-incremental--candidate-structural-caches
|
||||
old-state candidate-index dirty-set local-preparation))
|
||||
old-state candidate-index dirty-set
|
||||
(or local-preparation
|
||||
;; Newly prepared inheritance changes descendants whose
|
||||
;; source declarations are unchanged. Their retained
|
||||
;; render signatures must not survive the style refresh.
|
||||
(and styles-prepared-p
|
||||
(list :touched-node-ids style-node-ids)))))
|
||||
(render-signature-cache
|
||||
(plist-get structural-caches :render-signature-cache))
|
||||
(viewport-height-dependent-subtree-cache
|
||||
@ -8081,10 +8100,15 @@ suppresses the ordinary fallback when any fact is missing."
|
||||
(ebox-runtime-index-get node-id
|
||||
(plist-get candidate-state
|
||||
:parent-table)))
|
||||
(equal (ebox-incremental--layout-slot-style-signature
|
||||
;; Paint consumes effective values. Its newly
|
||||
;; computed style may explicitly store nil
|
||||
;; defaults that the retained node omitted.
|
||||
(null
|
||||
(ebox-fragment-plist-changed-keys
|
||||
(ebox-incremental--layout-slot-style-signature
|
||||
old-node)
|
||||
(ebox-incremental--layout-slot-style-signature
|
||||
new-node))
|
||||
new-node)))
|
||||
(equal (ebox-get old-node :width)
|
||||
(ebox-get new-node :width))
|
||||
(equal (ebox-get old-node :height)
|
||||
@ -8121,6 +8145,10 @@ suppresses the ordinary fallback when any fact is missing."
|
||||
(plist-put (copy-sequence geometry-span-proof)
|
||||
:retain-external-owner-suffix-p t)))
|
||||
(when (and geometry-proof paint-valid-p disjoint-p
|
||||
;; Reusing the style tree is safe only after the candidate's
|
||||
;; inherited paint closure was projected. Tree-dependent
|
||||
;; selectors keep the ordinary cascade/render fallback.
|
||||
(plist-get prepared :styles-prepared-p)
|
||||
allocation-disjoint-p cascade-safe-p
|
||||
;; Both the rendered geometry and inherited paint must leave
|
||||
;; every retained scroll producer outside their dependency scope.
|
||||
|
||||
@ -14487,4 +14487,117 @@ face patch must match that exactly (issue014)."
|
||||
(ebox-region-update 'status :content value))))
|
||||
(should (ebox-test--buffer-propertized-matches-runtime-render-p)))))))
|
||||
|
||||
(ert-deftest ebox-mixed-content-paint-refreshes-inherited-foreground ()
|
||||
"A changed sibling label must not retain another Box's inherited color."
|
||||
(ebox-test--reset-runtime-state)
|
||||
(let ((ebox-viewport-width 80) (ebox-viewport-height 24))
|
||||
(ebox-test--with-rendered-buffer
|
||||
(ebox-build
|
||||
'(column :width (ch 20)
|
||||
(box :id paint :color "#BBA9FF" "Alpha")
|
||||
(box :id label "Beta")))
|
||||
(dolist (step '(("B" "#674795")
|
||||
("Beta longer" "#BBA9FF")
|
||||
("Beta" "#674795")))
|
||||
(cl-letf (((symbol-function 'ebox-surface--render-candidate)
|
||||
(lambda (&rest _)
|
||||
(ert-fail "Mixed inherited paint rendered the root"))))
|
||||
(ebox-call-with-update-batch
|
||||
(lambda ()
|
||||
(ebox-region-update 'paint :color (cadr step))
|
||||
(ebox-region-update 'label :content (car step)))))
|
||||
(should
|
||||
(equal (ebox-test--visible-foreground
|
||||
(get-text-property (point-min) 'face))
|
||||
(cadr step)))
|
||||
(should (ebox-test--buffer-propertized-matches-runtime-render-p))))))
|
||||
|
||||
(ert-deftest ebox-mixed-content-paint-refreshes-ancestor-and-keeps-override ()
|
||||
"Ancestor paint reaches retained and replaced Text while keeping overrides."
|
||||
(ebox-test--reset-runtime-state)
|
||||
(let ((ebox-viewport-width 80) (ebox-viewport-height 24))
|
||||
(ebox-test--with-rendered-buffer
|
||||
(ebox-build
|
||||
'(column :id root :width (ch 20) :color "#BBA9FF"
|
||||
(column (box "Alpha"))
|
||||
(box :id label "Beta")
|
||||
(box :color "#123456" "Override")))
|
||||
(dolist (step '(("B" "#674795") ("Beta longer" "#BBA9FF")))
|
||||
(ebox-call-with-update-batch
|
||||
(lambda ()
|
||||
(ebox-region-update 'root :color (cadr step))
|
||||
(ebox-region-update 'label :content (car step))))
|
||||
(dolist (text (list "Alpha" (car step) "Override"))
|
||||
(goto-char (point-min))
|
||||
(search-forward text)
|
||||
(should
|
||||
(equal (ebox-test--visible-foreground
|
||||
(get-text-property (match-beginning 0) 'face))
|
||||
(if (equal text "Override") "#123456" (cadr step)))))
|
||||
(should (ebox-test--buffer-propertized-matches-runtime-render-p))))))
|
||||
|
||||
(ert-deftest ebox-mixed-content-paint-inheritance-rolls-back-and-retries ()
|
||||
"Failed mixed publication preserves the old style closure and accepts retry."
|
||||
(ebox-test--reset-runtime-state)
|
||||
(let ((ebox-viewport-width 80) (ebox-viewport-height 24))
|
||||
(ebox-test--with-rendered-buffer
|
||||
(ebox-build
|
||||
'(column :width (ch 20)
|
||||
(box :id paint :color "#BBA9FF" "Alpha")
|
||||
(box :id label "Beta")))
|
||||
(let* ((state (ebox--buffer-render-state (current-buffer)))
|
||||
(before (buffer-string))
|
||||
(revision (ebox-surface-buffer-revision (current-buffer)))
|
||||
(paint (plist-get
|
||||
(car (ebox-selector-query-buffer (current-buffer) "#paint"))
|
||||
:node))
|
||||
(text (car (ebox-tree-node-children paint)))
|
||||
(color (plist-get text :color))
|
||||
(update (lambda ()
|
||||
(ebox-region-update 'paint :color "#674795")
|
||||
(ebox-region-update 'label :content "B")))
|
||||
rejected)
|
||||
(should text)
|
||||
(should (equal color "#BBA9FF"))
|
||||
(let ((tp--surface-publication-step-function
|
||||
(lambda (step _surface)
|
||||
(when (eq step 'client-state)
|
||||
(setq rejected t)
|
||||
(error "Reject mixed inherited paint")))))
|
||||
(should-error (ebox-call-with-update-batch update)))
|
||||
(should rejected)
|
||||
(should (eq state (ebox--buffer-render-state (current-buffer))))
|
||||
(should (equal (plist-get text :color) color))
|
||||
(should (equal-including-properties before (buffer-string)))
|
||||
(should (= revision (ebox-surface-buffer-revision (current-buffer))))
|
||||
(ebox-call-with-update-batch update)
|
||||
(should (equal (ebox-test--visible-foreground
|
||||
(get-text-property (point-min) 'face))
|
||||
"#674795"))
|
||||
(should (= (1+ revision) (ebox-surface-buffer-revision (current-buffer))))
|
||||
(should (ebox-test--buffer-propertized-matches-runtime-render-p))))))
|
||||
|
||||
(ert-deftest ebox-mixed-content-paint-inheritance-keeps-cascade-fallback ()
|
||||
"Tree-dependent rules retain full style projection for mixed inheritance."
|
||||
(ebox-test--reset-runtime-state)
|
||||
(let ((ebox-viewport-width 80) (ebox-viewport-height 24)
|
||||
(ebox-style-stylesheet (ecss-stylesheet-create)))
|
||||
(ebox-style-add-rule "#paint text" '(:font-weight bold))
|
||||
(ebox-test--with-rendered-buffer
|
||||
(ebox-build
|
||||
'(column :width (ch 20)
|
||||
(box :id paint :color "#BBA9FF" "Alpha")
|
||||
(box :id label "Beta")))
|
||||
(cl-letf (((symbol-function 'ebox-surface--mixed-owner-output)
|
||||
(lambda (&rest _)
|
||||
(ert-fail "Unprepared cascade entered mixed projection"))))
|
||||
(ebox-call-with-update-batch
|
||||
(lambda ()
|
||||
(ebox-region-update 'paint :color "#674795")
|
||||
(ebox-region-update 'label :content "B"))))
|
||||
(should (equal (ebox-test--visible-foreground
|
||||
(get-text-property (point-min) 'face))
|
||||
"#674795"))
|
||||
(should (ebox-test--buffer-propertized-matches-runtime-render-p)))))
|
||||
|
||||
;;; ebox-core-render-tests.el ends here
|
||||
|
||||
Loading…
Reference in New Issue
Block a user