fix: publish inherited native paint updates
This commit is contained in:
parent
722791a01e
commit
54b3514668
@ -9824,6 +9824,10 @@ role, and outside-complement compatibility before publication."
|
||||
(setq overrides
|
||||
(plist-put overrides :native-removed-node-ids
|
||||
(plist-get prepared :removed-node-ids)))
|
||||
(setq overrides
|
||||
(plist-put overrides :native-inherited-dirty-node-ids
|
||||
(plist-get candidate-state
|
||||
:native-inherited-dirty-node-ids)))
|
||||
(setq overrides
|
||||
(plist-put
|
||||
overrides :native-topology-stable-p
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
(declare-function ebox--literal-root-pixel-width "ebox" (box))
|
||||
(declare-function ebox-get "ebox" (box key))
|
||||
(declare-function ebox-style-cascade-active-p "ebox-style" ())
|
||||
(declare-function ebox-style-property "ebox-style" (name))
|
||||
(declare-function ebox-tree-node-key "ebox-tree" (source-index node))
|
||||
(declare-function ebox-tree--children-raw "ebox-tree" (node))
|
||||
(declare-function ebox--node-direct-viewport-width-dependent-p
|
||||
@ -105,6 +106,17 @@
|
||||
(setq node-id (and parents (gethash node-id parents))))))
|
||||
(nreverse result)))
|
||||
|
||||
(defun ebox-native-commit-inherited-dirty-node-ids (prepared)
|
||||
"Return nodes whose PREPARED changes can alter descendant computed style."
|
||||
(cl-loop
|
||||
for entry in (plist-get prepared :dirty-set)
|
||||
when (cl-some
|
||||
(lambda (key)
|
||||
(when-let* ((property (ebox-style-property key)))
|
||||
(plist-get property :inherits)))
|
||||
(plist-get entry :changed-keys))
|
||||
collect (plist-get entry :node-id)))
|
||||
|
||||
(defun ebox-native-commit--node-position-table (state)
|
||||
"Return NODE-ID to `(PARENT-ID . POSITION)' table for STATE."
|
||||
(let ((nodes (plist-get state :node-table))
|
||||
@ -325,6 +337,8 @@ the committed text/fragment bases, compiler postorder, and projection support."
|
||||
old-state candidate-state))
|
||||
(plist-put candidate-state :native-topology-stable-p stable)
|
||||
(plist-put candidate-state :native-touched-node-ids layout-touched)
|
||||
(plist-put candidate-state :native-inherited-dirty-node-ids
|
||||
(ebox-native-commit-inherited-dirty-node-ids prepared))
|
||||
(when context-axes-stable
|
||||
(plist-put candidate-state :viewport-dependent-node-ids-ready t)
|
||||
(plist-put candidate-state :viewport-dependent-node-ids
|
||||
|
||||
@ -53,6 +53,8 @@
|
||||
(declare-function ebox-layout-config-props "ebox-layout-config" (config))
|
||||
(declare-function ebox-tree-node-children "ebox-tree" (node))
|
||||
(declare-function ebox-buffer--font-face "ebox-buffer-backend" (style))
|
||||
(declare-function ebox-buffer--text-decoration-face
|
||||
"ebox-buffer-backend" (style))
|
||||
(declare-function ebox--propertize-typography
|
||||
"ebox-buffer-backend" (string style))
|
||||
(declare-function ebox--ensure-node-id "ebox" (node))
|
||||
@ -71,6 +73,7 @@
|
||||
(declare-function ebox--layout-children "ebox-tree" (node))
|
||||
(declare-function ebox-tree-layout-children "ebox-tree" (node))
|
||||
(declare-function ebox-tree-node-local-source-signature "ebox-tree" (node))
|
||||
(declare-function ebox-source--index-record "ebox-source" (index handle))
|
||||
(declare-function ebox-buffer-side-border-face
|
||||
"ebox-buffer-backend" (color))
|
||||
(declare-function ebox--space-pixel-width "ebox-measure" ())
|
||||
@ -2419,7 +2422,7 @@ per call, and no call recursively visits the captured Ebox tree."
|
||||
(vconcat (nreverse nodes))))
|
||||
|
||||
(defun ebox-native-reflow--retained-layout-signature
|
||||
(node child-revisions flex-content-min-widths)
|
||||
(node child-revisions flex-content-min-widths source-index)
|
||||
"Return exact retained compiler signature for NODE and CHILD-REVISIONS."
|
||||
(let ((wrapper (and (eq (plist-get node :ebox-type) 'flex)
|
||||
(plist-get node :box))))
|
||||
@ -2430,6 +2433,12 @@ per call, and no call recursively visits the captured Ebox tree."
|
||||
(and wrapper (plist-get wrapper :region-id)))
|
||||
(ebox-tree-node-local-source-signature node)
|
||||
(and wrapper (ebox-tree-node-local-source-signature wrapper))
|
||||
(and source-index
|
||||
(when-let* ((handle (plist-get node :ebox-source-handle)))
|
||||
(ebox-source--index-record source-index handle)))
|
||||
(and source-index wrapper
|
||||
(when-let* ((handle (plist-get wrapper :ebox-source-handle)))
|
||||
(ebox-source--index-record source-index handle)))
|
||||
child-revisions
|
||||
(and (eq (plist-get node :ebox-type) 'flex)
|
||||
(mapcar
|
||||
@ -2455,12 +2464,18 @@ per call, and no call recursively visits the captured Ebox tree."
|
||||
0))
|
||||
(flex-content-min-widths
|
||||
(plist-get state :flex-content-min-widths))
|
||||
(source-index (plist-get state :source-index))
|
||||
(touched-ids (plist-get state :native-touched-node-ids))
|
||||
(inherited-dirty-ids
|
||||
(plist-get state :native-inherited-dirty-node-ids))
|
||||
(touched-set
|
||||
(and (plist-get state :native-topology-stable-p)
|
||||
(plist-member state :native-touched-node-ids)
|
||||
(proper-list-p touched-ids)
|
||||
(make-hash-table :test 'equal)))
|
||||
(inherited-touched-set
|
||||
(and touched-set inherited-dirty-ids
|
||||
(make-hash-table :test 'equal)))
|
||||
(retained-fast-p
|
||||
(and touched-set
|
||||
(= (hash-table-count old-cache) (length postorder))
|
||||
@ -2488,6 +2503,24 @@ per call, and no call recursively visits the captured Ebox tree."
|
||||
(make-hash-table :test 'eq)))
|
||||
(dolist (node-id touched-ids)
|
||||
(when touched-set (puthash node-id t touched-set)))
|
||||
(when (and touched-set inherited-dirty-ids)
|
||||
(let ((inherited-set (make-hash-table :test 'equal)))
|
||||
(dolist (node-id inherited-dirty-ids)
|
||||
(puthash node-id t inherited-set))
|
||||
(cl-labels
|
||||
((mark
|
||||
(current inherited-p)
|
||||
(let* ((node-id (plist-get current :node-id))
|
||||
(inherited-p
|
||||
(or inherited-p (gethash node-id inherited-set))))
|
||||
(when inherited-p (puthash node-id t touched-set))
|
||||
(when inherited-p
|
||||
(puthash node-id t inherited-touched-set))
|
||||
(dolist (child
|
||||
(ebox-native-reflow--retained-layout-children
|
||||
current))
|
||||
(mark child inherited-p)))))
|
||||
(mark node nil))))
|
||||
(cl-loop
|
||||
for template in ebox-native-reflow--compile-property-templates
|
||||
for index from 0
|
||||
@ -2521,9 +2554,12 @@ per call, and no call recursively visits the captured Ebox tree."
|
||||
children))
|
||||
(signature
|
||||
(ebox-native-reflow--retained-layout-signature
|
||||
current child-revisions flex-content-min-widths))
|
||||
current child-revisions flex-content-min-widths
|
||||
source-index))
|
||||
fragment entry)
|
||||
(if (and cached
|
||||
(not (and inherited-touched-set
|
||||
(gethash node-id inherited-touched-set)))
|
||||
(equal signature (plist-get cached :signature)))
|
||||
(setq fragment (plist-get cached :fragment)
|
||||
entry cached)
|
||||
|
||||
@ -1458,6 +1458,14 @@ the projection roots a second time."
|
||||
(ebox-tree-clear-author-style-pending root))
|
||||
projection))
|
||||
|
||||
(defun ebox-surface--native-full-frame-p (state projection-kind)
|
||||
"Return non-nil when STATE owns a complete native surface frame."
|
||||
(and (eq projection-kind 'native-frame)
|
||||
(plist-get state :native-topology-stable-p)
|
||||
(let ((frame (plist-get state :native-render-frame)))
|
||||
(and (plist-get frame :native-frame)
|
||||
(not (plist-get frame :native-patch))))))
|
||||
|
||||
(defun ebox-surface--projection-result
|
||||
(context projection state output &optional projection-kind)
|
||||
"Complete CONTEXT PROJECTION for STATE from rendered OUTPUT."
|
||||
@ -1468,13 +1476,14 @@ the projection roots a second time."
|
||||
(owner-id (plist-get state :span-patch-owner-id))
|
||||
(scroll-fast-p (and (eq projection-kind 'scroll-patch)
|
||||
(plist-get state :scroll-fast-window-p)))
|
||||
(full-surface-p
|
||||
(and scroll-fast-p
|
||||
(plist-get state :retained-scroll-content-p)
|
||||
root-id owner-id (= root-id owner-id)))
|
||||
(native-retained-p
|
||||
(and (eq projection-kind 'native-frame)
|
||||
(plist-get state :native-topology-stable-p)))
|
||||
(full-surface-p
|
||||
(or (and scroll-fast-p
|
||||
(plist-get state :retained-scroll-content-p)
|
||||
root-id owner-id (= root-id owner-id))
|
||||
(ebox-surface--native-full-frame-p state projection-kind)))
|
||||
(previous-owned-ranges
|
||||
(plist-get state :previous-surface-owned-ranges))
|
||||
(node-objects
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
(require 'ert)
|
||||
(require 'ebox)
|
||||
(require 'ebox-native-commit)
|
||||
(require 'ebox-native-reflow)
|
||||
|
||||
;; These tests lock the named Elisp projection proofs. Native commit has its
|
||||
;; own focused contract tests below; disable runtime module discovery here so
|
||||
@ -2091,6 +2092,71 @@ remain retained identities."
|
||||
(should-not mixed-output)))
|
||||
(when (buffer-live-p buffer) (kill-buffer buffer)))))
|
||||
|
||||
(ert-deftest ebox-native-inherited-dirty-domain-is-schema-owned ()
|
||||
"Native invalidation derives inherited propagation from the style schema."
|
||||
(should
|
||||
(equal '(7)
|
||||
(ebox-native-commit-inherited-dirty-node-ids
|
||||
'(:dirty-set
|
||||
((:node-id 7 :dirty-kind paint :changed-keys (:color)))))))
|
||||
(should-not
|
||||
(ebox-native-commit-inherited-dirty-node-ids
|
||||
'(:dirty-set
|
||||
((:node-id 7 :dirty-kind paint
|
||||
:changed-keys (:background-color)))))))
|
||||
|
||||
(ert-deftest ebox-native-retained-compiler-refreshes-inherited-descendants ()
|
||||
"An inherited parent paint change cannot reuse a stale child fragment."
|
||||
(require 'ebox-native-reflow)
|
||||
(let* ((input
|
||||
(ebox-test-box
|
||||
:color "#111111"
|
||||
(ebox-test-text "Paint" :color "#111111")))
|
||||
(root (ebox-test-root input))
|
||||
(_ids (ebox--runtime-node-ids root))
|
||||
(source-index (ebox-test-source-index input))
|
||||
(session
|
||||
(ebox-native-reflow--make-session
|
||||
:handle 'test :generation 0 :styles nil :layout-package nil
|
||||
:layout-fragment-cache (make-hash-table :test 'equal)
|
||||
:layout-fragment-revision 0))
|
||||
(initial-state
|
||||
(list :native-node-postorder
|
||||
(ebox-native-reflow--retained-layout-postorder root)
|
||||
:native-topology-stable-p nil
|
||||
:source-index source-index))
|
||||
(initial-package
|
||||
(ebox-native-reflow--compile-retained-layout-package
|
||||
session initial-state root))
|
||||
(next (copy-tree root))
|
||||
(next-child (car (ebox-tree-node-children next))))
|
||||
(setf (ebox-native-reflow-session-styles session)
|
||||
(plist-get initial-package :styles)
|
||||
(ebox-native-reflow-session-layout-package session)
|
||||
initial-package)
|
||||
;; Model a candidate computed-style projection: the child source record is
|
||||
;; unchanged, while its inherited runtime color follows the parent.
|
||||
(plist-put next :color "#222222")
|
||||
(plist-put next-child :color "#222222")
|
||||
(let* ((root-id (plist-get next :node-id))
|
||||
(next-state
|
||||
(list :native-node-postorder
|
||||
(ebox-native-reflow--retained-layout-postorder next)
|
||||
:native-topology-stable-p t
|
||||
:native-touched-node-ids (list root-id)
|
||||
:native-inherited-dirty-node-ids (list root-id)
|
||||
:source-index source-index))
|
||||
(package
|
||||
(ebox-native-reflow--compile-retained-layout-package
|
||||
session next-state next))
|
||||
(document-root (plist-get (plist-get package :document) :root))
|
||||
(style-id (plist-get document-root :content-foreground-style))
|
||||
(styles (plist-get package :styles)))
|
||||
(should (integerp style-id))
|
||||
(should
|
||||
(equal '(:foreground "#222222")
|
||||
(plist-get (aref styles style-id) :face))))))
|
||||
|
||||
(provide 'ebox-commit-tests)
|
||||
|
||||
;;; ebox-commit-tests.el ends here
|
||||
|
||||
@ -2995,6 +2995,24 @@ participant and rollback contract without creating a real frame."
|
||||
(when (buffer-live-p buffer)
|
||||
(kill-buffer buffer))))
|
||||
|
||||
(ert-deftest ebox-surface-native-full-frame-owns-full-publication-scope ()
|
||||
"A complete native frame is authoritative for the whole TP surface."
|
||||
(should
|
||||
(ebox-surface--native-full-frame-p
|
||||
'(:native-topology-stable-p t
|
||||
:native-render-frame (:native-frame t :native-patch nil))
|
||||
'native-frame))
|
||||
(should-not
|
||||
(ebox-surface--native-full-frame-p
|
||||
'(:native-topology-stable-p t
|
||||
:native-render-frame (:native-frame t :native-patch t))
|
||||
'native-frame))
|
||||
(should-not
|
||||
(ebox-surface--native-full-frame-p
|
||||
'(:native-topology-stable-p t
|
||||
:native-render-frame (:native-frame t :native-patch nil))
|
||||
'paint)))
|
||||
|
||||
(provide 'ebox-surface-tests)
|
||||
|
||||
;;; ebox-surface-tests.el ends here
|
||||
|
||||
Loading…
Reference in New Issue
Block a user