aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Jiménez Moreno <ferjmoreno@gmail.com>2019-01-25 13:00:26 +0100
committerFernando Jiménez Moreno <ferjmoreno@gmail.com>2019-04-26 10:17:45 +0200
commit640fc04743e38491e582a6ba30ded5bebb0a3ebb (patch)
tree7afea3eec1f1638d44968de3cf63e26cc58d8727
parent48975840dd3a4becfc5ee6adccabd303e06fc554 (diff)
downloadservo-640fc04743e38491e582a6ba30ded5bebb0a3ebb.tar.gz
servo-640fc04743e38491e582a6ba30ded5bebb0a3ebb.zip
Implement shadow-including root, set node as in doc when connected. Makes JS work in shadow trees
-rw-r--r--components/script/dom/element.rs9
-rw-r--r--components/script/dom/htmlscriptelement.rs6
-rw-r--r--components/script/dom/node.rs30
-rw-r--r--components/script/dom/shadowroot.rs9
-rw-r--r--components/script/dom/webidls/Node.webidl6
5 files changed, 44 insertions, 16 deletions
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::<Node>()
- .set_flag(NodeFlags::IS_IN_SHADOW_TREE, true);
-
// Steps 4, 5 and 6.
Ok(self
.shadow_root
@@ -3293,7 +3290,9 @@ impl Element {
/// <https://dom.spec.whatwg.org/#connected>
pub fn is_connected(&self) -> bool {
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>()
}
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::<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.
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<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()
}
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::<Node>()
+ .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;
+};