aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/gfx/display_list/mod.rs21
-rw-r--r--components/layout/construct.rs33
-rw-r--r--components/layout/css/matching.rs179
-rw-r--r--components/layout/data.rs35
-rw-r--r--components/layout/incremental.rs1
-rw-r--r--components/layout/layout_task.rs33
-rw-r--r--components/layout/lib.rs3
-rw-r--r--components/layout/parallel.rs70
-rw-r--r--components/layout/query.rs6
-rw-r--r--components/layout/traversal.rs10
-rw-r--r--components/layout/wrapper.rs490
-rw-r--r--components/script/dom/node.rs111
-rw-r--r--components/script/layout_interface.rs4
-rw-r--r--components/style/data.rs48
-rw-r--r--components/style/dom.rs274
-rw-r--r--components/style/lib.rs4
-rw-r--r--components/style/node.rs19
-rw-r--r--components/style/selector_matching.rs6
-rw-r--r--components/util/mem.rs2
-rw-r--r--tests/unit/script/size_of.rs14
20 files changed, 657 insertions, 706 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs
index bdb3e2e2d41..3a264d10147 100644
--- a/components/gfx/display_list/mod.rs
+++ b/components/gfx/display_list/mod.rs
@@ -22,7 +22,6 @@ use euclid::approxeq::ApproxEq;
use euclid::num::Zero;
use euclid::{Matrix2D, Matrix4, Point2D, Rect, SideOffsets2D, Size2D};
use gfx_traits::{color, LayerId, LayerKind, ScrollPolicy};
-use libc::uintptr_t;
use msg::constellation_msg::PipelineId;
use net_traits::image::base::Image;
use paint_context::PaintContext;
@@ -49,6 +48,8 @@ use util::opts;
use util::print_tree::PrintTree;
use util::range::Range;
+pub use style::dom::OpaqueNode;
+
// It seems cleaner to have layout code not mention Azure directly, so let's just reexport this for
// layout to use.
pub use azure::azure_hl::GradientStop;
@@ -59,24 +60,6 @@ pub mod optimizer;
/// items that involve a blur. This ensures that the display item boundaries include all the ink.
pub static BLUR_INFLATION_FACTOR: i32 = 3;
-/// An opaque handle to a node. The only safe operation that can be performed on this node is to
-/// compare it to another opaque handle or to another node.
-///
-/// Because the script task's GC does not trace layout, node data cannot be safely stored in layout
-/// data structures. Also, layout code tends to be faster when the DOM is not being accessed, for
-/// locality reasons. Using `OpaqueNode` enforces this invariant.
-#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf, Hash, Eq, Deserialize, Serialize)]
-pub struct OpaqueNode(pub uintptr_t);
-
-impl OpaqueNode {
- /// Returns the address of this node, for debugging purposes.
- #[inline]
- pub fn id(&self) -> uintptr_t {
- let OpaqueNode(pointer) = *self;
- pointer
- }
-}
-
/// LayerInfo is used to store PaintLayer metadata during DisplayList construction.
/// It is also used for tracking LayerIds when creating layers to preserve ordering when
/// layered DisplayItems should render underneath unlayered DisplayItems.
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index 49cc3567d57..6e6ea30332c 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -15,7 +15,7 @@
use block::BlockFlow;
use context::LayoutContext;
-use data::{HAS_NEWLY_CONSTRUCTED_FLOW, LayoutDataWrapper};
+use data::{HAS_NEWLY_CONSTRUCTED_FLOW, PrivateLayoutData};
use flex::FlexFlow;
use floats::FloatKind;
use flow::{MutableFlowUtils, MutableOwnedFlowUtils};
@@ -58,7 +58,7 @@ use traversal::PostorderNodeMutTraversal;
use url::Url;
use util::linked_list;
use util::opts;
-use wrapper::{PseudoElementType, TextContent, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
+use wrapper::{LayoutNode, PseudoElementType, TextContent, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
/// The results of flow construction for a DOM node.
#[derive(Clone)]
@@ -1326,10 +1326,9 @@ impl<'a, 'ln, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'ln>>
let mut style = node.style().clone();
- let mut layout_data_ref = node.mutate_layout_data();
- let layout_data = layout_data_ref.as_mut().expect("no layout data");
- let damage = layout_data.data.restyle_damage;
- match *node.construction_result_mut(layout_data) {
+ let mut data = node.mutate_layout_data().unwrap();
+ let damage = data.restyle_damage;
+ match *node.construction_result_mut(&mut *data) {
ConstructionResult::None => true,
ConstructionResult::Flow(ref mut flow, _) => {
// The node's flow is of the same type and has the same set of children and can
@@ -1580,7 +1579,7 @@ trait NodeUtils {
/// Returns true if this node doesn't render its kids and false otherwise.
fn is_replaced_content(&self) -> bool;
- fn construction_result_mut(self, layout_data: &mut LayoutDataWrapper) -> &mut ConstructionResult;
+ fn construction_result_mut(self, layout_data: &mut PrivateLayoutData) -> &mut ConstructionResult;
/// Sets the construction result of a flow.
fn set_flow_construction_result(self, result: ConstructionResult);
@@ -1611,30 +1610,26 @@ impl<'ln, ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNo
}
}
- fn construction_result_mut(self, layout_data: &mut LayoutDataWrapper) -> &mut ConstructionResult {
+ fn construction_result_mut(self, data: &mut PrivateLayoutData) -> &mut ConstructionResult {
match self.get_pseudo_element_type() {
- PseudoElementType::Before(_) => &mut layout_data.data.before_flow_construction_result,
- PseudoElementType::After (_) => &mut layout_data.data.after_flow_construction_result,
- PseudoElementType::Normal => &mut layout_data.data.flow_construction_result,
+ PseudoElementType::Before(_) => &mut data.before_flow_construction_result,
+ PseudoElementType::After (_) => &mut data.after_flow_construction_result,
+ PseudoElementType::Normal => &mut data.flow_construction_result,
}
}
#[inline(always)]
fn set_flow_construction_result(self, result: ConstructionResult) {
- let mut layout_data_ref = self.mutate_layout_data();
- let layout_data = layout_data_ref.as_mut().expect("no layout data");
-
- let dst = self.construction_result_mut(layout_data);
+ let mut layout_data = self.mutate_layout_data().unwrap();
+ let dst = self.construction_result_mut(&mut *layout_data);
*dst = result;
}
#[inline(always)]
fn swap_out_construction_result(self) -> ConstructionResult {
- let mut layout_data_ref = self.mutate_layout_data();
- let layout_data = layout_data_ref.as_mut().expect("no layout data");
-
- self.construction_result_mut(layout_data).swap_out()
+ let mut layout_data = self.mutate_layout_data().unwrap();
+ self.construction_result_mut(&mut *layout_data).swap_out()
}
}
diff --git a/components/layout/css/matching.rs b/components/layout/css/matching.rs
index ae136aea5ff..a9c07848309 100644
--- a/components/layout/css/matching.rs
+++ b/components/layout/css/matching.rs
@@ -8,7 +8,7 @@
use animation;
use context::SharedLayoutContext;
-use data::LayoutDataWrapper;
+use data::PrivateLayoutData;
use incremental::{self, RestyleDamage};
use msg::ParseErrorReporter;
use script::layout_interface::Animation;
@@ -20,18 +20,19 @@ use selectors::{Element};
use smallvec::SmallVec;
use std::borrow::ToOwned;
use std::hash::{Hash, Hasher};
+use std::mem::transmute;
use std::slice::Iter;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use string_cache::{Atom, Namespace};
-use style::node::TElementAttributes;
+use style::data::PrivateStyleData;
+use style::dom::{TElement, TNode};
use style::properties::{ComputedValues, PropertyDeclaration, cascade};
use style::selector_matching::{DeclarationBlock, Stylist};
use util::arc_ptr_eq;
use util::cache::{LRUCache, SimpleHashCache};
use util::opts;
use util::vec::ForgetfulSink;
-use wrapper::{LayoutElement, LayoutNode};
pub struct ApplicableDeclarations {
pub normal: SmallVec<[DeclarationBlock; 16]>,
@@ -160,7 +161,7 @@ pub struct StyleSharingCandidateCache {
cache: LRUCache<StyleSharingCandidate, ()>,
}
-fn create_common_style_affecting_attributes_from_element<'le, E: LayoutElement<'le>>(element: &E)
+fn create_common_style_affecting_attributes_from_element<'le, E: TElement<'le>>(element: &E)
-> CommonStyleAffectingAttributes {
let mut flags = CommonStyleAffectingAttributes::empty();
for attribute_info in &common_style_affecting_attributes() {
@@ -211,17 +212,17 @@ impl StyleSharingCandidate {
/// Attempts to create a style sharing candidate from this node. Returns
/// the style sharing candidate or `None` if this node is ineligible for
/// style sharing.
- fn new<'le, E: LayoutElement<'le>>(element: &E) -> Option<StyleSharingCandidate> {
+ fn new<'le, E: TElement<'le>>(element: &E) -> Option<StyleSharingCandidate> {
let parent_element = match element.parent_element() {
None => return None,
Some(parent_element) => parent_element,
};
let style = unsafe {
- match *element.as_node().borrow_layout_data_unchecked() {
+ match element.as_node().borrow_data_unchecked() {
None => return None,
- Some(ref layout_data_ref) => {
- match layout_data_ref.shared_data.style {
+ Some(data_ref) => {
+ match (*data_ref).style {
None => return None,
Some(ref data) => (*data).clone(),
}
@@ -229,10 +230,10 @@ impl StyleSharingCandidate {
}
};
let parent_style = unsafe {
- match *parent_element.as_node().borrow_layout_data_unchecked() {
+ match parent_element.as_node().borrow_data_unchecked() {
None => return None,
- Some(ref parent_layout_data_ref) => {
- match parent_layout_data_ref.shared_data.style {
+ Some(parent_data_ref) => {
+ match (*parent_data_ref).style {
None => return None,
Some(ref data) => (*data).clone(),
}
@@ -257,7 +258,7 @@ impl StyleSharingCandidate {
})
}
- fn can_share_style_with<'a, E: LayoutElement<'a>>(&self, element: &E) -> bool {
+ fn can_share_style_with<'a, E: TElement<'a>>(&self, element: &E) -> bool {
if *element.get_local_name() != self.local_name {
return false
}
@@ -342,7 +343,7 @@ impl StyleSharingCandidateCache {
self.cache.iter()
}
- pub fn insert_if_possible<'le, E: LayoutElement<'le>>(&mut self, element: &E) {
+ pub fn insert_if_possible<'le, E: TElement<'le>>(&mut self, element: &E) {
match StyleSharingCandidate::new(element) {
None => {}
Some(candidate) => self.cache.insert(candidate, ())
@@ -363,7 +364,7 @@ pub enum StyleSharingResult {
StyleWasShared(usize, RestyleDamage),
}
-pub trait ElementMatchMethods<'le, ConcreteLayoutElement: LayoutElement<'le>> {
+pub trait ElementMatchMethods<'le, ConcreteElement: TElement<'le>> {
fn match_element(&self,
stylist: &Stylist,
parent_bf: Option<&BloomFilter>,
@@ -376,11 +377,11 @@ pub trait ElementMatchMethods<'le, ConcreteLayoutElement: LayoutElement<'le>> {
unsafe fn share_style_if_possible(&self,
style_sharing_candidate_cache:
&mut StyleSharingCandidateCache,
- parent: Option<ConcreteLayoutElement::ConcreteLayoutNode>)
+ parent: Option<ConcreteElement::ConcreteNode>)
-> StyleSharingResult;
}
-pub trait MatchMethods<'ln, ConcreteLayoutNode: LayoutNode<'ln>> {
+pub trait MatchMethods<'ln, ConcreteNode: TNode<'ln>> {
/// Inserts and removes the matching `Descendant` selectors from a bloom
/// filter. This is used to speed up CSS selector matching to remove
/// unnecessary tree climbs for `Descendant` queries.
@@ -396,7 +397,7 @@ pub trait MatchMethods<'ln, ConcreteLayoutNode: LayoutNode<'ln>> {
unsafe fn cascade_node(&self,
layout_context: &SharedLayoutContext,
- parent: Option<ConcreteLayoutNode>,
+ parent: Option<ConcreteNode>,
applicable_declarations: &ApplicableDeclarations,
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
new_animations_sender: &Mutex<Sender<Animation>>);
@@ -420,15 +421,15 @@ trait PrivateMatchMethods {
-> bool;
}
-trait PrivateElementMatchMethods<'le, ConcreteLayoutElement: LayoutElement<'le>> {
+trait PrivateElementMatchMethods<'le, ConcreteElement: TElement<'le>> {
fn share_style_with_candidate_if_possible(&self,
- parent_node: Option<ConcreteLayoutElement::ConcreteLayoutNode>,
+ parent_node: Option<ConcreteElement::ConcreteNode>,
candidate: &StyleSharingCandidate)
-> Option<Arc<ComputedValues>>;
}
-impl<'ln, ConcreteLayoutNode> PrivateMatchMethods for ConcreteLayoutNode
- where ConcreteLayoutNode: LayoutNode<'ln> {
+impl<'ln, ConcreteNode> PrivateMatchMethods for ConcreteNode
+ where ConcreteNode: TNode<'ln> {
fn cascade_node_pseudo_element(&self,
layout_context: &SharedLayoutContext,
parent_style: Option<&Arc<ComputedValues>>,
@@ -547,11 +548,11 @@ impl<'ln, ConcreteLayoutNode> PrivateMatchMethods for ConcreteLayoutNode
}
}
-impl<'le, ConcreteLayoutElement> PrivateElementMatchMethods<'le, ConcreteLayoutElement>
- for ConcreteLayoutElement
- where ConcreteLayoutElement: LayoutElement<'le> {
+impl<'le, ConcreteElement> PrivateElementMatchMethods<'le, ConcreteElement>
+ for ConcreteElement
+ where ConcreteElement: TElement<'le> {
fn share_style_with_candidate_if_possible(&self,
- parent_node: Option<ConcreteLayoutElement::ConcreteLayoutNode>,
+ parent_node: Option<ConcreteElement::ConcreteNode>,
candidate: &StyleSharingCandidate)
-> Option<Arc<ComputedValues>> {
let parent_node = match parent_node {
@@ -559,13 +560,13 @@ impl<'le, ConcreteLayoutElement> PrivateElementMatchMethods<'le, ConcreteLayoutE
Some(_) | None => return None,
};
- let parent_layout_data: &Option<LayoutDataWrapper> = unsafe {
- &*parent_node.borrow_layout_data_unchecked()
+ let parent_data: Option<&PrivateStyleData> = unsafe {
+ parent_node.borrow_data_unchecked().map(|d| &*d)
};
- match *parent_layout_data {
- Some(ref parent_layout_data_ref) => {
+ match parent_data {
+ Some(parent_data_ref) => {
// Check parent style.
- let parent_style = parent_layout_data_ref.shared_data.style.as_ref().unwrap();
+ let parent_style = (*parent_data_ref).style.as_ref().unwrap();
if !arc_ptr_eq(parent_style, &candidate.parent_style) {
return None
}
@@ -584,9 +585,9 @@ impl<'le, ConcreteLayoutElement> PrivateElementMatchMethods<'le, ConcreteLayoutE
}
}
-impl<'le, ConcreteLayoutElement> ElementMatchMethods<'le, ConcreteLayoutElement>
- for ConcreteLayoutElement
- where ConcreteLayoutElement: LayoutElement<'le> {
+impl<'le, ConcreteElement> ElementMatchMethods<'le, ConcreteElement>
+ for ConcreteElement
+ where ConcreteElement: TElement<'le> {
fn match_element(&self,
stylist: &Stylist,
parent_bf: Option<&BloomFilter>,
@@ -619,7 +620,7 @@ impl<'le, ConcreteLayoutElement> ElementMatchMethods<'le, ConcreteLayoutElement>
unsafe fn share_style_if_possible(&self,
style_sharing_candidate_cache:
&mut StyleSharingCandidateCache,
- parent: Option<ConcreteLayoutElement::ConcreteLayoutNode>)
+ parent: Option<ConcreteElement::ConcreteNode>)
-> StyleSharingResult {
if opts::get().disable_share_style_cache {
return StyleSharingResult::CannotShare
@@ -637,9 +638,7 @@ impl<'le, ConcreteLayoutElement> ElementMatchMethods<'le, ConcreteLayoutElement>
Some(shared_style) => {
// Yay, cache hit. Share the style.
let node = self.as_node();
- let mut layout_data_ref = node.mutate_layout_data();
- let shared_data = &mut layout_data_ref.as_mut().unwrap().shared_data;
- let style = &mut shared_data.style;
+ let style = &mut node.mutate_data().unwrap().style;
let damage = incremental::compute_damage(style, &*shared_style);
*style = Some(shared_style);
return StyleSharingResult::StyleWasShared(i, damage)
@@ -652,9 +651,9 @@ impl<'le, ConcreteLayoutElement> ElementMatchMethods<'le, ConcreteLayoutElement>
}
}
-impl<'ln, ConcreteLayoutNode> MatchMethods<'ln, ConcreteLayoutNode>
- for ConcreteLayoutNode
- where ConcreteLayoutNode: LayoutNode<'ln> {
+impl<'ln, ConcreteNode> MatchMethods<'ln, ConcreteNode>
+ for ConcreteNode
+ where ConcreteNode: TNode<'ln> {
// The below two functions are copy+paste because I can't figure out how to
// write a function which takes a generic function. I don't think it can
// be done.
@@ -696,7 +695,7 @@ impl<'ln, ConcreteLayoutNode> MatchMethods<'ln, ConcreteLayoutNode>
unsafe fn cascade_node(&self,
layout_context: &SharedLayoutContext,
- parent: Option<ConcreteLayoutNode>,
+ parent: Option<ConcreteNode>,
applicable_declarations: &ApplicableDeclarations,
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
new_animations_sender: &Mutex<Sender<Animation>>) {
@@ -708,63 +707,57 @@ impl<'ln, ConcreteLayoutNode> MatchMethods<'ln, ConcreteLayoutNode>
let parent_style = match parent {
None => None,
Some(parent_node) => {
- let parent_layout_data_ref = parent_node.borrow_layout_data_unchecked();
- let parent_layout_data = (&*parent_layout_data_ref).as_ref()
- .expect("no parent data!?");
- let parent_style = parent_layout_data.shared_data
- .style
- .as_ref()
- .expect("parent hasn't been styled yet!");
+ let parent_style = (*parent_node.borrow_data_unchecked().unwrap()).style.as_ref().unwrap();
Some(parent_style)
}
};
- let mut layout_data_ref = self.mutate_layout_data();
- match *layout_data_ref {
- None => panic!("no layout data"),
- Some(ref mut layout_data) => {
- if self.is_text_node() {
- // Text nodes get a copy of the parent style. This ensures
- // that during fragment construction any non-inherited
- // CSS properties (such as vertical-align) are correctly
- // set on the fragment(s).
- let cloned_parent_style = parent_style.unwrap().clone();
- layout_data.shared_data.style = Some(cloned_parent_style);
- } else {
- let mut damage = self.cascade_node_pseudo_element(
- layout_context,
- parent_style,
- &applicable_declarations.normal,
- &mut layout_data.shared_data.style,
- applicable_declarations_cache,
- new_animations_sender,
- applicable_declarations.normal_shareable,
- true);
- if !applicable_declarations.before.is_empty() {
- damage = damage | self.cascade_node_pseudo_element(
- layout_context,
- Some(layout_data.shared_data.style.as_ref().unwrap()),
- &*applicable_declarations.before,
- &mut layout_data.data.before_style,
- applicable_declarations_cache,
- new_animations_sender,
- false,
- false);
- }
- if !applicable_declarations.after.is_empty() {
- damage = damage | self.cascade_node_pseudo_element(
- layout_context,
- Some(layout_data.shared_data.style.as_ref().unwrap()),
- &*applicable_declarations.after,
- &mut layout_data.data.after_style,
- applicable_declarations_cache,
- new_animations_sender,
- false,
- false);
- }
- layout_data.data.restyle_damage = damage;
- }
+ let mut data_ref = self.mutate_data().unwrap();
+ let mut data = &mut *data_ref;
+ if self.is_text_node() {
+ // Text nodes get a copy of the parent style. This ensures
+ // that during fragment construction any non-inherited
+ // CSS properties (such as vertical-align) are correctly
+ // set on the fragment(s).
+ let cloned_parent_style = parent_style.unwrap().clone();
+ data.style = Some(cloned_parent_style);
+ } else {
+ let mut damage = self.cascade_node_pseudo_element(
+ layout_context,
+ parent_style,
+ &applicable_declarations.normal,
+ &mut data.style,
+ applicable_declarations_cache,
+ new_animations_sender,
+ applicable_declarations.normal_shareable,
+ true);
+ if !applicable_declarations.before.is_empty() {
+ damage = damage | self.cascade_node_pseudo_element(
+ layout_context,
+ Some(data.style.as_ref().unwrap()),
+ &*applicable_declarations.before,
+ &mut data.before_style,
+ applicable_declarations_cache,
+ new_animations_sender,
+ false,
+ false);
}
+ if !applicable_declarations.after.is_empty() {
+ damage = damage | self.cascade_node_pseudo_element(
+ layout_context,
+ Some(data.style.as_ref().unwrap()),
+ &*applicable_declarations.after,
+ &mut data.after_style,
+ applicable_declarations_cache,
+ new_animations_sender,
+ false,
+ false);
+ }
+
+ // FIXME(bholley): This is the only dependency in this file on non-style
+ // stuff.
+ let layout_data: &mut PrivateLayoutData = transmute(data);
+ layout_data.restyle_damage = damage;
}
}
}
diff --git a/components/layout/data.rs b/components/layout/data.rs
index 5534773834a..459743cd689 100644
--- a/components/layout/data.rs
+++ b/components/layout/data.rs
@@ -4,18 +4,15 @@
use construct::ConstructionResult;
use incremental::RestyleDamage;
-use parallel::DomParallelInfo;
-use script::dom::node::SharedLayoutData;
-use std::sync::Arc;
-use style::properties::ComputedValues;
+use style::data::PrivateStyleData;
/// Data that layout associates with a node.
pub struct PrivateLayoutData {
- /// The results of CSS styling for this node's `before` pseudo-element, if any.
- pub before_style: Option<Arc<ComputedValues>>,
-
- /// The results of CSS styling for this node's `after` pseudo-element, if any.
- pub after_style: Option<Arc<ComputedValues>>,
+ /// Data that the style system associates with a node. When the
+ /// style system is being used standalone, this is all that hangs
+ /// off the node. This must be first to permit the various
+ /// transmuations between PrivateStyleData PrivateLayoutData.
+ pub style_data: PrivateStyleData,
/// Description of how to account for recent style changes.
pub restyle_damage: RestyleDamage,
@@ -28,9 +25,6 @@ pub struct PrivateLayoutData {
pub after_flow_construction_result: ConstructionResult,
- /// Information needed during parallel traversals.
- pub parallel: DomParallelInfo,
-
/// Various flags.
pub flags: LayoutDataFlags,
}
@@ -39,13 +33,11 @@ impl PrivateLayoutData {
/// Creates new layout data.
pub fn new() -> PrivateLayoutData {
PrivateLayoutData {
- before_style: None,
- after_style: None,
+ style_data: PrivateStyleData::new(),
restyle_damage: RestyleDamage::empty(),
flow_construction_result: ConstructionResult::None,
before_flow_construction_result: ConstructionResult::None,
after_flow_construction_result: ConstructionResult::None,
- parallel: DomParallelInfo::new(),
flags: LayoutDataFlags::empty(),
}
}
@@ -57,16 +49,3 @@ bitflags! {
const HAS_NEWLY_CONSTRUCTED_FLOW = 0x01
}
}
-
-pub struct LayoutDataWrapper {
- pub shared_data: SharedLayoutData,
- pub data: Box<PrivateLayoutData>,
-}
-
-#[allow(dead_code, unsafe_code)]
-fn static_assertion(x: Option<LayoutDataWrapper>) {
- unsafe {
- let _: Option<::script::dom::node::LayoutData> =
- ::std::intrinsics::transmute(x);
- }
-}
diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs
index de89c187120..d69610daa12 100644
--- a/components/layout/incremental.rs
+++ b/components/layout/incremental.rs
@@ -47,6 +47,7 @@ bitflags! {
}
}
+
impl RestyleDamage {
/// Supposing a flow has the given `position` property and this damage, returns the damage that
/// we should add to the *parent* of this flow.
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs
index 3063690778d..7cec9ed2948 100644
--- a/components/layout/layout_task.rs
+++ b/components/layout/layout_task.rs
@@ -13,7 +13,6 @@ use azure::azure::AzColor;
use canvas_traits::CanvasMsg;
use construct::ConstructionResult;
use context::{SharedLayoutContext, StylistWrapper, heap_size_of_local_context};
-use data::LayoutDataWrapper;
use display_list_builder::ToGfxColor;
use euclid::Matrix4;
use euclid::point::Point2D;
@@ -45,7 +44,7 @@ use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
use profile_traits::time::{self, TimerMetadata, profile};
use query::{LayoutRPCImpl, process_content_box_request, process_content_boxes_request};
use query::{process_node_geometry_request, process_offset_parent_query, process_resolved_style_request};
-use script::dom::node::LayoutData;
+use script::dom::node::OpaqueStyleAndLayoutData;
use script::layout_interface::Animation;
use script::layout_interface::{LayoutRPC, OffsetParentResponse};
use script::layout_interface::{Msg, NewLayoutTaskInfo, Reflow, ReflowGoal, ReflowQueryType};
@@ -65,6 +64,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex, MutexGuard, RwLock};
use style::computed_values::{filter, mix_blend_mode};
+use style::dom::{TDocument, TElement, TNode};
use style::media_queries::{Device, MediaType};
use style::selector_matching::{Stylist, USER_OR_USER_AGENT_STYLESHEETS};
use style::stylesheets::{CSSRuleIteratorExt, Stylesheet};
@@ -77,8 +77,7 @@ use util::opts;
use util::task;
use util::task_state;
use util::workqueue::WorkQueue;
-use wrapper::{LayoutDocument, LayoutElement, LayoutNode};
-use wrapper::{ServoLayoutNode, ThreadSafeLayoutNode};
+use wrapper::{LayoutNode, NonOpaqueStyleAndLayoutData, ServoLayoutNode, ThreadSafeLayoutNode};
/// The number of screens of data we're allowed to generate display lists for in each direction.
pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
@@ -607,9 +606,9 @@ impl LayoutTask {
Msg::SetVisibleRects(new_visible_rects) => {
self.set_visible_rects(new_visible_rects, possibly_locked_rw_data);
}
- Msg::ReapLayoutData(dead_layout_data) => {
+ Msg::ReapStyleAndLayoutData(dead_data) => {
unsafe {
- self.handle_reap_layout_data(dead_layout_data)
+ self.handle_reap_style_and_layout_data(dead_data)
}
}
Msg::CollectReports(reports_chan) => {
@@ -707,9 +706,9 @@ impl LayoutTask {
response_chan.send(()).unwrap();
loop {
match self.port.recv().unwrap() {
- Msg::ReapLayoutData(dead_layout_data) => {
+ Msg::ReapStyleAndLayoutData(dead_data) => {
unsafe {
- self.handle_reap_layout_data(dead_layout_data)
+ self.handle_reap_style_and_layout_data(dead_data)
}
}
Msg::ExitNow => {
@@ -765,14 +764,11 @@ impl LayoutTask {
}
fn try_get_layout_root<'ln, N: LayoutNode<'ln>>(&self, node: N) -> Option<FlowRef> {
- let mut layout_data_ref = node.mutate_layout_data();
- let layout_data =
- match layout_data_ref.as_mut() {
- None => return None,
- Some(layout_data) => layout_data,
- };
-
- let result = layout_data.data.flow_construction_result.swap_out();
+ let mut data = match node.mutate_layout_data() {
+ Some(x) => x,
+ None => return None,
+ };
+ let result = data.flow_construction_result.swap_out();
let mut flow = match result {
ConstructionResult::Flow(mut flow, abs_descendants) => {
@@ -1312,8 +1308,9 @@ impl LayoutTask {
/// Handles a message to destroy layout data. Layout data must be destroyed on *this* task
/// because the struct type is transmuted to a different type on the script side.
- unsafe fn handle_reap_layout_data(&self, layout_data: LayoutData) {
- let _: LayoutDataWrapper = transmute(layout_data);
+ unsafe fn handle_reap_style_and_layout_data(&self, data: OpaqueStyleAndLayoutData) {
+ let non_opaque: NonOpaqueStyleAndLayoutData = transmute(data.ptr);
+ let _ = Box::from_raw(non_opaque);
}
/// Returns profiling information which is passed to the time profiler.
diff --git a/components/layout/lib.rs b/components/layout/lib.rs
index fb28d47adac..e1d2f77f32b 100644
--- a/components/layout/lib.rs
+++ b/components/layout/lib.rs
@@ -2,11 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#![feature(as_unsafe_cell)]
#![feature(box_syntax)]
#![feature(cell_extras)]
#![feature(custom_derive)]
#![feature(hashmap_hasher)]
#![feature(mpsc_select)]
+#![feature(nonzero)]
#![feature(plugin)]
#![feature(raw)]
#![feature(step_by)]
@@ -22,6 +24,7 @@ extern crate azure;
#[macro_use]
extern crate bitflags;
extern crate canvas_traits;
+extern crate core;
extern crate cssparser;
extern crate encoding;
extern crate euclid;
diff --git a/components/layout/parallel.rs b/components/layout/parallel.rs
index 4023ed9fbf3..35c9b7f7955 100644
--- a/components/layout/parallel.rs
+++ b/components/layout/parallel.rs
@@ -15,6 +15,7 @@ use gfx::display_list::OpaqueNode;
use profile_traits::time::{self, TimerMetadata, profile};
use std::mem;
use std::sync::atomic::{AtomicIsize, Ordering};
+use style::dom::UnsafeNode;
use traversal::PostorderNodeMutTraversal;
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes, BubbleISizes};
use traversal::{BuildDisplayList, ComputeAbsolutePositions};
@@ -22,17 +23,17 @@ use traversal::{ConstructFlows, RecalcStyleForNode};
use traversal::{PostorderDomTraversal, PreorderDomTraversal};
use util::opts;
use util::workqueue::{WorkQueue, WorkUnit, WorkerProxy};
-use wrapper::{LayoutNode, UnsafeLayoutNode};
+use wrapper::LayoutNode;
const CHUNK_SIZE: usize = 64;
pub struct WorkQueueData(usize, usize);
#[allow(dead_code)]
-fn static_assertion(node: UnsafeLayoutNode) {
+fn static_assertion(node: UnsafeNode) {
unsafe {
let _: UnsafeFlow = ::std::intrinsics::transmute(node);
- let _: UnsafeLayoutNodeList = ::std::intrinsics::transmute(node);
+ let _: UnsafeNodeList = ::std::intrinsics::transmute(node);
}
}
@@ -55,31 +56,17 @@ pub fn borrowed_flow_to_unsafe_flow(flow: &Flow) -> UnsafeFlow {
}
}
-/// Information that we need stored in each DOM node.
-pub struct DomParallelInfo {
- /// The number of children that still need work done.
- pub children_count: AtomicIsize,
-}
-
-impl DomParallelInfo {
- pub fn new() -> DomParallelInfo {
- DomParallelInfo {
- children_count: AtomicIsize::new(0),
- }
- }
-}
-
-pub type UnsafeLayoutNodeList = (Box<Vec<UnsafeLayoutNode>>, OpaqueNode);
+pub type UnsafeNodeList = (Box<Vec<UnsafeNode>>, OpaqueNode);
-pub type UnsafeFlowList = (Box<Vec<UnsafeLayoutNode>>, usize);
+pub type UnsafeFlowList = (Box<Vec<UnsafeNode>>, usize);
pub type ChunkedDomTraversalFunction =
- extern "Rust" fn(UnsafeLayoutNodeList,
- &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>);
+ extern "Rust" fn(UnsafeNodeList,
+ &mut WorkerProxy<SharedLayoutContext, UnsafeNodeList>);
pub type DomTraversalFunction =
- extern "Rust" fn(OpaqueNode, UnsafeLayoutNode,
- &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>);
+ extern "Rust" fn(OpaqueNode, UnsafeNode,
+ &mut WorkerProxy<SharedLayoutContext, UnsafeNodeList>);
pub type ChunkedFlowTraversalFunction =
extern "Rust" fn(UnsafeFlowList, &mut WorkerProxy<SharedLayoutContext, UnsafeFlowList>);
@@ -91,14 +78,14 @@ pub trait ParallelPreorderDomTraversal<'ln, ConcreteLayoutNode>
: PreorderDomTraversal<'ln, ConcreteLayoutNode>
where ConcreteLayoutNode: LayoutNode<'ln> {
fn run_parallel(&self,
- nodes: UnsafeLayoutNodeList,
- proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>);
+ nodes: UnsafeNodeList,
+ proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeNodeList>);
#[inline(always)]
fn run_parallel_helper(
&self,
- unsafe_nodes: UnsafeLayoutNodeList,
- proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>,
+ unsafe_nodes: UnsafeNodeList,
+ proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeNodeList>,
top_down_func: ChunkedDomTraversalFunction,
bottom_up_func: DomTraversalFunction) {
let mut discovered_child_nodes = Vec::new();
@@ -113,10 +100,9 @@ pub trait ParallelPreorderDomTraversal<'ln, ConcreteLayoutNode>
// Reset the count of children.
{
- let mut layout_data_ref = node.mutate_layout_data();
- let layout_data = layout_data_ref.as_mut().expect("no layout data");
- layout_data.data.parallel.children_count.store(child_count as isize,
- Ordering::Relaxed);
+ let data = node.mutate_data().unwrap();
+ data.parallel.children_count.store(child_count as isize,
+ Ordering::Relaxed);
}
// Possibly enqueue the children.
@@ -156,7 +142,7 @@ trait ParallelPostorderDomTraversal<'ln, ConcreteLayoutNode>
///
/// The only communication between siblings is that they both
/// fetch-and-subtract the parent's children count.
- fn run_parallel(&self, unsafe_node: UnsafeLayoutNode) {
+ fn run_parallel(&self, unsafe_node: UnsafeNode) {
// Get a real layout node.
let mut node = unsafe { ConcreteLayoutNode::from_unsafe(&unsafe_node) };
loop {
@@ -168,13 +154,11 @@ trait ParallelPostorderDomTraversal<'ln, ConcreteLayoutNode>
Some(parent) => parent,
};
- let parent_layout_data = unsafe {
- &*parent.borrow_layout_data_unchecked()
+ let parent_data = unsafe {
+ &*parent.borrow_data_unchecked().unwrap()
};
- let parent_layout_data = parent_layout_data.as_ref().expect("no layout data");
- if parent_layout_data
- .data
+ if parent_data
.parallel
.children_count
.fetch_sub(1, Ordering::Relaxed) != 1 {
@@ -360,8 +344,8 @@ impl<'a, 'ln, ConcreteLayoutNode> ParallelPreorderDomTraversal<'ln, ConcreteLayo
for RecalcStyleForNode<'a>
where ConcreteLayoutNode: LayoutNode<'ln> {
fn run_parallel(&self,
- unsafe_nodes: UnsafeLayoutNodeList,
- proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>) {
+ unsafe_nodes: UnsafeNodeList,
+ proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeNodeList>) {
// Not exactly sure why we need UFCS here, but we seem to.
<RecalcStyleForNode<'a> as ParallelPreorderDomTraversal<'ln, ConcreteLayoutNode>>
::run_parallel_helper(self, unsafe_nodes, proxy,
@@ -370,8 +354,8 @@ impl<'a, 'ln, ConcreteLayoutNode> ParallelPreorderDomTraversal<'ln, ConcreteLayo
}
}
-fn recalc_style<'ln, ConcreteLayoutNode>(unsafe_nodes: UnsafeLayoutNodeList,
- proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>)
+fn recalc_style<'ln, ConcreteLayoutNode>(unsafe_nodes: UnsafeNodeList,
+ proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeNodeList>)
where ConcreteLayoutNode: LayoutNode<'ln> {
let shared_layout_context = proxy.user_data();
let layout_context = LayoutContext::new(shared_layout_context);
@@ -388,8 +372,8 @@ fn recalc_style<'ln, ConcreteLayoutNode>(unsafe_nodes: UnsafeLayoutNodeList,
fn construct_flows<'ln, ConcreteLayoutNode: LayoutNode<'ln>>(
root: OpaqueNode,
- unsafe_node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>) {
+ unsafe_node: UnsafeNode,
+ proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeNodeList>) {
let shared_layout_context = proxy.user_data();
let layout_context = LayoutContext::new(shared_layout_context);
let construct_flows_traversal = ConstructFlows {
diff --git a/components/layout/query.rs b/components/layout/query.rs
index 83f758b0f50..327bb3aa046 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -479,9 +479,9 @@ pub fn process_resolved_style_request<'ln, N: LayoutNode<'ln>>(
layout_root: &mut FlowRef,
requested_node: N,
property: &Atom) -> Option<String> {
- let layout_data = layout_node.borrow_layout_data();
- let position = layout_data.as_ref().map(|layout_data| {
- match layout_data.data.flow_construction_result {
+ let maybe_data = layout_node.borrow_layout_data();
+ let position = maybe_data.map(|data| {
+ match (*data).flow_construction_result {
ConstructionResult::Flow(ref flow_ref, _) =>
flow::base(flow_ref.deref()).stacking_relative_position,
// TODO(dzbarsky) search parents until we find node with a flow ref.
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs
index cf3be1b9d94..007b3a3626d 100644
--- a/components/layout/traversal.rs
+++ b/components/layout/traversal.rs
@@ -15,10 +15,10 @@ use script::layout_interface::ReflowGoal;
use selectors::bloom::BloomFilter;
use std::cell::RefCell;
use std::mem;
+use style::dom::UnsafeNode;
use util::opts;
use util::tid::tid;
-use wrapper::{LayoutNode, UnsafeLayoutNode};
-use wrapper::{ThreadSafeLayoutNode};
+use wrapper::{LayoutNode, ThreadSafeLayoutNode};
/// Every time we do another layout, the old bloom filters are invalid. This is
/// detected by ticking a generation number every layout.
@@ -45,7 +45,7 @@ type Generation = u32;
/// will no longer be the for the parent of the node we're currently on. When
/// this happens, the task local bloom filter will be thrown away and rebuilt.
thread_local!(
- static STYLE_BLOOM: RefCell<Option<(Box<BloomFilter>, UnsafeLayoutNode, Generation)>> = RefCell::new(None));
+ static STYLE_BLOOM: RefCell<Option<(Box<BloomFilter>, UnsafeNode, Generation)>> = RefCell::new(None));
/// Returns the task local bloom filter.
///
@@ -88,7 +88,7 @@ fn take_task_local_bloom_filter<'ln, N>(parent_node: Option<N>,
}
fn put_task_local_bloom_filter(bf: Box<BloomFilter>,
- unsafe_node: &UnsafeLayoutNode,
+ unsafe_node: &UnsafeNode,
layout_context: &LayoutContext) {
STYLE_BLOOM.with(move |style_bloom| {
assert!(style_bloom.borrow().is_none(),
@@ -153,7 +153,7 @@ impl<'a, 'ln, ConcreteLayoutNode> PreorderDomTraversal<'ln, ConcreteLayoutNode>
//
// FIXME(pcwalton): Stop allocating here. Ideally this should just be done by the HTML
// parser.
- node.initialize_layout_data();
+ node.initialize_data();
// Get the parent node.
let parent_opt = node.layout_parent_node(self.root);
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs
index ddb899b9db5..c2092a81e21 100644
--- a/components/layout/wrapper.rs
+++ b/components/layout/wrapper.rs
@@ -30,7 +30,8 @@
#![allow(unsafe_code)]
-use data::{LayoutDataFlags, LayoutDataWrapper, PrivateLayoutData};
+use core::nonzero::NonZero;
+use data::{LayoutDataFlags, PrivateLayoutData};
use gfx::display_list::OpaqueNode;
use gfx::text::glyph::CharIndex;
use incremental::RestyleDamage;
@@ -49,7 +50,7 @@ use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
use script::dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers};
use script::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers};
use script::dom::node::{HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY};
-use script::dom::node::{LayoutNodeHelpers, Node, SharedLayoutData};
+use script::dom::node::{LayoutNodeHelpers, Node, OpaqueStyleAndLayoutData};
use script::dom::text::Text;
use script::layout_interface::TrustedNodeAddress;
use selectors::matching::DeclarationBlock;
@@ -57,204 +58,38 @@ use selectors::parser::{AttrSelector, NamespaceConstraint};
use selectors::states::*;
use smallvec::VecLike;
use std::borrow::ToOwned;
-use std::cell::{Ref, RefMut};
+use std::cell::{Ref, RefCell, RefMut};
use std::marker::PhantomData;
-use std::mem;
+use std::mem::{transmute, transmute_copy};
use std::sync::Arc;
use string_cache::{Atom, Namespace};
use style::computed_values::content::ContentItem;
use style::computed_values::{content, display};
-use style::node::TElementAttributes;
+use style::data::PrivateStyleData;
+use style::dom::{TDocument, TElement, TNode, UnsafeNode};
use style::properties::ComputedValues;
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
-use style::restyle_hints::{ElementSnapshot, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
+use style::restyle_hints::ElementSnapshot;
use url::Url;
use util::str::{is_whitespace, search_index};
-/// Opaque type stored in type-unsafe work queues for parallel layout.
-/// Must be transmutable to and from LayoutNode.
-pub type UnsafeLayoutNode = (usize, usize);
+pub type NonOpaqueStyleAndLayoutData = *mut RefCell<PrivateLayoutData>;
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
/// only ever see these and must never see instances of `LayoutJS`.
-pub trait LayoutNode<'ln> : Sized + Copy + Clone {
+pub trait LayoutNode<'ln> : TNode<'ln> {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'ln>;
- type ConcreteLayoutElement: LayoutElement<'ln, ConcreteLayoutNode = Self,
- ConcreteLayoutDocument = Self::ConcreteLayoutDocument>;
- type ConcreteLayoutDocument: LayoutDocument<'ln, ConcreteLayoutNode = Self,
- ConcreteLayoutElement = Self::ConcreteLayoutElement>;
-
- fn to_unsafe(&self) -> UnsafeLayoutNode;
- unsafe fn from_unsafe(&UnsafeLayoutNode) -> Self;
-
fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode;
/// Returns the type ID of this node.
fn type_id(&self) -> NodeTypeId;
- /// Returns whether this is a text node. It turns out that this is all the style system cares
- /// about, and thus obviates the need to compute the full type id, which would be expensive in
- /// Gecko.
- fn is_text_node(&self) -> bool;
-
- fn is_element(&self) -> bool;
-
- fn dump(self);
-
- fn traverse_preorder(self) -> LayoutTreeIterator<'ln, Self> {
- LayoutTreeIterator::new(self)
- }
-
- /// Returns an iterator over this node's children.
- fn children(self) -> LayoutNodeChildrenIterator<'ln, Self> {
- LayoutNodeChildrenIterator {
- current: self.first_child(),
- phantom: PhantomData,
- }
- }
-
- fn rev_children(self) -> LayoutNodeReverseChildrenIterator<'ln, Self> {
- LayoutNodeReverseChildrenIterator {
- current: self.last_child(),
- phantom: PhantomData,
- }
- }
-
- /// Converts self into an `OpaqueNode`.
- fn opaque(&self) -> OpaqueNode;
-
- /// Resets layout data and styles for the node.
- ///
- /// FIXME(pcwalton): Do this as part of fragment building instead of in a traversal.
- fn initialize_layout_data(self);
-
- /// While doing a reflow, the node at the root has no parent, as far as we're
- /// concerned. This method returns `None` at the reflow root.
- fn layout_parent_node(self, reflow_root: OpaqueNode) -> Option<Self>;
-
- fn debug_id(self) -> usize;
-
- fn as_element(&self) -> Option<Self::ConcreteLayoutElement>;
-
- fn as_document(&self) -> Option<Self::ConcreteLayoutDocument>;
-
- fn children_count(&self) -> u32;
-
- fn has_changed(&self) -> bool;
-
- unsafe fn set_changed(&self, value: bool);
-
- fn is_dirty(&self) -> bool;
-
- unsafe fn set_dirty(&self, value: bool);
-
- fn has_dirty_descendants(&self) -> bool;
-
- unsafe fn set_dirty_descendants(&self, value: bool);
-
- fn dirty_self(&self) {
- unsafe {
- self.set_dirty(true);
- self.set_dirty_descendants(true);
- }
- }
-
- fn dirty_descendants(&self) {
- for ref child in self.children() {
- child.dirty_self();
- child.dirty_descendants();
- }
- }
-
- /// Borrows the layout data without checks.
- #[inline(always)]
- unsafe fn borrow_layout_data_unchecked(&self) -> *const Option<LayoutDataWrapper>;
-
- /// Borrows the layout data immutably. Fails on a conflicting borrow.
- #[inline(always)]
- fn borrow_layout_data(&self) -> Ref<Option<LayoutDataWrapper>>;
-
- /// Borrows the layout data mutably. Fails on a conflicting borrow.
- #[inline(always)]
- fn mutate_layout_data(&self) -> RefMut<Option<LayoutDataWrapper>>;
-
- fn parent_node(&self) -> Option<Self>;
-
- fn first_child(&self) -> Option<Self>;
-
- fn last_child(&self) -> Option<Self>;
-
- fn prev_sibling(&self) -> Option<Self>;
-
- fn next_sibling(&self) -> Option<Self>;
-}
-
-pub trait LayoutDocument<'ld> : Sized + Copy + Clone {
- type ConcreteLayoutNode: LayoutNode<'ld, ConcreteLayoutElement = Self::ConcreteLayoutElement,
- ConcreteLayoutDocument = Self>;
- type ConcreteLayoutElement: LayoutElement<'ld, ConcreteLayoutNode = Self::ConcreteLayoutNode,
- ConcreteLayoutDocument = Self>;
-
- fn as_node(&self) -> Self::ConcreteLayoutNode;
-
- fn root_node(&self) -> Option<Self::ConcreteLayoutNode>;
-
- fn drain_modified_elements(&self) -> Vec<(Self::ConcreteLayoutElement, ElementSnapshot)>;
-}
-
-pub trait LayoutElement<'le> : Sized + Copy + Clone + ::selectors::Element + TElementAttributes {
- type ConcreteLayoutNode: LayoutNode<'le, ConcreteLayoutElement = Self,
- ConcreteLayoutDocument = Self::ConcreteLayoutDocument>;
- type ConcreteLayoutDocument: LayoutDocument<'le, ConcreteLayoutNode = Self::ConcreteLayoutNode,
- ConcreteLayoutElement = Self>;
-
- fn as_node(&self) -> Self::ConcreteLayoutNode;
-
- fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock>;
-
- fn get_state(&self) -> ElementState;
-
- /// Properly marks nodes as dirty in response to restyle hints.
- fn note_restyle_hint(&self, mut hint: RestyleHint) {
- // Bail early if there's no restyling to do.
- if hint.is_empty() {
- return;
- }
-
- // If the restyle hint is non-empty, we need to restyle either this element
- // or one of its siblings. Mark our ancestor chain as having dirty descendants.
- let node = self.as_node();
- let mut curr = node;
- while let Some(parent) = curr.parent_node() {
- if parent.has_dirty_descendants() { break }
- unsafe { parent.set_dirty_descendants(true); }
- curr = parent;
- }
-
- // Process hints.
- if hint.contains(RESTYLE_SELF) {
- node.dirty_self();
-
- // FIXME(bholley, #8438): We currently need to RESTYLE_DESCENDANTS in the
- // RESTYLE_SELF case in order to make sure "inherit" style structs propagate
- // properly. See the explanation in the github issue.
- hint.insert(RESTYLE_DESCENDANTS);
- }
- if hint.contains(RESTYLE_DESCENDANTS) {
- unsafe { node.set_dirty_descendants(true); }
- node.dirty_descendants();
- }
- if hint.contains(RESTYLE_LATER_SIBLINGS) {
- let mut next = ::selectors::Element::next_sibling_element(self);
- while let Some(sib) = next {
- let sib_node = sib.as_node();
- sib_node.dirty_self();
- sib_node.dirty_descendants();
- next = ::selectors::Element::next_sibling_element(&sib);
- }
- }
- }
+ /// Similar to borrow_data*, but returns the full PrivateLayoutData rather
+ /// than only the PrivateStyleData.
+ unsafe fn borrow_layout_data_unchecked(&self) -> Option<*const PrivateLayoutData>;
+ fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>>;
+ fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>>;
}
#[derive(Copy, Clone)]
@@ -294,31 +129,20 @@ impl<'ln> ServoLayoutNode<'ln> {
}
}
-impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
- type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'ln>;
- type ConcreteLayoutElement = ServoLayoutElement<'ln>;
- type ConcreteLayoutDocument = ServoLayoutDocument<'ln>;
+impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> {
+ type ConcreteElement = ServoLayoutElement<'ln>;
+ type ConcreteDocument = ServoLayoutDocument<'ln>;
- fn to_unsafe(&self) -> UnsafeLayoutNode {
+ fn to_unsafe(&self) -> UnsafeNode {
unsafe {
- let ptr: usize = mem::transmute_copy(self);
+ let ptr: usize = transmute_copy(self);
(ptr, 0)
}
}
- unsafe fn from_unsafe(n: &UnsafeLayoutNode) -> Self {
+ unsafe fn from_unsafe(n: &UnsafeNode) -> Self {
let (node, _) = *n;
- mem::transmute(node)
- }
-
- fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode {
- ServoThreadSafeLayoutNode::new(self)
- }
-
- fn type_id(&self) -> NodeTypeId {
- unsafe {
- self.node.type_id_for_layout()
- }
+ transmute(node)
}
fn is_text_node(&self) -> bool {
@@ -339,16 +163,17 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
OpaqueNodeMethods::from_jsmanaged(unsafe { self.get_jsmanaged() })
}
- fn initialize_layout_data(self) {
- let mut layout_data_ref = self.mutate_layout_data();
- match *layout_data_ref {
- None => {
- *layout_data_ref = Some(LayoutDataWrapper {
- shared_data: SharedLayoutData { style: None },
- data: box PrivateLayoutData::new(),
- });
+ fn initialize_data(self) {
+ let has_data = unsafe { self.borrow_data_unchecked().is_some() };
+ if !has_data {
+ let ptr: NonOpaqueStyleAndLayoutData =
+ Box::into_raw(box RefCell::new(PrivateLayoutData::new()));
+ let opaque = OpaqueStyleAndLayoutData {
+ ptr: unsafe { NonZero::new(ptr as *mut ()) }
+ };
+ unsafe {
+ self.node.init_style_and_layout_data(opaque);
}
- Some(_) => {}
}
}
@@ -400,20 +225,16 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
self.node.set_flag(HAS_DIRTY_DESCENDANTS, value)
}
- unsafe fn borrow_layout_data_unchecked(&self) -> *const Option<LayoutDataWrapper> {
- mem::transmute(self.get_jsmanaged().layout_data_unchecked())
+ unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData> {
+ self.borrow_layout_data_unchecked().map(|d| &(*d).style_data as *const PrivateStyleData)
}
- fn borrow_layout_data(&self) -> Ref<Option<LayoutDataWrapper>> {
- unsafe {
- mem::transmute(self.get_jsmanaged().layout_data())
- }
+ fn borrow_data(&self) -> Option<Ref<PrivateStyleData>> {
+ unsafe { self.borrow_layout_data().map(|d| transmute(d)) }
}
- fn mutate_layout_data(&self) -> RefMut<Option<LayoutDataWrapper>> {
- unsafe {
- mem::transmute(self.get_jsmanaged().layout_data_mut())
- }
+ fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>> {
+ unsafe { self.mutate_layout_data().map(|d| transmute(d)) }
}
fn parent_node(&self) -> Option<ServoLayoutNode<'ln>> {
@@ -447,6 +268,46 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
}
}
+impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
+ type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'ln>;
+
+ fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode {
+ ServoThreadSafeLayoutNode::new(self)
+ }
+
+ fn type_id(&self) -> NodeTypeId {
+ unsafe {
+ self.node.type_id_for_layout()
+ }
+ }
+
+ unsafe fn borrow_layout_data_unchecked(&self) -> Option<*const PrivateLayoutData> {
+ self.get_jsmanaged().get_style_and_layout_data().map(|opaque| {
+ let container: NonOpaqueStyleAndLayoutData = transmute(opaque.ptr);
+ &(*(*container).as_unsafe_cell().get()) as *const PrivateLayoutData
+ })
+ }
+
+ fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>> {
+ unsafe {
+ self.get_jsmanaged().get_style_and_layout_data().map(|opaque| {
+ let container: NonOpaqueStyleAndLayoutData = transmute(opaque.ptr);
+ (*container).borrow()
+ })
+ }
+ }
+
+ fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>> {
+ unsafe {
+ self.get_jsmanaged().get_style_and_layout_data().map(|opaque| {
+ let container: NonOpaqueStyleAndLayoutData = transmute(opaque.ptr);
+ (*container).borrow_mut()
+ })
+ }
+ }
+}
+
+
impl<'ln> ServoLayoutNode<'ln> {
fn dump_indent(self, indent: u32) {
let mut s = String::new();
@@ -468,11 +329,7 @@ impl<'ln> ServoLayoutNode<'ln> {
}
pub fn flow_debug_id(self) -> usize {
- let layout_data_ref = self.borrow_layout_data();
- match *layout_data_ref {
- None => 0,
- Some(ref layout_data) => layout_data.data.flow_construction_result.debug_id()
- }
+ self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
}
/// Returns the interior of this node as a `LayoutJS`. This is highly unsafe for layout to
@@ -482,65 +339,6 @@ impl<'ln> ServoLayoutNode<'ln> {
}
}
-pub struct LayoutNodeChildrenIterator<'a, ConcreteLayoutNode> where ConcreteLayoutNode: LayoutNode<'a> {
- current: Option<ConcreteLayoutNode>,
- // Satisfy the compiler about the unused lifetime.
- phantom: PhantomData<&'a ()>,
-}
-
-impl<'a, ConcreteLayoutNode> Iterator for LayoutNodeChildrenIterator<'a, ConcreteLayoutNode>
- where ConcreteLayoutNode: LayoutNode<'a> {
- type Item = ConcreteLayoutNode;
- fn next(&mut self) -> Option<ConcreteLayoutNode> {
- let node = self.current;
- self.current = node.and_then(|node| node.next_sibling());
- node
- }
-}
-
-pub struct LayoutNodeReverseChildrenIterator<'a, ConcreteLayoutNode> where ConcreteLayoutNode: LayoutNode<'a> {
- current: Option<ConcreteLayoutNode>,
- // Satisfy the compiler about the unused lifetime.
- phantom: PhantomData<&'a ()>,
-}
-
-impl<'a, ConcreteLayoutNode> Iterator for LayoutNodeReverseChildrenIterator<'a, ConcreteLayoutNode>
- where ConcreteLayoutNode: LayoutNode<'a> {
- type Item = ConcreteLayoutNode;
- fn next(&mut self) -> Option<ConcreteLayoutNode> {
- let node = self.current;
- self.current = node.and_then(|node| node.prev_sibling());
- node
- }
-}
-
-pub struct LayoutTreeIterator<'a, ConcreteLayoutNode> where ConcreteLayoutNode: LayoutNode<'a> {
- stack: Vec<ConcreteLayoutNode>,
- // Satisfy the compiler about the unused lifetime.
- phantom: PhantomData<&'a ()>,
-}
-
-impl<'a, ConcreteLayoutNode> LayoutTreeIterator<'a, ConcreteLayoutNode> where ConcreteLayoutNode: LayoutNode<'a> {
- fn new(root: ConcreteLayoutNode) -> LayoutTreeIterator<'a, ConcreteLayoutNode> {
- let mut stack = vec!();
- stack.push(root);
- LayoutTreeIterator {
- stack: stack,
- phantom: PhantomData,
- }
- }
-}
-
-impl<'a, ConcreteLayoutNode> Iterator for LayoutTreeIterator<'a, ConcreteLayoutNode>
- where ConcreteLayoutNode: LayoutNode<'a> {
- type Item = ConcreteLayoutNode;
- fn next(&mut self) -> Option<ConcreteLayoutNode> {
- let ret = self.stack.pop();
- ret.map(|node| self.stack.extend(node.rev_children()));
- ret
- }
-}
-
// A wrapper around documents that ensures ayout can only ever access safe properties.
#[derive(Copy, Clone)]
pub struct ServoLayoutDocument<'ld> {
@@ -548,9 +346,9 @@ pub struct ServoLayoutDocument<'ld> {
chain: PhantomData<&'ld ()>,
}
-impl<'ld> LayoutDocument<'ld> for ServoLayoutDocument<'ld> {
- type ConcreteLayoutNode = ServoLayoutNode<'ld>;
- type ConcreteLayoutElement = ServoLayoutElement<'ld>;
+impl<'ld> TDocument<'ld> for ServoLayoutDocument<'ld> {
+ type ConcreteNode = ServoLayoutNode<'ld>;
+ type ConcreteElement = ServoLayoutElement<'ld>;
fn as_node(&self) -> ServoLayoutNode<'ld> {
ServoLayoutNode::from_layout_js(self.document.upcast())
@@ -582,9 +380,9 @@ pub struct ServoLayoutElement<'le> {
chain: PhantomData<&'le ()>,
}
-impl<'le> LayoutElement<'le> for ServoLayoutElement<'le> {
- type ConcreteLayoutNode = ServoLayoutNode<'le>;
- type ConcreteLayoutDocument = ServoLayoutDocument<'le>;
+impl<'le> TElement<'le> for ServoLayoutElement<'le> {
+ type ConcreteNode = ServoLayoutNode<'le>;
+ type ConcreteDocument = ServoLayoutDocument<'le>;
fn as_node(&self) -> ServoLayoutNode<'le> {
ServoLayoutNode::from_layout_js(self.element.upcast())
@@ -599,6 +397,28 @@ impl<'le> LayoutElement<'le> for ServoLayoutElement<'le> {
fn get_state(&self) -> ElementState {
self.element.get_state_for_layout()
}
+
+ fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
+ where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
+ {
+ unsafe {
+ self.element.synthesize_presentational_hints_for_legacy_attributes(hints);
+ }
+ }
+
+ #[inline]
+ fn get_attr<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> {
+ unsafe {
+ (*self.element.unsafe_get()).get_attr_val_for_layout(namespace, name)
+ }
+ }
+
+ #[inline]
+ fn get_attrs<'a>(&'a self, name: &Atom) -> Vec<&'a str> {
+ unsafe {
+ (*self.element.unsafe_get()).get_attr_vals_for_layout(name)
+ }
+ }
}
@@ -783,30 +603,6 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
}
}
-impl<'le> TElementAttributes for ServoLayoutElement<'le> {
- fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
- where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
- {
- unsafe {
- self.element.synthesize_presentational_hints_for_legacy_attributes(hints);
- }
- }
-
- #[inline]
- fn get_attr<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> {
- unsafe {
- (*self.element.unsafe_get()).get_attr_val_for_layout(namespace, name)
- }
- }
-
- #[inline]
- fn get_attrs<'a>(&'a self, name: &Atom) -> Vec<&'a str> {
- unsafe {
- (*self.element.unsafe_get()).get_attr_vals_for_layout(name)
- }
- }
-}
-
#[derive(Copy, PartialEq, Clone)]
pub enum PseudoElementType<T> {
Normal,
@@ -865,18 +661,14 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
#[inline]
fn get_before_pseudo(&self) -> Option<Self> {
- let layout_data_ref = self.borrow_layout_data();
- let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap();
- node_layout_data_wrapper.data.before_style.as_ref().map(|style| {
+ self.borrow_layout_data().unwrap().style_data.before_style.as_ref().map(|style| {
self.with_pseudo(PseudoElementType::Before(style.get_box().display))
})
}
#[inline]
fn get_after_pseudo(&self) -> Option<Self> {
- let layout_data_ref = self.borrow_layout_data();
- let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap();
- node_layout_data_wrapper.data.after_style.as_ref().map(|style| {
+ self.borrow_layout_data().unwrap().style_data.after_style.as_ref().map(|style| {
self.with_pseudo(PseudoElementType::After(style.get_box().display))
})
}
@@ -885,24 +677,23 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
///
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
#[inline(always)]
- fn borrow_layout_data(&self) -> Ref<Option<LayoutDataWrapper>>;
+ fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>>;
/// Borrows the layout data mutably. Fails on a conflicting borrow.
///
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
#[inline(always)]
- fn mutate_layout_data(&self) -> RefMut<Option<LayoutDataWrapper>>;
+ fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>>;
/// Returns the style results for the given node. If CSS selector matching
/// has not yet been performed, fails.
#[inline]
fn style(&self) -> Ref<Arc<ComputedValues>> {
- Ref::map(self.borrow_layout_data(), |layout_data_ref| {
- let layout_data = layout_data_ref.as_ref().expect("no layout data");
+ Ref::map(self.borrow_layout_data().unwrap(), |data| {
let style = match self.get_pseudo_element_type() {
- PseudoElementType::Before(_) => &layout_data.data.before_style,
- PseudoElementType::After(_) => &layout_data.data.after_style,
- PseudoElementType::Normal => &layout_data.shared_data.style,
+ PseudoElementType::Before(_) => &data.style_data.before_style,
+ PseudoElementType::After(_) => &data.style_data.after_style,
+ PseudoElementType::Normal => &data.style_data.style,
};
style.as_ref().unwrap()
})
@@ -910,14 +701,12 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
/// Removes the style from this node.
fn unstyle(self) {
- let mut layout_data_ref = self.mutate_layout_data();
- let layout_data = layout_data_ref.as_mut().expect("no layout data");
-
+ let mut data = self.mutate_layout_data().unwrap();
let style =
match self.get_pseudo_element_type() {
- PseudoElementType::Before(_) => &mut layout_data.data.before_style,
- PseudoElementType::After (_) => &mut layout_data.data.after_style,
- PseudoElementType::Normal => &mut layout_data.shared_data.style,
+ PseudoElementType::Before(_) => &mut data.style_data.before_style,
+ PseudoElementType::After (_) => &mut data.style_data.after_style,
+ PseudoElementType::Normal => &mut data.style_data.style,
};
*style = None;
@@ -928,17 +717,12 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
/// Get the description of how to account for recent style changes.
/// This is a simple bitfield and fine to copy by value.
fn restyle_damage(self) -> RestyleDamage {
- let layout_data_ref = self.borrow_layout_data();
- layout_data_ref.as_ref().unwrap().data.restyle_damage
+ self.borrow_layout_data().unwrap().restyle_damage
}
/// Set the restyle damage field.
fn set_restyle_damage(self, damage: RestyleDamage) {
- let mut layout_data_ref = self.mutate_layout_data();
- match *layout_data_ref {
- Some(ref mut layout_data) => layout_data.data.restyle_damage = damage,
- _ => panic!("no layout data for this node"),
- }
+ self.mutate_layout_data().unwrap().restyle_damage = damage;
}
/// Returns the layout data flags for this node.
@@ -946,20 +730,12 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
/// Adds the given flags to this node.
fn insert_flags(self, new_flags: LayoutDataFlags) {
- let mut layout_data_ref = self.mutate_layout_data();
- match *layout_data_ref {
- Some(ref mut layout_data) => layout_data.data.flags.insert(new_flags),
- _ => panic!("no layout data for this node"),
- }
+ self.mutate_layout_data().unwrap().flags.insert(new_flags);
}
/// Removes the given flags from this node.
fn remove_flags(self, flags: LayoutDataFlags) {
- let mut layout_data_ref = self.mutate_layout_data();
- match *layout_data_ref {
- Some(ref mut layout_data) => layout_data.data.flags.remove(flags),
- _ => panic!("no layout data for this node"),
- }
+ self.mutate_layout_data().unwrap().flags.remove(flags);
}
/// Returns true if this node contributes content. This is used in the implementation of
@@ -1049,14 +825,6 @@ impl<'ln> ServoThreadSafeLayoutNode<'ln> {
unsafe fn get_jsmanaged(&self) -> &LayoutJS<Node> {
self.node.get_jsmanaged()
}
-
- /// Borrows the layout data without checking.
- #[inline(always)]
- fn borrow_layout_data_unchecked(&self) -> *const Option<LayoutDataWrapper> {
- unsafe {
- self.node.borrow_layout_data_unchecked()
- }
- }
}
impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
@@ -1112,11 +880,11 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
self.pseudo
}
- fn borrow_layout_data(&self) -> Ref<Option<LayoutDataWrapper>> {
+ fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>> {
self.node.borrow_layout_data()
}
- fn mutate_layout_data(&self) -> RefMut<Option<LayoutDataWrapper>> {
+ fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>> {
self.node.mutate_layout_data()
}
@@ -1143,17 +911,13 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
fn flags(self) -> LayoutDataFlags {
unsafe {
- match *self.borrow_layout_data_unchecked() {
- None => panic!(),
- Some(ref layout_data) => layout_data.data.flags,
- }
+ (*self.node.borrow_layout_data_unchecked().unwrap()).flags
}
}
fn text_content(&self) -> TextContent {
if self.pseudo != PseudoElementType::Normal {
- let layout_data_ref = self.borrow_layout_data();
- let data = &layout_data_ref.as_ref().unwrap().data;
+ let data = &self.borrow_layout_data().unwrap().style_data;
let style = if self.pseudo.is_before() {
&data.before_style
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index a2a39979ad2..ee82a25733f 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -57,14 +57,12 @@ use selectors::matching::matches;
use selectors::parser::Selector;
use selectors::parser::parse_author_origin_selector_list_from_str;
use std::borrow::ToOwned;
-use std::cell::{Cell, Ref, RefCell, RefMut};
+use std::cell::Cell;
use std::cmp::max;
use std::default::Default;
use std::iter::{self, FilterMap, Peekable};
use std::mem;
-use std::sync::Arc;
use string_cache::{Atom, Namespace, QualName};
-use style::properties::ComputedValues;
use util::str::DOMString;
use util::task_state;
use uuid::Uuid;
@@ -115,11 +113,11 @@ pub struct Node {
/// are this node.
ranges: WeakRangeVec,
- /// Layout information. Only the layout task may touch this data.
+ /// Style+Layout information. Only the layout task may touch this data.
///
/// Must be sent back to the layout task to be destroyed when this
/// node is finalized.
- layout_data: LayoutDataRef,
+ style_and_layout_data: Cell<Option<OpaqueStyleAndLayoutData>>,
unique_id: DOMRefCell<Option<Box<Uuid>>>,
}
@@ -164,7 +162,7 @@ impl NodeFlags {
impl Drop for Node {
#[allow(unsafe_code)]
fn drop(&mut self) {
- self.layout_data.dispose(self);
+ self.style_and_layout_data.get().map(|d| d.dispose(self));
}
}
@@ -177,74 +175,27 @@ enum SuppressObserver {
Unsuppressed
}
-/// Layout data that is shared between the script and layout tasks.
-#[derive(HeapSizeOf)]
-pub struct SharedLayoutData {
- /// The results of CSS styling for this node.
- pub style: Option<Arc<ComputedValues>>,
-}
-
-/// Encapsulates the abstract layout data.
-#[derive(HeapSizeOf)]
-pub struct LayoutData {
- _shared_data: SharedLayoutData,
- #[ignore_heap_size_of = "TODO(#6910) Box value that should be counted but the type lives in layout"]
- _data: NonZero<*const ()>,
+#[derive(Copy, Clone, HeapSizeOf)]
+pub struct OpaqueStyleAndLayoutData {
+ #[ignore_heap_size_of = "TODO(#6910) Box value that should be counted but \
+ the type lives in layout"]
+ pub ptr: NonZero<*mut ()>
}
#[allow(unsafe_code)]
-unsafe impl Send for LayoutData {}
+unsafe impl Send for OpaqueStyleAndLayoutData {}
-#[derive(HeapSizeOf)]
-pub struct LayoutDataRef {
- data_cell: RefCell<Option<LayoutData>>,
-}
-
-no_jsmanaged_fields!(LayoutDataRef);
+no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
-impl LayoutDataRef {
- pub fn new() -> LayoutDataRef {
- LayoutDataRef {
- data_cell: RefCell::new(None),
- }
- }
- /// Sends layout data, if any, back to the layout task to be destroyed.
- pub fn dispose(&self, node: &Node) {
+impl OpaqueStyleAndLayoutData {
+ /// Sends the style and layout data, if any, back to the layout task to be destroyed.
+ pub fn dispose(self, node: &Node) {
debug_assert!(task_state::get().is_script());
- if let Some(layout_data) = mem::replace(&mut *self.data_cell.borrow_mut(), None) {
- let win = window_from_node(node);
- let LayoutChan(chan) = win.layout_chan();
- chan.send(Msg::ReapLayoutData(layout_data)).unwrap()
- }
- }
-
- /// Borrows the layout data immutably, *assuming that there are no mutators*. Bad things will
- /// happen if you try to mutate the layout data while this is held. This is the only thread-
- /// safe layout data accessor.
- #[inline]
- #[allow(unsafe_code)]
- pub unsafe fn borrow_unchecked(&self) -> *const Option<LayoutData> {
- debug_assert!(task_state::get().is_layout());
- self.data_cell.as_unsafe_cell().get() as *const _
- }
-
- /// Borrows the layout data immutably. This function is *not* thread-safe.
- #[inline]
- pub fn borrow(&self) -> Ref<Option<LayoutData>> {
- debug_assert!(task_state::get().is_layout());
- self.data_cell.borrow()
- }
-
- /// Borrows the layout data mutably. This function is *not* thread-safe.
- ///
- /// FIXME(pcwalton): We should really put this behind a `MutLayoutView` phantom type, to
- /// prevent CSS selector matching from mutably accessing nodes it's not supposed to and racing
- /// on it. This has already resulted in one bug!
- #[inline]
- pub fn borrow_mut(&self) -> RefMut<Option<LayoutData>> {
- debug_assert!(task_state::get().is_layout());
- self.data_cell.borrow_mut()
+ let win = window_from_node(node);
+ let LayoutChan(chan) = win.layout_chan();
+ node.style_and_layout_data.set(None);
+ chan.send(Msg::ReapStyleAndLayoutData(self)).unwrap();
}
}
@@ -334,7 +285,7 @@ impl Node {
for node in child.traverse_preorder() {
node.set_flag(IS_IN_DOC, false);
vtable_for(&&*node).unbind_from_tree(&context);
- node.layout_data.dispose(&node);
+ node.style_and_layout_data.get().map(|d| d.dispose(&node));
}
self.owner_doc().content_and_heritage_changed(self, NodeDamage::OtherNodeDamage);
@@ -378,7 +329,7 @@ impl<'a> Iterator for QuerySelectorIterator {
impl Node {
pub fn teardown(&self) {
- self.layout_data.dispose(self);
+ self.style_and_layout_data.get().map(|d| d.dispose(self));
for kid in self.children() {
kid.teardown();
}
@@ -966,9 +917,8 @@ pub trait LayoutNodeHelpers {
unsafe fn children_count(&self) -> u32;
- unsafe fn layout_data(&self) -> Ref<Option<LayoutData>>;
- unsafe fn layout_data_mut(&self) -> RefMut<Option<LayoutData>>;
- unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData>;
+ unsafe fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
+ unsafe fn init_style_and_layout_data(&self, OpaqueStyleAndLayoutData);
}
impl LayoutNodeHelpers for LayoutJS<Node> {
@@ -1049,20 +999,15 @@ impl LayoutNodeHelpers for LayoutJS<Node> {
#[inline]
#[allow(unsafe_code)]
- unsafe fn layout_data(&self) -> Ref<Option<LayoutData>> {
- (*self.unsafe_get()).layout_data.borrow()
- }
-
- #[inline]
- #[allow(unsafe_code)]
- unsafe fn layout_data_mut(&self) -> RefMut<Option<LayoutData>> {
- (*self.unsafe_get()).layout_data.borrow_mut()
+ unsafe fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
+ (*self.unsafe_get()).style_and_layout_data.get()
}
#[inline]
#[allow(unsafe_code)]
- unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData> {
- (*self.unsafe_get()).layout_data.borrow_unchecked()
+ unsafe fn init_style_and_layout_data(&self, val: OpaqueStyleAndLayoutData) {
+ debug_assert!((*self.unsafe_get()).style_and_layout_data.get().is_none());
+ (*self.unsafe_get()).style_and_layout_data.set(Some(val));
}
}
@@ -1322,7 +1267,7 @@ impl Node {
inclusive_descendants_version: Cell::new(0),
ranges: WeakRangeVec::new(),
- layout_data: LayoutDataRef::new(),
+ style_and_layout_data: Cell::new(None),
unique_id: DOMRefCell::new(None),
}
diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs
index a533fd6418d..90f83211db6 100644
--- a/components/script/layout_interface.rs
+++ b/components/script/layout_interface.rs
@@ -7,7 +7,7 @@
//! the DOM to be placed in a separate crate from layout.
use app_units::Au;
-use dom::node::LayoutData;
+use dom::node::OpaqueStyleAndLayoutData;
use euclid::point::Point2D;
use euclid::rect::Rect;
use gfx_traits::LayerId;
@@ -59,7 +59,7 @@ pub enum Msg {
/// Destroys layout data associated with a DOM node.
///
/// TODO(pcwalton): Maybe think about batching to avoid message traffic.
- ReapLayoutData(LayoutData),
+ ReapStyleAndLayoutData(OpaqueStyleAndLayoutData),
/// Requests that the layout task measure its memory usage. The resulting reports are sent back
/// via the supplied channel.
diff --git a/components/style/data.rs b/components/style/data.rs
new file mode 100644
index 00000000000..bfd1cd6113a
--- /dev/null
+++ b/components/style/data.rs
@@ -0,0 +1,48 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use properties::ComputedValues;
+use std::sync::Arc;
+use std::sync::atomic::AtomicIsize;
+
+pub struct PrivateStyleData {
+ /// The results of CSS styling for this node.
+ pub style: Option<Arc<ComputedValues>>,
+
+ /// The results of CSS styling for this node's `before` pseudo-element, if any.
+ pub before_style: Option<Arc<ComputedValues>>,
+
+ /// The results of CSS styling for this node's `after` pseudo-element, if any.
+ pub after_style: Option<Arc<ComputedValues>>,
+
+ /// Information needed during parallel traversals.
+ pub parallel: DomParallelInfo,
+}
+
+impl PrivateStyleData {
+ pub fn new() -> PrivateStyleData {
+ PrivateStyleData {
+ style: None,
+ before_style: None,
+ after_style: None,
+ parallel: DomParallelInfo::new(),
+ }
+ }
+}
+
+/// Information that we need stored in each DOM node.
+#[derive(HeapSizeOf)]
+pub struct DomParallelInfo {
+ /// The number of children that still need work done.
+ pub children_count: AtomicIsize,
+}
+
+impl DomParallelInfo {
+ pub fn new() -> DomParallelInfo {
+ DomParallelInfo {
+ children_count: AtomicIsize::new(0),
+ }
+ }
+}
+
diff --git a/components/style/dom.rs b/components/style/dom.rs
new file mode 100644
index 00000000000..4567e986bae
--- /dev/null
+++ b/components/style/dom.rs
@@ -0,0 +1,274 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#![allow(unsafe_code)]
+
+use data::PrivateStyleData;
+use properties::{PropertyDeclaration, PropertyDeclarationBlock};
+use restyle_hints::{ElementSnapshot, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
+use selectors::matching::DeclarationBlock;
+use selectors::states::ElementState;
+use smallvec::VecLike;
+use std::cell::{Ref, RefMut};
+use std::marker::PhantomData;
+use string_cache::{Atom, Namespace};
+
+/// Opaque type stored in type-unsafe work queues for parallel layout.
+/// Must be transmutable to and from TNode.
+pub type UnsafeNode = (usize, usize);
+
+/// An opaque handle to a node, which, unlike UnsafeNode, cannot be transformed
+/// back into a non-opaque representation. The only safe operation that can be
+/// performed on this node is to compare it to another opaque handle or to another
+/// OpaqueNode.
+///
+/// Layout and Graphics use this to safely represent nodes for comparison purposes.
+/// Because the script task's GC does not trace layout, node data cannot be safely stored in layout
+/// data structures. Also, layout code tends to be faster when the DOM is not being accessed, for
+/// locality reasons. Using `OpaqueNode` enforces this invariant.
+#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf, Hash, Eq, Deserialize, Serialize)]
+pub struct OpaqueNode(pub usize);
+
+impl OpaqueNode {
+ /// Returns the address of this node, for debugging purposes.
+ #[inline]
+ pub fn id(&self) -> usize {
+ let OpaqueNode(pointer) = *self;
+ pointer
+ }
+}
+
+
+pub trait TNode<'ln> : Sized + Copy + Clone {
+ type ConcreteElement: TElement<'ln, ConcreteNode = Self, ConcreteDocument = Self::ConcreteDocument>;
+ type ConcreteDocument: TDocument<'ln, ConcreteNode = Self, ConcreteElement = Self::ConcreteElement>;
+
+ fn to_unsafe(&self) -> UnsafeNode;
+ unsafe fn from_unsafe(n: &UnsafeNode) -> Self;
+
+ /// Returns whether this is a text node. It turns out that this is all the style system cares
+ /// about, and thus obviates the need to compute the full type id, which would be expensive in
+ /// Gecko.
+ fn is_text_node(&self) -> bool;
+
+ fn is_element(&self) -> bool;
+
+ fn dump(self);
+
+ fn traverse_preorder(self) -> TreeIterator<'ln, Self> {
+ TreeIterator::new(self)
+ }
+
+ /// Returns an iterator over this node's children.
+ fn children(self) -> ChildrenIterator<'ln, Self> {
+ ChildrenIterator {
+ current: self.first_child(),
+ phantom: PhantomData,
+ }
+ }
+
+ fn rev_children(self) -> ReverseChildrenIterator<'ln, Self> {
+ ReverseChildrenIterator {
+ current: self.last_child(),
+ phantom: PhantomData,
+ }
+ }
+
+ /// Converts self into an `OpaqueNode`.
+ fn opaque(&self) -> OpaqueNode;
+
+ /// Initializes style and layout data for the node. No-op if the data is already
+ /// initialized.
+ ///
+ /// FIXME(pcwalton): Do this as part of fragment building instead of in a traversal.
+ fn initialize_data(self);
+
+ /// While doing a reflow, the node at the root has no parent, as far as we're
+ /// concerned. This method returns `None` at the reflow root.
+ fn layout_parent_node(self, reflow_root: OpaqueNode) -> Option<Self>;
+
+ fn debug_id(self) -> usize;
+
+ fn as_element(&self) -> Option<Self::ConcreteElement>;
+
+ fn as_document(&self) -> Option<Self::ConcreteDocument>;
+
+ fn children_count(&self) -> u32;
+
+ fn has_changed(&self) -> bool;
+
+ unsafe fn set_changed(&self, value: bool);
+
+ fn is_dirty(&self) -> bool;
+
+ unsafe fn set_dirty(&self, value: bool);
+
+ fn has_dirty_descendants(&self) -> bool;
+
+ unsafe fn set_dirty_descendants(&self, value: bool);
+
+ fn dirty_self(&self) {
+ unsafe {
+ self.set_dirty(true);
+ self.set_dirty_descendants(true);
+ }
+ }
+
+ fn dirty_descendants(&self) {
+ for ref child in self.children() {
+ child.dirty_self();
+ child.dirty_descendants();
+ }
+ }
+
+ /// Borrows the PrivateStyleData without checks.
+ #[inline(always)]
+ unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData>;
+
+ /// Borrows the PrivateStyleData immutably. Fails on a conflicting borrow.
+ #[inline(always)]
+ fn borrow_data(&self) -> Option<Ref<PrivateStyleData>>;
+
+ /// Borrows the PrivateStyleData mutably. Fails on a conflicting borrow.
+ #[inline(always)]
+ fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>>;
+
+ fn parent_node(&self) -> Option<Self>;
+
+ fn first_child(&self) -> Option<Self>;
+
+ fn last_child(&self) -> Option<Self>;
+
+ fn prev_sibling(&self) -> Option<Self>;
+
+ fn next_sibling(&self) -> Option<Self>;
+}
+
+pub trait TDocument<'ld> : Sized + Copy + Clone {
+ type ConcreteNode: TNode<'ld, ConcreteElement = Self::ConcreteElement, ConcreteDocument = Self>;
+ type ConcreteElement: TElement<'ld, ConcreteNode = Self::ConcreteNode, ConcreteDocument = Self>;
+
+ fn as_node(&self) -> Self::ConcreteNode;
+
+ fn root_node(&self) -> Option<Self::ConcreteNode>;
+
+ fn drain_modified_elements(&self) -> Vec<(Self::ConcreteElement, ElementSnapshot)>;
+}
+
+pub trait TElement<'le> : Sized + Copy + Clone + ::selectors::Element {
+ type ConcreteNode: TNode<'le, ConcreteElement = Self, ConcreteDocument = Self::ConcreteDocument>;
+ type ConcreteDocument: TDocument<'le, ConcreteNode = Self::ConcreteNode, ConcreteElement = Self>;
+
+ fn as_node(&self) -> Self::ConcreteNode;
+
+ fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock>;
+
+ fn get_state(&self) -> ElementState;
+
+ fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, &mut V)
+ where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
+
+ fn get_attr<'a>(&'a self, namespace: &Namespace, attr: &Atom) -> Option<&'a str>;
+ fn get_attrs<'a>(&'a self, attr: &Atom) -> Vec<&'a str>;
+
+ /// Properly marks nodes as dirty in response to restyle hints.
+ fn note_restyle_hint(&self, mut hint: RestyleHint) {
+ // Bail early if there's no restyling to do.
+ if hint.is_empty() {
+ return;
+ }
+
+ // If the restyle hint is non-empty, we need to restyle either this element
+ // or one of its siblings. Mark our ancestor chain as having dirty descendants.
+ let node = self.as_node();
+ let mut curr = node;
+ while let Some(parent) = curr.parent_node() {
+ if parent.has_dirty_descendants() { break }
+ unsafe { parent.set_dirty_descendants(true); }
+ curr = parent;
+ }
+
+ // Process hints.
+ if hint.contains(RESTYLE_SELF) {
+ node.dirty_self();
+
+ // FIXME(bholley, #8438): We currently need to RESTYLE_DESCENDANTS in the
+ // RESTYLE_SELF case in order to make sure "inherit" style structs propagate
+ // properly. See the explanation in the github issue.
+ hint.insert(RESTYLE_DESCENDANTS);
+ }
+ if hint.contains(RESTYLE_DESCENDANTS) {
+ unsafe { node.set_dirty_descendants(true); }
+ node.dirty_descendants();
+ }
+ if hint.contains(RESTYLE_LATER_SIBLINGS) {
+ let mut next = ::selectors::Element::next_sibling_element(self);
+ while let Some(sib) = next {
+ let sib_node = sib.as_node();
+ sib_node.dirty_self();
+ sib_node.dirty_descendants();
+ next = ::selectors::Element::next_sibling_element(&sib);
+ }
+ }
+ }
+}
+
+pub struct TreeIterator<'a, ConcreteNode> where ConcreteNode: TNode<'a> {
+ stack: Vec<ConcreteNode>,
+ // Satisfy the compiler about the unused lifetime.
+ phantom: PhantomData<&'a ()>,
+}
+
+impl<'a, ConcreteNode> TreeIterator<'a, ConcreteNode> where ConcreteNode: TNode<'a> {
+ fn new(root: ConcreteNode) -> TreeIterator<'a, ConcreteNode> {
+ let mut stack = vec!();
+ stack.push(root);
+ TreeIterator {
+ stack: stack,
+ phantom: PhantomData,
+ }
+ }
+}
+
+impl<'a, ConcreteNode> Iterator for TreeIterator<'a, ConcreteNode>
+ where ConcreteNode: TNode<'a> {
+ type Item = ConcreteNode;
+ fn next(&mut self) -> Option<ConcreteNode> {
+ let ret = self.stack.pop();
+ ret.map(|node| self.stack.extend(node.rev_children()));
+ ret
+ }
+}
+
+pub struct ChildrenIterator<'a, ConcreteNode> where ConcreteNode: TNode<'a> {
+ current: Option<ConcreteNode>,
+ // Satisfy the compiler about the unused lifetime.
+ phantom: PhantomData<&'a ()>,
+}
+
+impl<'a, ConcreteNode> Iterator for ChildrenIterator<'a, ConcreteNode>
+ where ConcreteNode: TNode<'a> {
+ type Item = ConcreteNode;
+ fn next(&mut self) -> Option<ConcreteNode> {
+ let node = self.current;
+ self.current = node.and_then(|node| node.next_sibling());
+ node
+ }
+}
+
+pub struct ReverseChildrenIterator<'a, ConcreteNode> where ConcreteNode: TNode<'a> {
+ current: Option<ConcreteNode>,
+ // Satisfy the compiler about the unused lifetime.
+ phantom: PhantomData<&'a ()>,
+}
+
+impl<'a, ConcreteNode> Iterator for ReverseChildrenIterator<'a, ConcreteNode>
+ where ConcreteNode: TNode<'a> {
+ type Item = ConcreteNode;
+ fn next(&mut self) -> Option<ConcreteNode> {
+ let node = self.current;
+ self.current = node.and_then(|node| node.prev_sibling());
+ node
+ }
+}
diff --git a/components/style/lib.rs b/components/style/lib.rs
index 4baa68eeca5..81c34b4db5a 100644
--- a/components/style/lib.rs
+++ b/components/style/lib.rs
@@ -17,6 +17,7 @@
extern crate app_units;
#[macro_use]
extern crate bitflags;
+extern crate core;
#[macro_use]
extern crate cssparser;
extern crate encoding;
@@ -43,9 +44,10 @@ extern crate util;
pub mod animation;
pub mod attr;
mod custom_properties;
+pub mod data;
+pub mod dom;
pub mod font_face;
pub mod media_queries;
-pub mod node;
pub mod parser;
pub mod restyle_hints;
pub mod selector_matching;
diff --git a/components/style/node.rs b/components/style/node.rs
deleted file mode 100644
index 302ad48fd80..00000000000
--- a/components/style/node.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency between layout and
-//! style.
-
-use properties::PropertyDeclaration;
-use selectors::matching::DeclarationBlock;
-use smallvec::VecLike;
-use string_cache::{Atom, Namespace};
-
-pub trait TElementAttributes {
- fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, &mut V)
- where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
-
- fn get_attr<'a>(&'a self, namespace: &Namespace, attr: &Atom) -> Option<&'a str>;
- fn get_attrs<'a>(&'a self, attr: &Atom) -> Vec<&'a str>;
-}
diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs
index 4dae08ce9bd..dd99a3f26b4 100644
--- a/components/style/selector_matching.rs
+++ b/components/style/selector_matching.rs
@@ -3,11 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::{Parser, SourcePosition};
+use dom::TElement;
use log;
use media_queries::{Device, MediaType};
use msg::ParseErrorReporter;
use msg::constellation_msg::PipelineId;
-use node::TElementAttributes;
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet};
use selectors::Element;
@@ -270,7 +270,7 @@ impl Stylist {
/// The returned boolean indicates whether the style is *shareable*; that is, whether the
/// matched selectors are simple enough to allow the matching logic to be reduced to the logic
/// in `css::matching::PrivateMatchMethods::candidate_element_allows_for_style_sharing`.
- pub fn push_applicable_declarations<E, V>(
+ pub fn push_applicable_declarations<'le, E, V>(
&self,
element: &E,
parent_bf: Option<&BloomFilter>,
@@ -278,7 +278,7 @@ impl Stylist {
pseudo_element: Option<PseudoElement>,
applicable_declarations: &mut V)
-> bool
- where E: Element + TElementAttributes,
+ where E: Element + TElement<'le>,
V: VecLike<DeclarationBlock> {
assert!(!self.is_device_dirty);
assert!(style_attribute.is_none() || pseudo_element.is_none(),
diff --git a/components/util/mem.rs b/components/util/mem.rs
index 5b976d468e4..6c60186ff0e 100644
--- a/components/util/mem.rs
+++ b/components/util/mem.rs
@@ -35,6 +35,7 @@ use std::mem::{size_of, transmute};
use std::rc::Rc;
use std::result::Result;
use std::sync::Arc;
+use std::sync::atomic::{AtomicIsize, AtomicUsize};
use str::{DOMString, LengthOrPercentageOrAuto};
use string_cache::atom::Atom;
use string_cache::namespace::{QualName, Namespace};
@@ -418,6 +419,7 @@ impl HeapSizeOf for Value {
known_heap_size!(0, u8, u16, u32, u64, usize);
known_heap_size!(0, i8, i16, i32, i64, isize);
known_heap_size!(0, bool, f32, f64);
+known_heap_size!(0, AtomicIsize, AtomicUsize);
known_heap_size!(0, Rect<T>, Point2D<T>, Size2D<T>, Matrix2D<T>, SideOffsets2D<T>, Range<T>);
known_heap_size!(0, Length<T, U>, ScaleFactor<T, U, V>);
diff --git a/tests/unit/script/size_of.rs b/tests/unit/script/size_of.rs
index 28c7c52449f..b89ca9dd837 100644
--- a/tests/unit/script/size_of.rs
+++ b/tests/unit/script/size_of.rs
@@ -38,10 +38,10 @@ macro_rules! sizeof_checker (
// Update the sizes here
sizeof_checker!(size_event_target, EventTarget, 40);
-sizeof_checker!(size_node, Node, 184);
-sizeof_checker!(size_element, Element, 328);
-sizeof_checker!(size_htmlelement, HTMLElement, 344);
-sizeof_checker!(size_div, HTMLDivElement, 344);
-sizeof_checker!(size_span, HTMLSpanElement, 344);
-sizeof_checker!(size_text, Text, 216);
-sizeof_checker!(size_characterdata, CharacterData, 216);
+sizeof_checker!(size_node, Node, 168);
+sizeof_checker!(size_element, Element, 312);
+sizeof_checker!(size_htmlelement, HTMLElement, 328);
+sizeof_checker!(size_div, HTMLDivElement, 328);
+sizeof_checker!(size_span, HTMLSpanElement, 328);
+sizeof_checker!(size_text, Text, 200);
+sizeof_checker!(size_characterdata, CharacterData, 200);