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: | DOM | Assignee: | 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
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 | ||
|---|---|---|
| Add attachment proposed patch, testcase, etc. |
Anne van Kesteren
I have a fix for this.
Anne van Kesteren
Pull request: https://github.com/WebKit/WebKit/pull/75264
Anne van Kesteren
Submitted web-platform-tests pull request: https://github.com/web-platform-tests/wpt/pull/63051
Anne van Kesteren
*** Bug 324715 has been marked as a duplicate of this bug. ***
Anne van Kesteren
Submitted web-platform-tests pull request: https://github.com/web-platform-tests/wpt/pull/63051
EWS
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
<rdar://problem/188785171>