Bug 1367904 - Part 8: stylo: Replace Arc<ComputedValues> with StrongComputedValues so we can use a different refptr later; r?bholley draft
authorManish Goregaokar <manishearth@gmail.com>
Thu, 15 Jun 2017 22:49:50 -0700
changeset 599368 859fef1f640384ae67b7e354213b7329c3ad07cb
parent 599367 fc323372d3777d500aa7826a625b510298c31766
child 599369 25b838f81b6e9d2a47c1966d6926e1856b1c902b
push id65502
push userbmo:manishearth@gmail.com
push dateFri, 23 Jun 2017 02:54:27 +0000
reviewersbholley
bugs1367904
milestone56.0a1
Bug 1367904 - Part 8: stylo: Replace Arc<ComputedValues> with StrongComputedValues so we can use a different refptr later; r?bholley MozReview-Commit-ID: C6PEL5pM8md
servo/components/style/animation.rs
servo/components/style/context.rs
servo/components/style/data.rs
servo/components/style/dom.rs
servo/components/style/gecko/restyle_damage.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/matching.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/stylist.rs
--- a/servo/components/style/animation.rs
+++ b/servo/components/style/animation.rs
@@ -6,17 +6,17 @@
 #![deny(missing_docs)]
 
 use Atom;
 use bezier::Bezier;
 use context::SharedStyleContext;
 use dom::OpaqueNode;
 use euclid::Point2D;
 use font_metrics::FontMetricsProvider;
-use properties::{self, CascadeFlags, ComputedValues, ComputedValuesInner, Importance};
+use properties::{self, CascadeFlags, ComputedValues, ComputedValuesInner, Importance, StrongComputedValues};
 use properties::animated_properties::{AnimatableLonghand, AnimatedProperty, TransitionProperty};
 use properties::longhands::animation_direction::computed_value::single_value::T as AnimationDirection;
 use properties::longhands::animation_iteration_count::single_value::computed_value::T as AnimationIterationCount;
 use properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
 use rule_tree::CascadeLevel;
 use std::sync::mpsc::Sender;
 use stylearc::Arc;
 use stylesheets::keyframes_rule::{KeyframesStep, KeyframesStepValue};
@@ -68,17 +68,17 @@ pub struct KeyframesAnimationState {
     /// The declared animation direction of this animation.
     pub direction: AnimationDirection,
     /// The current animation direction. This can only be `normal` or `reverse`.
     pub current_direction: AnimationDirection,
     /// Werther this keyframe animation is outdated due to a restyle.
     pub expired: bool,
     /// The original cascade style, needed to compute the generated keyframes of
     /// the animation.
-    pub cascade_style: Arc<ComputedValues>,
+    pub cascade_style: StrongComputedValues,
 }
 
 impl KeyframesAnimationState {
     /// Performs a tick in the animation state, i.e., increments the counter of
     /// the current iteration count, updates times and then toggles the
     /// direction if appropriate.
     ///
     /// Returns true if the animation should keep running.
@@ -429,17 +429,17 @@ impl PropertyAnimation {
 /// Returns true if any animations were kicked off and false otherwise.
 //
 // TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a
 // cloneable part and a non-cloneable part..
 #[cfg(feature = "servo")]
 pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>,
                                        opaque_node: OpaqueNode,
                                        old_style: &ComputedValues,
-                                       new_style: &mut Arc<ComputedValues>,
+                                       new_style: &mut StrongComputedValues,
                                        timer: &Timer,
                                        possibly_expired_animations: &[PropertyAnimation])
                                        -> bool {
     let mut had_animations = false;
     for i in 0..new_style.get_box().transition_property_count() {
         // Create any property animations, if applicable.
         let property_animations = PropertyAnimation::from_transition(i,
                                                                      old_style,
@@ -516,17 +516,17 @@ fn compute_style_for_animation_step(cont
     }
 }
 
 /// Triggers animations for a given node looking at the animation property
 /// values.
 pub fn maybe_start_animations(context: &SharedStyleContext,
                               new_animations_sender: &Sender<Animation>,
                               node: OpaqueNode,
-                              new_style: &Arc<ComputedValues>)
+                              new_style: &StrongComputedValues)
                               -> bool {
     let mut had_animations = false;
 
     let box_style = new_style.get_box();
     for (i, name) in box_style.animation_name_iter().enumerate() {
         let name = if let Some(atom) = name.as_atom() {
             atom
         } else {
@@ -590,17 +590,17 @@ pub fn maybe_start_animations(context: &
         }
     }
 
     had_animations
 }
 
 /// Updates a given computed style for a given animation frame. Returns a bool
 /// representing if the style was indeed updated.
-pub fn update_style_for_animation_frame(mut new_style: &mut Arc<ComputedValues>,
+pub fn update_style_for_animation_frame(mut new_style: &mut StrongComputedValues,
                                         now: f64,
                                         start_time: f64,
                                         frame: &AnimationFrame) -> bool {
     let mut progress = (now - start_time) / frame.duration;
     if progress > 1.0 {
         progress = 1.0
     }
 
@@ -611,17 +611,17 @@ pub fn update_style_for_animation_frame(
     frame.property_animation.update(Arc::make_mut(&mut new_style), progress);
 
     true
 }
 /// Updates a single animation and associated style based on the current time.
 /// If `damage` is provided, inserts the appropriate restyle damage.
 pub fn update_style_for_animation(context: &SharedStyleContext,
                                   animation: &Animation,
-                                  style: &mut Arc<ComputedValues>,
+                                  style: &mut StrongComputedValues,
                                   font_metrics_provider: &FontMetricsProvider) {
     debug!("update_style_for_animation: entering");
     debug_assert!(!animation.is_expired());
 
     match *animation {
         Animation::Transition(_, start_time, ref frame, _) => {
             debug!("update_style_for_animation: transition found");
             let now = context.timer.seconds();
@@ -785,17 +785,17 @@ pub fn update_style_for_animation(contex
             debug!("update_style_for_animation: got style change in animation \"{}\"", name);
             *style = new_style;
         }
     }
 }
 
 /// Update the style in the node when it finishes.
 #[cfg(feature = "servo")]
-pub fn complete_expired_transitions(node: OpaqueNode, style: &mut Arc<ComputedValues>,
+pub fn complete_expired_transitions(node: OpaqueNode, style: &mut StrongComputedValues,
                                     context: &SharedStyleContext) -> bool {
     let had_animations_to_expire;
     {
         let all_expired_animations = context.expired_animations.read();
         let animations_to_expire = all_expired_animations.get(&node);
         had_animations_to_expire = animations_to_expire.is_some();
         if let Some(ref animations) = animations_to_expire {
             for animation in *animations {
--- a/servo/components/style/context.rs
+++ b/servo/components/style/context.rs
@@ -12,26 +12,26 @@ use cache::LRUCache;
 use data::ElementData;
 use dom::{OpaqueNode, TNode, TElement, SendElement};
 use error_reporting::ParseErrorReporter;
 use euclid::Size2D;
 use fnv::FnvHashMap;
 use font_metrics::FontMetricsProvider;
 #[cfg(feature = "gecko")] use gecko_bindings::structs;
 #[cfg(feature = "servo")] use parking_lot::RwLock;
-#[cfg(feature = "gecko")] use properties::ComputedValues;
+#[cfg(feature = "gecko")] use properties::StrongComputedValues;
 use selector_parser::SnapshotMap;
 use selectors::matching::ElementSelectorFlags;
 use shared_lock::StylesheetGuards;
 use sharing::{ValidationData, StyleSharingCandidateCache};
 use std::fmt;
 use std::ops::Add;
 #[cfg(feature = "servo")] use std::sync::Mutex;
 #[cfg(feature = "servo")] use std::sync::mpsc::Sender;
-use stylearc::Arc;
+#[cfg(feature = "servo")] use stylearc::Arc;
 use stylist::Stylist;
 use thread_state;
 use time;
 use timer::Timer;
 use traversal::{DomTraversal, TraversalFlags};
 
 pub use selectors::matching::QuirksMode;
 
@@ -291,17 +291,17 @@ pub enum SequentialTask<E: TElement> {
     /// |tasks| field. These include updating CSS animations/transitions that changed as part
     /// of the non-animation style traversal, and updating the computed effect properties.
     #[cfg(feature = "gecko")]
     UpdateAnimations {
         /// The target element or pseudo-element.
         el: SendElement<E>,
         /// The before-change style for transitions. We use before-change style as the initial
         /// value of its Keyframe. Required if |tasks| includes CSSTransitions.
-        before_change_style: Option<Arc<ComputedValues>>,
+        before_change_style: Option<StrongComputedValues>,
         /// The tasks which are performed in this SequentialTask.
         tasks: UpdateAnimationsTasks
     },
 }
 
 impl<E: TElement> SequentialTask<E> {
     /// Executes this task.
     pub fn execute(self) {
@@ -315,17 +315,17 @@ impl<E: TElement> SequentialTask<E> {
             }
         }
     }
 
     /// Creates a task to update various animation-related state on
     /// a given (pseudo-)element.
     #[cfg(feature = "gecko")]
     pub fn update_animations(el: E,
-                             before_change_style: Option<Arc<ComputedValues>>,
+                             before_change_style: Option<StrongComputedValues>,
                              tasks: UpdateAnimationsTasks) -> Self {
         use self::SequentialTask::*;
         UpdateAnimations {
             el: unsafe { SendElement::new(el) },
             before_change_style: before_change_style,
             tasks: tasks,
         }
     }
--- a/servo/components/style/data.rs
+++ b/servo/components/style/data.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Per-node data used in style calculation.
 
 use arrayvec::ArrayVec;
 use context::SharedStyleContext;
 use dom::TElement;
 use invalidation::element::restyle_hints::RestyleHint;
-use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock};
+use properties::{AnimationRules, StrongComputedValues, PropertyDeclarationBlock};
 use properties::longhands::display::computed_value as display;
 use rule_tree::StrongRuleNode;
 use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage};
 use selectors::matching::VisitedHandlingMode;
 use shared_lock::{Locked, StylesheetGuards};
 use std::fmt;
 use stylearc::Arc;
 
@@ -24,37 +24,37 @@ use stylearc::Arc;
 pub struct ComputedStyle {
     /// The rule node representing the ordered list of rules matched for this
     /// node.
     pub rules: StrongRuleNode,
 
     /// The computed values for each property obtained by cascading the
     /// matched rules. This can only be none during a transient interval of
     /// the styling algorithm, and callers can safely unwrap it.
-    pub values: Option<Arc<ComputedValues>>,
+    pub values: Option<StrongComputedValues>,
 
     /// The rule node representing the ordered list of rules matched for this
     /// node if visited, only computed if there's a relevant link for this
     /// element. A element's "relevant link" is the element being matched if it
     /// is a link or the nearest ancestor link.
     visited_rules: Option<StrongRuleNode>,
 
     /// The element's computed values if visited, only computed if there's a
     /// relevant link for this element. A element's "relevant link" is the
     /// element being matched if it is a link or the nearest ancestor link.
     ///
     /// We also store a reference to this inside the regular ComputedValues to
     /// avoid refactoring all APIs to become aware of multiple ComputedValues
     /// objects.
-    visited_values: Option<Arc<ComputedValues>>,
+    visited_values: Option<StrongComputedValues>,
 }
 
 impl ComputedStyle {
     /// Trivially construct a new `ComputedStyle`.
-    pub fn new(rules: StrongRuleNode, values: Arc<ComputedValues>) -> Self {
+    pub fn new(rules: StrongRuleNode, values: StrongComputedValues) -> Self {
         ComputedStyle {
             rules: rules,
             values: Some(values),
             visited_rules: None,
             visited_values: None,
         }
     }
 
@@ -66,17 +66,17 @@ impl ComputedStyle {
             values: None,
             visited_rules: None,
             visited_values: None,
         }
     }
 
     /// Returns a reference to the ComputedValues. The values can only be null during
     /// the styling algorithm, so this is safe to call elsewhere.
-    pub fn values(&self) -> &Arc<ComputedValues> {
+    pub fn values(&self) -> &StrongComputedValues {
         self.values.as_ref().unwrap()
     }
 
     /// Whether there are any visited rules.
     pub fn has_visited_rules(&self) -> bool {
         self.visited_rules.is_some()
     }
 
@@ -109,33 +109,33 @@ impl ComputedStyle {
 
     /// Takes the visited rule node.
     pub fn take_visited_rules(&mut self) -> Option<StrongRuleNode> {
         self.visited_rules.take()
     }
 
     /// Gets a reference to the visited computed values. Panic if the element
     /// does not have visited computed values.
-    pub fn visited_values(&self) -> &Arc<ComputedValues> {
+    pub fn visited_values(&self) -> &StrongComputedValues {
         self.visited_values.as_ref().unwrap()
     }
 
     /// Sets the visited computed values.
-    pub fn set_visited_values(&mut self, values: Arc<ComputedValues>) {
+    pub fn set_visited_values(&mut self, values: StrongComputedValues) {
         self.visited_values = Some(values);
     }
 
     /// Take the visited computed values.
-    pub fn take_visited_values(&mut self) -> Option<Arc<ComputedValues>> {
+    pub fn take_visited_values(&mut self) -> Option<StrongComputedValues> {
         self.visited_values.take()
     }
 
     /// Clone the visited computed values Arc.  Used to store a reference to the
     /// visited values inside the regular values.
-    pub fn clone_visited_values(&self) -> Option<Arc<ComputedValues>> {
+    pub fn clone_visited_values(&self) -> Option<StrongComputedValues> {
         self.visited_values.clone()
     }
 }
 
 // We manually implement Debug for ComputedStyle so that we can avoid the
 // verbose stringification of ComputedValues for normal logging.
 impl fmt::Debug for ComputedStyle {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -11,16 +11,17 @@ use {Atom, Namespace, LocalName};
 use applicable_declarations::ApplicableDeclarationBlock;
 use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
 #[cfg(feature = "gecko")] use context::UpdateAnimationsTasks;
 use data::ElementData;
 use element_state::ElementState;
 use font_metrics::FontMetricsProvider;
 use media_queries::Device;
 use properties::{ComputedValues, PropertyDeclarationBlock};
+#[cfg(feature = "gecko")] use properties::StrongComputedValues;
 #[cfg(feature = "gecko")] use properties::animated_properties::AnimationValue;
 #[cfg(feature = "gecko")] use properties::animated_properties::TransitionProperty;
 use rule_tree::CascadeLevel;
 use selector_parser::{AttrValue, ElementExt, PreExistingComputedValues};
 use selector_parser::{PseudoClassStringArg, PseudoElement};
 use selectors::matching::{ElementSelectorFlags, VisitedHandlingMode};
 use selectors::sink::Push;
 use shared_lock::Locked;
@@ -566,17 +567,17 @@ pub trait TElement : Eq + PartialEq + De
     /// In Gecko, element has a flag that represents the element may have
     /// any type of animations or not to bail out animation stuff early.
     /// Whereas Servo doesn't have such flag.
     fn may_have_animations(&self) -> bool { false }
 
     /// Creates a task to update various animation state on a given (pseudo-)element.
     #[cfg(feature = "gecko")]
     fn update_animations(&self,
-                         before_change_style: Option<Arc<ComputedValues>>,
+                         before_change_style: Option<StrongComputedValues>,
                          tasks: UpdateAnimationsTasks);
 
     /// Returns true if the element has relevant animations. Relevant
     /// animations are those animations that are affecting the element's style
     /// or are scheduled to do so in the future.
     fn has_animations(&self) -> bool;
 
     /// Returns true if the element has a CSS animation.
--- a/servo/components/style/gecko/restyle_damage.rs
+++ b/servo/components/style/gecko/restyle_damage.rs
@@ -4,19 +4,18 @@
 
 //! Gecko's restyle damage computation (aka change hints, aka `nsChangeHint`).
 
 use gecko_bindings::bindings;
 use gecko_bindings::structs;
 use gecko_bindings::structs::{nsChangeHint, nsStyleContext};
 use gecko_bindings::sugar::ownership::FFIArcHelpers;
 use matching::{StyleChange, StyleDifference};
-use properties::ComputedValues;
+use properties::StrongComputedValues;
 use std::ops::{BitAnd, BitOr, BitOrAssign, Not};
-use stylearc::Arc;
 
 /// The representation of Gecko's restyle damage is just a wrapper over
 /// `nsChangeHint`.
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub struct GeckoRestyleDamage(nsChangeHint);
 
 impl GeckoRestyleDamage {
     /// Trivially construct a new `GeckoRestyleDamage`.
@@ -43,17 +42,17 @@ impl GeckoRestyleDamage {
     /// given an old style (in the form of a `nsStyleContext`, and a new style
     /// (in the form of `ComputedValues`).
     ///
     /// Note that we could in theory just get two `ComputedValues` here and diff
     /// them, but Gecko has an interesting optimization when they mark accessed
     /// structs, so they effectively only diff structs that have ever been
     /// accessed from layout.
     pub fn compute_style_difference(source: &nsStyleContext,
-                                    new_style: &Arc<ComputedValues>)
+                                    new_style: &StrongComputedValues)
                                     -> 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(),
                                                 &mut any_style_changed)
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -60,17 +60,17 @@ use gecko_bindings::structs::ELEMENT_HAS
 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::sugar::ownership::{HasArcFFI, HasSimpleFFI};
 use logical_geometry::WritingMode;
 use media_queries::Device;
-use properties::{ComputedValues, parse_style_attribute};
+use properties::{ComputedValues, parse_style_attribute, StrongComputedValues};
 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;
 use selector_parser::{AttrValue, ElementExt, PseudoClassStringArg};
 use selectors::Element;
 use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator, CaseSensitivity, NamespaceConstraint};
@@ -973,17 +973,17 @@ impl<'le> TElement for GeckoElement<'le>
     }
 
     #[inline]
     fn may_have_animations(&self) -> bool {
         self.as_node().get_bool_flag(nsINode_BooleanFlag::ElementHasAnimations)
     }
 
     fn update_animations(&self,
-                         before_change_style: Option<Arc<ComputedValues>>,
+                         before_change_style: Option<StrongComputedValues>,
                          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.values());
         let computed_values_opt =
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -12,17 +12,17 @@ use cascade_info::CascadeInfo;
 use context::{SelectorFlagsMap, SharedStyleContext, StyleContext};
 use data::{ComputedStyle, ElementData, RestyleData};
 use dom::{TElement, TNode};
 use font_metrics::FontMetricsProvider;
 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 log::LogLevel::Trace;
-use properties::{AnimationRules, CascadeFlags, ComputedValues};
+use properties::{AnimationRules, CascadeFlags, ComputedValues, StrongComputedValues};
 use properties::{IS_ROOT_ELEMENT, PROHIBIT_DISPLAY_CONTENTS, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP};
 use properties::{VISITED_DEPENDENT_ONLY, cascade};
 use properties::longhands::display::computed_value as display;
 use rule_tree::{CascadeLevel, StrongRuleNode};
 use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
 use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode, StyleRelations};
 use selectors::matching::{VisitedHandlingMode, AFFECTED_BY_PSEUDO_ELEMENTS};
 use sharing::StyleSharingBehavior;
@@ -167,36 +167,36 @@ impl CascadeVisitedMode {
             CascadeVisitedMode::Unvisited => Some(&mut style.rules),
             CascadeVisitedMode::Visited => style.get_visited_rules_mut(),
         }
     }
 
     /// Returns the computed values based on the cascade mode.  In visited mode,
     /// visited values are only returned if they already exist.  If they don't,
     /// we fallback to the regular, unvisited styles.
-    fn values<'a>(&self, style: &'a ComputedStyle) -> &'a Arc<ComputedValues> {
+    fn values<'a>(&self, style: &'a ComputedStyle) -> &'a StrongComputedValues {
         let mut values = style.values();
 
         if *self == CascadeVisitedMode::Visited && values.get_visited_style().is_some() {
             values = values.visited_style();
         }
 
         values
     }
 
     /// Set the computed values based on the cascade mode.
-    fn set_values(&self, style: &mut ComputedStyle, values: Arc<ComputedValues>) {
+    fn set_values(&self, style: &mut ComputedStyle, values: StrongComputedValues) {
         match *self {
             CascadeVisitedMode::Unvisited => style.values = Some(values),
             CascadeVisitedMode::Visited => style.set_visited_values(values),
         }
     }
 
     /// Take the computed values based on the cascade mode.
-    fn take_values(&self, style: &mut ComputedStyle) -> Option<Arc<ComputedValues>> {
+    fn take_values(&self, style: &mut ComputedStyle) -> Option<StrongComputedValues> {
         match *self {
             CascadeVisitedMode::Unvisited => style.values.take(),
             CascadeVisitedMode::Visited => style.take_visited_values(),
         }
     }
 
     /// Returns whether there might be visited values that should be inserted
     /// within the regular computed values based on the cascade mode.
@@ -256,18 +256,18 @@ trait PrivateMatchMethods: TElement {
 
     fn cascade_with_rules(&self,
                           shared_context: &SharedStyleContext,
                           font_metrics_provider: &FontMetricsProvider,
                           rule_node: &StrongRuleNode,
                           primary_style: &ComputedStyle,
                           cascade_target: CascadeTarget,
                           cascade_visited: CascadeVisitedMode,
-                          visited_values_to_insert: Option<Arc<ComputedValues>>)
-                          -> Arc<ComputedValues> {
+                          visited_values_to_insert: Option<StrongComputedValues>)
+                          -> StrongComputedValues {
         let mut cascade_info = CascadeInfo::new();
         let mut cascade_flags = CascadeFlags::empty();
         if self.skip_root_and_item_based_display_fixup() {
             cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP)
         }
         if cascade_visited.visited_dependent_only() {
             cascade_flags.insert(VISITED_DEPENDENT_ONLY);
         }
@@ -348,17 +348,17 @@ trait PrivateMatchMethods: TElement {
         values
     }
 
     fn cascade_internal(&self,
                         context: &StyleContext<Self>,
                         primary_style: &ComputedStyle,
                         eager_pseudo_style: Option<&ComputedStyle>,
                         cascade_visited: CascadeVisitedMode)
-                        -> Arc<ComputedValues> {
+                        -> StrongComputedValues {
         if let Some(pseudo) = self.implemented_pseudo_element() {
             debug_assert!(eager_pseudo_style.is_none());
 
             // This is an element-backed pseudo, just grab the styles from the
             // parent if it's eager, and recascade otherwise.
             //
             // We also recascade if the eager pseudo-style has any animation
             // rules, because we don't cascade those during the eager traversal.
@@ -525,17 +525,17 @@ trait PrivateMatchMethods: TElement {
     }
 
     /// get_after_change_style removes the transition rules from the ComputedValues.
     /// If there is no transition rule in the ComputedValues, it returns None.
     #[cfg(feature = "gecko")]
     fn get_after_change_style(&self,
                               context: &mut StyleContext<Self>,
                               primary_style: &ComputedStyle)
-                              -> Option<Arc<ComputedValues>> {
+                              -> Option<StrongComputedValues> {
         let rule_node = &primary_style.rules;
         let without_transition_rules =
             context.shared.stylist.rule_tree().remove_transition_rule_if_applicable(rule_node);
         if without_transition_rules == *rule_node {
             // We don't have transition rule in this case, so return None to let the caller
             // use the original ComputedValues.
             return None;
         }
@@ -549,17 +549,17 @@ trait PrivateMatchMethods: TElement {
                                      CascadeTarget::Normal,
                                      CascadeVisitedMode::Unvisited,
                                      None))
     }
 
     #[cfg(feature = "gecko")]
     fn needs_animations_update(&self,
                                context: &mut StyleContext<Self>,
-                               old_values: Option<&Arc<ComputedValues>>,
+                               old_values: Option<&StrongComputedValues>,
                                new_values: &ComputedValues)
                                -> bool {
         let new_box_style = new_values.get_box();
         let has_new_animation_style = new_box_style.animation_name_count() >= 1 &&
                                       new_box_style.animation_name_at(0).0.is_some();
         let has_animations = self.has_css_animations();
 
         old_values.map_or(has_new_animation_style, |old| {
@@ -578,18 +578,18 @@ trait PrivateMatchMethods: TElement {
               new_display_style == display::T::none &&
               has_animations)
         })
     }
 
     #[cfg(feature = "gecko")]
     fn process_animations(&self,
                           context: &mut StyleContext<Self>,
-                          old_values: &mut Option<Arc<ComputedValues>>,
-                          new_values: &mut Arc<ComputedValues>,
+                          old_values: &mut Option<StrongComputedValues>,
+                          new_values: &mut StrongComputedValues,
                           primary_style: &ComputedStyle,
                           important_rules_changed: bool) {
         use context::{CASCADE_RESULTS, CSS_ANIMATIONS, CSS_TRANSITIONS, EFFECT_PROPERTIES};
         use context::UpdateAnimationsTasks;
 
         let mut tasks = UpdateAnimationsTasks::empty();
         if self.needs_animations_update(context, old_values.as_ref(), new_values) {
             tasks.insert(CSS_ANIMATIONS);
@@ -644,18 +644,18 @@ trait PrivateMatchMethods: TElement {
                                                                     tasks);
             context.thread_local.tasks.push(task);
         }
     }
 
     #[cfg(feature = "servo")]
     fn process_animations(&self,
                           context: &mut StyleContext<Self>,
-                          old_values: &mut Option<Arc<ComputedValues>>,
-                          new_values: &mut Arc<ComputedValues>,
+                          old_values: &mut Option<StrongComputedValues>,
+                          new_values: &mut StrongComputedValues,
                           _primary_style: &ComputedStyle,
                           _important_rules_changed: bool) {
         use animation;
 
         let possibly_expired_animations =
             &mut context.thread_local.current_element_info.as_mut().unwrap()
                         .possibly_expired_animations;
         let shared_context = context.shared;
@@ -686,17 +686,17 @@ trait PrivateMatchMethods: TElement {
     }
 
     /// Computes and applies non-redundant damage.
     #[cfg(feature = "gecko")]
     fn accumulate_damage_for(&self,
                              shared_context: &SharedStyleContext,
                              restyle: &mut RestyleData,
                              old_values: &ComputedValues,
-                             new_values: &Arc<ComputedValues>,
+                             new_values: &StrongComputedValues,
                              pseudo: Option<&PseudoElement>)
                              -> ChildCascadeRequirement {
         // Don't accumulate damage if we're in a restyle for reconstruction.
         if shared_context.traversal_flags.for_reconstruct() {
             return ChildCascadeRequirement::MustCascadeChildren;
         }
 
         // If an ancestor is already getting reconstructed by Gecko's top-down
@@ -719,28 +719,28 @@ trait PrivateMatchMethods: TElement {
     }
 
     /// Computes and applies restyle damage unless we've already maxed it out.
     #[cfg(feature = "servo")]
     fn accumulate_damage_for(&self,
                              _shared_context: &SharedStyleContext,
                              restyle: &mut RestyleData,
                              old_values: &ComputedValues,
-                             new_values: &Arc<ComputedValues>,
+                             new_values: &StrongComputedValues,
                              pseudo: Option<&PseudoElement>)
                              -> ChildCascadeRequirement {
         let difference = self.compute_style_difference(&old_values, &new_values, pseudo);
         restyle.damage |= difference.damage;
         difference.change.into()
     }
 
     #[cfg(feature = "servo")]
     fn update_animations_for_cascade(&self,
                                      context: &SharedStyleContext,
-                                     style: &mut Arc<ComputedValues>,
+                                     style: &mut StrongComputedValues,
                                      possibly_expired_animations: &mut Vec<::animation::PropertyAnimation>,
                                      font_metrics: &FontMetricsProvider) {
         use animation::{self, Animation};
 
         // Finish any expired transitions.
         let this_opaque = self.as_node().opaque();
         animation::complete_expired_transitions(this_opaque, style, context);
 
@@ -1252,17 +1252,17 @@ pub trait MatchMethods : TElement {
         }
     }
 
     /// Computes and applies restyle damage.
     fn accumulate_damage(&self,
                          shared_context: &SharedStyleContext,
                          restyle: &mut RestyleData,
                          old_values: Option<&ComputedValues>,
-                         new_values: &Arc<ComputedValues>,
+                         new_values: &StrongComputedValues,
                          pseudo: Option<&PseudoElement>)
                          -> ChildCascadeRequirement {
         let old_values = match old_values {
             Some(v) => v,
             None => return ChildCascadeRequirement::MustCascadeChildren,
         };
 
         // ::before and ::after are element-backed in Gecko, so they do the
@@ -1394,17 +1394,17 @@ pub trait MatchMethods : TElement {
         false
     }
 
     /// Given the old and new style of this element, and whether it's a
     /// pseudo-element, compute the restyle damage used to determine which
     /// kind of layout or painting operations we'll need.
     fn compute_style_difference(&self,
                                 old_values: &ComputedValues,
-                                new_values: &Arc<ComputedValues>,
+                                new_values: &StrongComputedValues,
                                 pseudo: Option<&PseudoElement>)
                                 -> StyleDifference
     {
         if let Some(source) = self.existing_style_for_restyle_damage(old_values, pseudo) {
             return RestyleDamage::compute_style_difference(source, new_values)
         }
 
         let new_style_is_display_none =
@@ -1461,17 +1461,17 @@ pub trait MatchMethods : TElement {
     }
 
     /// Returns computed values without animation and transition rules.
     fn get_base_style(&self,
                       shared_context: &SharedStyleContext,
                       font_metrics_provider: &FontMetricsProvider,
                       primary_style: &ComputedStyle,
                       pseudo_style: Option<&ComputedStyle>)
-                      -> Arc<ComputedValues> {
+                      -> StrongComputedValues {
         let relevant_style = pseudo_style.unwrap_or(primary_style);
         let rule_node = &relevant_style.rules;
         let without_animation_rules =
             shared_context.stylist.rule_tree().remove_animation_rules(rule_node);
         if without_animation_rules == *rule_node {
             // Note that unwrapping here is fine, because the style is
             // only incomplete during the styling process.
             return relevant_style.values.as_ref().unwrap().clone();
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -51,17 +51,17 @@ use gecko::values::convert_nscolor_to_rg
 use gecko::values::convert_rgba_to_nscolor;
 use gecko::values::GeckoStyleCoordConvertible;
 use gecko::values::round_border_to_device_pixels;
 use logical_geometry::WritingMode;
 use media_queries::Device;
 use properties::animated_properties::TransitionProperty;
 use properties::longhands;
 use properties:: FontComputationData;
-use properties::{Importance, LonghandId};
+use properties::{Importance, LonghandId, StrongComputedValues};
 use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
 use std::mem::{forget, transmute, zeroed};
 use std::{cmp, ops, ptr};
 use stylearc::{Arc, RawOffsetArc};
 use values::{Auto, CustomIdent, Either, KeyframesName};
 use values::computed::{Shadow, ToComputedValue};
 use values::specified::length::Percentage;
 use computed_values::border_style;
@@ -93,17 +93,17 @@ impl Clone for ComputedValuesInner {
         }
     }
 }
 
 impl ComputedValuesInner {
     pub fn new(custom_properties: Option<Arc<ComputedValuesMap>>,
                writing_mode: WritingMode,
                font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
-               visited_style: Option<Arc<ComputedValues>>,
+               visited_style: Option<StrongComputedValues>,
                % for style_struct in data.style_structs:
                ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
                % endfor
     ) -> Self {
         ComputedValuesInner {
             custom_properties: custom_properties,
             writing_mode: writing_mode,
             font_computation_data: FontComputationData::new(font_size_keyword),
@@ -120,17 +120,17 @@ impl ComputedValuesInner {
                 writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious
                 font_computation_data: FontComputationData::default_values(),
                 visited_style: None,
                 % for style_struct in data.style_structs:
                     ${style_struct.gecko_name}: Arc::into_raw_offset(style_structs::${style_struct.name}::default(pres_context)),
                 % endfor
         }
     }
-    pub fn to_outer(self) -> Arc<ComputedValues> {
+    pub fn to_outer(self) -> StrongComputedValues {
         Arc::new(ComputedValues {inner: self})
     }
 }
 
 impl ops::Deref for ComputedValues {
     type Target = ComputedValuesInner;
     fn deref(&self) -> &ComputedValuesInner {
         &self.inner
@@ -173,29 +173,29 @@ impl ComputedValuesInner {
 
     #[inline]
     pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
         RawOffsetArc::make_mut(&mut self.${style_struct.gecko_name})
     }
     % endfor
 
     /// Gets a reference to the visited computed values, if any.
-    pub fn get_visited_style(&self) -> Option<<&Arc<ComputedValues>> {
+    pub fn get_visited_style(&self) -> Option<<&StrongComputedValues> {
         self.visited_style.as_ref()
     }
 
     /// Gets a reference to the visited computed values. Panic if the element
     /// does not have visited computed values.
-    pub fn visited_style(&self) -> &Arc<ComputedValues> {
+    pub fn visited_style(&self) -> &StrongComputedValues {
         self.get_visited_style().unwrap()
     }
 
     /// Clone the visited computed values Arc.  Used for inheriting parent styles
     /// in StyleBuilder::for_inheritance.
-    pub fn clone_visited_style(&self) -> Option<Arc<ComputedValues>> {
+    pub fn clone_visited_style(&self) -> Option<StrongComputedValues> {
         self.visited_style.clone()
     }
 
     pub fn custom_properties(&self) -> Option<Arc<ComputedValuesMap>> {
         self.custom_properties.clone()
     }
 
     #[allow(non_snake_case)]
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -1796,32 +1796,39 @@ pub mod style_structs {
 
 #[cfg(feature = "gecko")]
 pub use gecko_properties::ComputedValues;
 #[cfg(feature = "gecko")]
 pub use gecko_properties::ComputedValuesInner;
 
 
 #[cfg(feature = "servo")]
+/// Strong reference to ComputedValues; equivalent to Arc<ComputedValues>
+pub type StrongComputedValues = Arc<ComputedValues>;
+#[cfg(feature = "gecko")]
+/// Strong reference to ComputedValues, equivalent to Arc<ComputedValues>
+pub type StrongComputedValues = Arc<ComputedValues>;
+
+#[cfg(feature = "servo")]
 #[cfg_attr(feature = "servo", derive(Clone, Debug))]
 /// Actual data of ComputedValues, to match up with Gecko
 pub struct ComputedValuesInner {
     % for style_struct in data.active_style_structs():
         ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
     % endfor
     custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
     /// The writing mode of this computed values struct.
     pub writing_mode: WritingMode,
     /// The keyword behind the current font-size property, if any
     pub font_computation_data: FontComputationData,
 
     /// The element's computed values if visited, only computed if there's a
     /// relevant link for this element. A element's "relevant link" is the
     /// element being matched if it is a link or the nearest ancestor link.
-    visited_style: Option<Arc<ComputedValues>>,
+    visited_style: Option<StrongComputedValues>,
 }
 
 /// The struct that Servo uses to represent computed values.
 ///
 /// This struct contains an immutable atomically-reference-counted pointer to
 /// every kind of style struct.
 ///
 /// When needed, the structs may be copied in order to get mutated.
@@ -1833,17 +1840,17 @@ pub struct ComputedValues {
 }
 
 #[cfg(feature = "servo")]
 impl ComputedValuesInner {
     /// Construct a `ComputedValues` instance.
     pub fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
                writing_mode: WritingMode,
                font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
-               visited_style: Option<Arc<ComputedValues>>,
+               visited_style: Option<StrongComputedValues>,
             % for style_struct in data.active_style_structs():
                ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
             % endfor
     ) -> Self {
         ComputedValuesInner {
             custom_properties: custom_properties,
             writing_mode: writing_mode,
             font_computation_data: FontComputationData::new(font_size_keyword),
@@ -1870,18 +1877,18 @@ impl ops::Deref for ComputedValues {
 impl ops::DerefMut for ComputedValues {
     fn deref_mut(&mut self) -> &mut ComputedValuesInner {
         &mut self.inner
     }
 }
 
 #[cfg(feature = "servo")]
 impl ComputedValuesInner {
-    /// Convert to an Arc<ComputedValues>
-    pub fn to_outer(self) -> Arc<ComputedValues> {
+    /// Convert to an StrongComputedValues
+    pub fn to_outer(self) -> StrongComputedValues {
         Arc::new(ComputedValues {inner: self})
     }
 
     % for style_struct in data.active_style_structs():
         /// Clone the ${style_struct.name} struct.
         #[inline]
         pub fn clone_${style_struct.name_lower}(&self) -> Arc<style_structs::${style_struct.name}> {
             self.${style_struct.ident}.clone()
@@ -1902,29 +1909,29 @@ impl ComputedValuesInner {
         /// Get a mutable reference to the ${style_struct.name} struct.
         #[inline]
         pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
             Arc::make_mut(&mut self.${style_struct.ident})
         }
     % endfor
 
     /// Gets a reference to the visited computed values, if any.
-    pub fn get_visited_style(&self) -> Option<<&Arc<ComputedValues>> {
+    pub fn get_visited_style(&self) -> Option<<&StrongComputedValues> {
         self.visited_style.as_ref()
     }
 
     /// Gets a reference to the visited computed values. Panic if the element
     /// does not have visited computed values.
-    pub fn visited_style(&self) -> &Arc<ComputedValues> {
+    pub fn visited_style(&self) -> &StrongComputedValues {
         self.get_visited_style().unwrap()
     }
 
     /// Clone the visited computed values Arc.  Used for inheriting parent styles
     /// in StyleBuilder::for_inheritance.
-    pub fn clone_visited_style(&self) -> Option<Arc<ComputedValues>> {
+    pub fn clone_visited_style(&self) -> Option<StrongComputedValues> {
         self.visited_style.clone()
     }
 
     // Aah! The << in the return type below is not valid syntax, but we must
     // escape < that way for Mako.
     /// Gets a reference to the custom properties map (if one exists).
     pub fn get_custom_properties(&self) -> Option<<&::custom_properties::ComputedValuesMap> {
         self.custom_properties.as_ref().map(|x| &**x)
@@ -2324,29 +2331,29 @@ pub struct StyleBuilder<'a> {
     ///
     /// TODO(emilio): Make private.
     pub writing_mode: WritingMode,
     /// The keyword behind the current font-size property, if any.
     pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
     /// The element's style if visited, only computed if there's a relevant link
     /// for this element.  A element's "relevant link" is the element being
     /// matched if it is a link or the nearest ancestor link.
-    visited_style: Option<Arc<ComputedValues>>,
+    visited_style: Option<StrongComputedValues>,
     % for style_struct in data.active_style_structs():
         ${style_struct.ident}: StyleStructRef<'a, style_structs::${style_struct.name}>,
     % endfor
 }
 
 impl<'a> StyleBuilder<'a> {
     /// Trivially construct a `StyleBuilder`.
     pub fn new(
         custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
         writing_mode: WritingMode,
         font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
-        visited_style: Option<Arc<ComputedValues>>,
+        visited_style: Option<StrongComputedValues>,
         % for style_struct in data.active_style_structs():
             ${style_struct.ident}: &'a BuilderArc<style_structs::${style_struct.name}>,
         % endfor
     ) -> Self {
         StyleBuilder {
             custom_properties: custom_properties,
             writing_mode: writing_mode,
             font_size_keyword: font_size_keyword,
@@ -2552,17 +2559,17 @@ bitflags! {
 /// Returns the computed values.
 ///   * `flags`: Various flags.
 ///
 pub fn cascade(device: &Device,
                rule_node: &StrongRuleNode,
                guards: &StylesheetGuards,
                parent_style: Option<<&ComputedValuesInner>,
                layout_parent_style: Option<<&ComputedValuesInner>,
-               visited_style: Option<Arc<ComputedValues>>,
+               visited_style: Option<StrongComputedValues>,
                cascade_info: Option<<&mut CascadeInfo>,
                error_reporter: &ParseErrorReporter,
                font_metrics_provider: &FontMetricsProvider,
                flags: CascadeFlags,
                quirks_mode: QuirksMode)
                -> ComputedValuesInner {
     debug_assert_eq!(parent_style.is_some(), layout_parent_style.is_some());
     let (inherited_style, layout_parent_style) = match parent_style {
@@ -2614,17 +2621,17 @@ pub fn cascade(device: &Device,
 
 /// NOTE: This function expects the declaration with more priority to appear
 /// first.
 #[allow(unused_mut)] // conditionally compiled code for "position"
 pub fn apply_declarations<'a, F, I>(device: &Device,
                                     iter_declarations: F,
                                     inherited_style: &ComputedValuesInner,
                                     layout_parent_style: &ComputedValuesInner,
-                                    visited_style: Option<Arc<ComputedValues>>,
+                                    visited_style: Option<StrongComputedValues>,
                                     mut cascade_info: Option<<&mut CascadeInfo>,
                                     error_reporter: &ParseErrorReporter,
                                     font_metrics_provider: &FontMetricsProvider,
                                     flags: CascadeFlags,
                                     quirks_mode: QuirksMode)
                                     -> ComputedValuesInner
     where F: Fn() -> I,
           I: Iterator<Item = (&'a PropertyDeclaration, CascadeLevel)>,
@@ -2945,20 +2952,20 @@ pub fn adjust_border_width(style: &mut S
 
 /// Adjusts borders as appropriate to account for a fragment's status as the
 /// first or last fragment within the range of an element.
 ///
 /// Specifically, this function sets border widths to zero on the sides for
 /// which the fragment is not outermost.
 #[cfg(feature = "servo")]
 #[inline]
-pub fn modify_border_style_for_inline_sides(style: &mut Arc<ComputedValues>,
+pub fn modify_border_style_for_inline_sides(style: &mut StrongComputedValues,
                                             is_first_fragment_of_element: bool,
                                             is_last_fragment_of_element: bool) {
-    fn modify_side(style: &mut Arc<ComputedValues>, side: PhysicalSide) {
+    fn modify_side(style: &mut StrongComputedValues, side: PhysicalSide) {
         {
             let border = &style.border;
             let current_style = match side {
                 PhysicalSide::Left =>   (border.border_left_width,   border.border_left_style),
                 PhysicalSide::Right =>  (border.border_right_width,  border.border_right_style),
                 PhysicalSide::Top =>    (border.border_top_width,    border.border_top_style),
                 PhysicalSide::Bottom => (border.border_bottom_width, border.border_bottom_style),
             };
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -13,18 +13,18 @@ use dom::TElement;
 use element_state::ElementState;
 use error_reporting::create_error_reporter;
 use font_metrics::FontMetricsProvider;
 #[cfg(feature = "gecko")]
 use gecko_bindings::structs::{nsIAtom, StyleRuleInclusion};
 use invalidation::element::invalidation_map::InvalidationMap;
 use invalidation::media_queries::EffectiveMediaQueryResults;
 use media_queries::Device;
-use properties::{self, CascadeFlags, ComputedValues, ComputedValuesInner};
-use properties::{AnimationRules, PropertyDeclarationBlock};
+use properties::{self, CascadeFlags, ComputedValuesInner};
+use properties::{AnimationRules, StrongComputedValues, PropertyDeclarationBlock};
 #[cfg(feature = "servo")]
 use properties::INHERIT_ALL;
 use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
 use selector_map::{SelectorMap, SelectorMapEntry};
 use selector_parser::{SelectorImpl, PseudoElement};
 use selectors::attr::NamespaceConstraint;
 use selectors::bloom::BloomFilter;
 use selectors::matching::{ElementSelectorFlags, matches_selector, MatchingContext, MatchingMode};
@@ -632,17 +632,17 @@ impl Stylist {
     }
 
     /// Returns the style for an anonymous box of the given type.
     #[cfg(feature = "servo")]
     pub fn style_for_anonymous(&self,
                                guards: &StylesheetGuards,
                                pseudo: &PseudoElement,
                                parent_style: &ComputedValuesInner)
-                               -> Arc<ComputedValues> {
+                               -> StrongComputedValues {
         use font_metrics::ServoMetricsProvider;
 
         // For most (but not all) pseudo-elements, we inherit all values from the parent.
         let inherit_all = match *pseudo {
             PseudoElement::ServoText |
             PseudoElement::ServoInputText => false,
             PseudoElement::ServoAnonymousBlock |
             PseudoElement::ServoAnonymousTable |
@@ -1243,17 +1243,17 @@ impl Stylist {
         results
     }
 
     /// Computes styles for a given declaration with parent_style.
     pub fn compute_for_declarations(&self,
                                     guards: &StylesheetGuards,
                                     parent_style: &ComputedValuesInner,
                                     declarations: Arc<Locked<PropertyDeclarationBlock>>)
-                                    -> Arc<ComputedValues> {
+                                    -> StrongComputedValues {
         use font_metrics::get_metrics_provider_for_product;
 
         let v = vec![
             ApplicableDeclarationBlock::from_declarations(declarations.clone(),
                                                           CascadeLevel::StyleAttributeNormal)
         ];
         let rule_node =
             self.rule_tree.insert_ordered_rules(v.into_iter().map(|a| a.order_and_level()));