mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Unify DocumentOrShadowRoot implementation
This commit is contained in:
parent
f3e707306f
commit
48975840dd
4 changed files with 238 additions and 161 deletions
|
@ -43,7 +43,7 @@ use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||||
use crate::dom::customelementregistry::CustomElementDefinition;
|
use crate::dom::customelementregistry::CustomElementDefinition;
|
||||||
use crate::dom::customevent::CustomEvent;
|
use crate::dom::customevent::CustomEvent;
|
||||||
use crate::dom::documentfragment::DocumentFragment;
|
use crate::dom::documentfragment::DocumentFragment;
|
||||||
use crate::dom::documentorshadowroot::DocumentOrShadowRoot;
|
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl};
|
||||||
use crate::dom::documenttype::DocumentType;
|
use crate::dom::documenttype::DocumentType;
|
||||||
use crate::dom::domimplementation::DOMImplementation;
|
use crate::dom::domimplementation::DOMImplementation;
|
||||||
use crate::dom::element::CustomElementCreationMode;
|
use crate::dom::element::CustomElementCreationMode;
|
||||||
|
@ -114,7 +114,6 @@ use euclid::Point2D;
|
||||||
use html5ever::{LocalName, Namespace, QualName};
|
use html5ever::{LocalName, Namespace, QualName};
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use js::jsapi::JS_GetRuntime;
|
|
||||||
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
use js::jsapi::{JSContext, JSObject, JSRuntime};
|
||||||
use keyboard_types::{Key, KeyState, Modifiers};
|
use keyboard_types::{Key, KeyState, Modifiers};
|
||||||
use metrics::{
|
use metrics::{
|
||||||
|
@ -133,7 +132,7 @@ use num_traits::ToPrimitive;
|
||||||
use profile_traits::ipc as profile_ipc;
|
use profile_traits::ipc as profile_ipc;
|
||||||
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType};
|
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType};
|
||||||
use ref_slice::ref_slice;
|
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::{AnimationState, DocumentActivity, MouseButton, MouseEventType};
|
||||||
use script_traits::{MsDuration, ScriptMsg, TouchEventType, TouchId, UntrustedNodeAddress};
|
use script_traits::{MsDuration, ScriptMsg, TouchEventType, TouchId, UntrustedNodeAddress};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
@ -267,6 +266,7 @@ impl ::style::stylesheets::StylesheetInDocument for StyleSheetInDocument {
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct Document {
|
pub struct Document {
|
||||||
node: Node,
|
node: Node,
|
||||||
|
document_or_shadow_root: DocumentOrShadowRootImpl,
|
||||||
window: Dom<Window>,
|
window: Dom<Window>,
|
||||||
implementation: MutNullableDom<DOMImplementation>,
|
implementation: MutNullableDom<DOMImplementation>,
|
||||||
#[ignore_malloc_size_of = "type from external crate"]
|
#[ignore_malloc_size_of = "type from external crate"]
|
||||||
|
@ -487,6 +487,11 @@ impl Document {
|
||||||
self.has_browsing_context
|
self.has_browsing_context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn browsing_context(&self) -> Option<DomRoot<WindowProxy>> {
|
||||||
|
self.document_or_shadow_root.browsing_context()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn window(&self) -> &Window {
|
pub fn window(&self) -> &Window {
|
||||||
&*self.window
|
&*self.window
|
||||||
|
@ -2613,10 +2618,12 @@ impl Document {
|
||||||
.and_then(|charset| Encoding::for_label(charset.as_str().as_bytes()))
|
.and_then(|charset| Encoding::for_label(charset.as_str().as_bytes()))
|
||||||
.unwrap_or(UTF_8);
|
.unwrap_or(UTF_8);
|
||||||
|
|
||||||
|
let has_browsing_context = has_browsing_context == HasBrowsingContext::Yes;
|
||||||
Document {
|
Document {
|
||||||
node: Node::new_document_node(),
|
node: Node::new_document_node(),
|
||||||
|
document_or_shadow_root: DocumentOrShadowRootImpl::new(window, has_browsing_context),
|
||||||
window: Dom::from_ref(window),
|
window: Dom::from_ref(window),
|
||||||
has_browsing_context: has_browsing_context == HasBrowsingContext::Yes,
|
has_browsing_context,
|
||||||
implementation: Default::default(),
|
implementation: Default::default(),
|
||||||
content_type,
|
content_type,
|
||||||
last_modified: last_modified,
|
last_modified: last_modified,
|
||||||
|
@ -2665,7 +2672,7 @@ impl Document {
|
||||||
deferred_scripts: Default::default(),
|
deferred_scripts: Default::default(),
|
||||||
asap_in_order_scripts_list: Default::default(),
|
asap_in_order_scripts_list: Default::default(),
|
||||||
asap_scripts_set: 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_ident: Cell::new(0),
|
||||||
animation_frame_list: DomRefCell::new(vec![]),
|
animation_frame_list: DomRefCell::new(vec![]),
|
||||||
running_animation_callbacks: Cell::new(false),
|
running_animation_callbacks: Cell::new(false),
|
||||||
|
@ -3246,8 +3253,6 @@ impl Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_document_or_shadow_root_helpers!();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element {
|
impl Element {
|
||||||
|
@ -3277,8 +3282,15 @@ impl ProfilerMetadataFactory for Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DocumentMethods for Document {
|
impl DocumentMethods for Document {
|
||||||
// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
|
// https://drafts.csswg.org/cssom/#dom-document-stylesheets
|
||||||
impl_document_or_shadow_root_methods!(Document);
|
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
|
// https://dom.spec.whatwg.org/#dom-document-implementation
|
||||||
fn Implementation(&self) -> DomRoot<DOMImplementation> {
|
fn Implementation(&self) -> DomRoot<DOMImplementation> {
|
||||||
|
@ -3290,6 +3302,15 @@ impl DocumentMethods for Document {
|
||||||
USVString(String::from(self.url().as_str()))
|
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
|
// https://html.spec.whatwg.org/multipage/#dom-document-hasfocus
|
||||||
fn HasFocus(&self) -> bool {
|
fn HasFocus(&self) -> bool {
|
||||||
// Step 1-2.
|
// Step 1-2.
|
||||||
|
@ -4234,6 +4255,18 @@ impl DocumentMethods for Document {
|
||||||
SetOnreadystatechange
|
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
|
// https://html.spec.whatwg.org/multipage/#dom-document-open
|
||||||
fn Open(
|
fn Open(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -2,10 +2,22 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||||
use crate::dom::document::Document;
|
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::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(
|
macro_rules! proxy_call(
|
||||||
($fn_name:ident, $return_type:ty) => (
|
($fn_name:ident, $return_type:ty) => (
|
||||||
|
@ -38,3 +50,150 @@ impl DocumentOrShadowRoot {
|
||||||
proxy_call!(stylesheet_count, usize);
|
proxy_call!(stylesheet_count, usize);
|
||||||
proxy_call!(stylesheet_at, index, usize, Option<DomRoot<CSSStyleSheet>>);
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -632,132 +632,3 @@ macro_rules! handle_potential_webgl_error {
|
||||||
handle_potential_webgl_error!($context, $call, ());
|
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))))
|
|
||||||
}
|
|
||||||
);
|
|
||||||
);
|
|
||||||
|
|
|
@ -2,33 +2,25 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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::ShadowRootBinding::ShadowRootMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{self, ShadowRootMode};
|
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::num::Finite;
|
||||||
use crate::dom::bindings::reflector::reflect_dom_object;
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::documentfragment::DocumentFragment;
|
use crate::dom::documentfragment::DocumentFragment;
|
||||||
use crate::dom::documentorshadowroot::DocumentOrShadowRoot;
|
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, DocumentOrShadowRootImpl};
|
||||||
use crate::dom::element::Element;
|
use crate::dom::element::Element;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
|
||||||
use crate::dom::node;
|
|
||||||
use crate::dom::stylesheetlist::StyleSheetList;
|
use crate::dom::stylesheetlist::StyleSheetList;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use crate::dom::windowproxy::WindowProxy;
|
|
||||||
use dom_struct::dom_struct;
|
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
|
// https://dom.spec.whatwg.org/#interface-shadowroot
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct ShadowRoot {
|
pub struct ShadowRoot {
|
||||||
document_fragment: DocumentFragment,
|
document_fragment: DocumentFragment,
|
||||||
|
document_or_shadow_root: DocumentOrShadowRootImpl,
|
||||||
has_browsing_context: bool,
|
has_browsing_context: bool,
|
||||||
host: Dom<Element>,
|
host: Dom<Element>,
|
||||||
stylesheet_list: MutNullableDom<StyleSheetList>,
|
stylesheet_list: MutNullableDom<StyleSheetList>,
|
||||||
|
@ -37,9 +29,14 @@ pub struct ShadowRoot {
|
||||||
|
|
||||||
impl ShadowRoot {
|
impl ShadowRoot {
|
||||||
fn new_inherited(host: &Element, document: &Document) -> ShadowRoot {
|
fn new_inherited(host: &Element, document: &Document) -> ShadowRoot {
|
||||||
|
let has_browsing_context = true;
|
||||||
ShadowRoot {
|
ShadowRoot {
|
||||||
document_fragment: DocumentFragment::new_inherited(document),
|
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),
|
host: Dom::from_ref(host),
|
||||||
stylesheet_list: MutNullableDom::new(None),
|
stylesheet_list: MutNullableDom::new(None),
|
||||||
window: Dom::from_ref(document.window()),
|
window: Dom::from_ref(document.window()),
|
||||||
|
@ -59,14 +56,6 @@ impl ShadowRoot {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetDocumentElement(&self) -> Option<DomRoot<Element>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn GetBody(&self) -> Option<DomRoot<HTMLElement>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stylesheet_count(&self) -> usize {
|
pub fn stylesheet_count(&self) -> usize {
|
||||||
//XXX handle shadowroot stylesheets
|
//XXX handle shadowroot stylesheets
|
||||||
0
|
0
|
||||||
|
@ -76,13 +65,28 @@ impl ShadowRoot {
|
||||||
//XXX handle shadowroot stylesheets
|
//XXX handle shadowroot stylesheets
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_document_or_shadow_root_helpers!();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShadowRootMethods for ShadowRoot {
|
impl ShadowRootMethods for ShadowRoot {
|
||||||
/// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
|
// https://html.spec.whatwg.org/multipage/#dom-document-activeelement
|
||||||
impl_document_or_shadow_root_methods!(ShadowRoot);
|
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
|
/// https://dom.spec.whatwg.org/#dom-shadowroot-mode
|
||||||
fn Mode(&self) -> ShadowRootMode {
|
fn Mode(&self) -> ShadowRootMode {
|
||||||
|
@ -93,4 +97,14 @@ impl ShadowRootMethods for ShadowRoot {
|
||||||
fn Host(&self) -> DomRoot<Element> {
|
fn Host(&self) -> DomRoot<Element> {
|
||||||
DomRoot::from_ref(&self.host)
|
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)),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue