mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
script: Move the layout_wrapper outside of script.
This allows us to have ensure_data() and clear_data() functions on the TElement trait, instead of hacking around it adding methods in random traits. This also allows us to do some further cleanup, which I'd rather do in a followup.
This commit is contained in:
parent
f9642b36bd
commit
bf9369b29d
17 changed files with 128 additions and 166 deletions
|
@ -550,6 +550,17 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
|
|||
/// traversal. Returns the number of children left to process.
|
||||
fn did_process_child(&self) -> isize;
|
||||
|
||||
/// Gets a reference to the ElementData container, or creates one.
|
||||
///
|
||||
/// Unsafe because it can race to allocate and leak if not used with
|
||||
/// exclusive access to the element.
|
||||
unsafe fn ensure_data(&self) -> AtomicRefMut<ElementData>;
|
||||
|
||||
/// Clears the element data reference, if any.
|
||||
///
|
||||
/// Unsafe following the same reasoning as ensure_data.
|
||||
unsafe fn clear_data(&self);
|
||||
|
||||
/// Gets a reference to the ElementData container.
|
||||
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>>;
|
||||
|
||||
|
|
|
@ -4,10 +4,8 @@
|
|||
|
||||
//! Gecko-specific bits for the styling DOM traversal.
|
||||
|
||||
use atomic_refcell::AtomicRefCell;
|
||||
use context::{SharedStyleContext, StyleContext};
|
||||
use data::ElementData;
|
||||
use dom::{NodeInfo, TNode};
|
||||
use dom::{NodeInfo, TNode, TElement};
|
||||
use gecko::wrapper::{GeckoElement, GeckoNode};
|
||||
use traversal::{DomTraversal, PerLevelTraversalData, TraversalDriver, recalc_style_at};
|
||||
|
||||
|
@ -36,7 +34,7 @@ impl<'recalc, 'le> DomTraversal<GeckoElement<'le>> for RecalcStyleOnly<'recalc>
|
|||
{
|
||||
if node.is_element() {
|
||||
let el = node.as_element().unwrap();
|
||||
let mut data = unsafe { el.ensure_data() }.borrow_mut();
|
||||
let mut data = unsafe { el.ensure_data() };
|
||||
recalc_style_at(self, traversal_data, context, el, &mut data);
|
||||
}
|
||||
}
|
||||
|
@ -48,14 +46,6 @@ impl<'recalc, 'le> DomTraversal<GeckoElement<'le>> for RecalcStyleOnly<'recalc>
|
|||
/// We don't use the post-order traversal for anything.
|
||||
fn needs_postorder_traversal() -> bool { false }
|
||||
|
||||
unsafe fn ensure_element_data<'a>(element: &'a GeckoElement<'le>) -> &'a AtomicRefCell<ElementData> {
|
||||
element.ensure_data()
|
||||
}
|
||||
|
||||
unsafe fn clear_element_data<'a>(element: &'a GeckoElement<'le>) {
|
||||
element.clear_data()
|
||||
}
|
||||
|
||||
fn shared_context(&self) -> &SharedStyleContext {
|
||||
&self.shared
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
use CaseSensitivityExt;
|
||||
use app_units::Au;
|
||||
use applicable_declarations::ApplicableDeclarationBlock;
|
||||
use atomic_refcell::AtomicRefCell;
|
||||
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
|
||||
use context::{QuirksMode, SharedStyleContext, UpdateAnimationsTasks};
|
||||
use data::ElementData;
|
||||
use dom::{self, DescendantsBit, LayoutIterator, NodeInfo, TElement, TNode, UnsafeNode};
|
||||
|
@ -581,42 +581,6 @@ impl<'le> GeckoElement<'le> {
|
|||
self.namespace_id() == (structs::root::kNameSpaceID_XUL as i32)
|
||||
}
|
||||
|
||||
/// Clear the element data for a given element.
|
||||
pub fn clear_data(&self) {
|
||||
let ptr = self.0.mServoData.get();
|
||||
unsafe {
|
||||
self.unset_flags(ELEMENT_HAS_SNAPSHOT as u32 |
|
||||
ELEMENT_HANDLED_SNAPSHOT as u32);
|
||||
}
|
||||
if !ptr.is_null() {
|
||||
debug!("Dropping ElementData for {:?}", self);
|
||||
let data = unsafe { Box::from_raw(self.0.mServoData.get()) };
|
||||
self.0.mServoData.set(ptr::null_mut());
|
||||
|
||||
// Perform a mutable borrow of the data in debug builds. This
|
||||
// serves as an assertion that there are no outstanding borrows
|
||||
// when we destroy the data.
|
||||
debug_assert!({ let _ = data.borrow_mut(); true });
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures the element has data, returning the existing data or allocating
|
||||
/// it.
|
||||
///
|
||||
/// Only safe to call with exclusive access to the element, given otherwise
|
||||
/// it could race to allocate and leak.
|
||||
pub unsafe fn ensure_data(&self) -> &AtomicRefCell<ElementData> {
|
||||
match self.get_data() {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
debug!("Creating ElementData for {:?}", self);
|
||||
let ptr = Box::into_raw(Box::new(AtomicRefCell::new(ElementData::default())));
|
||||
self.0.mServoData.set(ptr);
|
||||
unsafe { &* ptr }
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the specified element data, return any existing data.
|
||||
///
|
||||
/// Like `ensure_data`, only safe to call with exclusive access to the
|
||||
|
@ -1067,6 +1031,33 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
unsafe { self.0.mServoData.get().as_ref() }
|
||||
}
|
||||
|
||||
unsafe fn ensure_data(&self) -> AtomicRefMut<ElementData> {
|
||||
if self.get_data().is_none() {
|
||||
debug!("Creating ElementData for {:?}", self);
|
||||
let ptr = Box::into_raw(Box::new(AtomicRefCell::new(ElementData::default())));
|
||||
self.0.mServoData.set(ptr);
|
||||
}
|
||||
self.mutate_data().unwrap()
|
||||
}
|
||||
|
||||
unsafe fn clear_data(&self) {
|
||||
let ptr = self.0.mServoData.get();
|
||||
unsafe {
|
||||
self.unset_flags(ELEMENT_HAS_SNAPSHOT as u32 |
|
||||
ELEMENT_HANDLED_SNAPSHOT as u32);
|
||||
}
|
||||
if !ptr.is_null() {
|
||||
debug!("Dropping ElementData for {:?}", self);
|
||||
let data = unsafe { Box::from_raw(self.0.mServoData.get()) };
|
||||
self.0.mServoData.set(ptr::null_mut());
|
||||
|
||||
// Perform a mutable borrow of the data in debug builds. This
|
||||
// serves as an assertion that there are no outstanding borrows
|
||||
// when we destroy the data.
|
||||
debug_assert!({ let _ = data.borrow_mut(); true });
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_root_and_item_based_display_fixup(&self) -> bool {
|
||||
// We don't want to fix up display values of native anonymous content.
|
||||
// Additionally, we want to skip root-based display fixup for document
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
//! Traversing the DOM tree; the bloom filter.
|
||||
|
||||
use atomic_refcell::AtomicRefCell;
|
||||
use context::{ElementCascadeInputs, StyleContext, SharedStyleContext};
|
||||
use data::{ElementData, ElementStyles};
|
||||
use dom::{NodeInfo, OpaqueNode, TElement, TNode};
|
||||
|
@ -489,20 +488,6 @@ pub trait DomTraversal<E: TElement> : Sync {
|
|||
}
|
||||
}
|
||||
|
||||
/// Ensures the existence of the ElementData, and returns it. This can't
|
||||
/// live on TNode because of the trait-based separation between Servo's
|
||||
/// script and layout crates.
|
||||
///
|
||||
/// This is only safe to call in top-down traversal before processing the
|
||||
/// children of |element|.
|
||||
unsafe fn ensure_element_data(element: &E) -> &AtomicRefCell<ElementData>;
|
||||
|
||||
/// Clears the ElementData attached to this element, if any.
|
||||
///
|
||||
/// This is only safe to call in top-down traversal before processing the
|
||||
/// children of |element|.
|
||||
unsafe fn clear_element_data(element: &E);
|
||||
|
||||
/// Return the shared style context common to all worker threads.
|
||||
fn shared_context(&self) -> &SharedStyleContext;
|
||||
|
||||
|
@ -647,7 +632,7 @@ where
|
|||
if data.styles.is_display_none() {
|
||||
debug!("{:?} style is display:none - clearing data from descendants.",
|
||||
element);
|
||||
clear_descendant_data(element, &|e| unsafe { D::clear_element_data(&e) });
|
||||
clear_descendant_data(element)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -855,8 +840,7 @@ where
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut child_data =
|
||||
unsafe { D::ensure_element_data(&child).borrow_mut() };
|
||||
let mut child_data = unsafe { child.ensure_data() };
|
||||
|
||||
trace!(" > {:?} -> {:?} + {:?}, pseudo: {:?}",
|
||||
child,
|
||||
|
@ -880,13 +864,9 @@ where
|
|||
}
|
||||
|
||||
/// Clear style data for all the subtree under `el`.
|
||||
pub fn clear_descendant_data<E, F>(
|
||||
el: E,
|
||||
clear_data: &F
|
||||
)
|
||||
pub fn clear_descendant_data<E>(el: E)
|
||||
where
|
||||
E: TElement,
|
||||
F: Fn(E),
|
||||
{
|
||||
for kid in el.as_node().traversal_children() {
|
||||
if let Some(kid) = kid.as_element() {
|
||||
|
@ -896,8 +876,8 @@ where
|
|||
// By consequence, any element without data has no descendants with
|
||||
// data.
|
||||
if kid.get_data().is_some() {
|
||||
clear_data(kid);
|
||||
clear_descendant_data(kid, clear_data);
|
||||
unsafe { kid.clear_data() };
|
||||
clear_descendant_data(kid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue