aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorFernando Jiménez Moreno <ferjmoreno@gmail.com>2019-01-21 20:58:52 +0100
committerFernando Jiménez Moreno <ferjmoreno@gmail.com>2019-04-26 10:17:44 +0200
commit4304ee28dceffa8ad66f5b088754705bc2bb3b4e (patch)
tree57045d149bab44e0c6fe38e02c75f5762807ed25 /components/script
parent18ae0fcbd6af223f978a527d7d5039633d3c22ed (diff)
downloadservo-4304ee28dceffa8ad66f5b088754705bc2bb3b4e.tar.gz
servo-4304ee28dceffa8ad66f5b088754705bc2bb3b4e.zip
Partial ShadowRoot implementation of DocumentOrShadowRoot
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/document.rs30
-rw-r--r--components/script/dom/documentorshadowroot.rs40
-rw-r--r--components/script/dom/macros.rs47
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/node.rs14
-rw-r--r--components/script/dom/range.rs11
-rw-r--r--components/script/dom/shadowroot.rs52
-rw-r--r--components/script/dom/stylesheetlist.rs18
-rw-r--r--components/script/dom/webidls/ShadowRoot.webidl2
9 files changed, 161 insertions, 54 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 81bd243aab8..2ff1516b231 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -43,6 +43,7 @@ use crate::dom::cssstylesheet::CSSStyleSheet;
use crate::dom::customelementregistry::CustomElementDefinition;
use crate::dom::customevent::CustomEvent;
use crate::dom::documentfragment::DocumentFragment;
+use crate::dom::documentorshadowroot::DocumentOrShadowRoot;
use crate::dom::documenttype::DocumentType;
use crate::dom::domimplementation::DOMImplementation;
use crate::dom::element::CustomElementCreationMode;
@@ -486,16 +487,6 @@ impl Document {
self.has_browsing_context
}
- /// <https://html.spec.whatwg.org/multipage/#concept-document-bc>
- #[inline]
- pub fn browsing_context(&self) -> Option<DomRoot<WindowProxy>> {
- if self.has_browsing_context {
- self.window.undiscarded_window_proxy()
- } else {
- None
- }
- }
-
#[inline]
pub fn window(&self) -> &Window {
&*self.window
@@ -2395,21 +2386,6 @@ impl Document {
!self.has_browsing_context || !url_has_network_scheme(&self.url())
}
- pub fn nodes_from_point(
- &self,
- client_point: &Point2D<f32>,
- reflow_goal: NodesFromPointQueryType,
- ) -> Vec<UntrustedNodeAddress> {
- if !self
- .window
- .layout_reflow(QueryMsg::NodesFromPointQuery(*client_point, reflow_goal))
- {
- return vec![];
- };
-
- self.window.layout().nodes_from_point_response()
- }
-
/// <https://html.spec.whatwg.org/multipage/#look-up-a-custom-element-definition>
pub fn lookup_custom_element_definition(
&self,
@@ -3270,6 +3246,8 @@ impl Document {
}
}
}
+
+ impl_document_or_shadow_root_helpers!();
}
impl Element {
@@ -3300,7 +3278,7 @@ impl ProfilerMetadataFactory for Document {
impl DocumentMethods for Document {
// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
- impl_document_or_shadow_root!();
+ impl_document_or_shadow_root_methods!(Document);
// https://dom.spec.whatwg.org/#dom-document-implementation
fn Implementation(&self) -> DomRoot<DOMImplementation> {
diff --git a/components/script/dom/documentorshadowroot.rs b/components/script/dom/documentorshadowroot.rs
new file mode 100644
index 00000000000..c305afce1d6
--- /dev/null
+++ b/components/script/dom/documentorshadowroot.rs
@@ -0,0 +1,40 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::dom::bindings::root::{Dom, DomRoot};
+use crate::dom::cssstylesheet::CSSStyleSheet;
+use crate::dom::document::Document;
+use crate::dom::shadowroot::ShadowRoot;
+
+macro_rules! proxy_call(
+ ($fn_name:ident, $return_type:ty) => (
+ pub fn $fn_name(&self) -> $return_type {
+ match self {
+ DocumentOrShadowRoot::Document(doc) => doc.$fn_name(),
+ DocumentOrShadowRoot::ShadowRoot(root) => root.$fn_name(),
+ }
+ }
+ );
+
+ ($fn_name:ident, $arg1:ident, $arg1_type:ty, $return_type:ty) => (
+ pub fn $fn_name(&self, $arg1: $arg1_type) -> $return_type {
+ match self {
+ DocumentOrShadowRoot::Document(doc) => doc.$fn_name($arg1),
+ DocumentOrShadowRoot::ShadowRoot(root) => root.$fn_name($arg1),
+ }
+ }
+ );
+);
+
+#[must_root]
+#[derive(JSTraceable, MallocSizeOf)]
+pub enum DocumentOrShadowRoot {
+ Document(Dom<Document>),
+ ShadowRoot(Dom<ShadowRoot>),
+}
+
+impl DocumentOrShadowRoot {
+ proxy_call!(stylesheet_count, usize);
+ proxy_call!(stylesheet_at, index, usize, Option<DomRoot<CSSStyleSheet>>);
+}
diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs
index 94a0779732c..c64902d8f94 100644
--- a/components/script/dom/macros.rs
+++ b/components/script/dom/macros.rs
@@ -633,16 +633,44 @@ macro_rules! handle_potential_webgl_error {
};
}
-macro_rules! impl_document_or_shadow_root {
+macro_rules! impl_document_or_shadow_root_helpers(
() => (
+ /// <https://html.spec.whatwg.org/multipage/#concept-document-bc>
+ #[inline]
+ pub fn browsing_context(&self) -> Option<DomRoot<WindowProxy>> {
+ if self.has_browsing_context {
+ self.window.undiscarded_window_proxy()
+ } else {
+ None
+ }
+ }
+
+ pub fn nodes_from_point(
+ &self,
+ client_point: &Point2D<f32>,
+ reflow_goal: NodesFromPointQueryType,
+ ) -> Vec<UntrustedNodeAddress> {
+ if !self
+ .window
+ .layout_reflow(QueryMsg::NodesFromPointQuery(*client_point, reflow_goal))
+ {
+ return vec![];
+ };
+
+ self.window.layout().nodes_from_point_response()
+ }
+ );
+);
+
+macro_rules! impl_document_or_shadow_root_methods(
+ ($struct:ident) => (
#[allow(unsafe_code)]
// https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
fn ElementFromPoint(&self, x: Finite<f64>, y: Finite<f64>) -> Option<DomRoot<Element>> {
let x = *x as f32;
let y = *y as f32;
let point = &Point2D::new(x, y);
- let window = window_from_node(self);
- let viewport = window.window_size().initial_viewport;
+ let viewport = self.window.window_size().initial_viewport;
if self.browsing_context().is_none() {
return None;
@@ -657,7 +685,7 @@ macro_rules! impl_document_or_shadow_root {
.first()
{
Some(address) => {
- let js_runtime = unsafe { JS_GetRuntime(window.get_cx()) };
+ let js_runtime = unsafe { JS_GetRuntime(self.window.get_cx()) };
let node = unsafe { node::from_untrusted_node_address(js_runtime, *address) };
let parent_node = node.GetParentNode().unwrap();
let element_ref = node
@@ -676,8 +704,7 @@ macro_rules! impl_document_or_shadow_root {
let x = *x as f32;
let y = *y as f32;
let point = &Point2D::new(x, y);
- let window = window_from_node(self);
- let viewport = window.window_size().initial_viewport;
+ let viewport = self.window.window_size().initial_viewport;
if self.browsing_context().is_none() {
return vec![];
@@ -688,7 +715,7 @@ macro_rules! impl_document_or_shadow_root {
return vec![];
}
- let js_runtime = unsafe { JS_GetRuntime(window.get_cx()) };
+ let js_runtime = unsafe { JS_GetRuntime(self.window.get_cx()) };
// Step 1 and Step 3
let nodes = self.nodes_from_point(point, NodesFromPointQueryType::All);
@@ -730,7 +757,7 @@ macro_rules! impl_document_or_shadow_root {
// https://drafts.csswg.org/cssom/#dom-document-stylesheets
fn StyleSheets(&self) -> DomRoot<StyleSheetList> {
self.stylesheet_list
- .or_init(|| StyleSheetList::new(&self.window, Dom::from_ref(&self)))
+ .or_init(|| StyleSheetList::new(&self.window, DocumentOrShadowRoot::$struct(Dom::from_ref(self))))
}
- )
-}
+ );
+);
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 17d55d3c3a3..15d3ba34a23 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -280,6 +280,7 @@ pub mod dissimilaroriginlocation;
pub mod dissimilaroriginwindow;
pub mod document;
pub mod documentfragment;
+pub mod documentorshadowroot;
pub mod documenttype;
pub mod domexception;
pub mod domimplementation;
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index a015324b449..33c05aa2a5a 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -1560,7 +1560,9 @@ impl Node {
) -> ErrorResult {
// Step 1.
match parent.type_id() {
- NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => (),
+ NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
+ ()
+ },
_ => return Err(Error::HierarchyRequest),
}
@@ -2248,7 +2250,9 @@ impl NodeMethods for Node {
fn ReplaceChild(&self, node: &Node, child: &Node) -> Fallible<DomRoot<Node>> {
// Step 1.
match self.type_id() {
- NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => (),
+ NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
+ ()
+ },
_ => return Err(Error::HierarchyRequest),
}
@@ -2351,8 +2355,10 @@ impl NodeMethods for Node {
// Step 12.
rooted_vec!(let mut nodes);
- let nodes = if node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) ||
- node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) {
+ let nodes = if node.type_id() ==
+ NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) ||
+ node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot)
+ {
nodes.extend(node.children().map(|node| Dom::from_ref(&*node)));
nodes.r()
} else {
diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs
index 9a1bc5db7a6..96f276944bc 100644
--- a/components/script/dom/range.rs
+++ b/components/script/dom/range.rs
@@ -764,8 +764,11 @@ impl RangeMethods for Range {
// Step 11
let new_offset = new_offset +
- if node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) ||
- node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) {
+ if node.type_id() ==
+ NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) ||
+ node.type_id() ==
+ NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot)
+ {
node.len()
} else {
1
@@ -880,7 +883,9 @@ impl RangeMethods for Range {
// Step 2.
match new_parent.type_id() {
- NodeTypeId::Document(_) | NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => {
+ NodeTypeId::Document(_) |
+ NodeTypeId::DocumentType |
+ NodeTypeId::DocumentFragment(_) => {
return Err(Error::InvalidNodeType);
},
_ => (),
diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs
index bb3b646a9d2..7f21ca57ad0 100644
--- a/components/script/dom/shadowroot.rs
+++ b/components/script/dom/shadowroot.rs
@@ -2,19 +2,36 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-use crate::dom::documentfragment::DocumentFragment;
+use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods;
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods;
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootMode;
-use crate::dom::bindings::root::{Dom, DomRoot};
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::num::Finite;
+use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
+use crate::dom::cssstylesheet::CSSStyleSheet;
use crate::dom::document::Document;
+use crate::dom::documentfragment::DocumentFragment;
+use crate::dom::documentorshadowroot::DocumentOrShadowRoot;
use crate::dom::element::Element;
+use crate::dom::htmlelement::HTMLElement;
+use crate::dom::node;
+use crate::dom::stylesheetlist::StyleSheetList;
+use crate::dom::window::Window;
+use crate::dom::windowproxy::WindowProxy;
use dom_struct::dom_struct;
+use euclid::Point2D;
+use js::jsapi::JS_GetRuntime;
+use script_layout_interface::message::{NodesFromPointQueryType, QueryMsg};
+use script_traits::UntrustedNodeAddress;
// https://dom.spec.whatwg.org/#interface-shadowroot
#[dom_struct]
pub struct ShadowRoot {
document_fragment: DocumentFragment,
+ has_browsing_context: bool,
host: Dom<Element>,
+ stylesheet_list: MutNullableDom<StyleSheetList>,
+ window: Dom<Window>,
}
impl ShadowRoot {
@@ -22,12 +39,43 @@ impl ShadowRoot {
pub fn new_inherited(host: &Element, document: &Document) -> ShadowRoot {
ShadowRoot {
document_fragment: DocumentFragment::new_inherited(document),
+ has_browsing_context: true,
host: Dom::from_ref(host),
+ stylesheet_list: MutNullableDom::new(None),
+ window: Dom::from_ref(document.window()),
}
}
+
+ pub fn get_focused_element(&self) -> Option<DomRoot<Element>> {
+ //XXX get retargeted focused element
+ None
+ }
+
+ pub fn GetDocumentElement(&self) -> Option<DomRoot<Element>> {
+ None
+ }
+
+ pub fn GetBody(&self) -> Option<DomRoot<HTMLElement>> {
+ None
+ }
+
+ pub fn stylesheet_count(&self) -> usize {
+ //XXX handle shadowroot stylesheets
+ 0
+ }
+
+ pub fn stylesheet_at(&self, _index: usize) -> Option<DomRoot<CSSStyleSheet>> {
+ //XXX handle shadowroot stylesheets
+ None
+ }
+
+ impl_document_or_shadow_root_helpers!();
}
impl ShadowRootMethods for ShadowRoot {
+ /// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
+ impl_document_or_shadow_root_methods!(ShadowRoot);
+
/// https://dom.spec.whatwg.org/#dom-shadowroot-mode
fn Mode(&self) -> ShadowRootMode {
ShadowRootMode::Closed
diff --git a/components/script/dom/stylesheetlist.rs b/components/script/dom/stylesheetlist.rs
index c1c5c0b2d5f..79afcfed21f 100644
--- a/components/script/dom/stylesheetlist.rs
+++ b/components/script/dom/stylesheetlist.rs
@@ -5,8 +5,8 @@
use crate::dom::bindings::codegen::Bindings::StyleSheetListBinding;
use crate::dom::bindings::codegen::Bindings::StyleSheetListBinding::StyleSheetListMethods;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
-use crate::dom::bindings::root::{Dom, DomRoot};
-use crate::dom::document::Document;
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::documentorshadowroot::DocumentOrShadowRoot;
use crate::dom::stylesheet::StyleSheet;
use crate::dom::window::Window;
use dom_struct::dom_struct;
@@ -14,22 +14,22 @@ use dom_struct::dom_struct;
#[dom_struct]
pub struct StyleSheetList {
reflector_: Reflector,
- document: Dom<Document>,
+ document_or_shadow_root: DocumentOrShadowRoot,
}
impl StyleSheetList {
#[allow(unrooted_must_root)]
- fn new_inherited(doc: Dom<Document>) -> StyleSheetList {
+ fn new_inherited(doc_or_sr: DocumentOrShadowRoot) -> StyleSheetList {
StyleSheetList {
reflector_: Reflector::new(),
- document: doc,
+ document_or_shadow_root: doc_or_sr,
}
}
#[allow(unrooted_must_root)]
- pub fn new(window: &Window, document: Dom<Document>) -> DomRoot<StyleSheetList> {
+ pub fn new(window: &Window, doc_or_sr: DocumentOrShadowRoot) -> DomRoot<StyleSheetList> {
reflect_dom_object(
- Box::new(StyleSheetList::new_inherited(document)),
+ Box::new(StyleSheetList::new_inherited(doc_or_sr)),
window,
StyleSheetListBinding::Wrap,
)
@@ -39,14 +39,14 @@ impl StyleSheetList {
impl StyleSheetListMethods for StyleSheetList {
// https://drafts.csswg.org/cssom/#dom-stylesheetlist-length
fn Length(&self) -> u32 {
- self.document.stylesheet_count() as u32
+ self.document_or_shadow_root.stylesheet_count() as u32
}
// https://drafts.csswg.org/cssom/#dom-stylesheetlist-item
fn Item(&self, index: u32) -> Option<DomRoot<StyleSheet>> {
// XXXManishearth this doesn't handle the origin clean flag and is a
// cors vulnerability
- self.document
+ self.document_or_shadow_root
.stylesheet_at(index as usize)
.map(DomRoot::upcast)
}
diff --git a/components/script/dom/webidls/ShadowRoot.webidl b/components/script/dom/webidls/ShadowRoot.webidl
index f8372bdb6cd..711d4f853bd 100644
--- a/components/script/dom/webidls/ShadowRoot.webidl
+++ b/components/script/dom/webidls/ShadowRoot.webidl
@@ -13,3 +13,5 @@ interface ShadowRoot : DocumentFragment {
};
enum ShadowRootMode { "open", "closed"};
+
+ShadowRoot implements DocumentOrShadowRoot;