diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 599efd4a8cc..20b51fbfaa1 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -14,7 +14,7 @@ use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods; use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function; use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods; -use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; +use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, NodeMethods}; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions}; use crate::dom::bindings::codegen::UnionTypes::NodeOrString; @@ -484,9 +484,6 @@ impl Element { return Err(Error::InvalidState); } - self.upcast::() - .set_flag(NodeFlags::IS_IN_SHADOW_TREE, true); - // Steps 4, 5 and 6. Ok(self .shadow_root @@ -3293,7 +3290,9 @@ impl Element { /// pub fn is_connected(&self) -> bool { let node = self.upcast::(); - let root = node.GetRootNode(); + let mut options = GetRootNodeOptions::empty(); + options.composed = true; // shadow included. + let root = node.GetRootNode(&options); root.is::() } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 627cfc7e779..12399c3b58e 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -778,12 +778,12 @@ impl VirtualMethods for HTMLScriptElement { } } - fn bind_to_tree(&self, tree_in_doc: bool) { + fn bind_to_tree(&self, is_connected: bool) { if let Some(ref s) = self.super_type() { - s.bind_to_tree(tree_in_doc); + s.bind_to_tree(is_connected); } - if tree_in_doc && !self.parser_inserted.get() { + if is_connected && !self.parser_inserted.get() { let script = Trusted::new(self); document_from_node(self).add_delayed_task(task!(ScriptDelayedInitialize: move || { script.root().prepare(); diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 4aa6f390b16..d27b6fad873 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -10,9 +10,12 @@ use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterData use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods; -use crate::dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods}; +use crate::dom::bindings::codegen::Bindings::NodeBinding::{ + GetRootNodeOptions, NodeConstants, NodeMethods, +}; use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods; +use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use crate::dom::bindings::codegen::InheritTypes::DocumentFragmentTypeId; use crate::dom::bindings::codegen::UnionTypes::NodeOrString; @@ -274,14 +277,23 @@ impl Node { let parent_in_doc = self.is_in_doc(); let parent_in_shadow_tree = self.is_in_shadow_tree(); for node in new_child.traverse_preorder() { - node.set_flag(NodeFlags::IS_IN_DOC, parent_in_doc); - node.set_flag(NodeFlags::IS_IN_SHADOW_TREE, parent_in_shadow_tree); if parent_in_shadow_tree { - node.set_owner_shadow_root(&*self.owner_shadow_root()); + if let Some(shadow_root) = self.downcast::() { + node.set_owner_shadow_root(&*shadow_root); + } else { + node.set_owner_shadow_root(&*self.owner_shadow_root()); + } } + let is_connected = if let Some(element) = node.downcast::() { + element.is_connected() + } else { + false + }; + node.set_flag(NodeFlags::IS_IN_DOC, parent_in_doc || is_connected); + node.set_flag(NodeFlags::IS_IN_SHADOW_TREE, parent_in_shadow_tree); // Out-of-document elements never have the descendants flag set. debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS)); - vtable_for(&&*node).bind_to_tree(parent_in_doc); + vtable_for(&&*node).bind_to_tree(is_connected); } } @@ -2163,7 +2175,13 @@ impl NodeMethods for Node { } // https://dom.spec.whatwg.org/#dom-node-getrootnode - fn GetRootNode(&self) -> DomRoot { + fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot { + if options.composed { + if let Some(shadow_root) = self.owner_shadow_root.get() { + // shadow-including root. + return shadow_root.Host().upcast::().GetRootNode(options); + } + } self.inclusive_ancestors().last().unwrap() } diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs index e543750e6da..a7a3bb693e5 100644 --- a/components/script/dom/shadowroot.rs +++ b/components/script/dom/shadowroot.rs @@ -4,6 +4,7 @@ use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods; use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{self, ShadowRootMode}; +use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; @@ -12,6 +13,7 @@ use crate::dom::document::Document; use crate::dom::documentfragment::DocumentFragment; use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl}; use crate::dom::element::Element; +use crate::dom::node::{Node, NodeFlags}; use crate::dom::stylesheetlist::StyleSheetList; use crate::dom::window::Window; use dom_struct::dom_struct; @@ -28,10 +30,15 @@ pub struct ShadowRoot { } impl ShadowRoot { + #[allow(unrooted_must_root)] fn new_inherited(host: &Element, document: &Document) -> ShadowRoot { let has_browsing_context = true; + let document_fragment = DocumentFragment::new_inherited(document); + document_fragment + .upcast::() + .set_flag(NodeFlags::IS_IN_SHADOW_TREE, true); ShadowRoot { - document_fragment: DocumentFragment::new_inherited(document), + document_fragment, document_or_shadow_root: DocumentOrShadowRootImpl::new( document.window(), has_browsing_context, diff --git a/components/script/dom/webidls/Node.webidl b/components/script/dom/webidls/Node.webidl index cddb776e416..479bec28a1f 100644 --- a/components/script/dom/webidls/Node.webidl +++ b/components/script/dom/webidls/Node.webidl @@ -32,7 +32,7 @@ interface Node : EventTarget { readonly attribute Document? ownerDocument; [Pure] - Node getRootNode(); + Node getRootNode(optional GetRootNodeOptions options); [Pure] readonly attribute Node? parentNode; @@ -92,3 +92,7 @@ interface Node : EventTarget { [CEReactions, Throws] Node removeChild(Node child); }; + +dictionary GetRootNodeOptions { + boolean composed = false; +};