mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
First bits of shadow dom layout
This commit is contained in:
parent
be06f1e9b3
commit
7c9e8aa4cc
5 changed files with 118 additions and 30 deletions
|
@ -40,13 +40,16 @@ use net_traits::image::base::{Image, ImageMetadata};
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use script::layout_exports::NodeFlags;
|
use script::layout_exports::NodeFlags;
|
||||||
use script::layout_exports::PendingRestyle;
|
use script::layout_exports::PendingRestyle;
|
||||||
|
use script::layout_exports::ShadowRoot;
|
||||||
use script::layout_exports::{
|
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::{Document, Element, Node, Text};
|
||||||
use script::layout_exports::{LayoutCharacterDataHelpers, LayoutDocumentHelpers};
|
use script::layout_exports::{LayoutCharacterDataHelpers, LayoutDocumentHelpers};
|
||||||
use script::layout_exports::{
|
use script::layout_exports::{
|
||||||
LayoutDom, LayoutElementHelpers, LayoutNodeHelpers, RawLayoutElementHelpers,
|
LayoutDom, LayoutElementHelpers, LayoutNodeHelpers, LayoutShadowRootHelpers,
|
||||||
|
RawLayoutElementHelpers,
|
||||||
};
|
};
|
||||||
use script_layout_interface::wrapper_traits::{
|
use script_layout_interface::wrapper_traits::{
|
||||||
DangerousThreadSafeLayoutNode, GetLayoutData, LayoutNode,
|
DangerousThreadSafeLayoutNode, GetLayoutData, LayoutNode,
|
||||||
|
@ -160,35 +163,60 @@ impl<'ln> NodeInfo for ServoLayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy)]
|
||||||
enum Impossible {}
|
pub struct ServoShadowRoot<'a> {
|
||||||
|
/// The wrapped shadow root.
|
||||||
|
shadow_root: LayoutDom<ShadowRoot>,
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
/// Being chained to a PhantomData prevents `ShadowRoot`s from escaping.
|
||||||
pub struct ShadowRoot<'lr>(Impossible, PhantomData<&'lr ()>);
|
chain: PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'lr> TShadowRoot for ShadowRoot<'lr> {
|
impl<'sr> Debug for ServoShadowRoot<'sr> {
|
||||||
type ConcreteNode = ServoLayoutNode<'lr>;
|
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 {
|
fn as_node(&self) -> Self::ConcreteNode {
|
||||||
match self.0 {}
|
ServoLayoutNode::from_layout_js(self.shadow_root.upcast())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn host(&self) -> ServoLayoutElement<'lr> {
|
fn host(&self) -> ServoLayoutElement<'sr> {
|
||||||
match self.0 {}
|
ServoLayoutElement::from_layout_js(unsafe { self.shadow_root.get_host_for_layout() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_data<'a>(&self) -> Option<&'a CascadeData>
|
fn style_data<'a>(&self) -> Option<&'a CascadeData>
|
||||||
where
|
where
|
||||||
Self: 'a,
|
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> {
|
impl<'ln> TNode for ServoLayoutNode<'ln> {
|
||||||
type ConcreteDocument = ServoLayoutDocument<'ln>;
|
type ConcreteDocument = ServoLayoutDocument<'ln>;
|
||||||
type ConcreteElement = ServoLayoutElement<'ln>;
|
type ConcreteElement = ServoLayoutElement<'ln>;
|
||||||
type ConcreteShadowRoot = ShadowRoot<'ln>;
|
type ConcreteShadowRoot = ServoShadowRoot<'ln>;
|
||||||
|
|
||||||
fn parent_node(&self) -> Option<Self> {
|
fn parent_node(&self) -> Option<Self> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -256,8 +284,8 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
||||||
.map(ServoLayoutDocument::from_layout_js)
|
.map(ServoLayoutDocument::from_layout_js)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_shadow_root(&self) -> Option<ShadowRoot<'ln>> {
|
fn as_shadow_root(&self) -> Option<ServoShadowRoot<'ln>> {
|
||||||
None
|
self.node.downcast().map(ServoShadowRoot::from_layout_js)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_connected(&self) -> bool {
|
fn is_connected(&self) -> bool {
|
||||||
|
@ -616,12 +644,23 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shadow_root(&self) -> Option<ShadowRoot<'le>> {
|
/// The shadow root this element is a host of.
|
||||||
None
|
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>> {
|
/// The shadow root which roots the subtree this element is contained in.
|
||||||
None
|
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 {
|
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> {
|
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>> {
|
fn prev_sibling_element(&self) -> Option<ServoLayoutElement<'le>> {
|
||||||
|
|
|
@ -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::FunctionBinding::Function;
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, NodeMethods};
|
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::WindowMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
|
||||||
use crate::dom::bindings::codegen::UnionTypes::NodeOrString;
|
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::nodelist::NodeList;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::dom::servoparser::ServoParser;
|
use crate::dom::servoparser::ServoParser;
|
||||||
use crate::dom::shadowroot::ShadowRoot;
|
use crate::dom::shadowroot::{LayoutShadowRootHelpers, ShadowRoot};
|
||||||
use crate::dom::text::Text;
|
use crate::dom::text::Text;
|
||||||
use crate::dom::validation::Validatable;
|
use crate::dom::validation::Validatable;
|
||||||
use crate::dom::virtualmethods::{vtable_for, VirtualMethods};
|
use crate::dom::virtualmethods::{vtable_for, VirtualMethods};
|
||||||
|
@ -587,6 +588,9 @@ pub trait LayoutElementHelpers {
|
||||||
fn get_state_for_layout(&self) -> ElementState;
|
fn get_state_for_layout(&self) -> ElementState;
|
||||||
fn insert_selector_flags(&self, flags: ElementSelectorFlags);
|
fn insert_selector_flags(&self, flags: ElementSelectorFlags);
|
||||||
fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool;
|
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> {
|
impl LayoutElementHelpers for LayoutDom<Element> {
|
||||||
|
@ -1049,6 +1053,12 @@ impl LayoutElementHelpers for LayoutDom<Element> {
|
||||||
fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool {
|
fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool {
|
||||||
unsafe { (*self.unsafe_get()).selector_flags.get().contains(flags) }
|
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 {
|
impl Element {
|
||||||
|
@ -2877,11 +2887,18 @@ impl<'a> SelectorsElement for DomRoot<Element> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent_node_is_shadow_root(&self) -> bool {
|
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> {
|
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(
|
fn match_pseudo_element(
|
||||||
|
|
|
@ -295,8 +295,8 @@ impl Node {
|
||||||
if parent_in_shadow_tree {
|
if parent_in_shadow_tree {
|
||||||
if let Some(shadow_root) = self.downcast::<ShadowRoot>() {
|
if let Some(shadow_root) = self.downcast::<ShadowRoot>() {
|
||||||
node.set_owner_shadow_root(&*shadow_root);
|
node.set_owner_shadow_root(&*shadow_root);
|
||||||
} else {
|
} else if let Some(shadow_root) = self.owner_shadow_root() {
|
||||||
node.set_owner_shadow_root(&*self.owner_shadow_root());
|
node.set_owner_shadow_root(&*shadow_root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut is_connected = parent_is_connected;
|
let mut is_connected = parent_is_connected;
|
||||||
|
@ -946,8 +946,8 @@ impl Node {
|
||||||
self.owner_doc.set(Some(document));
|
self.owner_doc.set(Some(document));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn owner_shadow_root(&self) -> DomRoot<ShadowRoot> {
|
pub fn owner_shadow_root(&self) -> Option<DomRoot<ShadowRoot>> {
|
||||||
self.owner_shadow_root.get().unwrap()
|
self.owner_shadow_root.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_owner_shadow_root(&self, shadow_root: &ShadowRoot) {
|
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 next_sibling_ref(&self) -> Option<LayoutDom<Node>>;
|
||||||
|
|
||||||
unsafe fn owner_doc_for_layout(&self) -> LayoutDom<Document>;
|
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 is_element_for_layout(&self) -> bool;
|
||||||
unsafe fn get_flag(&self, flag: NodeFlags) -> bool;
|
unsafe fn get_flag(&self, flag: NodeFlags) -> bool;
|
||||||
|
@ -1260,6 +1261,12 @@ impl LayoutNodeHelpers for LayoutDom<Node> {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[inline]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_flag(&self, flag: NodeFlags) -> bool {
|
unsafe fn get_flag(&self, flag: NodeFlags) -> bool {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{self, ShadowRoo
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
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, LayoutDom, 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;
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -84,7 +84,9 @@ mod webdriver_handlers;
|
||||||
///
|
///
|
||||||
/// TODO(emilio): A few of the FooHelpers can go away, presumably...
|
/// TODO(emilio): A few of the FooHelpers can go away, presumably...
|
||||||
pub mod layout_exports {
|
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::inheritance::{HTMLElementTypeId, NodeTypeId, TextTypeId};
|
||||||
pub use crate::dom::bindings::root::LayoutDom;
|
pub use crate::dom::bindings::root::LayoutDom;
|
||||||
pub use crate::dom::characterdata::LayoutCharacterDataHelpers;
|
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::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
|
||||||
pub use crate::dom::node::NodeFlags;
|
pub use crate::dom::node::NodeFlags;
|
||||||
pub use crate::dom::node::{LayoutNodeHelpers, Node};
|
pub use crate::dom::node::{LayoutNodeHelpers, Node};
|
||||||
|
pub use crate::dom::shadowroot::{LayoutShadowRootHelpers, ShadowRoot};
|
||||||
pub use crate::dom::text::Text;
|
pub use crate::dom::text::Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue