mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
style: Refactor children handling.
Moving traversal_children away from TNode I can make TNode trivial enough, in order to share a QuerySelector implementation between Servo and Gecko.
This commit is contained in:
parent
7c2265360f
commit
a11d268468
9 changed files with 149 additions and 158 deletions
|
@ -68,7 +68,7 @@ use style::attr::AttrValue;
|
|||
use style::computed_values::display;
|
||||
use style::context::SharedStyleContext;
|
||||
use style::data::ElementData;
|
||||
use style::dom::{LayoutIterator, NodeInfo, OpaqueNode};
|
||||
use style::dom::{DomChildren, LayoutIterator, NodeInfo, OpaqueNode};
|
||||
use style::dom::{PresentationalHintsSynthesizer, TElement, TNode};
|
||||
use style::element_state::*;
|
||||
use style::font_metrics::ServoMetricsProvider;
|
||||
|
@ -159,7 +159,6 @@ impl<'ln> NodeInfo for ServoLayoutNode<'ln> {
|
|||
|
||||
impl<'ln> TNode for ServoLayoutNode<'ln> {
|
||||
type ConcreteElement = ServoLayoutElement<'ln>;
|
||||
type ConcreteChildrenIterator = ServoChildrenIterator<'ln>;
|
||||
|
||||
fn parent_node(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
|
@ -167,20 +166,34 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
|||
}
|
||||
}
|
||||
|
||||
fn children(&self) -> LayoutIterator<ServoChildrenIterator<'ln>> {
|
||||
LayoutIterator(ServoChildrenIterator {
|
||||
current: self.first_child(),
|
||||
})
|
||||
fn first_child(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
self.node.first_child_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
}
|
||||
}
|
||||
|
||||
fn last_child(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
self.node.last_child_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
}
|
||||
}
|
||||
|
||||
fn prev_sibling(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
}
|
||||
}
|
||||
|
||||
fn next_sibling(&self) -> Option<Self> {
|
||||
unsafe {
|
||||
self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
}
|
||||
}
|
||||
|
||||
fn traversal_parent(&self) -> Option<ServoLayoutElement<'ln>> {
|
||||
self.parent_element()
|
||||
}
|
||||
|
||||
fn traversal_children(&self) -> LayoutIterator<ServoChildrenIterator<'ln>> {
|
||||
self.children()
|
||||
}
|
||||
|
||||
fn opaque(&self) -> OpaqueNode {
|
||||
unsafe { self.get_jsmanaged().opaque() }
|
||||
}
|
||||
|
@ -206,19 +219,6 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ServoChildrenIterator<'a> {
|
||||
current: Option<ServoLayoutNode<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ServoChildrenIterator<'a> {
|
||||
type Item = ServoLayoutNode<'a>;
|
||||
fn next(&mut self) -> Option<ServoLayoutNode<'a>> {
|
||||
let node = self.current;
|
||||
self.current = node.and_then(|node| node.next_sibling());
|
||||
node
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
|
||||
type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'ln>;
|
||||
|
||||
|
@ -248,30 +248,6 @@ impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
|
|||
unsafe fn take_style_and_layout_data(&self) -> OpaqueStyleAndLayoutData {
|
||||
self.get_jsmanaged().take_style_and_layout_data()
|
||||
}
|
||||
|
||||
fn first_child(&self) -> Option<ServoLayoutNode<'ln>> {
|
||||
unsafe {
|
||||
self.node.first_child_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
}
|
||||
}
|
||||
|
||||
fn last_child(&self) -> Option<ServoLayoutNode<'ln>> {
|
||||
unsafe {
|
||||
self.node.last_child_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
}
|
||||
}
|
||||
|
||||
fn prev_sibling(&self) -> Option<ServoLayoutNode<'ln>> {
|
||||
unsafe {
|
||||
self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
}
|
||||
}
|
||||
|
||||
fn next_sibling(&self) -> Option<ServoLayoutNode<'ln>> {
|
||||
unsafe {
|
||||
self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ln> GetLayoutData for ServoLayoutNode<'ln> {
|
||||
|
@ -320,8 +296,8 @@ impl<'ld> ServoLayoutDocument<'ld> {
|
|||
ServoLayoutNode::from_layout_js(self.document.upcast())
|
||||
}
|
||||
|
||||
pub fn root_node(&self) -> Option<ServoLayoutNode<'ld>> {
|
||||
self.as_node().children().find(ServoLayoutNode::is_element)
|
||||
pub fn root_element(&self) -> Option<ServoLayoutElement<'ld>> {
|
||||
self.as_node().dom_children().flat_map(|n| n.as_element()).next()
|
||||
}
|
||||
|
||||
pub fn drain_pending_restyles(&self) -> Vec<(ServoLayoutElement<'ld>, PendingRestyle)> {
|
||||
|
@ -380,6 +356,7 @@ impl<'le> PresentationalHintsSynthesizer for ServoLayoutElement<'le> {
|
|||
|
||||
impl<'le> TElement for ServoLayoutElement<'le> {
|
||||
type ConcreteNode = ServoLayoutNode<'le>;
|
||||
type TraversalChildrenIterator = DomChildren<Self::ConcreteNode>;
|
||||
|
||||
type FontMetricsProvider = ServoMetricsProvider;
|
||||
|
||||
|
@ -387,6 +364,10 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
|||
ServoLayoutNode::from_layout_js(self.element.upcast())
|
||||
}
|
||||
|
||||
fn traversal_children(&self) -> LayoutIterator<Self::TraversalChildrenIterator> {
|
||||
LayoutIterator(self.as_node().dom_children())
|
||||
}
|
||||
|
||||
fn style_attribute(&self) -> Option<ArcBorrow<StyleLocked<PropertyDeclarationBlock>>> {
|
||||
unsafe {
|
||||
(*self.element.style_attribute()).as_ref().map(|x| x.borrow_arc())
|
||||
|
@ -629,7 +610,7 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
|
|||
}
|
||||
|
||||
fn first_child_element(&self) -> Option<ServoLayoutElement<'le>> {
|
||||
self.as_node().children().filter_map(|n| n.as_element()).next()
|
||||
self.as_node().dom_children().filter_map(|n| n.as_element()).next()
|
||||
}
|
||||
|
||||
fn last_child_element(&self) -> Option<ServoLayoutElement<'le>> {
|
||||
|
@ -690,7 +671,7 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
|
|||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.as_node().children().all(|node| match node.script_type_id() {
|
||||
self.as_node().dom_children().all(|node| match node.script_type_id() {
|
||||
NodeTypeId::Element(..) => false,
|
||||
NodeTypeId::CharacterData(CharacterDataTypeId::Text) => unsafe {
|
||||
node.node.downcast().unwrap().data_for_layout().is_empty()
|
||||
|
@ -850,20 +831,14 @@ impl<'ln> ServoThreadSafeLayoutNode<'ln> {
|
|||
}
|
||||
}
|
||||
|
||||
// NB: The implementation here is a bit tricky because elements implementing
|
||||
// pseudos are supposed to return false for is_element().
|
||||
impl<'ln> NodeInfo for ServoThreadSafeLayoutNode<'ln> {
|
||||
fn is_element(&self) -> bool {
|
||||
self.pseudo == PseudoElementType::Normal && self.node.is_element()
|
||||
self.node.is_element()
|
||||
}
|
||||
|
||||
fn is_text_node(&self) -> bool {
|
||||
self.node.is_text_node()
|
||||
}
|
||||
|
||||
fn needs_layout(&self) -> bool {
|
||||
self.node.is_text_node() || self.node.is_element()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
|
||||
|
|
|
@ -1067,7 +1067,7 @@ impl LayoutThread {
|
|||
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
|
||||
let element: ServoLayoutElement = match document.root_node() {
|
||||
let element = match document.root_element() {
|
||||
None => {
|
||||
// Since we cannot compute anything, give spec-required placeholders.
|
||||
debug!("layout: No root node: bailing");
|
||||
|
@ -1112,7 +1112,7 @@ impl LayoutThread {
|
|||
}
|
||||
return;
|
||||
},
|
||||
Some(x) => x.as_element().unwrap(),
|
||||
Some(x) => x,
|
||||
};
|
||||
|
||||
debug!("layout: processing reflow request for: {:?} ({}) (query={:?})",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue