aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorFernando Jiménez Moreno <ferjmoreno@gmail.com>2019-01-31 16:10:26 +0100
committerFernando Jiménez Moreno <ferjmoreno@gmail.com>2019-04-26 10:17:46 +0200
commit7c9e8aa4cc3131c42a9412e1fa3e4f99b4324763 (patch)
treed1efcca0aef19a5dd3c00d717e8e7ac8cecf4442 /components
parentbe06f1e9b346d16538ddac5dea468f346cb1f18c (diff)
downloadservo-7c9e8aa4cc3131c42a9412e1fa3e4f99b4324763.tar.gz
servo-7c9e8aa4cc3131c42a9412e1fa3e4f99b4324763.zip
First bits of shadow dom layout
Diffstat (limited to 'components')
-rw-r--r--components/layout_thread/dom_wrapper.rs90
-rw-r--r--components/script/dom/element.rs23
-rw-r--r--components/script/dom/node.rs15
-rw-r--r--components/script/dom/shadowroot.rs15
-rw-r--r--components/script/lib.rs5
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;
}