style: Introduce a TDocument trait.

This will be useful for querySelector optimizations.
This commit is contained in:
Emilio Cobos Álvarez 2017-10-26 12:48:59 +02:00
parent 6c796b50ec
commit 4d4fa69018
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
3 changed files with 58 additions and 9 deletions

View file

@ -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;

View file

@ -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 isnt useful for Gecko?