aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/element.rs6
-rw-r--r--components/script/dom/node.rs40
2 files changed, 34 insertions, 12 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 006d99eb2f1..ca7effd3e09 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -3665,7 +3665,11 @@ impl VirtualMethods for Element {
}
if let Some(ref value) = *self.id_attribute.borrow() {
if let Some(ref shadow_root) = self.containing_shadow_root() {
- shadow_root.unregister_element_id(self, value.clone());
+ // 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());
+ }
} else {
doc.unregister_element_id(self, value.clone());
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 09684c5d9e9..aaa25abc3a6 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -316,17 +316,28 @@ impl Node {
/// Clean up flags and unbind from tree.
pub fn complete_remove_subtree(root: &Node, context: &UnbindContext) {
- for node in root.traverse_preorder(ShadowIncluding::Yes) {
- // Out-of-document elements never have the descendants flag set.
- node.set_flag(
- NodeFlags::IS_IN_DOC |
- NodeFlags::IS_CONNECTED |
- NodeFlags::HAS_DIRTY_DESCENDANTS |
- NodeFlags::HAS_SNAPSHOT |
- NodeFlags::HANDLED_SNAPSHOT,
- false,
- );
+ // Flags that reset when a node is disconnected
+ const RESET_FLAGS: NodeFlags = NodeFlags::IS_IN_DOC
+ .union(NodeFlags::IS_CONNECTED)
+ .union(NodeFlags::HAS_DIRTY_DESCENDANTS)
+ .union(NodeFlags::HAS_SNAPSHOT)
+ .union(NodeFlags::HANDLED_SNAPSHOT);
+
+ for node in root.traverse_preorder(ShadowIncluding::No) {
+ 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) {
node.clean_up_style_and_layout_data();
@@ -608,6 +619,11 @@ impl Node {
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.
pub fn type_id(&self) -> NodeTypeId {
match *self.eventtarget.type_id() {
@@ -3559,6 +3575,8 @@ pub struct UnbindContext<'a> {
/// The next sibling of the inclusive ancestor that was removed.
pub next_sibling: Option<&'a Node>,
/// Whether the tree is connected.
+ ///
+ /// A tree is connected iff it's root is a Document or a ShadowRoot.
pub tree_connected: bool,
/// Whether the tree is in doc.
pub tree_in_doc: bool,
@@ -3577,7 +3595,7 @@ impl<'a> UnbindContext<'a> {
parent,
prev_sibling,
next_sibling,
- tree_connected: parent.is_connected(),
+ tree_connected: parent.is_connected_to_tree(),
tree_in_doc: parent.is_in_doc(),
}
}