diff options
-rw-r--r-- | components/layout_thread/dom_wrapper.rs | 19 | ||||
-rw-r--r-- | components/style/dom.rs | 15 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 33 |
3 files changed, 58 insertions, 9 deletions
diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs index fdf93bf66b8..c26b3a57315 100644 --- a/components/layout_thread/dom_wrapper.rs +++ b/components/layout_thread/dom_wrapper.rs @@ -69,7 +69,7 @@ use style::computed_values::display; use style::context::SharedStyleContext; use style::data::ElementData; use style::dom::{DomChildren, LayoutIterator, NodeInfo, OpaqueNode}; -use style::dom::{TElement, TNode}; +use style::dom::{TDocument, TElement, TNode}; use style::element_state::*; use style::font_metrics::ServoMetricsProvider; use style::properties::{ComputedValues, PropertyDeclarationBlock}; @@ -139,10 +139,6 @@ impl<'ln> ServoLayoutNode<'ln> { self.node.type_id_for_layout() } } - - pub fn as_document(&self) -> Option<ServoLayoutDocument<'ln>> { - self.node.downcast().map(ServoLayoutDocument::from_layout_js) - } } impl<'ln> NodeInfo for ServoLayoutNode<'ln> { @@ -158,6 +154,7 @@ impl<'ln> NodeInfo for ServoLayoutNode<'ln> { } impl<'ln> TNode for ServoLayoutNode<'ln> { + type ConcreteDocument = ServoLayoutDocument<'ln>; type ConcreteElement = ServoLayoutElement<'ln>; fn parent_node(&self) -> Option<Self> { @@ -206,6 +203,10 @@ impl<'ln> TNode for ServoLayoutNode<'ln> { as_element(self.node) } + fn as_document(&self) -> Option<ServoLayoutDocument<'ln>> { + self.node.downcast().map(ServoLayoutDocument::from_layout_js) + } + fn can_be_fragmented(&self) -> bool { unsafe { self.node.get_flag(CAN_BE_FRAGMENTED) } } @@ -287,11 +288,15 @@ pub struct ServoLayoutDocument<'ld> { chain: PhantomData<&'ld ()>, } -impl<'ld> ServoLayoutDocument<'ld> { - fn as_node(&self) -> ServoLayoutNode<'ld> { +impl<'ld> TDocument for ServoLayoutDocument<'ld> { + type ConcreteNode = ServoLayoutNode<'ld>; + + fn as_node(&self) -> Self::ConcreteNode { ServoLayoutNode::from_layout_js(self.document.upcast()) } +} +impl<'ld> ServoLayoutDocument<'ld> { pub fn root_element(&self) -> Option<ServoLayoutElement<'ld>> { self.as_node().dom_children().flat_map(|n| n.as_element()).next() } diff --git a/components/style/dom.rs b/components/style/dom.rs index a9a8897a087..ff6ca9fa9d1 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -133,12 +133,24 @@ where } } +/// The `TDocument` trait, to represent a document node. +pub trait TDocument : Sized + Copy + Clone { + /// The concrete `TNode` type. + type ConcreteNode: TNode<ConcreteDocument = Self>; + + /// Get this document as a `TNode`. + fn as_node(&self) -> Self::ConcreteNode; +} + /// The `TNode` trait. This is the main generic trait over which the style /// system can be implemented. pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo + PartialEq { /// The concrete `TElement` type. type ConcreteElement: TElement<ConcreteNode = Self>; + /// The concrete `TDocument` type. + type ConcreteDocument: TDocument<ConcreteNode = Self>; + /// Get this node's parent node. fn parent_node(&self) -> Option<Self>; @@ -211,6 +223,9 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo + PartialEq { /// Get this node as an element, if it's one. fn as_element(&self) -> Option<Self::ConcreteElement>; + /// Get this node as a document, if it's one. + fn as_document(&self) -> Option<Self::ConcreteDocument>; + /// Whether this node can be fragmented. This is used for multicol, and only /// for Servo. fn can_be_fragmented(&self) -> bool; diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 5f7a6ca9719..02c79b76799 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -20,7 +20,7 @@ use applicable_declarations::ApplicableDeclarationBlock; use atomic_refcell::{AtomicRefCell, AtomicRef, AtomicRefMut}; use context::{QuirksMode, SharedStyleContext, PostAnimationTasks, UpdateAnimationsTasks}; use data::ElementData; -use dom::{LayoutIterator, NodeInfo, OpaqueNode, TElement, TNode}; +use dom::{LayoutIterator, NodeInfo, OpaqueNode, TElement, TDocument, TNode}; use element_state::{ElementState, DocumentState, NS_DOCUMENT_STATE_WINDOW_INACTIVE}; use error_reporting::ParseErrorReporter; use font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult}; @@ -92,6 +92,18 @@ use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use stylesheets::UrlExtraData; use stylist::Stylist; +/// A simple wrapper over `nsIDocument`. +#[derive(Clone, Copy)] +pub struct GeckoDocument<'ld>(pub &'ld structs::nsIDocument); + +impl<'ld> TDocument for GeckoDocument<'ld> { + type ConcreteNode = GeckoNode<'ld>; + + fn as_node(&self) -> Self::ConcreteNode { + GeckoNode(&self.0._base) + } +} + /// A simple wrapper over a non-null Gecko node (`nsINode`) pointer. /// /// Important: We don't currently refcount the DOM, because the wrapper lifetime @@ -125,6 +137,13 @@ impl<'ln> fmt::Debug for GeckoNode<'ln> { impl<'ln> GeckoNode<'ln> { #[inline] + fn is_document(&self) -> bool { + // This is a DOM constant that isn't going to change. + const DOCUMENT_NODE: u16 = 9; + self.node_info().mInner.mNodeType == DOCUMENT_NODE + } + + #[inline] fn from_content(content: &'ln nsIContent) -> Self { GeckoNode(&content._base) } @@ -164,7 +183,7 @@ impl<'ln> GeckoNode<'ln> { self.bool_flags() & (1u32 << flag as u32) != 0 } - fn owner_doc(&self) -> &structs::nsIDocument { + fn owner_doc(&self) -> &'ln structs::nsIDocument { debug_assert!(!self.node_info().mDocument.is_null()); unsafe { &*self.node_info().mDocument } } @@ -223,6 +242,7 @@ impl<'ln> NodeInfo for GeckoNode<'ln> { } impl<'ln> TNode for GeckoNode<'ln> { + type ConcreteDocument = GeckoDocument<'ln>; type ConcreteElement = GeckoElement<'ln>; fn parent_node(&self) -> Option<Self> { @@ -271,6 +291,15 @@ impl<'ln> TNode for GeckoNode<'ln> { } } + #[inline] + fn as_document(&self) -> Option<Self::ConcreteDocument> { + if self.is_document() { + Some(GeckoDocument(self.owner_doc())) + } else { + None + } + } + fn can_be_fragmented(&self) -> bool { // FIXME(SimonSapin): Servo uses this to implement CSS multicol / fragmentation // Maybe this isn’t useful for Gecko? |