mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
style: Introduce a TDocument trait.
This will be useful for querySelector optimizations.
This commit is contained in:
parent
6c796b50ec
commit
4d4fa69018
3 changed files with 58 additions and 9 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
@ -124,6 +136,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?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue