Bug 325616

Summary: moveBefore() updates id and name maps of shadow trees inside the moved subtree against the wrong tree scope
Product: WebKit Reporter: Anne van Kesteren <annevk>
Component: DOMAssignee: Anne van Kesteren <annevk>
Status: RESOLVED FIXED    
Severity: Normal CC: ntim, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://github.com/web-platform-tests/wpt/pull/63051
Bug Depends on:    
Bug Blocks: 325123, 314067, 325644    

Anne van Kesteren
Reported 2026-09-29 01:02:52 PDT
Element::movingSteps() re-registers ids and names for every shadow-including inclusive descendant of the moved node, and always uses the old parent's tree scope as the scope to remove from. For nodes in a shadow tree inside the moved subtree that is wrong: their tree scope is their own shadow root, which the move does not change. They get removed from the old parent's maps, where they were never registered, and then registered a second time in their shadow root's maps. This is reached by moving a <select> or <details>, or an ancestor of one, because their user agent shadow trees contain a named <slot>. It is also reached by moving any shadow host whose shadow tree has an element with an id or name. Steps to reproduce: <div id=host1></div> <div id=inner></div> <img name=x> <div id=from><select></select><details></details></div> <div id=to></div> <script> host1.attachShadow({mode: "open"}).innerHTML = '<div id=inner></div>'; to.moveBefore(host1, null); to.moveBefore(from, null); </script> In a Debug build this asserts in TreeScopeOrderedMap: registeredElements.remove() fails in remove() when the id is moved, and !entry.registeredElements.contains(&element) fails in add() via TreeScope::addElementByName() when the named slot of <select> or <details> is moved. From reading the code, release builds are affected too: - If the document's name map lacks the slot's name, the removal hits RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(it != m_map.end()). - If the document has an element with the same id as one in the moved shadow tree, the removal either hits the RELEASE_ASSERT in remove() or silently drops the document's registration, and document.getElementById() stops finding it. Bug 324715 has the same root cause for a move inside a disconnected tree, where the old parent's tree scope is the document. The insertion and removal steps already avoid this: they pass TreeScopeChange::DidNotChange for shadow roots, and only update the maps when the tree scope changed. The moving steps can do the same, and they should only remove from the old tree scope when the old parent was in one. A patch with web-platform-tests is ready. imported/w3c/web-platform-tests/html/semantics/forms/the-select-element/customizable-select/selectedcontent-subtree-mutations.html is skipped because of this.
Attachments
Anne van Kesteren
Comment 1 2026-09-29 04:27:37 PDT
I have a fix for this.
Anne van Kesteren
Comment 2 2026-09-29 04:52:10 PDT
Anne van Kesteren
Comment 3 2026-09-29 04:54:55 PDT
Submitted web-platform-tests pull request: https://github.com/web-platform-tests/wpt/pull/63051
Anne van Kesteren
Comment 4 2026-09-29 04:58:35 PDT
*** Bug 324715 has been marked as a duplicate of this bug. ***
Anne van Kesteren
Comment 5 2026-09-29 06:01:17 PDT
Submitted web-platform-tests pull request: https://github.com/web-platform-tests/wpt/pull/63051
EWS
Comment 6 2026-09-29 23:21:20 PDT
Committed 322249@main (537fe4583eb1): <https://commits.webkit.org/322249@main> Reviewed commits have been landed. Closing PR #75264 and removing active labels.
Radar WebKit Bug Importer
Comment 7 2026-09-29 23:22:15 PDT
Note You need to log in before you can comment on or make changes to this bug.