aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Jiménez Moreno <ferjmoreno@gmail.com>2019-01-24 18:16:20 +0100
committerFernando Jiménez Moreno <ferjmoreno@gmail.com>2019-04-26 10:17:45 +0200
commit48975840dd3a4becfc5ee6adccabd303e06fc554 (patch)
tree6c76ac86fffba6222c6197bb7eca0e4ce17257e6
parentf3e707306f64d714e4b631fcd76513625469233e (diff)
downloadservo-48975840dd3a4becfc5ee6adccabd303e06fc554.tar.gz
servo-48975840dd3a4becfc5ee6adccabd303e06fc554.zip
Unify DocumentOrShadowRoot implementation
-rw-r--r--components/script/dom/document.rs51
-rw-r--r--components/script/dom/documentorshadowroot.rs159
-rw-r--r--components/script/dom/macros.rs129
-rw-r--r--components/script/dom/shadowroot.rs60
4 files changed, 238 insertions, 161 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 2ff1516b231..5b1de4e6b85 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -43,7 +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::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl};
use crate::dom::documenttype::DocumentType;
use crate::dom::domimplementation::DOMImplementation;
use crate::dom::element::CustomElementCreationMode;
@@ -114,7 +114,6 @@ use euclid::Point2D;
use html5ever::{LocalName, Namespace, QualName};
use hyper_serde::Serde;
use ipc_channel::ipc::{self, IpcSender};
-use js::jsapi::JS_GetRuntime;
use js::jsapi::{JSContext, JSObject, JSRuntime};
use keyboard_types::{Key, KeyState, Modifiers};
use metrics::{
@@ -133,7 +132,7 @@ use num_traits::ToPrimitive;
use profile_traits::ipc as profile_ipc;
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType};
use ref_slice::ref_slice;
-use script_layout_interface::message::{Msg, NodesFromPointQueryType, QueryMsg, ReflowGoal};
+use script_layout_interface::message::{Msg, ReflowGoal};
use script_traits::{AnimationState, DocumentActivity, MouseButton, MouseEventType};
use script_traits::{MsDuration, ScriptMsg, TouchEventType, TouchId, UntrustedNodeAddress};
use servo_arc::Arc;
@@ -267,6 +266,7 @@ impl ::style::stylesheets::StylesheetInDocument for StyleSheetInDocument {
#[dom_struct]
pub struct Document {
node: Node,
+ document_or_shadow_root: DocumentOrShadowRootImpl,
window: Dom<Window>,
implementation: MutNullableDom<DOMImplementation>,
#[ignore_malloc_size_of = "type from external crate"]
@@ -488,6 +488,11 @@ impl Document {
}
#[inline]
+ pub fn browsing_context(&self) -> Option<DomRoot<WindowProxy>> {
+ self.document_or_shadow_root.browsing_context()
+ }
+
+ #[inline]
pub fn window(&self) -> &Window {
&*self.window
}
@@ -2613,10 +2618,12 @@ impl Document {
.and_then(|charset| Encoding::for_label(charset.as_str().as_bytes()))
.unwrap_or(UTF_8);
+ let has_browsing_context = has_browsing_context == HasBrowsingContext::Yes;
Document {
node: Node::new_document_node(),
+ document_or_shadow_root: DocumentOrShadowRootImpl::new(window, has_browsing_context),
window: Dom::from_ref(window),
- has_browsing_context: has_browsing_context == HasBrowsingContext::Yes,
+ has_browsing_context,
implementation: Default::default(),
content_type,
last_modified: last_modified,
@@ -2665,7 +2672,7 @@ impl Document {
deferred_scripts: Default::default(),
asap_in_order_scripts_list: Default::default(),
asap_scripts_set: Default::default(),
- scripting_enabled: has_browsing_context == HasBrowsingContext::Yes,
+ scripting_enabled: has_browsing_context,
animation_frame_ident: Cell::new(0),
animation_frame_list: DomRefCell::new(vec![]),
running_animation_callbacks: Cell::new(false),
@@ -3246,8 +3253,6 @@ impl Document {
}
}
}
-
- impl_document_or_shadow_root_helpers!();
}
impl Element {
@@ -3277,8 +3282,15 @@ 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_methods!(Document);
+ // https://drafts.csswg.org/cssom/#dom-document-stylesheets
+ fn StyleSheets(&self) -> DomRoot<StyleSheetList> {
+ self.stylesheet_list.or_init(|| {
+ StyleSheetList::new(
+ &self.window,
+ DocumentOrShadowRoot::Document(Dom::from_ref(self)),
+ )
+ })
+ }
// https://dom.spec.whatwg.org/#dom-document-implementation
fn Implementation(&self) -> DomRoot<DOMImplementation> {
@@ -3290,6 +3302,15 @@ impl DocumentMethods for Document {
USVString(String::from(self.url().as_str()))
}
+ // https://html.spec.whatwg.org/multipage/#dom-document-activeelement
+ fn GetActiveElement(&self) -> Option<DomRoot<Element>> {
+ self.document_or_shadow_root.get_active_element(
+ self.get_focused_element(),
+ self.GetBody(),
+ self.GetDocumentElement(),
+ )
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-document-hasfocus
fn HasFocus(&self) -> bool {
// Step 1-2.
@@ -4234,6 +4255,18 @@ impl DocumentMethods for Document {
SetOnreadystatechange
);
+ // https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
+ fn ElementFromPoint(&self, x: Finite<f64>, y: Finite<f64>) -> Option<DomRoot<Element>> {
+ self.document_or_shadow_root
+ .element_from_point(x, y, self.GetDocumentElement())
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-document-elementsfrompoint
+ fn ElementsFromPoint(&self, x: Finite<f64>, y: Finite<f64>) -> Vec<DomRoot<Element>> {
+ self.document_or_shadow_root
+ .elements_from_point(x, y, self.GetDocumentElement())
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-document-open
fn Open(
&self,
diff --git a/components/script/dom/documentorshadowroot.rs b/components/script/dom/documentorshadowroot.rs
index c305afce1d6..91ce83af659 100644
--- a/components/script/dom/documentorshadowroot.rs
+++ b/components/script/dom/documentorshadowroot.rs
@@ -2,10 +2,22 @@
* 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::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods;
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::num::Finite;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::cssstylesheet::CSSStyleSheet;
use crate::dom::document::Document;
+use crate::dom::element::Element;
+use crate::dom::htmlelement::HTMLElement;
+use crate::dom::node;
use crate::dom::shadowroot::ShadowRoot;
+use crate::dom::window::Window;
+use crate::dom::windowproxy::WindowProxy;
+use euclid::Point2D;
+use js::jsapi::JS_GetRuntime;
+use script_layout_interface::message::{NodesFromPointQueryType, QueryMsg};
+use script_traits::UntrustedNodeAddress;
macro_rules! proxy_call(
($fn_name:ident, $return_type:ty) => (
@@ -38,3 +50,150 @@ impl DocumentOrShadowRoot {
proxy_call!(stylesheet_count, usize);
proxy_call!(stylesheet_at, index, usize, Option<DomRoot<CSSStyleSheet>>);
}
+
+// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
+#[must_root]
+#[derive(JSTraceable, MallocSizeOf)]
+pub struct DocumentOrShadowRootImpl {
+ has_browsing_context: bool,
+ window: Dom<Window>,
+}
+
+impl DocumentOrShadowRootImpl {
+ pub fn new(window: &Window, has_browsing_context: bool) -> Self {
+ Self {
+ has_browsing_context,
+ window: Dom::from_ref(window),
+ }
+ }
+
+ /// <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()
+ }
+
+ #[allow(unsafe_code)]
+ // https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
+ pub fn element_from_point(
+ &self,
+ x: Finite<f64>,
+ y: Finite<f64>,
+ document_element: Option<DomRoot<Element>>,
+ ) -> Option<DomRoot<Element>> {
+ let x = *x as f32;
+ let y = *y as f32;
+ let point = &Point2D::new(x, y);
+ let viewport = self.window.window_size().initial_viewport;
+
+ if self.browsing_context().is_none() {
+ return None;
+ }
+
+ if x < 0.0 || y < 0.0 || x > viewport.width || y > viewport.height {
+ return None;
+ }
+
+ match self
+ .nodes_from_point(point, NodesFromPointQueryType::Topmost)
+ .first()
+ {
+ Some(address) => {
+ 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
+ .downcast::<Element>()
+ .unwrap_or_else(|| parent_node.downcast::<Element>().unwrap());
+
+ Some(DomRoot::from_ref(element_ref))
+ },
+ None => document_element,
+ }
+ }
+
+ #[allow(unsafe_code)]
+ // https://drafts.csswg.org/cssom-view/#dom-document-elementsfrompoint
+ pub fn elements_from_point(
+ &self,
+ x: Finite<f64>,
+ y: Finite<f64>,
+ document_element: Option<DomRoot<Element>>,
+ ) -> Vec<DomRoot<Element>> {
+ let x = *x as f32;
+ let y = *y as f32;
+ let point = &Point2D::new(x, y);
+ let viewport = self.window.window_size().initial_viewport;
+
+ if self.browsing_context().is_none() {
+ return vec![];
+ }
+
+ // Step 2
+ if x < 0.0 || y < 0.0 || x > viewport.width || y > viewport.height {
+ return vec![];
+ }
+
+ let js_runtime = unsafe { JS_GetRuntime(self.window.get_cx()) };
+
+ // Step 1 and Step 3
+ let nodes = self.nodes_from_point(point, NodesFromPointQueryType::All);
+ let mut elements: Vec<DomRoot<Element>> = nodes
+ .iter()
+ .flat_map(|&untrusted_node_address| {
+ let node = unsafe {
+ node::from_untrusted_node_address(js_runtime, untrusted_node_address)
+ };
+ DomRoot::downcast::<Element>(node)
+ })
+ .collect();
+
+ // Step 4
+ if let Some(root_element) = document_element {
+ if elements.last() != Some(&root_element) {
+ elements.push(root_element);
+ }
+ }
+
+ // Step 5
+ elements
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-document-activeelement
+ pub fn get_active_element(
+ &self,
+ focused_element: Option<DomRoot<Element>>,
+ body: Option<DomRoot<HTMLElement>>,
+ document_element: Option<DomRoot<Element>>,
+ ) -> Option<DomRoot<Element>> {
+ // TODO: Step 2.
+
+ match focused_element {
+ Some(element) => Some(element), // Step 3. and 4.
+ None => match body {
+ // Step 5.
+ Some(body) => Some(DomRoot::upcast(body)),
+ None => document_element,
+ },
+ }
+ }
+}
diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs
index c64902d8f94..a566fee4fb6 100644
--- a/components/script/dom/macros.rs
+++ b/components/script/dom/macros.rs
@@ -632,132 +632,3 @@ macro_rules! handle_potential_webgl_error {
handle_potential_webgl_error!($context, $call, ());
};
}
-
-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 viewport = self.window.window_size().initial_viewport;
-
- if self.browsing_context().is_none() {
- return None;
- }
-
- if x < 0.0 || y < 0.0 || x > viewport.width || y > viewport.height {
- return None;
- }
-
- match self
- .nodes_from_point(point, NodesFromPointQueryType::Topmost)
- .first()
- {
- Some(address) => {
- 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
- .downcast::<Element>()
- .unwrap_or_else(|| parent_node.downcast::<Element>().unwrap());
-
- Some(DomRoot::from_ref(element_ref))
- },
- None => self.GetDocumentElement(),
- }
- }
-
- #[allow(unsafe_code)]
- // https://drafts.csswg.org/cssom-view/#dom-document-elementsfrompoint
- fn ElementsFromPoint(&self, x: Finite<f64>, y: Finite<f64>) -> Vec<DomRoot<Element>> {
- let x = *x as f32;
- let y = *y as f32;
- let point = &Point2D::new(x, y);
- let viewport = self.window.window_size().initial_viewport;
-
- if self.browsing_context().is_none() {
- return vec![];
- }
-
- // Step 2
- if x < 0.0 || y < 0.0 || x > viewport.width || y > viewport.height {
- return vec![];
- }
-
- let js_runtime = unsafe { JS_GetRuntime(self.window.get_cx()) };
-
- // Step 1 and Step 3
- let nodes = self.nodes_from_point(point, NodesFromPointQueryType::All);
- let mut elements: Vec<DomRoot<Element>> = nodes
- .iter()
- .flat_map(|&untrusted_node_address| {
- let node = unsafe {
- node::from_untrusted_node_address(js_runtime, untrusted_node_address)
- };
- DomRoot::downcast::<Element>(node)
- })
- .collect();
-
- // Step 4
- if let Some(root_element) = self.GetDocumentElement() {
- if elements.last() != Some(&root_element) {
- elements.push(root_element);
- }
- }
-
- // Step 5
- elements
- }
-
- // https://html.spec.whatwg.org/multipage/#dom-document-activeelement
- fn GetActiveElement(&self) -> Option<DomRoot<Element>> {
- // TODO: Step 2.
-
- match self.get_focused_element() {
- Some(element) => Some(element), // Step 3. and 4.
- None => match self.GetBody() {
- // Step 5.
- Some(body) => Some(DomRoot::upcast(body)),
- None => self.GetDocumentElement(),
- },
- }
- }
-
- // https://drafts.csswg.org/cssom/#dom-document-stylesheets
- fn StyleSheets(&self) -> DomRoot<StyleSheetList> {
- self.stylesheet_list
- .or_init(|| StyleSheetList::new(&self.window, DocumentOrShadowRoot::$struct(Dom::from_ref(self))))
- }
- );
-);
diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs
index c16c77f6b64..e543750e6da 100644
--- a/components/script/dom/shadowroot.rs
+++ b/components/script/dom/shadowroot.rs
@@ -2,33 +2,25 @@
* 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::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods;
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};
use crate::dom::cssstylesheet::CSSStyleSheet;
use crate::dom::document::Document;
use crate::dom::documentfragment::DocumentFragment;
-use crate::dom::documentorshadowroot::DocumentOrShadowRoot;
+use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl};
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,
+ document_or_shadow_root: DocumentOrShadowRootImpl,
has_browsing_context: bool,
host: Dom<Element>,
stylesheet_list: MutNullableDom<StyleSheetList>,
@@ -37,9 +29,14 @@ pub struct ShadowRoot {
impl ShadowRoot {
fn new_inherited(host: &Element, document: &Document) -> ShadowRoot {
+ let has_browsing_context = true;
ShadowRoot {
document_fragment: DocumentFragment::new_inherited(document),
- has_browsing_context: true,
+ document_or_shadow_root: DocumentOrShadowRootImpl::new(
+ document.window(),
+ has_browsing_context,
+ ),
+ has_browsing_context,
host: Dom::from_ref(host),
stylesheet_list: MutNullableDom::new(None),
window: Dom::from_ref(document.window()),
@@ -59,14 +56,6 @@ impl ShadowRoot {
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
@@ -76,13 +65,28 @@ impl ShadowRoot {
//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://html.spec.whatwg.org/multipage/#dom-document-activeelement
+ fn GetActiveElement(&self) -> Option<DomRoot<Element>> {
+ self.document_or_shadow_root
+ .get_active_element(self.get_focused_element(), None, None)
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
+ fn ElementFromPoint(&self, x: Finite<f64>, y: Finite<f64>) -> Option<DomRoot<Element>> {
+ // XXX return the result of running the retargeting algorithm with context object
+ // and the original result as input
+ self.document_or_shadow_root.element_from_point(x, y, None)
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-document-elementsfrompoint
+ fn ElementsFromPoint(&self, x: Finite<f64>, y: Finite<f64>) -> Vec<DomRoot<Element>> {
+ // XXX return the result of running the retargeting algorithm with context object
+ // and the original result as input
+ self.document_or_shadow_root.elements_from_point(x, y, None)
+ }
/// https://dom.spec.whatwg.org/#dom-shadowroot-mode
fn Mode(&self) -> ShadowRootMode {
@@ -93,4 +97,14 @@ impl ShadowRootMethods for ShadowRoot {
fn Host(&self) -> DomRoot<Element> {
DomRoot::from_ref(&self.host)
}
+
+ // https://drafts.csswg.org/cssom/#dom-document-stylesheets
+ fn StyleSheets(&self) -> DomRoot<StyleSheetList> {
+ self.stylesheet_list.or_init(|| {
+ StyleSheetList::new(
+ &self.window,
+ DocumentOrShadowRoot::ShadowRoot(Dom::from_ref(self)),
+ )
+ })
+ }
}