DocumentOrShadowRoot mixin

This commit is contained in:
Fernando Jiménez Moreno 2019-01-18 18:22:09 +01:00
parent 9b20187793
commit cbcf21c248
4 changed files with 124 additions and 109 deletions

View file

@ -3299,11 +3299,8 @@ impl ProfilerMetadataFactory for Document {
}
impl DocumentMethods for Document {
// 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)))
}
// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
impl_document_or_shadow_root!();
// https://dom.spec.whatwg.org/#dom-document-implementation
fn Implementation(&self) -> DomRoot<DOMImplementation> {
@ -3315,20 +3312,6 @@ 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>> {
// 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://html.spec.whatwg.org/multipage/#dom-document-hasfocus
fn HasFocus(&self) -> bool {
// Step 1-2.
@ -4273,84 +4256,6 @@ impl DocumentMethods for Document {
SetOnreadystatechange
);
#[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;
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(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 window = window_from_node(self);
let viewport = 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(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-open
fn Open(
&self,

View file

@ -632,3 +632,105 @@ macro_rules! handle_potential_webgl_error {
handle_potential_webgl_error!($context, $call, ());
};
}
macro_rules! impl_document_or_shadow_root {
() => (
#[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;
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(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 window = window_from_node(self);
let viewport = 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(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, Dom::from_ref(&self)))
}
)
}

View file

@ -132,7 +132,6 @@ partial /*sealed*/ interface Document {
// user interaction
readonly attribute Window?/*Proxy?*/ defaultView;
readonly attribute Element? activeElement;
boolean hasFocus();
// [CEReactions]
// attribute DOMString designMode;
@ -199,17 +198,6 @@ partial interface Document {
TouchList createTouchList(Touch... touches);
};
// https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
partial interface Document {
Element? elementFromPoint(double x, double y);
sequence<Element> elementsFromPoint(double x, double y);
};
// https://drafts.csswg.org/cssom/#extensions-to-the-document-interface
partial interface Document {
[SameObject] readonly attribute StyleSheetList styleSheets;
};
// https://fullscreen.spec.whatwg.org/#api
partial interface Document {
[LenientSetter] readonly attribute boolean fullscreenEnabled;
@ -221,3 +209,5 @@ partial interface Document {
attribute EventHandler onfullscreenchange;
attribute EventHandler onfullscreenerror;
};
Document implements DocumentOrShadowRoot;

View file

@ -0,0 +1,18 @@
/* 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/. */
/*
* The origin of this IDL file is
* https://dom.spec.whatwg.org/#documentorshadowroot
* https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
*/
[NoInterfaceObject]
interface DocumentOrShadowRoot {
// Selection? getSelection();
Element? elementFromPoint (double x, double y);
sequence<Element> elementsFromPoint (double x, double y);
// CaretPosition? caretPositionFromPoint (double x, double y);
readonly attribute Element? activeElement;
readonly attribute StyleSheetList styleSheets;
};