--- a/servo/components/servo_arc/lib.rs
+++ b/servo/components/servo_arc/lib.rs
@@ -189,16 +189,40 @@ impl<T> Arc<T> {
pub unsafe fn from_raw(ptr: *const T) -> Self {
// To find the corresponding pointer to the `ArcInner` we need
// to subtract the offset of the `data` field from the pointer.
let ptr = (ptr as *const u8).offset(-offset_of!(ArcInner<T>, data));
Arc {
p: NonZeroPtrMut::new(ptr as *mut ArcInner<T>),
}
}
+
+ /// Produce a pointer to the data that can be converted back
+ /// to an arc
+ pub fn borrow_arc<'a>(&'a self) -> ArcBorrow<'a, T> {
+ ArcBorrow(&**self)
+ }
+ /// Temporarily converts |self| into a bonafide RawOffsetArc and exposes it to the
+ /// provided callback. The refcount is not modified.
+ #[inline(always)]
+ pub fn with_raw_offset_arc<F, U>(&self, f: F) -> U
+ where F: FnOnce(&RawOffsetArc<T>) -> U
+ {
+ // Synthesize transient Arc, which never touches the refcount of the ArcInner.
+ let transient = unsafe { NoDrop::new(Arc::into_raw_offset(ptr::read(self))) };
+
+ // Expose the transient Arc to the callback, which may clone it if it wants.
+ let result = f(&transient);
+
+ // Forget the transient Arc to leave the refcount untouched.
+ mem::forget(transient);
+
+ // Forward the result.
+ result
+ }
}
impl<T: ?Sized> Arc<T> {
#[inline]
fn inner(&self) -> &ArcInner<T> {
// This unsafety is ok because while this arc is alive we're guaranteed
// that the inner pointer is valid. Furthermore, we know that the
// `ArcInner` structure itself is `Sync` because the inner data is
@@ -712,49 +736,60 @@ impl<H: Eq + 'static, T: Eq + 'static> E
/// ---------------------
/// | RefCount | T (data) | [ArcInner<T>]
/// ---------------------
/// ```
///
/// This means that this is a direct pointer to
/// its contained data (and can be read from by both C++ and Rust),
/// but we can also convert it to a "regular" Arc<T> by removing the offset
+#[derive(Eq)]
pub struct RawOffsetArc<T: 'static> {
ptr: NonZeroPtrMut<T>,
}
unsafe impl<T: 'static + Sync + Send> Send for RawOffsetArc<T> {}
unsafe impl<T: 'static + Sync + Send> Sync for RawOffsetArc<T> {}
impl<T: 'static> Deref for RawOffsetArc<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr.ptr() }
}
}
impl<T: 'static> Clone for RawOffsetArc<T> {
fn clone(&self) -> Self {
- RawOffsetArc::with_arc(self, |a| Arc::into_raw_offset(a.clone()))
+ Arc::into_raw_offset(self.clone_arc())
}
}
impl<T: 'static> Drop for RawOffsetArc<T> {
fn drop(&mut self) {
let _ = Arc::from_raw_offset(RawOffsetArc { ptr: self.ptr.clone() });
}
}
impl<T: fmt::Debug + 'static> fmt::Debug for RawOffsetArc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
+impl<T: PartialEq> PartialEq for RawOffsetArc<T> {
+ fn eq(&self, other: &RawOffsetArc<T>) -> bool {
+ *(*self) == *(*other)
+ }
+
+ fn ne(&self, other: &RawOffsetArc<T>) -> bool {
+ *(*self) != *(*other)
+ }
+}
+
impl<T: 'static> RawOffsetArc<T> {
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
/// provided callback. The refcount is not modified.
#[inline(always)]
pub fn with_arc<F, U>(&self, f: F) -> U
where F: FnOnce(&Arc<T>) -> U
{
// Synthesize transient Arc, which never touches the refcount of the ArcInner.
@@ -784,16 +819,27 @@ impl<T: 'static> RawOffsetArc<T> {
// This may mutate `arc`
let ret = Arc::make_mut(&mut arc) as *mut _;
// Store the possibly-mutated arc back inside, after converting
// it to a RawOffsetArc again
ptr::write(self, Arc::into_raw_offset(arc));
&mut *ret
}
}
+
+ /// Clone it as an Arc
+ pub fn clone_arc(&self) -> Arc<T> {
+ RawOffsetArc::with_arc(self, |a| a.clone())
+ }
+
+ /// Produce a pointer to the data that can be converted back
+ /// to an arc
+ pub fn borrow_arc<'a>(&'a self) -> ArcBorrow<'a, T> {
+ ArcBorrow(&**self)
+ }
}
impl<T: 'static> Arc<T> {
/// Converts an Arc into a RawOffsetArc. This consumes the Arc, so the refcount
/// is not modified.
#[inline]
pub fn into_raw_offset(a: Self) -> RawOffsetArc<T> {
RawOffsetArc {
@@ -806,16 +852,72 @@ impl<T: 'static> Arc<T> {
#[inline]
pub fn from_raw_offset(a: RawOffsetArc<T>) -> Self {
let ptr = a.ptr.ptr();
mem::forget(a);
unsafe { Arc::from_raw(ptr) }
}
}
+/// A "borrowed Arc". This is a pointer to
+/// a T that is known to have been allocated within an
+/// Arc.
+///
+/// This is equivalent in guarantees to `&Arc<T>`, however it is
+/// a bit more flexible. To obtain an `&Arc<T>` you must have
+/// an Arc<T> instance somewhere pinned down until we're done with it.
+///
+/// However, Gecko hands us refcounted things as pointers to T directly,
+/// so we have to conjure up a temporary Arc on the stack each time. The
+/// same happens for when the object is managed by a RawOffsetArc.
+///
+/// ArcBorrow lets us deal with borrows of known-refcounted objects
+/// without needing to worry about how they're actually stored.
+#[derive(PartialEq, Eq)]
+pub struct ArcBorrow<'a, T: 'a>(&'a T);
+
+impl<'a, T> Copy for ArcBorrow<'a, T> {}
+impl<'a, T> Clone for ArcBorrow<'a, T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<'a, T> ArcBorrow<'a, T> {
+ pub fn clone_arc(&self) -> Arc<T> {
+ let arc = unsafe { Arc::from_raw(self.0) };
+ // addref it!
+ mem::forget(arc.clone());
+ arc
+ }
+
+ pub fn with_arc<F, U>(&self, f: F) -> U where F: FnOnce(&Arc<T>) -> U, T: 'static {
+ // Synthesize transient Arc, which never touches the refcount.
+ let transient = unsafe { NoDrop::new(Arc::from_raw(self.0)) };
+
+ // Expose the transient Arc to the callback, which may clone it if it wants.
+ let result = f(&transient);
+
+ // Forget the transient Arc to leave the refcount untouched.
+ // XXXManishearth this can be removed when unions stabilize,
+ // since then NoDrop becomes zero overhead
+ mem::forget(transient);
+
+ // Forward the result.
+ result
+ }
+}
+
+impl<'a, T> Deref for ArcBorrow<'a, T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ &*self.0
+ }
+}
+
#[cfg(test)]
mod tests {
use std::clone::Clone;
use std::ops::Drop;
use std::sync::atomic;
use std::sync::atomic::Ordering::{Acquire, SeqCst};
use super::{Arc, HeaderWithLength, ThinArc};
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -25,17 +25,17 @@ use selectors::matching::{ElementSelecto
use selectors::sink::Push;
use shared_lock::Locked;
use smallvec::VecLike;
use std::fmt;
#[cfg(feature = "gecko")] use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::Deref;
-use stylearc::Arc;
+use stylearc::{Arc, ArcBorrow};
use stylist::Stylist;
use thread_state;
pub use style_traits::UnsafeNode;
/// 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
@@ -355,25 +355,25 @@ pub trait TElement : Eq + PartialEq + De
/// For a given NAC element, return the closest non-NAC ancestor, which is
/// guaranteed to exist.
fn closest_non_native_anonymous_ancestor(&self) -> Option<Self> {
unreachable!("Servo doesn't know about NAC");
}
/// Get this element's style attribute.
- fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>>;
+ fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>;
/// Unset the style attribute's dirty bit.
/// Servo doesn't need to manage ditry bit for style attribute.
fn unset_dirty_style_attribute(&self) {
}
/// Get this element's SMIL override declarations.
- fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
+ fn get_smil_override(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
None
}
/// Get this element's animation rule by the cascade level.
fn get_animation_rule_by_cascade(&self,
_cascade_level: CascadeLevel)
-> Option<Arc<Locked<PropertyDeclarationBlock>>> {
None
--- a/servo/components/style/gecko/restyle_damage.rs
+++ b/servo/components/style/gecko/restyle_damage.rs
@@ -51,17 +51,17 @@ impl GeckoRestyleDamage {
source: &nsStyleContext,
new_style: &Arc<ComputedValues>
) -> StyleDifference {
// TODO(emilio): Const-ify this?
let context = source as *const nsStyleContext as *mut nsStyleContext;
let mut any_style_changed: bool = false;
let hint = unsafe {
bindings::Gecko_CalcStyleDifference(context,
- new_style.as_borrowed_opt().unwrap(),
+ new_style.as_borrowed(),
&mut any_style_changed)
};
let change = if any_style_changed { StyleChange::Changed } else { StyleChange::Unchanged };
StyleDifference::new(GeckoRestyleDamage(hint), change)
}
/// Returns true if this restyle damage contains all the damage of |other|.
pub fn contains(self, other: Self) -> bool {
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -59,17 +59,17 @@ use gecko_bindings::structs::{nsIAtom, n
use gecko_bindings::structs::ELEMENT_HANDLED_SNAPSHOT;
use gecko_bindings::structs::ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::ELEMENT_HAS_SNAPSHOT;
use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
use gecko_bindings::structs::NODE_IS_NATIVE_ANONYMOUS;
use gecko_bindings::structs::nsIDocument_DocumentTheme as DocumentTheme;
-use gecko_bindings::sugar::ownership::{HasArcFFI, HasSimpleFFI};
+use gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasSimpleFFI};
use logical_geometry::WritingMode;
use media_queries::Device;
use properties::{ComputedValues, parse_style_attribute};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
use properties::animated_properties::{AnimatableLonghand, AnimationValue, AnimationValueMap};
use properties::animated_properties::TransitionProperty;
use properties::style_structs::Font;
use rule_tree::CascadeLevel as ServoCascadeLevel;
@@ -83,17 +83,17 @@ use shared_lock::Locked;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::DerefMut;
use std::ptr;
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
-use stylearc::Arc;
+use stylearc::{Arc, ArcBorrow, RawOffsetArc};
use stylesheets::UrlExtraData;
use stylist::Stylist;
/// A simple wrapper over a non-null Gecko node (`nsINode`) pointer.
///
/// Important: We don't currently refcount the DOM, because the wrapper lifetime
/// magic guarantees that our LayoutFoo references won't outlive the root, and
/// we don't mutate any of the references on the Gecko side during restyle.
@@ -849,36 +849,40 @@ impl<'le> TElement for GeckoElement<'le>
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
}
fn owner_doc_matches_for_testing(&self, device: &Device) -> bool {
self.as_node().owner_doc() as *const structs::nsIDocument ==
device.pres_context().mDocument.raw::<structs::nsIDocument>()
}
- fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
+ fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
if !self.may_have_style_attribute() {
return None;
}
let declarations = unsafe { Gecko_GetStyleAttrDeclarationBlock(self.0) };
- declarations.map_or(None, |s| s.as_arc_opt())
+ let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
+ = declarations.and_then(|s| s.as_arc_opt());
+ declarations.map(|s| s.borrow_arc())
}
fn unset_dirty_style_attribute(&self) {
if !self.may_have_style_attribute() {
return;
}
unsafe { Gecko_UnsetDirtyStyleAttr(self.0) };
}
- fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
+ fn get_smil_override(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
let declarations = unsafe { Gecko_GetSMILOverrideDeclarationBlock(self.0) };
- declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
+ let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
+ = declarations.and_then(|s| s.as_arc_opt());
+ declarations.map(|s| s.borrow_arc())
}
fn get_animation_rule_by_cascade(&self, cascade_level: ServoCascadeLevel)
-> Option<Arc<Locked<PropertyDeclarationBlock>>> {
match cascade_level {
ServoCascadeLevel::Animations => self.get_animation_rule(),
ServoCascadeLevel::Transitions => self.get_transition_rule(),
_ => panic!("Unsupported cascade level for getting the animation rule")
@@ -1087,19 +1091,19 @@ impl<'le> TElement for GeckoElement<'le>
tasks: UpdateAnimationsTasks) {
// We have to update animations even if the element has no computed
// style since it means the element is in a display:none subtree, we
// should destroy all CSS animations in display:none subtree.
let computed_data = self.borrow_data();
let computed_values =
computed_data.as_ref().map(|d| d.styles.primary());
let computed_values_opt =
- computed_values.map(|v| *HasArcFFI::arc_as_borrowed(v));
+ computed_values.map(|v| v.as_borrowed());
let before_change_values =
- before_change_style.as_ref().map(|v| *HasArcFFI::arc_as_borrowed(v));
+ before_change_style.as_ref().map(|v| v.as_borrowed());
unsafe {
Gecko_UpdateAnimations(self.0,
before_change_values,
computed_values_opt,
tasks.bits());
}
}
@@ -1171,17 +1175,17 @@ impl<'le> TElement for GeckoElement<'le>
let mut map = HashMap::with_capacity(collection_length);
for i in 0..collection_length {
let (property, raw_end_value) = unsafe {
(Gecko_ElementTransitions_PropertyAt(self.0, i as usize).into(),
Gecko_ElementTransitions_EndValueAt(self.0, i as usize))
};
let end_value = AnimationValue::arc_from_borrowed(&raw_end_value);
debug_assert!(end_value.is_some());
- map.insert(property, end_value.unwrap().clone());
+ map.insert(property, end_value.unwrap().clone_arc());
}
map
}
fn might_need_transitions_update(&self,
old_values: Option<&ComputedValues>,
new_values: &ComputedValues) -> bool {
use properties::longhands::display::computed_value as display;
@@ -1417,27 +1421,29 @@ impl<'le> PresentationalHintsSynthesizer
if self.get_local_name().as_ptr() == atom!("th").as_ptr() {
hints.push(TH_RULE.clone());
} else if self.get_local_name().as_ptr() == atom!("table").as_ptr() &&
self.as_node().owner_doc().mCompatMode == structs::nsCompatibility::eCompatibility_NavQuirks {
hints.push(TABLE_COLOR_RULE.clone());
}
}
let declarations = unsafe { Gecko_GetHTMLPresentationAttrDeclarationBlock(self.0) };
- let declarations = declarations.and_then(|s| s.as_arc_opt());
+ let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
+ = declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
- ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
+ ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}
let declarations = unsafe { Gecko_GetExtraContentStyleDeclarations(self.0) };
- let declarations = declarations.and_then(|s| s.as_arc_opt());
+ let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
+ = declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
- ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
+ ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}
// Support for link, vlink, and alink presentation hints on <body>
if self.is_link() {
// Unvisited vs. visited styles are computed up-front based on the
// visited mode (not the element's actual state).
let declarations = match visited_handling {
@@ -1447,30 +1453,32 @@ impl<'le> PresentationalHintsSynthesizer
},
VisitedHandlingMode::AllLinksUnvisited => unsafe {
Gecko_GetUnvisitedLinkAttrDeclarationBlock(self.0)
},
VisitedHandlingMode::RelevantLinkVisited => unsafe {
Gecko_GetVisitedLinkAttrDeclarationBlock(self.0)
},
};
- let declarations = declarations.and_then(|s| s.as_arc_opt());
+ let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>> =
+ declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
- ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
+ ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}
let active = self.get_state().intersects(NonTSPseudoClass::Active.state_flag());
if active {
let declarations = unsafe { Gecko_GetActiveLinkAttrDeclarationBlock(self.0) };
- let declarations = declarations.and_then(|s| s.as_arc_opt());
+ let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
+ = declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
- ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
+ ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}
}
}
// xml:lang has precedence over lang, which can be
// set by Gecko_GetHTMLPresentationAttrDeclarationBlock
//
--- a/servo/components/style/gecko_bindings/sugar/ownership.rs
+++ b/servo/components/style/gecko_bindings/sugar/ownership.rs
@@ -3,17 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Helpers for different FFI pointer kinds that Gecko's FFI layer uses.
use std::marker::PhantomData;
use std::mem::{forget, transmute};
use std::ops::{Deref, DerefMut};
use std::ptr;
-use stylearc::Arc;
+use stylearc::{Arc, RawOffsetArc};
/// Indicates that a given Servo type has a corresponding Gecko FFI type.
pub unsafe trait HasFFI : Sized + 'static {
/// The corresponding Gecko type that this rust type represents.
///
/// See the examples in `components/style/gecko/conversions.rs`.
type FFIType: Sized;
}
@@ -83,61 +83,61 @@ pub unsafe trait HasArcFFI : HasFFI {
}
/// Given a (possibly null) borrowed FFI reference, decrements the refcount.
/// Unsafe since it doesn't consume the backing Arc. Run it only when you
/// know that a strong reference to the backing Arc is disappearing
/// (usually on the C++ side) without running the Arc destructor.
unsafe fn release_opt(ptr: Option<&Self::FFIType>) {
if let Some(arc) = Self::arc_from_borrowed(&ptr) {
- let _: Arc<_> = ptr::read(arc as *const Arc<_>);
+ let _: RawOffsetArc<_> = ptr::read(arc as *const RawOffsetArc<_>);
}
}
/// Artificially increments the refcount of a borrowed Arc over FFI.
unsafe fn addref(ptr: &Self::FFIType) {
forget(Self::as_arc(&ptr).clone())
}
/// Given a non-null borrowed FFI reference, decrements the refcount.
/// Unsafe since it doesn't consume the backing Arc. Run it only when you
/// know that a strong reference to the backing Arc is disappearing
/// (usually on the C++ side) without running the Arc destructor.
unsafe fn release(ptr: &Self::FFIType) {
- let _: Arc<_> = ptr::read(Self::as_arc(&ptr) as *const Arc<_>);
+ let _: RawOffsetArc<_> = ptr::read(Self::as_arc(&ptr) as *const RawOffsetArc<_>);
}
#[inline]
/// Converts a borrowed FFI reference to a borrowed Arc.
///
/// &GeckoType -> &Arc<ServoType>
- fn as_arc<'a>(ptr: &'a &Self::FFIType) -> &'a Arc<Self> {
+ fn as_arc<'a>(ptr: &'a &Self::FFIType) -> &'a RawOffsetArc<Self> {
debug_assert!(!(ptr as *const _).is_null());
unsafe {
- transmute::<&&Self::FFIType, &Arc<Self>>(ptr)
+ transmute::<&&Self::FFIType, &RawOffsetArc<Self>>(ptr)
}
}
#[inline]
/// Converts a borrowed Arc to a borrowed FFI reference.
///
/// &Arc<ServoType> -> &GeckoType
- fn arc_as_borrowed<'a>(arc: &'a Arc<Self>) -> &'a &Self::FFIType {
+ fn arc_as_borrowed<'a>(arc: &'a RawOffsetArc<Self>) -> &'a &Self::FFIType {
unsafe {
- transmute::<&Arc<Self>, &&Self::FFIType>(arc)
+ transmute::<&RawOffsetArc<Self>, &&Self::FFIType>(arc)
}
}
#[inline]
/// Converts a borrowed nullable FFI reference to a borrowed Arc.
///
/// &GeckoType -> &Arc<ServoType>
- fn arc_from_borrowed<'a>(ptr: &'a Option<&Self::FFIType>) -> Option<&'a Arc<Self>> {
+ fn arc_from_borrowed<'a>(ptr: &'a Option<&Self::FFIType>) -> Option<&'a RawOffsetArc<Self>> {
unsafe {
if let Some(ref reference) = *ptr {
- Some(transmute::<&&Self::FFIType, &Arc<_>>(reference))
+ Some(transmute::<&&Self::FFIType, &RawOffsetArc<_>>(reference))
} else {
None
}
}
}
}
#[repr(C)]
@@ -160,46 +160,46 @@ impl<GeckoType> Strong<GeckoType> {
#[inline]
/// Given a non-null strong FFI reference, converts it into a servo-side
/// Arc.
///
/// Panics on null.
///
/// Strong<GeckoType> -> Arc<ServoType>
- pub fn into_arc<ServoType>(self) -> Arc<ServoType>
+ pub fn into_arc<ServoType>(self) -> RawOffsetArc<ServoType>
where ServoType: HasArcFFI<FFIType = GeckoType>,
{
self.into_arc_opt().unwrap()
}
#[inline]
/// Given a strong FFI reference,
/// converts it into a servo-side Arc
/// Returns None on null.
///
/// Strong<GeckoType> -> Arc<ServoType>
- pub fn into_arc_opt<ServoType>(self) -> Option<Arc<ServoType>>
+ pub fn into_arc_opt<ServoType>(self) -> Option<RawOffsetArc<ServoType>>
where ServoType: HasArcFFI<FFIType = GeckoType>,
{
if self.is_null() {
None
} else {
unsafe { Some(transmute(self)) }
}
}
#[inline]
/// Given a reference to a strong FFI reference, converts it to a reference
/// to a servo-side Arc.
///
/// Returns None on null.
///
/// Strong<GeckoType> -> Arc<ServoType>
- pub fn as_arc_opt<ServoType>(&self) -> Option<&Arc<ServoType>>
+ pub fn as_arc_opt<ServoType>(&self) -> Option<&RawOffsetArc<ServoType>>
where ServoType: HasArcFFI<FFIType = GeckoType>,
{
if self.is_null() {
None
} else {
unsafe { Some(transmute(self)) }
}
}
@@ -217,39 +217,49 @@ pub unsafe trait FFIArcHelpers {
/// The Rust FFI type that we're implementing methods for.
type Inner: HasArcFFI;
/// Converts an Arc into a strong FFI reference.
///
/// Arc<ServoType> -> Strong<GeckoType>
fn into_strong(self) -> Strong<<Self::Inner as HasFFI>::FFIType>;
- /// Produces a (nullable) borrowed FFI reference by borrowing an Arc.
+ /// Produces a borrowed FFI reference by borrowing an Arc.
///
- /// &Arc<ServoType> -> Option<&GeckoType>
- ///
- /// FIXME(emilio): What's the point of the nullability? Arc should be
- /// non-null, right?
+ /// &Arc<ServoType> -> &GeckoType
///
/// Then the `arc_as_borrowed` method can go away.
- fn as_borrowed_opt(&self) -> Option<&<Self::Inner as HasFFI>::FFIType>;
+ fn as_borrowed(&self) -> &<Self::Inner as HasFFI>::FFIType;
}
-unsafe impl<T: HasArcFFI> FFIArcHelpers for Arc<T> {
+unsafe impl<T: HasArcFFI> FFIArcHelpers for RawOffsetArc<T> {
type Inner = T;
#[inline]
fn into_strong(self) -> Strong<T::FFIType> {
unsafe { transmute(self) }
}
#[inline]
- fn as_borrowed_opt(&self) -> Option<&T::FFIType> {
- let borrowedptr = self as *const Arc<T> as *const Option<&T::FFIType>;
- unsafe { ptr::read(borrowedptr) }
+ fn as_borrowed(&self) -> &T::FFIType {
+ unsafe { &*(&**self as *const T as *const T::FFIType) }
+ }
+}
+
+unsafe impl<T: HasArcFFI> FFIArcHelpers for Arc<T> {
+ type Inner = T;
+
+ #[inline]
+ fn into_strong(self) -> Strong<T::FFIType> {
+ Arc::into_raw_offset(self).into_strong()
+ }
+
+ #[inline]
+ fn as_borrowed(&self) -> &T::FFIType {
+ unsafe { &*(&**self as *const T as *const T::FFIType) }
}
}
#[repr(C)]
#[derive(Debug)]
/// Gecko-FFI-safe owned pointer.
///
/// Cannot be null, and leaks on drop, so needs to be converted into a rust-side
--- a/servo/components/style/gecko_bindings/sugar/refptr.rs
+++ b/servo/components/style/gecko_bindings/sugar/refptr.rs
@@ -206,17 +206,17 @@ impl<T: RefCounted> structs::RefPtr<T> {
*self = other.forget();
}
}
impl<T> structs::RefPtr<T> {
/// Sets the contents to an Arc<T>
/// will leak existing contents
pub fn set_arc_leaky<U>(&mut self, other: Arc<U>) where U: HasArcFFI<FFIType = T> {
- *self = unsafe { mem::transmute(other) }; // Arc::into_raw is unstable :(
+ *self = unsafe { mem::transmute(Arc::into_raw_offset(other)) };
}
}
impl<T: RefCounted> Drop for RefPtr<T> {
fn drop(&mut self) {
unsafe { self.release() }
}
}
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -13,17 +13,17 @@ use dom::TElement;
use invalidation::element::restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS};
use invalidation::element::restyle_hints::{RESTYLE_SMIL, RESTYLE_STYLE_ATTRIBUTE};
use invalidation::element::restyle_hints::RestyleHint;
use properties::ComputedValues;
use properties::longhands::display::computed_value as display;
use rule_tree::{CascadeLevel, StrongRuleNode};
use selector_parser::{PseudoElement, RestyleDamage};
use selectors::matching::ElementSelectorFlags;
-use stylearc::Arc;
+use stylearc::{Arc, ArcBorrow};
/// Represents the result of comparing an element's old and new style.
pub struct StyleDifference {
/// The resulting damage.
pub damage: RestyleDamage,
/// Whether any styles changed.
pub change: StyleChange,
@@ -685,17 +685,17 @@ pub trait MatchMethods : TElement {
};
let primary_rules = match primary_rules {
Some(r) => r,
None => return false,
};
let replace_rule_node = |level: CascadeLevel,
- pdb: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
+ pdb: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
path: &mut StrongRuleNode| -> bool {
let new_node = stylist.rule_tree()
.update_rule_at_level(level, pdb, path, guards);
match new_node {
Some(n) => {
*path = n;
level.is_important()
},
@@ -732,17 +732,17 @@ pub trait MatchMethods : TElement {
self.get_smil_override(),
primary_rules);
}
let replace_rule_node_for_animation = |level: CascadeLevel,
primary_rules: &mut StrongRuleNode| {
let animation_rule = self.get_animation_rule_by_cascade(level);
replace_rule_node(level,
- animation_rule.as_ref(),
+ animation_rule.as_ref().map(|a| a.borrow_arc()),
primary_rules);
};
// Apply Transition rules and Animation rules if the corresponding restyle hint
// is contained.
if replacements.contains(RESTYLE_CSS_TRANSITIONS) {
replace_rule_node_for_animation(CascadeLevel::Transitions,
primary_rules);
--- a/servo/components/style/rule_tree/mod.rs
+++ b/servo/components/style/rule_tree/mod.rs
@@ -11,17 +11,17 @@ use applicable_declarations::ApplicableD
use heapsize::HeapSizeOf;
use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
use smallvec::SmallVec;
use std::io::{self, Write};
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
-use stylearc::{Arc, NonZeroPtrMut};
+use stylearc::{Arc, ArcBorrow, NonZeroPtrMut};
use stylesheets::StyleRule;
use thread_state;
/// The rule tree, the structure servo uses to preserve the results of selector
/// matching.
///
/// This is organized as a tree of rules. When a node matches a set of rules,
/// they're inserted in order in the tree, starting with the less specific one.
@@ -303,17 +303,17 @@ impl RuleTree {
}
/// Replaces a rule in a given level (if present) for another rule.
///
/// Returns the resulting node that represents the new path, or None if
/// the old path is still valid.
pub fn update_rule_at_level(&self,
level: CascadeLevel,
- pdb: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
+ pdb: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
path: &StrongRuleNode,
guards: &StylesheetGuards)
-> Option<StrongRuleNode> {
debug_assert!(level.is_unique_per_element());
// TODO(emilio): Being smarter with lifetimes we could avoid a bit of
// the refcount churn.
let mut current = path.clone();
@@ -342,17 +342,17 @@ impl RuleTree {
// TODO(emilio): Another potential optimization is the one where
// we can just replace the rule at that level for `pdb`, and
// then we don't need to re-create the children, and `path` is
// also equally valid. This is less likely, and would require an
// in-place mutation of the source, which is, at best, fiddly,
// so let's skip it for now.
let is_here_already = match ¤t.get().source {
&StyleSource::Declarations(ref already_here) => {
- Arc::ptr_eq(pdb, already_here)
+ pdb.with_arc(|arc| Arc::ptr_eq(arc, already_here))
},
_ => unreachable!("Replacing non-declarations style?"),
};
if is_here_already {
debug!("Picking the fast path in rule replacement");
return None;
}
@@ -366,23 +366,23 @@ impl RuleTree {
//
// These optimizations are likely to be important, because the levels
// where replacements apply (style and animations) tend to trigger
// pretty bad styling cases already.
if let Some(pdb) = pdb {
if level.is_important() {
if pdb.read_with(level.guard(guards)).any_important() {
current = current.ensure_child(self.root.downgrade(),
- StyleSource::Declarations(pdb.clone()),
+ StyleSource::Declarations(pdb.clone_arc()),
level);
}
} else {
if pdb.read_with(level.guard(guards)).any_normal() {
current = current.ensure_child(self.root.downgrade(),
- StyleSource::Declarations(pdb.clone()),
+ StyleSource::Declarations(pdb.clone_arc()),
level);
}
}
}
// Now the rule is in the relevant place, push the children as
// necessary.
let rule =
--- a/servo/components/style/sharing/checks.rs
+++ b/servo/components/style/sharing/checks.rs
@@ -38,17 +38,17 @@ pub fn have_same_style_attribute<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>
) -> bool
where E: TElement,
{
match (target.style_attribute(), candidate.style_attribute()) {
(None, None) => true,
(Some(_), None) | (None, Some(_)) => false,
- (Some(a), Some(b)) => Arc::ptr_eq(a, b)
+ (Some(a), Some(b)) => &*a as *const _ == &*b as *const _
}
}
/// Whether two elements have the same same presentational attributes.
pub fn have_same_presentational_hints<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>
) -> bool
--- a/servo/components/style/stylesheets/rule_list.rs
+++ b/servo/components/style/stylesheets/rule_list.rs
@@ -1,16 +1,16 @@
/* 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/. */
//! A list of CSS rules.
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard};
-use stylearc::Arc;
+use stylearc::{Arc, RawOffsetArc};
use stylesheets::{CssRule, RulesMutateError};
use stylesheets::loader::StylesheetLoader;
use stylesheets::memory::{MallocSizeOfFn, MallocSizeOfWithGuard};
use stylesheets::rule_parser::State;
use stylesheets::stylesheet::StylesheetContents;
/// A list of CSS rules.
#[derive(Debug)]
@@ -104,17 +104,17 @@ pub trait CssRulesHelpers {
rule: &str,
parent_stylesheet_contents: &StylesheetContents,
index: usize,
nested: bool,
loader: Option<&StylesheetLoader>)
-> Result<CssRule, RulesMutateError>;
}
-impl CssRulesHelpers for Arc<Locked<CssRules>> {
+impl CssRulesHelpers for RawOffsetArc<Locked<CssRules>> {
fn insert_rule(&self,
lock: &SharedRwLock,
rule: &str,
parent_stylesheet_contents: &StylesheetContents,
index: usize,
nested: bool,
loader: Option<&StylesheetLoader>)
-> Result<CssRule, RulesMutateError> {
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -32,17 +32,17 @@ use selectors::parser::{SelectorIter, Se
use selectors::sink::Push;
use selectors::visitor::SelectorVisitor;
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
use smallvec::VecLike;
use std::fmt::Debug;
#[cfg(feature = "servo")]
use std::marker::PhantomData;
use style_traits::viewport::ViewportConstraints;
-use stylearc::Arc;
+use stylearc::{Arc, ArcBorrow};
#[cfg(feature = "gecko")]
use stylesheets::{CounterStyleRule, FontFaceRule};
use stylesheets::{CssRule, StyleRule};
use stylesheets::{StylesheetInDocument, Origin, UserAgentStylesheets};
use stylesheets::keyframes_rule::KeyframesAnimation;
use stylesheets::viewport_rule::{self, MaybeNew, ViewportRule};
use thread_state;
@@ -1098,18 +1098,18 @@ impl Stylist {
/// This corresponds to `ElementRuleCollector` in WebKit.
///
/// The `StyleRelations` recorded in `MatchingContext` indicate hints about
/// which kind of rules have matched.
pub fn push_applicable_declarations<E, V, F>(
&self,
element: &E,
pseudo_element: Option<&PseudoElement>,
- style_attribute: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
- smil_override: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
+ style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
+ smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
animation_rules: AnimationRules,
rule_inclusion: RuleInclusion,
applicable_declarations: &mut V,
context: &mut MatchingContext,
flags_setter: &mut F)
where E: TElement,
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> + Debug,
F: FnMut(&E, ElementSelectorFlags),
@@ -1203,26 +1203,26 @@ impl Stylist {
debug!("skipping author normal rules");
}
if !only_default_rules {
// Step 4: Normal style attributes.
if let Some(sa) = style_attribute {
Push::push(
applicable_declarations,
- ApplicableDeclarationBlock::from_declarations(sa.clone(),
+ ApplicableDeclarationBlock::from_declarations(sa.clone_arc(),
CascadeLevel::StyleAttributeNormal));
}
// Step 5: SMIL override.
// Declarations from SVG SMIL animation elements.
if let Some(so) = smil_override {
Push::push(
applicable_declarations,
- ApplicableDeclarationBlock::from_declarations(so.clone(),
+ ApplicableDeclarationBlock::from_declarations(so.clone_arc(),
CascadeLevel::SMILOverride));
}
// Step 6: Animations.
// The animations sheet (CSS animations, script-generated animations,
// and CSS transitions that are no longer tied to CSS markup)
if let Some(anim) = animation_rules.0 {
Push::push(
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -85,28 +85,28 @@ use style::gecko_bindings::structs::nsre
use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasFFI, HasArcFFI, HasBoxFFI};
use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
use style::gecko_bindings::sugar::refptr::RefPtr;
use style::gecko_properties::{self, style_structs};
use style::invalidation::element::restyle_hints::{self, RestyleHint};
use style::media_queries::{MediaList, parse_media_query_list};
use style::parallel;
use style::parser::ParserContext;
-use style::properties::{ComputedValues, Importance, SourcePropertyDeclaration};
+use style::properties::{ComputedValues, ComputedValuesInner, Importance, SourcePropertyDeclaration};
use style::properties::{LonghandIdSet, PropertyDeclaration, PropertyDeclarationBlock, PropertyId, StyleBuilder};
use style::properties::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
use style::properties::animated_properties::{Animatable, AnimatableLonghand, AnimationValue};
use style::properties::parse_one_declaration_into;
use style::rule_tree::StyleSource;
use style::selector_parser::PseudoElementCascadeType;
use style::sequential;
use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
use style::string_cache::Atom;
use style::style_adjuster::StyleAdjuster;
-use style::stylearc::Arc;
+use style::stylearc::{Arc, RawOffsetArc};
use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers, DocumentRule};
use style::stylesheets::{ImportRule, KeyframesRule, MallocSizeOfWithGuard, MediaRule};
use style::stylesheets::{NamespaceRule, Origin, PageRule, StyleRule, SupportsRule};
use style::stylesheets::StylesheetContents;
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
use style::stylesheets::supports_rule::parse_condition_or_declaration;
use style::stylist::RuleInclusion;
@@ -424,17 +424,17 @@ pub extern "C" fn Servo_AnimationCompose
// If either of the segment endpoints are null, get the underlying value to
// use from the current value in the values map (set by a lower-priority
// effect), or, if there is no current value, look up the cached base value
// for this property.
let underlying_value = if need_underlying_value {
let previous_composed_value = value_map.get(&property).cloned();
previous_composed_value.or_else(|| {
let raw_base_style = unsafe { Gecko_AnimationGetBaseStyle(base_values, css_property) };
- AnimationValue::arc_from_borrowed(&raw_base_style).map(|v| v.as_ref()).cloned()
+ AnimationValue::arc_from_borrowed(&raw_base_style).map(|v| &**v).cloned()
})
} else {
None
};
if need_underlying_value && underlying_value.is_none() {
warn!("Underlying value should be valid when we expect to use it");
return;
@@ -454,17 +454,17 @@ pub extern "C" fn Servo_AnimationCompose
raw_to_value = unsafe { &*segment.mToValue.mServo.mRawPtr };
Some(AnimationValue::as_arc(&raw_to_value))
} else {
None
};
// Composite with underlying value.
// A return value of None means, "Just use keyframe_value as-is."
- let composite_endpoint = |keyframe_value: Option<&Arc<AnimationValue>>,
+ let composite_endpoint = |keyframe_value: Option<&RawOffsetArc<AnimationValue>>,
composite_op: CompositeOperation| -> Option<AnimationValue> {
match keyframe_value {
Some(keyframe_value) => {
match composite_op {
CompositeOperation::Add => {
debug_assert!(need_underlying_value,
"Should have detected we need an underlying value");
underlying_value.as_ref().unwrap().add(keyframe_value).ok()
@@ -493,25 +493,25 @@ pub extern "C" fn Servo_AnimationCompose
"Should have a suitable to value to use");
// Apply iteration composite behavior.
if iteration_composite == IterationCompositeOperation::Accumulate &&
computed_timing.mCurrentIteration > 0 {
let raw_last_value;
let last_value = if !last_segment.mToValue.mServo.mRawPtr.is_null() {
raw_last_value = unsafe { &*last_segment.mToValue.mServo.mRawPtr };
- AnimationValue::as_arc(&raw_last_value).as_ref()
+ &*AnimationValue::as_arc(&raw_last_value)
} else {
debug_assert!(need_underlying_value,
"Should have detected we need an underlying value");
underlying_value.as_ref().unwrap()
};
// As with composite_endpoint, a return value of None means, "Use keyframe_value as-is."
- let apply_iteration_composite = |keyframe_value: Option<&Arc<AnimationValue>>,
+ let apply_iteration_composite = |keyframe_value: Option<&RawOffsetArc<AnimationValue>>,
composited_value: Option<AnimationValue>|
-> Option<AnimationValue> {
let count = computed_timing.mCurrentIteration;
match composited_value {
Some(endpoint) => last_value.accumulate(&endpoint, count)
.ok()
.or(Some(endpoint)),
None => last_value.accumulate(keyframe_value.unwrap(), count)
@@ -1239,17 +1239,17 @@ pub extern "C" fn Servo_StyleRule_GetSty
})
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
declarations: RawServoDeclarationBlockBorrowed) {
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
write_locked_arc(rule, |rule: &mut StyleRule| {
- rule.block = declarations.clone();
+ rule.block = declarations.clone_arc();
})
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) {
read_locked_arc(rule, |rule: &StyleRule| {
rule.selectors.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
})
@@ -1377,17 +1377,17 @@ pub extern "C" fn Servo_Keyframe_GetStyl
read_locked_arc(keyframe, |keyframe: &Keyframe| keyframe.block.clone().into_strong())
}
#[no_mangle]
pub extern "C" fn Servo_Keyframe_SetStyle(keyframe: RawServoKeyframeBorrowed,
declarations: RawServoDeclarationBlockBorrowed) {
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
write_locked_arc(keyframe, |keyframe: &mut Keyframe| {
- keyframe.block = declarations.clone();
+ keyframe.block = declarations.clone_arc();
})
}
#[no_mangle]
pub extern "C" fn Servo_KeyframesRule_GetName(rule: RawServoKeyframesRuleBorrowed) -> *mut nsIAtom {
read_locked_arc(rule, |rule: &KeyframesRule| rule.name.as_atom().as_ptr())
}
@@ -1475,17 +1475,17 @@ pub extern "C" fn Servo_PageRule_GetStyl
})
}
#[no_mangle]
pub extern "C" fn Servo_PageRule_SetStyle(rule: RawServoPageRuleBorrowed,
declarations: RawServoDeclarationBlockBorrowed) {
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
write_locked_arc(rule, |rule: &mut PageRule| {
- rule.block = declarations.clone();
+ rule.block = declarations.clone_arc();
})
}
#[no_mangle]
pub extern "C" fn Servo_SupportsRule_GetConditionText(rule: RawServoSupportsRuleBorrowed,
result: *mut nsAString) {
read_locked_arc(rule, |rule: &SupportsRule| {
rule.condition.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
@@ -1554,17 +1554,17 @@ pub extern "C" fn Servo_ResolvePseudoSty
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let style = get_pseudo_style(
&guard,
element,
&pseudo,
RuleInclusion::All,
&data.styles,
- ComputedValues::arc_from_borrowed(&inherited_style),
+ ComputedValues::arc_from_borrowed(&inherited_style).map(|x| &***x),
&*doc_data,
is_probe
);
match style {
Some(s) => s.into_strong(),
None => {
debug_assert!(is_probe);
@@ -1579,17 +1579,17 @@ pub extern "C" fn Servo_SetExplicitStyle
{
let element = GeckoElement(element);
let style = ComputedValues::as_arc(&style);
debug!("Servo_SetExplicitStyle: {:?}", element);
// We only support this API for initial styling. There's no reason it couldn't
// work for other things, we just haven't had a reason to do so.
debug_assert!(element.get_data().is_none());
let mut data = unsafe { element.ensure_data() };
- data.styles.primary = Some(style.clone());
+ data.styles.primary = Some(style.clone_arc());
}
#[no_mangle]
pub extern "C" fn Servo_HasAuthorSpecifiedRules(element: RawGeckoElementBorrowed,
rule_type_mask: u32,
author_colors_allowed: bool)
-> bool
{
@@ -1608,17 +1608,17 @@ pub extern "C" fn Servo_HasAuthorSpecifi
}
fn get_pseudo_style(
guard: &SharedRwLockReadGuard,
element: GeckoElement,
pseudo: &PseudoElement,
rule_inclusion: RuleInclusion,
styles: &ElementStyles,
- inherited_styles: Option<&Arc<ComputedValues>>,
+ inherited_styles: Option<&ComputedValuesInner>,
doc_data: &PerDocumentStyleDataImpl,
is_probe: bool,
) -> Option<Arc<ComputedValues>> {
let style = match pseudo.cascade_type() {
PseudoElementCascadeType::Eager => {
match *pseudo {
PseudoElement::FirstLetter => {
styles.pseudos.get(&pseudo).and_then(|pseudo_styles| {
@@ -1637,27 +1637,27 @@ fn get_pseudo_style(
&inputs,
&guards,
inherited_styles,
&metrics)
})
},
_ => {
debug_assert!(inherited_styles.is_none() ||
- ptr::eq(&**inherited_styles.unwrap(),
- &**styles.primary()));
+ ptr::eq(&*inherited_styles.unwrap(),
+ &***styles.primary()));
styles.pseudos.get(&pseudo).cloned()
},
}
}
PseudoElementCascadeType::Precomputed => unreachable!("No anonymous boxes"),
PseudoElementCascadeType::Lazy => {
debug_assert!(inherited_styles.is_none() ||
- ptr::eq(&**inherited_styles.unwrap(),
- &**styles.primary()));
+ ptr::eq(&*inherited_styles.unwrap(),
+ &***styles.primary()));
let base = if pseudo.inherits_from_default_values() {
doc_data.default_computed_values()
} else {
styles.primary()
};
let guards = StylesheetGuards::same(guard);
let metrics = get_metrics_provider_for_product();
doc_data.stylist
@@ -1756,22 +1756,24 @@ pub extern "C" fn Servo_ComputedValues_E
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoComputedValuesBorrowed,
rules: RawGeckoServoStyleRuleListBorrowedMut) {
let values = ComputedValues::as_arc(&values);
if let Some(ref rule_node) = values.rules {
let mut result = vec![];
for node in rule_node.self_and_ancestors() {
if let &StyleSource::Style(ref rule) = node.style_source() {
- result.push(Locked::<StyleRule>::arc_as_borrowed(&rule));
+ result.push(rule);
}
}
unsafe { rules.set_len(result.len() as u32) };
- for (&src, dest) in result.into_iter().zip(rules.iter_mut()) {
- *dest = src;
+ for (ref src, ref mut dest) in result.into_iter().zip(rules.iter_mut()) {
+ src.with_raw_offset_arc(|arc| {
+ **dest = *Locked::<StyleRule>::arc_as_borrowed(arc);
+ })
}
}
}
/// See the comment in `Device` to see why it's ok to pass an owned reference to
/// the pres context (hint: the context outlives the StyleSet, that holds the
/// device alive).
#[no_mangle]
@@ -3268,17 +3270,17 @@ pub extern "C" fn Servo_StyleSet_Resolve
Some(parent) => &parent.inner,
None => doc_data.default_computed_values(),
};
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
doc_data.stylist.compute_for_declarations(&guards,
parent_style,
- declarations.clone()).into_strong()
+ declarations.clone_arc()).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency(
raw_data: RawServoStyleSetBorrowed,
element: RawGeckoElementBorrowed,
local_name: *mut nsIAtom,
) -> bool {