diff options
author | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2019-01-21 20:58:52 +0100 |
---|---|---|
committer | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2019-04-26 10:17:44 +0200 |
commit | 4304ee28dceffa8ad66f5b088754705bc2bb3b4e (patch) | |
tree | 57045d149bab44e0c6fe38e02c75f5762807ed25 /components/script | |
parent | 18ae0fcbd6af223f978a527d7d5039633d3c22ed (diff) | |
download | servo-4304ee28dceffa8ad66f5b088754705bc2bb3b4e.tar.gz servo-4304ee28dceffa8ad66f5b088754705bc2bb3b4e.zip |
Partial ShadowRoot implementation of DocumentOrShadowRoot
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/document.rs | 30 | ||||
-rw-r--r-- | components/script/dom/documentorshadowroot.rs | 40 | ||||
-rw-r--r-- | components/script/dom/macros.rs | 47 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/node.rs | 14 | ||||
-rw-r--r-- | components/script/dom/range.rs | 11 | ||||
-rw-r--r-- | components/script/dom/shadowroot.rs | 52 | ||||
-rw-r--r-- | components/script/dom/stylesheetlist.rs | 18 | ||||
-rw-r--r-- | components/script/dom/webidls/ShadowRoot.webidl | 2 |
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; |