diff options
author | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2019-01-31 16:10:26 +0100 |
---|---|---|
committer | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2019-04-26 10:17:46 +0200 |
commit | 7c9e8aa4cc3131c42a9412e1fa3e4f99b4324763 (patch) | |
tree | d1efcca0aef19a5dd3c00d717e8e7ac8cecf4442 /components | |
parent | be06f1e9b346d16538ddac5dea468f346cb1f18c (diff) | |
download | servo-7c9e8aa4cc3131c42a9412e1fa3e4f99b4324763.tar.gz servo-7c9e8aa4cc3131c42a9412e1fa3e4f99b4324763.zip |
First bits of shadow dom layout
Diffstat (limited to 'components')
-rw-r--r-- | components/layout_thread/dom_wrapper.rs | 90 | ||||
-rw-r--r-- | components/script/dom/element.rs | 23 | ||||
-rw-r--r-- | components/script/dom/node.rs | 15 | ||||
-rw-r--r-- | components/script/dom/shadowroot.rs | 15 | ||||
-rw-r--r-- | components/script/lib.rs | 5 |
5 files changed, 118 insertions, 30 deletions
diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs index 497c7f135d2..6227df9f04c 100644 --- a/components/layout_thread/dom_wrapper.rs +++ b/components/layout_thread/dom_wrapper.rs @@ -40,13 +40,16 @@ use net_traits::image::base::{Image, ImageMetadata}; use range::Range; use script::layout_exports::NodeFlags; use script::layout_exports::PendingRestyle; +use script::layout_exports::ShadowRoot; use script::layout_exports::{ - CharacterDataTypeId, ElementTypeId, HTMLElementTypeId, NodeTypeId, TextTypeId, + CharacterDataTypeId, DocumentFragmentTypeId, ElementTypeId, HTMLElementTypeId, NodeTypeId, + TextTypeId, }; use script::layout_exports::{Document, Element, Node, Text}; use script::layout_exports::{LayoutCharacterDataHelpers, LayoutDocumentHelpers}; use script::layout_exports::{ - LayoutDom, LayoutElementHelpers, LayoutNodeHelpers, RawLayoutElementHelpers, + LayoutDom, LayoutElementHelpers, LayoutNodeHelpers, LayoutShadowRootHelpers, + RawLayoutElementHelpers, }; use script_layout_interface::wrapper_traits::{ DangerousThreadSafeLayoutNode, GetLayoutData, LayoutNode, @@ -160,35 +163,60 @@ impl<'ln> NodeInfo for ServoLayoutNode<'ln> { } } -#[derive(Clone, Copy, PartialEq)] -enum Impossible {} +#[derive(Clone, Copy)] +pub struct ServoShadowRoot<'a> { + /// The wrapped shadow root. + shadow_root: LayoutDom<ShadowRoot>, -#[derive(Clone, Copy, PartialEq)] -pub struct ShadowRoot<'lr>(Impossible, PhantomData<&'lr ()>); + /// Being chained to a PhantomData prevents `ShadowRoot`s from escaping. + chain: PhantomData<&'a ()>, +} -impl<'lr> TShadowRoot for ShadowRoot<'lr> { - type ConcreteNode = ServoLayoutNode<'lr>; +impl<'sr> Debug for ServoShadowRoot<'sr> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.as_node().fmt(f) + } +} + +impl<'a> PartialEq for ServoShadowRoot<'a> { + #[inline] + fn eq(&self, other: &ServoShadowRoot) -> bool { + self.shadow_root == other.shadow_root + } +} + +impl<'sr> TShadowRoot for ServoShadowRoot<'sr> { + type ConcreteNode = ServoLayoutNode<'sr>; fn as_node(&self) -> Self::ConcreteNode { - match self.0 {} + ServoLayoutNode::from_layout_js(self.shadow_root.upcast()) } - fn host(&self) -> ServoLayoutElement<'lr> { - match self.0 {} + fn host(&self) -> ServoLayoutElement<'sr> { + ServoLayoutElement::from_layout_js(unsafe { self.shadow_root.get_host_for_layout() }) } fn style_data<'a>(&self) -> Option<&'a CascadeData> where Self: 'a, { - match self.0 {} + None + } +} + +impl<'sr> ServoShadowRoot<'sr> { + fn from_layout_js(shadow_root: LayoutDom<ShadowRoot>) -> ServoShadowRoot<'sr> { + ServoShadowRoot { + shadow_root, + chain: PhantomData, + } } } impl<'ln> TNode for ServoLayoutNode<'ln> { type ConcreteDocument = ServoLayoutDocument<'ln>; type ConcreteElement = ServoLayoutElement<'ln>; - type ConcreteShadowRoot = ShadowRoot<'ln>; + type ConcreteShadowRoot = ServoShadowRoot<'ln>; fn parent_node(&self) -> Option<Self> { unsafe { @@ -256,8 +284,8 @@ impl<'ln> TNode for ServoLayoutNode<'ln> { .map(ServoLayoutDocument::from_layout_js) } - fn as_shadow_root(&self) -> Option<ShadowRoot<'ln>> { - None + fn as_shadow_root(&self) -> Option<ServoShadowRoot<'ln>> { + self.node.downcast().map(ServoShadowRoot::from_layout_js) } fn is_connected(&self) -> bool { @@ -616,12 +644,23 @@ impl<'le> TElement for ServoLayoutElement<'le> { } } - fn shadow_root(&self) -> Option<ShadowRoot<'le>> { - None + /// The shadow root this element is a host of. + fn shadow_root(&self) -> Option<ServoShadowRoot<'le>> { + unsafe { + self.element + .get_shadow_root_for_layout() + .map(ServoShadowRoot::from_layout_js) + } } - fn containing_shadow(&self) -> Option<ShadowRoot<'le>> { - None + /// The shadow root which roots the subtree this element is contained in. + fn containing_shadow(&self) -> Option<ServoShadowRoot<'le>> { + unsafe { + self.element + .upcast() + .owner_shadow_root_for_layout() + .map(ServoShadowRoot::from_layout_js) + } } } @@ -706,11 +745,20 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> { } fn parent_node_is_shadow_root(&self) -> bool { - false + match self.as_node().parent_node() { + None => false, + Some(node) => { + node.script_type_id() == + NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) + }, + } } fn containing_shadow_host(&self) -> Option<Self> { - None + match self.containing_shadow() { + Some(shadow) => Some(shadow.host()), + None => None, + } } fn prev_sibling_element(&self) -> Option<ServoLayoutElement<'le>> { diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 5b5b93f78c1..f9923da3fea 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -15,6 +15,7 @@ use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods; use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function; use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods; use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, NodeMethods}; +use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions}; use crate::dom::bindings::codegen::UnionTypes::NodeOrString; @@ -76,7 +77,7 @@ use crate::dom::node::{NodeDamage, NodeFlags, UnbindContext}; use crate::dom::nodelist::NodeList; use crate::dom::promise::Promise; use crate::dom::servoparser::ServoParser; -use crate::dom::shadowroot::ShadowRoot; +use crate::dom::shadowroot::{LayoutShadowRootHelpers, ShadowRoot}; use crate::dom::text::Text; use crate::dom::validation::Validatable; use crate::dom::virtualmethods::{vtable_for, VirtualMethods}; @@ -587,6 +588,9 @@ pub trait LayoutElementHelpers { fn get_state_for_layout(&self) -> ElementState; fn insert_selector_flags(&self, flags: ElementSelectorFlags); fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool; + /// The shadow root this element is a host of. + #[allow(unsafe_code)] + unsafe fn get_shadow_root_for_layout(&self) -> Option<LayoutDom<ShadowRoot>>; } impl LayoutElementHelpers for LayoutDom<Element> { @@ -1049,6 +1053,12 @@ impl LayoutElementHelpers for LayoutDom<Element> { fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool { unsafe { (*self.unsafe_get()).selector_flags.get().contains(flags) } } + + #[inline] + #[allow(unsafe_code)] + unsafe fn get_shadow_root_for_layout(&self) -> Option<LayoutDom<ShadowRoot>> { + (*self.unsafe_get()).shadow_root.get_inner_as_layout() + } } impl Element { @@ -2877,11 +2887,18 @@ impl<'a> SelectorsElement for DomRoot<Element> { } fn parent_node_is_shadow_root(&self) -> bool { - false + match self.upcast::<Node>().GetParentNode() { + None => false, + Some(node) => node.is::<ShadowRoot>(), + } } fn containing_shadow_host(&self) -> Option<Self> { - None + if let Some(shadow_root) = self.upcast::<Node>().owner_shadow_root() { + Some(shadow_root.Host()) + } else { + None + } } fn match_pseudo_element( diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index d8c1a2f4d5d..b20f8cf037e 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -295,8 +295,8 @@ impl Node { if parent_in_shadow_tree { if let Some(shadow_root) = self.downcast::<ShadowRoot>() { node.set_owner_shadow_root(&*shadow_root); - } else { - node.set_owner_shadow_root(&*self.owner_shadow_root()); + } else if let Some(shadow_root) = self.owner_shadow_root() { + node.set_owner_shadow_root(&*shadow_root); } } let mut is_connected = parent_is_connected; @@ -946,8 +946,8 @@ impl Node { self.owner_doc.set(Some(document)); } - pub fn owner_shadow_root(&self) -> DomRoot<ShadowRoot> { - self.owner_shadow_root.get().unwrap() + pub fn owner_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> { + self.owner_shadow_root.get() } pub fn set_owner_shadow_root(&self, shadow_root: &ShadowRoot) { @@ -1184,6 +1184,7 @@ pub trait LayoutNodeHelpers { unsafe fn next_sibling_ref(&self) -> Option<LayoutDom<Node>>; unsafe fn owner_doc_for_layout(&self) -> LayoutDom<Document>; + unsafe fn owner_shadow_root_for_layout(&self) -> Option<LayoutDom<ShadowRoot>>; unsafe fn is_element_for_layout(&self) -> bool; unsafe fn get_flag(&self, flag: NodeFlags) -> bool; @@ -1262,6 +1263,12 @@ impl LayoutNodeHelpers for LayoutDom<Node> { #[inline] #[allow(unsafe_code)] + unsafe fn owner_shadow_root_for_layout(&self) -> Option<LayoutDom<ShadowRoot>> { + (*self.unsafe_get()).owner_shadow_root.get_inner_as_layout() + } + + #[inline] + #[allow(unsafe_code)] unsafe fn get_flag(&self, flag: NodeFlags) -> bool { (*self.unsafe_get()).flags.get().contains(flag) } diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs index e64401ab494..55470a9935d 100644 --- a/components/script/dom/shadowroot.rs +++ b/components/script/dom/shadowroot.rs @@ -7,7 +7,7 @@ use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{self, ShadowRoo 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::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom}; use crate::dom::cssstylesheet::CSSStyleSheet; use crate::dom::document::Document; use crate::dom::documentfragment::DocumentFragment; @@ -121,3 +121,16 @@ impl ShadowRootMethods for ShadowRoot { }) } } + +#[allow(unsafe_code)] +pub trait LayoutShadowRootHelpers { + unsafe fn get_host_for_layout(&self) -> LayoutDom<Element>; +} + +impl LayoutShadowRootHelpers for LayoutDom<ShadowRoot> { + #[inline] + #[allow(unsafe_code)] + unsafe fn get_host_for_layout(&self) -> LayoutDom<Element> { + (*self.unsafe_get()).host.to_layout() + } +} diff --git a/components/script/lib.rs b/components/script/lib.rs index a057540ae22..3f48e3d9118 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -84,7 +84,9 @@ mod webdriver_handlers; /// /// TODO(emilio): A few of the FooHelpers can go away, presumably... pub mod layout_exports { - pub use crate::dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId}; + pub use crate::dom::bindings::inheritance::{ + CharacterDataTypeId, DocumentFragmentTypeId, ElementTypeId, + }; pub use crate::dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId, TextTypeId}; pub use crate::dom::bindings::root::LayoutDom; pub use crate::dom::characterdata::LayoutCharacterDataHelpers; @@ -92,6 +94,7 @@ pub mod layout_exports { pub use crate::dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers}; pub use crate::dom::node::NodeFlags; pub use crate::dom::node::{LayoutNodeHelpers, Node}; + pub use crate::dom::shadowroot::{LayoutShadowRootHelpers, ShadowRoot}; pub use crate::dom::text::Text; } |