mirror of
https://github.com/servo/servo.git
synced 2025-08-01 03:30:33 +01:00
Fix IS_IN_SHADOW_TREE flag for descendants after Node::remove call (#34803)
* Consider a UnbindContext to be tree-connected if its in a shadow root Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Properly track whether a node is in a shadow tree after removing subtree Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Update WPT expectations Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
e8f75c9aea
commit
1ab55e6b11
3 changed files with 34 additions and 15 deletions
|
@ -3665,7 +3665,11 @@ impl VirtualMethods for Element {
|
||||||
}
|
}
|
||||||
if let Some(ref value) = *self.id_attribute.borrow() {
|
if let Some(ref value) = *self.id_attribute.borrow() {
|
||||||
if let Some(ref shadow_root) = self.containing_shadow_root() {
|
if let Some(ref shadow_root) = self.containing_shadow_root() {
|
||||||
|
// Only unregister the element id if the node was disconnected from it's shadow root
|
||||||
|
// (as opposed to the whole shadow tree being disconnected as a whole)
|
||||||
|
if !self.upcast::<Node>().is_in_shadow_tree() {
|
||||||
shadow_root.unregister_element_id(self, value.clone());
|
shadow_root.unregister_element_id(self, value.clone());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
doc.unregister_element_id(self, value.clone());
|
doc.unregister_element_id(self, value.clone());
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,17 +316,28 @@ impl Node {
|
||||||
|
|
||||||
/// Clean up flags and unbind from tree.
|
/// Clean up flags and unbind from tree.
|
||||||
pub fn complete_remove_subtree(root: &Node, context: &UnbindContext) {
|
pub fn complete_remove_subtree(root: &Node, context: &UnbindContext) {
|
||||||
for node in root.traverse_preorder(ShadowIncluding::Yes) {
|
// Flags that reset when a node is disconnected
|
||||||
// Out-of-document elements never have the descendants flag set.
|
const RESET_FLAGS: NodeFlags = NodeFlags::IS_IN_DOC
|
||||||
node.set_flag(
|
.union(NodeFlags::IS_CONNECTED)
|
||||||
NodeFlags::IS_IN_DOC |
|
.union(NodeFlags::HAS_DIRTY_DESCENDANTS)
|
||||||
NodeFlags::IS_CONNECTED |
|
.union(NodeFlags::HAS_SNAPSHOT)
|
||||||
NodeFlags::HAS_DIRTY_DESCENDANTS |
|
.union(NodeFlags::HANDLED_SNAPSHOT);
|
||||||
NodeFlags::HAS_SNAPSHOT |
|
|
||||||
NodeFlags::HANDLED_SNAPSHOT,
|
for node in root.traverse_preorder(ShadowIncluding::No) {
|
||||||
false,
|
node.set_flag(RESET_FLAGS | NodeFlags::IS_IN_SHADOW_TREE, false);
|
||||||
);
|
|
||||||
|
// If the element has a shadow root attached to it then we traverse that as well,
|
||||||
|
// but without touching the IS_IN_SHADOW_TREE flags of the children
|
||||||
|
if let Some(shadow_root) = node.downcast::<Element>().and_then(Element::shadow_root) {
|
||||||
|
for node in shadow_root
|
||||||
|
.upcast::<Node>()
|
||||||
|
.traverse_preorder(ShadowIncluding::Yes)
|
||||||
|
{
|
||||||
|
node.set_flag(RESET_FLAGS, false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for node in root.traverse_preorder(ShadowIncluding::Yes) {
|
for node in root.traverse_preorder(ShadowIncluding::Yes) {
|
||||||
node.clean_up_style_and_layout_data();
|
node.clean_up_style_and_layout_data();
|
||||||
|
|
||||||
|
@ -608,6 +619,11 @@ impl Node {
|
||||||
self.flags.get().contains(NodeFlags::IS_CONNECTED)
|
self.flags.get().contains(NodeFlags::IS_CONNECTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true iff the node's root is a Document or a ShadowRoot
|
||||||
|
pub fn is_connected_to_tree(&self) -> bool {
|
||||||
|
self.is_connected() || self.is_in_shadow_tree()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the type ID of this node.
|
/// Returns the type ID of this node.
|
||||||
pub fn type_id(&self) -> NodeTypeId {
|
pub fn type_id(&self) -> NodeTypeId {
|
||||||
match *self.eventtarget.type_id() {
|
match *self.eventtarget.type_id() {
|
||||||
|
@ -3559,6 +3575,8 @@ pub struct UnbindContext<'a> {
|
||||||
/// The next sibling of the inclusive ancestor that was removed.
|
/// The next sibling of the inclusive ancestor that was removed.
|
||||||
pub next_sibling: Option<&'a Node>,
|
pub next_sibling: Option<&'a Node>,
|
||||||
/// Whether the tree is connected.
|
/// Whether the tree is connected.
|
||||||
|
///
|
||||||
|
/// A tree is connected iff it's root is a Document or a ShadowRoot.
|
||||||
pub tree_connected: bool,
|
pub tree_connected: bool,
|
||||||
/// Whether the tree is in doc.
|
/// Whether the tree is in doc.
|
||||||
pub tree_in_doc: bool,
|
pub tree_in_doc: bool,
|
||||||
|
@ -3577,7 +3595,7 @@ impl<'a> UnbindContext<'a> {
|
||||||
parent,
|
parent,
|
||||||
prev_sibling,
|
prev_sibling,
|
||||||
next_sibling,
|
next_sibling,
|
||||||
tree_connected: parent.is_connected(),
|
tree_connected: parent.is_connected_to_tree(),
|
||||||
tree_in_doc: parent.is_in_doc(),
|
tree_in_doc: parent.is_in_doc(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[getElementById-dynamic-001.html]
|
|
||||||
[ShadowRoot.getElementById keeps working after host has been removed]
|
|
||||||
expected: FAIL
|
|
Loading…
Add table
Add a link
Reference in a new issue