mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Implement shadow-including root, set node as in doc when connected. Makes JS work in shadow trees
This commit is contained in:
parent
48975840dd
commit
640fc04743
5 changed files with 44 additions and 16 deletions
|
@ -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::EventBinding::EventMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
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::WindowMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
|
||||||
use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
|
use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
|
||||||
|
@ -484,9 +484,6 @@ impl Element {
|
||||||
return Err(Error::InvalidState);
|
return Err(Error::InvalidState);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.upcast::<Node>()
|
|
||||||
.set_flag(NodeFlags::IS_IN_SHADOW_TREE, true);
|
|
||||||
|
|
||||||
// Steps 4, 5 and 6.
|
// Steps 4, 5 and 6.
|
||||||
Ok(self
|
Ok(self
|
||||||
.shadow_root
|
.shadow_root
|
||||||
|
@ -3293,7 +3290,9 @@ impl Element {
|
||||||
/// <https://dom.spec.whatwg.org/#connected>
|
/// <https://dom.spec.whatwg.org/#connected>
|
||||||
pub fn is_connected(&self) -> bool {
|
pub fn is_connected(&self) -> bool {
|
||||||
let node = self.upcast::<Node>();
|
let node = self.upcast::<Node>();
|
||||||
let root = node.GetRootNode();
|
let mut options = GetRootNodeOptions::empty();
|
||||||
|
options.composed = true; // shadow included.
|
||||||
|
let root = node.GetRootNode(&options);
|
||||||
root.is::<Document>()
|
root.is::<Document>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
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);
|
let script = Trusted::new(self);
|
||||||
document_from_node(self).add_delayed_task(task!(ScriptDelayedInitialize: move || {
|
document_from_node(self).add_delayed_task(task!(ScriptDelayedInitialize: move || {
|
||||||
script.root().prepare();
|
script.root().prepare();
|
||||||
|
|
|
@ -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::DocumentBinding::DocumentMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
|
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::NodeListBinding::NodeListMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods;
|
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::Bindings::WindowBinding::WindowMethods;
|
||||||
use crate::dom::bindings::codegen::InheritTypes::DocumentFragmentTypeId;
|
use crate::dom::bindings::codegen::InheritTypes::DocumentFragmentTypeId;
|
||||||
use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
|
use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
|
||||||
|
@ -274,14 +277,23 @@ impl Node {
|
||||||
let parent_in_doc = self.is_in_doc();
|
let parent_in_doc = self.is_in_doc();
|
||||||
let parent_in_shadow_tree = self.is_in_shadow_tree();
|
let parent_in_shadow_tree = self.is_in_shadow_tree();
|
||||||
for node in new_child.traverse_preorder() {
|
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 {
|
if parent_in_shadow_tree {
|
||||||
node.set_owner_shadow_root(&*self.owner_shadow_root());
|
if let Some(shadow_root) = self.downcast::<ShadowRoot>() {
|
||||||
|
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>() {
|
||||||
|
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.
|
// Out-of-document elements never have the descendants flag set.
|
||||||
debug_assert!(!node.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS));
|
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
|
// https://dom.spec.whatwg.org/#dom-node-getrootnode
|
||||||
fn GetRootNode(&self) -> DomRoot<Node> {
|
fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> {
|
||||||
|
if options.composed {
|
||||||
|
if let Some(shadow_root) = self.owner_shadow_root.get() {
|
||||||
|
// shadow-including root.
|
||||||
|
return shadow_root.Host().upcast::<Node>().GetRootNode(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
self.inclusive_ancestors().last().unwrap()
|
self.inclusive_ancestors().last().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods;
|
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{self, ShadowRootMode};
|
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::num::Finite;
|
||||||
use crate::dom::bindings::reflector::reflect_dom_object;
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
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::documentfragment::DocumentFragment;
|
||||||
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl};
|
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl};
|
||||||
use crate::dom::element::Element;
|
use crate::dom::element::Element;
|
||||||
|
use crate::dom::node::{Node, NodeFlags};
|
||||||
use crate::dom::stylesheetlist::StyleSheetList;
|
use crate::dom::stylesheetlist::StyleSheetList;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
@ -28,10 +30,15 @@ pub struct ShadowRoot {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShadowRoot {
|
impl ShadowRoot {
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
fn new_inherited(host: &Element, document: &Document) -> ShadowRoot {
|
fn new_inherited(host: &Element, document: &Document) -> ShadowRoot {
|
||||||
let has_browsing_context = true;
|
let has_browsing_context = true;
|
||||||
|
let document_fragment = DocumentFragment::new_inherited(document);
|
||||||
|
document_fragment
|
||||||
|
.upcast::<Node>()
|
||||||
|
.set_flag(NodeFlags::IS_IN_SHADOW_TREE, true);
|
||||||
ShadowRoot {
|
ShadowRoot {
|
||||||
document_fragment: DocumentFragment::new_inherited(document),
|
document_fragment,
|
||||||
document_or_shadow_root: DocumentOrShadowRootImpl::new(
|
document_or_shadow_root: DocumentOrShadowRootImpl::new(
|
||||||
document.window(),
|
document.window(),
|
||||||
has_browsing_context,
|
has_browsing_context,
|
||||||
|
|
|
@ -32,7 +32,7 @@ interface Node : EventTarget {
|
||||||
readonly attribute Document? ownerDocument;
|
readonly attribute Document? ownerDocument;
|
||||||
|
|
||||||
[Pure]
|
[Pure]
|
||||||
Node getRootNode();
|
Node getRootNode(optional GetRootNodeOptions options);
|
||||||
|
|
||||||
[Pure]
|
[Pure]
|
||||||
readonly attribute Node? parentNode;
|
readonly attribute Node? parentNode;
|
||||||
|
@ -92,3 +92,7 @@ interface Node : EventTarget {
|
||||||
[CEReactions, Throws]
|
[CEReactions, Throws]
|
||||||
Node removeChild(Node child);
|
Node removeChild(Node child);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dictionary GetRootNodeOptions {
|
||||||
|
boolean composed = false;
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue