Backed out 11 changesets (bug 1630676) for causing multiple failures CLOSED TREE
authorCiure Andrei <aciure@mozilla.com>
Thu, 16 Apr 2020 21:45:51 +0300
changeset 524467 4b37ed1b9347726da7ede3d117875b65fdd61d20
parent 524466 931f4791ca8919044752b372d2aec550d6fd6d13
child 524468 feaa9875d5c74420810fdd6c79cbd1e78166760f
push id113205
push useraciure@mozilla.com
push dateThu, 16 Apr 2020 18:46:29 +0000
treeherderautoland@4b37ed1b9347 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1630676
milestone77.0a1
backs outc1fbe364b76c546447fbd1f0bfb1765f872cc1ee
629970c8f0b75acfcbec0ff1326d0ac080e1e090
1530f4a9aef278170949686ce18490b358de030e
a5b60fb5a0e11d0816646d4cd2484bcb7bde5320
a6e1a31c3e0dde262ea21427cfb9695ce2888224
4df9717e28f0962b0b3fee60f771d5cd0fc3d008
c76b0b0e503b1f1f5ad7d8f984cba020cb496b88
3c89aec57d0a84bc3f8dea20b7727aa40c522b57
369cf504584d9596860c6b5dd5f4d9dc763b472b
d7eff4acb61687bdaef2bd82a6db690e694de622
1d47c9354eebc9434be6c878621a16e7560b52a2
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 11 changesets (bug 1630676) for causing multiple failures CLOSED TREE Backed out changeset c1fbe364b76c (bug 1630676) Backed out changeset 629970c8f0b7 (bug 1630676) Backed out changeset 1530f4a9aef2 (bug 1630676) Backed out changeset a5b60fb5a0e1 (bug 1630676) Backed out changeset a6e1a31c3e0d (bug 1630676) Backed out changeset 4df9717e28f0 (bug 1630676) Backed out changeset c76b0b0e503b (bug 1630676) Backed out changeset 3c89aec57d0a (bug 1630676) Backed out changeset 369cf504584d (bug 1630676) Backed out changeset d7eff4acb616 (bug 1630676) Backed out changeset 1d47c9354eeb (bug 1630676)
servo/components/selectors/parser.rs
servo/components/style/Cargo.toml
servo/components/style/animation.rs
servo/components/style/attr.rs
servo/components/style/counter_style/mod.rs
servo/components/style/custom_properties.rs
servo/components/style/dom.rs
servo/components/style/driver.rs
servo/components/style/encoding_support.rs
servo/components/style/gecko/conversions.rs
servo/components/style/gecko/media_queries.rs
servo/components/style/gecko/selector_parser.rs
servo/components/style/gecko/snapshot_helpers.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/gecko_string_cache/namespace.rs
servo/components/style/invalidation/element/state_and_attributes.rs
servo/components/style/matching.rs
servo/components/style/properties/longhands/box.mako.rs
servo/components/style/properties/longhands/counters.mako.rs
servo/components/style/properties/longhands/effects.mako.rs
servo/components/style/properties/longhands/position.mako.rs
servo/components/style/properties/longhands/text.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/properties/shorthands/text.mako.rs
servo/components/style/rule_collector.rs
servo/components/style/scoped_tls.rs
servo/components/style/style_adjuster.rs
servo/components/style/stylesheet_set.rs
servo/components/style/stylesheets/mod.rs
servo/components/style/stylesheets/rule_list.rs
servo/components/style/traversal.rs
servo/components/style/values/computed/font.rs
servo/components/style/values/computed/image.rs
servo/components/style/values/computed/length.rs
servo/components/style/values/computed/length_percentage.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/computed/position.rs
servo/components/style/values/generics/basic_shape.rs
servo/components/style/values/generics/calc.rs
servo/components/style/values/generics/counters.rs
servo/components/style/values/generics/image.rs
servo/components/style/values/generics/transform.rs
servo/components/style/values/resolved/mod.rs
servo/components/style/values/specified/basic_shape.rs
servo/components/style/values/specified/calc.rs
servo/components/style/values/specified/counters.rs
servo/components/style/values/specified/font.rs
servo/components/style/values/specified/image.rs
servo/components/style/values/specified/length.rs
servo/components/style/values/specified/mod.rs
servo/components/style/values/specified/svg.rs
servo/components/style/values/specified/svg_path.rs
servo/components/style/values/specified/text.rs
servo/components/style/values/specified/ui.rs
servo/components/style_derive/to_computed_value.rs
servo/ports/geckolib/glue.rs
--- a/servo/components/selectors/parser.rs
+++ b/servo/components/selectors/parser.rs
@@ -2038,20 +2038,17 @@ where
                 //
                 // https://drafts.csswg.org/selectors-4/#featureless:
                 //
                 //     A featureless element does not match any selector at all,
                 //     except those it is explicitly defined to match. If a
                 //     given selector is allowed to match a featureless element,
                 //     it must do so while ignoring the default namespace.
                 //
-                if !matches!(
-                    result,
-                    SimpleSelectorParseResult::SimpleSelector(Component::Host(..))
-                ) {
+                if !matches!(result, SimpleSelectorParseResult::SimpleSelector(Component::Host(..))) {
                     builder.push_simple_selector(Component::DefaultNamespace(url));
                 }
             }
         }
 
         empty = false;
 
         match result {
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -28,17 +28,17 @@ gecko_profiler = []
 
 [dependencies]
 app_units = "0.7"
 arrayvec = "0.5"
 atomic_refcell = "0.1"
 bitflags = "1.0"
 byteorder = "1.0"
 cssparser = "0.27"
-crossbeam-channel = { version = "0.4", optional = true }
+crossbeam-channel = { version = "0.3", optional = true }
 derive_more = "0.99"
 new_debug_unreachable = "1.0"
 encoding_rs = {version = "0.8", optional = true}
 euclid = "0.20"
 fallible = { path = "../fallible" }
 fxhash = "0.2"
 hashglobe = { path = "../hashglobe" }
 html5ever = {version = "0.24", optional = true}
--- a/servo/components/style/animation.rs
+++ b/servo/components/style/animation.rs
@@ -323,18 +323,18 @@ impl PropertyAnimation {
         duration: Time,
         old_style: &ComputedValues,
         new_style: &ComputedValues,
     ) -> Option<PropertyAnimation> {
         let animated_property = AnimatedProperty::from_longhand(longhand, old_style, new_style)?;
 
         let property_animation = PropertyAnimation {
             property: animated_property,
-            timing_function,
-            duration,
+            timing_function: timing_function,
+            duration: duration,
         };
 
         if property_animation.does_animate() {
             Some(property_animation)
         } else {
             None
         }
     }
@@ -406,17 +406,17 @@ impl PropertyAnimation {
 /// the given style difference. This is called from the layout worker threads.
 /// Returns true if any animations were kicked off and false otherwise.
 pub fn start_transitions_if_applicable(
     new_animations_sender: &Sender<Animation>,
     opaque_node: OpaqueNode,
     old_style: &ComputedValues,
     new_style: &mut Arc<ComputedValues>,
     timer: &Timer,
-    running_and_expired_transitions: &[PropertyAnimation],
+    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, Arc::make_mut(new_style));
         for property_animation in property_animations {
             // Set the property to the initial value.
@@ -425,34 +425,31 @@ pub fn start_transitions_if_applicable(
             // above.
             property_animation.update(Arc::get_mut(new_style).unwrap(), 0.0);
 
             // Per [1], don't trigger a new transition if the end state for that
             // transition is the same as that of a transition that's already
             // running on the same node.
             //
             // [1]: https://drafts.csswg.org/css-transitions/#starting
-            debug!(
-                "checking {:?} for matching end value",
-                running_and_expired_transitions
-            );
-            if running_and_expired_transitions
+            if possibly_expired_animations
                 .iter()
                 .any(|animation| animation.has_the_same_end_value_as(&property_animation))
             {
                 debug!(
                     "Not initiating transition for {}, other transition \
                      found with the same end value",
                     property_animation.property_name()
                 );
                 continue;
             }
 
+            debug!("Kicking off transition of {:?}", property_animation);
+
             // Kick off the animation.
-            debug!("Kicking off transition of {:?}", property_animation);
             let box_style = new_style.get_box();
             let now = timer.seconds();
             let start_time = now + (box_style.transition_delay_mod(i).seconds() as f64);
             new_animations_sender
                 .send(Animation::Transition(
                     opaque_node,
                     start_time,
                     AnimationFrame {
@@ -843,8 +840,38 @@ where
                 "update_style_for_animation: got style change in animation \"{}\"",
                 name
             );
             *style = new_style;
             AnimationUpdate::Regular
         },
     }
 }
+
+/// Update the style in the node when it finishes.
+#[cfg(feature = "servo")]
+pub fn complete_expired_transitions(
+    node: OpaqueNode,
+    style: &mut Arc<ComputedValues>,
+    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 {
+                debug!("Updating expired animation {:?}", animation);
+                // TODO: support animation-fill-mode
+                if let Animation::Transition(_, _, ref frame) = *animation {
+                    frame.property_animation.update(Arc::make_mut(style), 1.0);
+                }
+            }
+        }
+    }
+
+    if had_animations_to_expire {
+        context.expired_animations.write().remove(&node);
+    }
+
+    had_animations_to_expire
+}
--- a/servo/components/style/attr.rs
+++ b/servo/components/style/attr.rs
@@ -534,28 +534,38 @@ pub fn parse_legacy_color(mut input: &st
 // TODO: this function can be rewritten to return Result<LengthPercentage, _>
 pub fn parse_length(mut value: &str) -> LengthOrPercentageOrAuto {
     // Steps 1 & 2 are not relevant
 
     // Step 3
     value = value.trim_start_matches(HTML_SPACE_CHARACTERS);
 
     // Step 4
+    if value.is_empty() {
+        return LengthOrPercentageOrAuto::Auto;
+    }
+
+    // Step 5
+    if value.starts_with('+') {
+        value = &value[1..]
+    }
+
+    // Steps 6 & 7
     match value.chars().nth(0) {
         Some('0'..='9') => {},
         _ => return LengthOrPercentageOrAuto::Auto,
     }
 
-    // Steps 5 to 8
+    // Steps 8 to 13
     // We trim the string length to the minimum of:
     // 1. the end of the string
     // 2. the first occurence of a '%' (U+0025 PERCENT SIGN)
     // 3. the second occurrence of a '.' (U+002E FULL STOP)
     // 4. the occurrence of a character that is neither a digit nor '%' nor '.'
-    // Note: Step 7.4 is directly subsumed by FromStr::from_str
+    // Note: Step 10 is directly subsumed by FromStr::from_str
     let mut end_index = value.len();
     let (mut found_full_stop, mut found_percent) = (false, false);
     for (i, ch) in value.chars().enumerate() {
         match ch {
             '0'..='9' => continue,
             '%' => {
                 found_percent = true;
                 end_index = i;
--- a/servo/components/style/counter_style/mod.rs
+++ b/servo/components/style/counter_style/mod.rs
@@ -403,19 +403,17 @@ impl ToCss for System {
                 dest.write_str("extends ")?;
                 other.to_css(dest)
             },
         }
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#typedef-symbol>
-#[derive(
-    Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToCss, ToShmem,
-)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToCss, ToShmem)]
 #[repr(u8)]
 pub enum Symbol {
     /// <string>
     String(crate::OwnedStr),
     /// <custom-ident>
     Ident(CustomIdent),
     // Not implemented:
     // /// <image>
@@ -551,19 +549,17 @@ impl Parse for Fallback {
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         Ok(Fallback(parse_counter_style_name(input)?))
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols>
-#[derive(
-    Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToCss, ToShmem,
-)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToCss, ToShmem)]
 #[repr(C)]
 pub struct Symbols(#[css(iterable)] pub crate::OwnedSlice<Symbol>);
 
 impl Parse for Symbols {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
--- a/servo/components/style/custom_properties.rs
+++ b/servo/components/style/custom_properties.rs
@@ -577,17 +577,17 @@ impl<'a> CustomPropertiesBuilder<'a> {
                 let value = if !has_references && unparsed_value.references_environment {
                     let result = substitute_references_in_value(unparsed_value, &map, &self.device);
                     match result {
                         Ok(new_value) => Arc::new(new_value),
                         Err(..) => {
                             // Don't touch the map, this has the same effect as
                             // making it compute to the inherited one.
                             return;
-                        },
+                        }
                     }
                 } else {
                     (*unparsed_value).clone()
                 };
                 map.insert(name.clone(), value);
             },
             CustomDeclarationValue::CSSWideKeyword(keyword) => match keyword {
                 CSSWideKeyword::Revert => {
@@ -843,29 +843,29 @@ fn substitute_all(
 
         // Now we have shown that this variable is not in a loop, and all of its
         // dependencies should have been resolved. We can start substitution
         // now.
         let result = substitute_references_in_value(&value, &context.map, &context.device);
         match result {
             Ok(computed_value) => {
                 context.map.insert(name, Arc::new(computed_value));
-            },
+            }
             Err(..) => {
                 // This is invalid, reset it to the unset (inherited) value.
                 let inherited = context.inherited.and_then(|m| m.get(&name)).cloned();
                 match inherited {
                     Some(computed_value) => {
                         context.map.insert(name, computed_value);
                     },
                     None => {
                         context.map.remove(&name);
                     },
                 };
-            },
+            }
         }
 
         // All resolved, so return the signal value.
         None
     }
 
     // We have to clone the names so that we can mutably borrow the map
     // in the context we create for traversal.
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -17,17 +17,17 @@ use crate::element_state::ElementState;
 use crate::font_metrics::FontMetricsProvider;
 use crate::media_queries::Device;
 use crate::properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock};
 use crate::selector_parser::{AttrValue, Lang, PseudoElement, SelectorImpl};
 use crate::shared_lock::Locked;
 use crate::stylist::CascadeData;
 use crate::traversal_flags::TraversalFlags;
 use crate::{Atom, LocalName, Namespace, WeakAtom};
-use atomic_refcell::{AtomicRef, AtomicRefMut};
+use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
 use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode};
 use selectors::sink::Push;
 use selectors::Element as SelectorsElement;
 use servo_arc::{Arc, ArcBorrow};
 use std::fmt;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::ops::Deref;
@@ -692,24 +692,28 @@ pub trait TElement:
     /// exclusive access to the element.
     unsafe fn ensure_data(&self) -> AtomicRefMut<ElementData>;
 
     /// Clears the element data reference, if any.
     ///
     /// Unsafe following the same reasoning as ensure_data.
     unsafe fn clear_data(&self);
 
-    /// Whether there is an ElementData container.
-    fn has_data(&self) -> bool;
+    /// Gets a reference to the ElementData container.
+    fn get_data(&self) -> Option<&AtomicRefCell<ElementData>>;
 
     /// Immutably borrows the ElementData.
-    fn borrow_data(&self) -> Option<AtomicRef<ElementData>>;
+    fn borrow_data(&self) -> Option<AtomicRef<ElementData>> {
+        self.get_data().map(|x| x.borrow())
+    }
 
     /// Mutably borrows the ElementData.
-    fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>>;
+    fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>> {
+        self.get_data().map(|x| x.borrow_mut())
+    }
 
     /// Whether we should skip any root- or item-based display property
     /// blockification on this element.  (This function exists so that Gecko
     /// native anonymous content can opt out of this style fixup.)
     fn skip_item_display_fixup(&self) -> bool;
 
     /// Sets selector flags, which indicate what kinds of selectors may have
     /// matched on this element and therefore what kind of work may need to
--- a/servo/components/style/driver.rs
+++ b/servo/components/style/driver.rs
@@ -160,19 +160,20 @@ pub fn traverse_dom<E, D>(
             nodes_remaining_at_current_depth = discovered.len();
         }
     }
 
     // Collect statistics from thread-locals if requested.
     if dump_stats || report_stats {
         let mut aggregate = mem::replace(&mut context.thread_local.statistics, Default::default());
         let parallel = maybe_tls.is_some();
-        if let Some(tls) = maybe_tls {
-            for mut slot in tls.into_slots().into_vec() {
-                if let Some(cx) = slot.get_mut() {
+        if let Some(ref mut tls) = maybe_tls {
+            let slots = unsafe { tls.unsafe_get() };
+            for slot in slots {
+                if let Some(ref cx) = *slot.borrow() {
                     aggregate += cx.statistics.clone();
                 }
             }
         }
 
         if report_stats {
             report_statistics(&aggregate);
         }
--- a/servo/components/style/encoding_support.rs
+++ b/servo/components/style/encoding_support.rs
@@ -5,17 +5,17 @@
 //! Parsing stylesheets from bytes (not `&str`).
 
 extern crate encoding_rs;
 
 use crate::context::QuirksMode;
 use crate::error_reporting::ParseErrorReporter;
 use crate::media_queries::MediaList;
 use crate::shared_lock::SharedRwLock;
-use crate::stylesheets::{AllowImportRules, Origin, Stylesheet, StylesheetLoader, UrlExtraData};
+use crate::stylesheets::{Origin, Stylesheet, StylesheetLoader, UrlExtraData};
 use cssparser::{stylesheet_encoding, EncodingSupport};
 use servo_arc::Arc;
 use std::borrow::Cow;
 use std::str;
 
 struct EncodingRs;
 
 impl EncodingSupport for EncodingRs {
@@ -73,17 +73,16 @@ impl Stylesheet {
             url_data,
             origin,
             Arc::new(shared_lock.wrap(media)),
             shared_lock,
             stylesheet_loader,
             error_reporter,
             quirks_mode,
             0,
-            AllowImportRules::Yes,
         )
     }
 
     /// Updates an empty stylesheet with a set of bytes that reached over the
     /// network.
     pub fn update_from_bytes(
         existing: &Stylesheet,
         bytes: &[u8],
@@ -96,12 +95,11 @@ impl Stylesheet {
         let string = decode_stylesheet_bytes(bytes, protocol_encoding_label, environment_encoding);
         Self::update_from_str(
             existing,
             &string,
             url_data,
             stylesheet_loader,
             error_reporter,
             0,
-            AllowImportRules::Yes,
         )
     }
 }
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -5,17 +5,17 @@
 //! This module contains conversion helpers between Servo and Gecko types
 //! Ideally, it would be in geckolib itself, but coherence
 //! forces us to keep the traits and implementations here
 //!
 //! FIXME(emilio): This file should generally just die.
 
 #![allow(unsafe_code)]
 
-use crate::gecko_bindings::structs::{nsresult, Matrix4x4Components};
+use crate::gecko_bindings::structs::{Matrix4x4Components, nsresult};
 use crate::stylesheets::RulesMutateError;
 use crate::values::computed::transform::Matrix3D;
 
 impl From<RulesMutateError> for nsresult {
     fn from(other: RulesMutateError) -> Self {
         match other {
             RulesMutateError::Syntax => nsresult::NS_ERROR_DOM_SYNTAX_ERR,
             RulesMutateError::IndexSize => nsresult::NS_ERROR_DOM_INDEX_SIZE_ERR,
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -313,14 +313,12 @@ impl Device {
         let pc = match self.pres_context() {
             Some(pc) => pc,
             None => return SideOffsets2D::zero(),
         };
         let mut top = 0.0;
         let mut right = 0.0;
         let mut bottom = 0.0;
         let mut left = 0.0;
-        unsafe {
-            bindings::Gecko_GetSafeAreaInsets(pc, &mut top, &mut right, &mut bottom, &mut left)
-        };
+        unsafe { bindings::Gecko_GetSafeAreaInsets(pc, &mut top, &mut right, &mut bottom, &mut left) };
         SideOffsets2D::new(top, right, bottom, left)
     }
 }
--- a/servo/components/style/gecko/selector_parser.rs
+++ b/servo/components/style/gecko/selector_parser.rs
@@ -168,17 +168,17 @@ impl NonTSPseudoClass {
         }
         apply_non_ts_list!(pseudo_class_check_is_enabled_in)
     }
 
     /// Returns whether the pseudo-class is enabled in content sheets.
     #[inline]
     fn is_enabled_in_content(&self) -> bool {
         if matches!(*self, NonTSPseudoClass::FocusVisible) {
-            return static_prefs::pref!("layout.css.focus-visible.enabled");
+            return static_prefs::pref!("layout.css.focus-visible.enabled")
         }
         !self.has_any_flag(NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME)
     }
 
     /// Get the state flag associated with a pseudo-class, if any.
     pub fn state_flag(&self) -> ElementState {
         macro_rules! flag {
             (_) => {
--- a/servo/components/style/gecko/snapshot_helpers.rs
+++ b/servo/components/style/gecko/snapshot_helpers.rs
@@ -88,17 +88,23 @@ pub(super) fn each_exported_part(
     name: &Atom,
     mut callback: impl FnMut(&Atom),
 ) {
     let attr = match find_attr(attrs, &atom!("exportparts")) {
         Some(attr) => attr,
         None => return,
     };
     let mut length = 0;
-    let atoms = unsafe { bindings::Gecko_Element_ExportedParts(attr, name.as_ptr(), &mut length) };
+    let atoms = unsafe {
+        bindings::Gecko_Element_ExportedParts(
+            attr,
+            name.as_ptr(),
+            &mut length,
+        )
+    };
     if atoms.is_null() {
         return;
     }
 
     unsafe {
         for atom in std::slice::from_raw_parts(atoms, length) {
             Atom::with(*atom, &mut callback)
         }
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -67,17 +67,17 @@ use crate::selector_parser::{AttrValue, 
 use crate::shared_lock::Locked;
 use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
 use crate::stylist::CascadeData;
 use crate::values::computed::font::GenericFontFamily;
 use crate::values::computed::Length;
 use crate::values::specified::length::FontBaseSize;
 use crate::CaseSensitivityExt;
 use app_units::Au;
-use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
+use atomic_refcell::{AtomicRefCell, AtomicRefMut};
 use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator};
 use selectors::attr::{CaseSensitivity, NamespaceConstraint};
 use selectors::matching::VisitedHandlingMode;
 use selectors::matching::{ElementSelectorFlags, MatchingContext};
 use selectors::sink::Push;
 use selectors::{Element, OpaqueElement};
 use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
 use std::cell::RefCell;
@@ -552,22 +552,16 @@ impl<'le> fmt::Debug for GeckoElement<'l
             bindings::Gecko_Element_DebugListAttributes(self.0, &mut attrs);
         }
         write!(f, "{}", attrs)?;
         write!(f, "> ({:#x})", self.as_node().opaque().0)
     }
 }
 
 impl<'le> GeckoElement<'le> {
-    /// Gets the raw `ElementData` refcell for the element.
-    #[inline(always)]
-    pub fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
-        unsafe { self.0.mServoData.get().as_ref() }
-    }
-
     #[inline(always)]
     fn attrs(&self) -> &[structs::AttrArray_InternalAttr] {
         unsafe {
             let attrs = match self.0.mAttrs.mImpl.mPtr.as_ref() {
                 Some(attrs) => attrs,
                 None => return &[],
             };
 
@@ -1308,27 +1302,27 @@ impl<'le> TElement for GeckoElement<'le>
     }
 
     #[inline]
     fn handled_snapshot(&self) -> bool {
         self.flags() & (ELEMENT_HANDLED_SNAPSHOT as u32) != 0
     }
 
     unsafe fn set_handled_snapshot(&self) {
-        debug_assert!(self.has_data());
+        debug_assert!(self.get_data().is_some());
         self.set_flags(ELEMENT_HANDLED_SNAPSHOT as u32)
     }
 
     #[inline]
     fn has_dirty_descendants(&self) -> bool {
         self.flags() & (ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0
     }
 
     unsafe fn set_dirty_descendants(&self) {
-        debug_assert!(self.has_data());
+        debug_assert!(self.get_data().is_some());
         debug!("Setting dirty descendants: {:?}", self);
         self.set_flags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
     }
 
     unsafe fn unset_dirty_descendants(&self) {
         self.unset_flags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
     }
 
@@ -1387,18 +1381,23 @@ impl<'le> TElement for GeckoElement<'le>
     fn store_children_to_process(&self, _: isize) {
         // This is only used for bottom-up traversal, and is thus a no-op for Gecko.
     }
 
     fn did_process_child(&self) -> isize {
         panic!("Atomic child count not implemented in Gecko");
     }
 
+    #[inline(always)]
+    fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
+        unsafe { self.0.mServoData.get().as_ref() }
+    }
+
     unsafe fn ensure_data(&self) -> AtomicRefMut<ElementData> {
-        if !self.has_data() {
+        if self.get_data().is_none() {
             debug!("Creating ElementData for {:?}", self);
             let ptr = Box::into_raw(Box::new(AtomicRefCell::new(ElementData::default())));
             self.0.mServoData.set(ptr);
         }
         self.mutate_data().unwrap()
     }
 
     unsafe fn clear_data(&self) {
@@ -1623,32 +1622,16 @@ impl<'le> TElement for GeckoElement<'le>
 
         // Check if we have to cancel the running transition because this is not
         // a matching transition-property value.
         existing_transitions
             .keys()
             .any(|property| !transitions_to_keep.contains(*property))
     }
 
-    /// Whether there is an ElementData container.
-    #[inline]
-    fn has_data(&self) -> bool {
-        self.get_data().is_some()
-    }
-
-    /// Immutably borrows the ElementData.
-    fn borrow_data(&self) -> Option<AtomicRef<ElementData>> {
-        self.get_data().map(|x| x.borrow())
-    }
-
-    /// Mutably borrows the ElementData.
-    fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>> {
-        self.get_data().map(|x| x.borrow_mut())
-    }
-
     #[inline]
     fn lang_attr(&self) -> Option<AttrValue> {
         let ptr = unsafe { bindings::Gecko_LangValue(self.0) };
         if ptr.is_null() {
             None
         } else {
             Some(unsafe { Atom::from_addrefed(ptr) })
         }
--- a/servo/components/style/gecko_string_cache/namespace.rs
+++ b/servo/components/style/gecko_string_cache/namespace.rs
@@ -19,28 +19,17 @@ macro_rules! ns {
         $crate::string_cache::Namespace(atom!(""))
     };
     ($s:tt) => {
         $crate::string_cache::Namespace(atom!($s))
     };
 }
 
 /// A Gecko namespace is just a wrapped atom.
-#[derive(
-    Clone,
-    Debug,
-    Default,
-    Eq,
-    Hash,
-    MallocSizeOf,
-    PartialEq,
-    ToComputedValue,
-    ToResolvedValue,
-    ToShmem,
-)]
+#[derive(Clone, Debug, Default, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
 #[repr(transparent)]
 pub struct Namespace(pub Atom);
 
 impl PrecomputedHash for Namespace {
     #[inline]
     fn precomputed_hash(&self) -> u32 {
         self.0.precomputed_hash()
     }
--- a/servo/components/style/invalidation/element/state_and_attributes.rs
+++ b/servo/components/style/invalidation/element/state_and_attributes.rs
@@ -85,17 +85,17 @@ pub fn should_process_descendants(data: 
     !data.styles.is_display_none() && !data.hint.contains(RestyleHint::RESTYLE_DESCENDANTS)
 }
 
 /// Propagates the bits after invalidating a descendant child.
 pub fn invalidated_descendants<E>(element: E, child: E)
 where
     E: TElement,
 {
-    if !child.has_data() {
+    if child.get_data().is_none() {
         return;
     }
 
     // The child may not be a flattened tree child of the current element,
     // but may be arbitrarily deep.
     //
     // Since we keep the traversal flags in terms of the flattened tree,
     // we need to propagate it as appropriate.
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -7,18 +7,16 @@
 #![allow(unsafe_code)]
 #![deny(missing_docs)]
 
 use crate::computed_value_flags::ComputedValueFlags;
 use crate::context::{ElementCascadeInputs, QuirksMode, SelectorFlagsMap};
 use crate::context::{SharedStyleContext, StyleContext};
 use crate::data::ElementData;
 use crate::dom::TElement;
-#[cfg(feature = "servo")]
-use crate::dom::{OpaqueNode, TNode};
 use crate::invalidation::element::restyle_hints::RestyleHint;
 use crate::properties::longhands::display::computed_value::T as Display;
 use crate::properties::ComputedValues;
 use crate::rule_tree::{CascadeLevel, StrongRuleNode};
 use crate::selector_parser::{PseudoElement, RestyleDamage};
 use crate::style_resolver::ResolvedElementStyles;
 use crate::traversal_flags::TraversalFlags;
 use selectors::matching::ElementSelectorFlags;
@@ -433,64 +431,51 @@ trait PrivateMatchMethods: TElement {
         &self,
         context: &mut StyleContext<Self>,
         old_values: &mut Option<Arc<ComputedValues>>,
         new_values: &mut Arc<ComputedValues>,
         _restyle_hint: RestyleHint,
         _important_rules_changed: bool,
     ) {
         use crate::animation;
+        use crate::dom::TNode;
 
-        let this_opaque = self.as_node().opaque();
-        let mut running_and_expired_transitions = vec![];
+        let mut possibly_expired_animations = vec![];
         let shared_context = context.shared;
-        if let Some(ref mut old_values) = *old_values {
-            // We apply the expired transitions and animations to the old style
-            // here, because we later compare the old style to the new style in
-            // `start_transitions_if_applicable`. If the styles differ then it will
-            // cause the expired transition to restart.
-            //
-            // TODO(mrobinson): We should really be following spec behavior and calculate
-            // after-change-style and before-change-style here.
-            Self::collect_and_update_style_for_expired_transitions(
+        if let Some(ref mut old) = *old_values {
+            // FIXME(emilio, #20116): This makes no sense.
+            self.update_animations_for_cascade(
                 shared_context,
-                this_opaque,
-                old_values,
-                &mut running_and_expired_transitions,
-            );
-
-            Self::update_style_for_animations_and_collect_running_transitions(
-                shared_context,
-                this_opaque,
-                old_values,
-                &mut running_and_expired_transitions,
+                old,
+                &mut possibly_expired_animations,
                 &context.thread_local.font_metrics_provider,
             );
         }
 
         let new_animations_sender = &context.thread_local.new_animations_sender;
+        let this_opaque = self.as_node().opaque();
         // Trigger any present animations if necessary.
         animation::maybe_start_animations(
             *self,
             &shared_context,
             new_animations_sender,
             this_opaque,
             &new_values,
         );
 
-        // Trigger transitions if necessary. This will set `new_values` to
-        // the starting value of the transition if it did trigger a transition.
-        if let Some(ref values) = old_values {
+        // Trigger transitions if necessary. This will reset `new_values` back
+        // to its old value if it did trigger a transition.
+        if let Some(ref values) = *old_values {
             animation::start_transitions_if_applicable(
                 new_animations_sender,
                 this_opaque,
                 &values,
                 new_values,
                 &shared_context.timer,
-                &running_and_expired_transitions,
+                &possibly_expired_animations,
             );
         }
     }
 
     /// Computes and applies non-redundant damage.
     fn accumulate_damage_for(
         &self,
         shared_context: &SharedStyleContext,
@@ -598,58 +583,51 @@ trait PrivateMatchMethods: TElement {
             }
         }
 
         // We could prove that, if our children don't inherit reset
         // properties, we can stop the cascade.
         ChildCascadeRequirement::MustCascadeChildrenIfInheritResetStyle
     }
 
+    // FIXME(emilio, #20116): It's not clear to me that the name of this method
+    // represents anything of what it does.
+    //
+    // Also, this function gets the old style, for some reason I don't really
+    // get, but the functions called (mainly update_style_for_animation) expects
+    // the new style, wtf?
     #[cfg(feature = "servo")]
-    fn collect_and_update_style_for_expired_transitions(
+    fn update_animations_for_cascade(
+        &self,
         context: &SharedStyleContext,
-        node: OpaqueNode,
         style: &mut Arc<ComputedValues>,
-        expired_transitions: &mut Vec<crate::animation::PropertyAnimation>,
-    ) {
-        use crate::animation::Animation;
-
-        let mut all_expired_animations = context.expired_animations.write();
-        if let Some(animations) = all_expired_animations.remove(&node) {
-            debug!("removing expired animations for {:?}", node);
-            for animation in animations {
-                debug!("Updating expired animation {:?}", animation);
-                // TODO: support animation-fill-mode
-                if let Animation::Transition(_, _, frame) = animation {
-                    frame.property_animation.update(Arc::make_mut(style), 1.0);
-                    expired_transitions.push(frame.property_animation);
-                }
-            }
-        }
-    }
-
-    #[cfg(feature = "servo")]
-    fn update_style_for_animations_and_collect_running_transitions(
-        context: &SharedStyleContext,
-        node: OpaqueNode,
-        style: &mut Arc<ComputedValues>,
-        running_transitions: &mut Vec<crate::animation::PropertyAnimation>,
+        possibly_expired_animations: &mut Vec<crate::animation::PropertyAnimation>,
         font_metrics: &dyn crate::font_metrics::FontMetricsProvider,
     ) {
         use crate::animation::{self, Animation, AnimationUpdate};
+        use crate::dom::TNode;
 
-        let had_running_animations = context.running_animations.read().get(&node).is_some();
+        // Finish any expired transitions.
+        let this_opaque = self.as_node().opaque();
+        animation::complete_expired_transitions(this_opaque, style, context);
+
+        // Merge any running animations into the current style, and cancel them.
+        let had_running_animations = context
+            .running_animations
+            .read()
+            .get(&this_opaque)
+            .is_some();
         if !had_running_animations {
             return;
         }
 
         let mut all_running_animations = context.running_animations.write();
-        for mut running_animation in all_running_animations.get_mut(&node).unwrap() {
+        for mut running_animation in all_running_animations.get_mut(&this_opaque).unwrap() {
             if let Animation::Transition(_, _, ref frame) = *running_animation {
-                running_transitions.push(frame.property_animation.clone());
+                possibly_expired_animations.push(frame.property_animation.clone());
                 continue;
             }
 
             let update = animation::update_style_for_animation::<Self>(
                 context,
                 &mut running_animation,
                 style,
                 font_metrics,
--- a/servo/components/style/properties/longhands/box.mako.rs
+++ b/servo/components/style/properties/longhands/box.mako.rs
@@ -340,16 +340,17 @@ impl computed_value::T {
 
 <% transform_extra_prefixes = "moz:layout.css.prefixes.transforms webkit" %>
 
 ${helpers.predefined_type(
     "transform",
     "Transform",
     "generics::transform::Transform::none()",
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     extra_prefixes=transform_extra_prefixes,
     animation_value_type="ComputedValue",
     flags="CREATES_STACKING_CONTEXT FIXPOS_CB CAN_ANIMATE_ON_COMPOSITOR",
     spec="https://drafts.csswg.org/css-transforms/#propdef-transform",
     servo_restyle_damage="reflow_out_of_flow",
 )}
 
 ${helpers.predefined_type(
@@ -543,41 +544,41 @@ impl computed_value::T {
     gecko_ffi_name="mResize",
     spec="https://drafts.csswg.org/css-ui/#propdef-resize",
 )}
 
 ${helpers.predefined_type(
     "perspective",
     "Perspective",
     "computed::Perspective::none()",
-    engines="gecko servo-2013 servo-2020",
+    engines="gecko servo-2013",
     gecko_ffi_name="mChildPerspective",
     spec="https://drafts.csswg.org/css-transforms/#perspective",
     extra_prefixes=transform_extra_prefixes,
     flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
     animation_value_type="AnimatedPerspective",
     servo_restyle_damage = "reflow_out_of_flow",
 )}
 
 ${helpers.predefined_type(
     "perspective-origin",
     "Position",
     "computed::position::Position::center()",
-    engines="gecko servo-2013 servo-2020",
+    engines="gecko servo-2013",
     boxed=True,
     extra_prefixes=transform_extra_prefixes,
     spec="https://drafts.csswg.org/css-transforms-2/#perspective-origin-property",
     animation_value_type="ComputedValue",
     servo_restyle_damage="reflow_out_of_flow"
 )}
 
 ${helpers.single_keyword(
     "backface-visibility",
     "visible hidden",
-    engines="gecko servo-2013 servo-2020",
+    engines="gecko servo-2013",
     gecko_enum_prefix="StyleBackfaceVisibility",
     spec="https://drafts.csswg.org/css-transforms/#backface-visibility-property",
     extra_prefixes=transform_extra_prefixes,
     animation_value_type="discrete",
 )}
 
 ${helpers.single_keyword(
     "transform-box",
@@ -590,29 +591,30 @@ impl computed_value::T {
     animation_value_type="discrete",
 )}
 
 ${helpers.predefined_type(
     "transform-style",
     "TransformStyle",
     "computed::TransformStyle::Flat",
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     spec="https://drafts.csswg.org/css-transforms-2/#transform-style-property",
     needs_context=False,
     extra_prefixes=transform_extra_prefixes,
     flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
     animation_value_type="discrete",
     servo_restyle_damage = "reflow_out_of_flow",
 )}
 
 ${helpers.predefined_type(
     "transform-origin",
     "TransformOrigin",
     "computed::TransformOrigin::initial_value()",
-    engines="gecko servo-2013 servo-2020",
+    engines="gecko servo-2013",
     animation_value_type="ComputedValue",
     extra_prefixes=transform_extra_prefixes,
     gecko_ffi_name="mTransformOrigin",
     boxed=True,
     spec="https://drafts.csswg.org/css-transforms/#transform-origin-property",
     servo_restyle_damage="reflow_out_of_flow",
 )}
 
--- a/servo/components/style/properties/longhands/counters.mako.rs
+++ b/servo/components/style/properties/longhands/counters.mako.rs
@@ -6,16 +6,17 @@
 
 <% data.new_style_struct("Counters", inherited=False, gecko_name="Content") %>
 
 ${helpers.predefined_type(
     "content",
     "Content",
     "computed::Content::normal()",
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     initial_specified_value="specified::Content::normal()",
     animation_value_type="discrete",
     spec="https://drafts.csswg.org/css-content/#propdef-content",
     servo_restyle_damage="rebuild_and_reflow",
 )}
 
 ${helpers.predefined_type(
     "counter-increment",
--- a/servo/components/style/properties/longhands/effects.mako.rs
+++ b/servo/components/style/properties/longhands/effects.mako.rs
@@ -7,16 +7,17 @@
 // Box-shadow, etc.
 <% data.new_style_struct("Effects", inherited=False) %>
 
 ${helpers.predefined_type(
     "opacity",
     "Opacity",
     "1.0",
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     animation_value_type="ComputedValue",
     flags="CREATES_STACKING_CONTEXT CAN_ANIMATE_ON_COMPOSITOR",
     spec="https://drafts.csswg.org/css-color/#transparency",
     servo_restyle_damage = "reflow_out_of_flow",
 )}
 
 ${helpers.predefined_type(
     "box-shadow",
@@ -45,16 +46,17 @@
     spec="https://drafts.fxtf.org/css-masking/#clip-property",
 )}
 
 ${helpers.predefined_type(
     "filter",
     "Filter",
     None,
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     vector=True,
     simple_vector_bindings=True,
     gecko_ffi_name="mFilters",
     separator="Space",
     animation_value_type="AnimatedFilterList",
     vector_animation_type="with_zero",
     extra_prefixes="webkit",
     flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
@@ -78,13 +80,14 @@
 )}
 
 ${helpers.single_keyword(
     "mix-blend-mode",
     """normal multiply screen overlay darken lighten color-dodge
     color-burn hard-light soft-light difference exclusion hue
     saturation color luminosity""",
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     gecko_enum_prefix="StyleBlend",
     animation_value_type="discrete",
     flags="CREATES_STACKING_CONTEXT",
     spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode",
 )}
--- a/servo/components/style/properties/longhands/position.mako.rs
+++ b/servo/components/style/properties/longhands/position.mako.rs
@@ -55,16 +55,17 @@ macro_rules! impl_align_conversions {
     };
 }
 
 ${helpers.predefined_type(
     "z-index",
     "ZIndex",
     "computed::ZIndex::auto()",
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     spec="https://www.w3.org/TR/CSS2/visuren.html#z-index",
     flags="CREATES_STACKING_CONTEXT",
     animation_value_type="ComputedValue",
 )}
 
 // CSS Flexible Box Layout Module Level 1
 // http://www.w3.org/TR/css3-flexbox/
 
@@ -308,16 +309,17 @@ macro_rules! impl_align_conversions {
         servo_restyle_damage="reflow",
     )}
 % endfor
 
 ${helpers.single_keyword(
     "box-sizing",
     "content-box border-box",
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     extra_prefixes="moz:layout.css.prefixes.box-sizing webkit",
     spec="https://drafts.csswg.org/css-ui/#propdef-box-sizing",
     gecko_enum_prefix="StyleBoxSizing",
     custom_consts={ "content-box": "Content", "border-box": "Border" },
     animation_value_type="discrete",
     servo_restyle_damage = "reflow",
 )}
 
--- a/servo/components/style/properties/longhands/text.mako.rs
+++ b/servo/components/style/properties/longhands/text.mako.rs
@@ -27,35 +27,36 @@
     servo_restyle_damage="rebuild_and_reflow",
 )}
 
 ${helpers.predefined_type(
     "text-decoration-line",
     "TextDecorationLine",
     "specified::TextDecorationLine::none()",
     engines="gecko servo-2013 servo-2020",
+    servo_2020_pref="layout.2020.unimplemented",
     initial_specified_value="specified::TextDecorationLine::none()",
     animation_value_type="discrete",
     spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line",
     servo_restyle_damage="rebuild_and_reflow",
 )}
 
 ${helpers.single_keyword(
     "text-decoration-style",
     "solid double dotted dashed wavy -moz-none",
-    engines="gecko servo-2020",
+    engines="gecko",
     animation_value_type="discrete",
     spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style",
 )}
 
 ${helpers.predefined_type(
     "text-decoration-color",
     "Color",
     "computed_value::T::currentcolor()",
-    engines="gecko servo-2020",
+    engines="gecko",
     initial_specified_value="specified::Color::currentcolor()",
     animation_value_type="AnimatedColor",
     ignored_when_colors_disabled=True,
     spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color",
 )}
 
 ${helpers.predefined_type(
     "initial-letter",
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -896,18 +896,17 @@ impl LonghandIdSet {
     }
 
     /// Returns the set of border properties for the purpose of disabling native
     /// appearance.
     #[inline]
     pub fn border_background_properties() -> &'static Self {
         ${static_longhand_id_set(
             "BORDER_BACKGROUND_PROPERTIES",
-            lambda p: (p.logical_group and p.logical_group.startswith("border")) or \
-                       p.name in ["background-color", "background-image"]
+            lambda p: (p.logical_group and p.logical_group.startswith("border")) or p.name in ["background-color", "background-image"]
         )}
         &BORDER_BACKGROUND_PROPERTIES
     }
 
     /// Iterate over the current longhand id set.
     pub fn iter(&self) -> LonghandIdSetIterator {
         LonghandIdSetIterator { longhands: self, cur: 0, }
     }
--- a/servo/components/style/properties/shorthands/text.mako.rs
+++ b/servo/components/style/properties/shorthands/text.mako.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 https://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <%helpers:shorthand name="text-decoration"
-                    engines="gecko servo-2013 servo-2020"
+                    engines="gecko servo-2013"
                     flags="SHORTHAND_IN_GETCS"
                     sub_properties="text-decoration-line
                     ${' text-decoration-style text-decoration-color text-decoration-thickness' if engine == 'gecko' else ''}"
                     spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration">
 
     % if engine == "gecko":
         use crate::values::specified;
         use crate::properties::longhands::{text_decoration_style, text_decoration_color, text_decoration_thickness};
--- a/servo/components/style/rule_collector.rs
+++ b/servo/components/style/rule_collector.rs
@@ -143,18 +143,17 @@ where
     fn in_tree(&mut self, host: Option<E>, f: impl FnOnce(&mut Self)) {
         debug_assert!(!self.in_sort_scope, "Nested sorting makes no sense");
         let start = self.rules.len();
         self.in_sort_scope = true;
         let old_host = self.context.current_host.take();
         self.context.current_host = host.map(|e| e.opaque());
         f(self);
         if start != self.rules.len() {
-            self.rules[start..]
-                .sort_unstable_by_key(|block| (block.specificity, block.source_order()));
+            self.rules[start..].sort_unstable_by_key(|block| (block.specificity, block.source_order()));
         }
         self.context.current_host = old_host;
         self.in_sort_scope = false;
     }
 
     #[inline]
     fn in_shadow_tree(&mut self, host: E, f: impl FnOnce(&mut Self)) {
         self.in_tree(Some(host), f);
@@ -210,30 +209,38 @@ where
                 for declaration in &self.rules[length_before_preshints..] {
                     assert_eq!(declaration.level(), CascadeLevel::PresHints);
                 }
             }
         }
     }
 
     #[inline]
-    fn collect_rules_in_list(&mut self, part_rules: &[Rule], cascade_level: CascadeLevel) {
+    fn collect_rules_in_list(
+        &mut self,
+        part_rules: &[Rule],
+        cascade_level: CascadeLevel,
+    ) {
         debug_assert!(self.in_sort_scope, "Rules gotta be sorted");
         SelectorMap::get_matching_rules(
             self.element,
             part_rules,
             &mut self.rules,
             &mut self.context,
             &mut self.flags_setter,
             cascade_level,
         );
     }
 
     #[inline]
-    fn collect_rules_in_map(&mut self, map: &SelectorMap<Rule>, cascade_level: CascadeLevel) {
+    fn collect_rules_in_map(
+        &mut self,
+        map: &SelectorMap<Rule>,
+        cascade_level: CascadeLevel,
+    ) {
         debug_assert!(self.in_sort_scope, "Rules gotta be sorted");
         map.get_all_matching_rules(
             self.element,
             self.rule_hash_target,
             &mut self.rules,
             &mut self.context,
             &mut self.flags_setter,
             cascade_level,
@@ -401,17 +408,20 @@ where
             if let Some(part_rules) = part_rules {
                 let containing_host = outer_shadow.map(|s| s.host());
                 let cascade_level = CascadeLevel::AuthorNormal {
                     shadow_cascade_order,
                 };
                 self.in_tree(containing_host, |collector| {
                     for p in &parts {
                         if let Some(part_rules) = part_rules.get(p) {
-                            collector.collect_rules_in_list(part_rules, cascade_level);
+                            collector.collect_rules_in_list(
+                                part_rules,
+                                cascade_level,
+                            );
                         }
                     }
                 });
                 shadow_cascade_order.inc();
             }
 
             inner_shadow = match outer_shadow {
                 Some(s) => s,
--- a/servo/components/style/scoped_tls.rs
+++ b/servo/components/style/scoped_tls.rs
@@ -66,13 +66,14 @@ impl<'scope, T: Send> ScopedTLS<'scope, 
         let mut opt = self.borrow_mut();
         if opt.is_none() {
             f(opt.deref_mut());
         }
 
         RefMut::map(opt, |x| x.as_mut().unwrap())
     }
 
-    /// Returns the slots, consuming the scope.
-    pub fn into_slots(self) -> Box<[RefCell<Option<T>>]> {
-        self.slots
+    /// Unsafe access to the slots. This can be used to access the TLS when
+    /// the caller knows that the pool does not have access to the TLS.
+    pub unsafe fn unsafe_get(&self) -> &[RefCell<Option<T>>] {
+        &self.slots
     }
 }
--- a/servo/components/style/style_adjuster.rs
+++ b/servo/components/style/style_adjuster.rs
@@ -224,20 +224,20 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
     }
 
     /// Compute a few common flags for both text and element's style.
     fn set_bits(&mut self) {
         let display = self.style.get_box().clone_display();
 
         if !display.is_contents() {
             if !self
-                .style
-                .get_text()
-                .clone_text_decoration_line()
-                .is_empty()
+                    .style
+                    .get_text()
+                    .clone_text_decoration_line()
+                    .is_empty()
             {
                 self.style
                     .add_flags(ComputedValueFlags::HAS_TEXT_DECORATION_LINES);
             }
 
             if self.style.get_effects().clone_opacity() == 0. {
                 self.style
                     .add_flags(ComputedValueFlags::IS_IN_OPACITY_ZERO_SUBTREE);
--- a/servo/components/style/stylesheet_set.rs
+++ b/servo/components/style/stylesheet_set.rs
@@ -385,18 +385,17 @@ macro_rules! sheet_set_methods {
     ($set_name:expr) => {
         fn collect_invalidations_for(
             &mut self,
             device: Option<&Device>,
             sheet: &S,
             guard: &SharedRwLockReadGuard,
         ) {
             if let Some(device) = device {
-                self.invalidations
-                    .collect_invalidations_for(device, sheet, guard);
+                self.invalidations.collect_invalidations_for(device, sheet, guard);
             }
         }
 
         /// Appends a new stylesheet to the current set.
         ///
         /// No device implies not computing invalidations.
         pub fn append_stylesheet(
             &mut self,
@@ -433,17 +432,17 @@ macro_rules! sheet_set_methods {
             guard: &SharedRwLockReadGuard,
         ) {
             debug!(concat!($set_name, "::remove_stylesheet"));
             self.collect_invalidations_for(device, &sheet, guard);
 
             let collection = self.collection_for(&sheet, guard);
             collection.remove(&sheet)
         }
-    };
+    }
 }
 
 impl<S> DocumentStylesheetSet<S>
 where
     S: StylesheetInDocument + PartialEq + 'static,
 {
     /// Create a new empty DocumentStylesheetSet.
     pub fn new() -> Self {
--- a/servo/components/style/stylesheets/mod.rs
+++ b/servo/components/style/stylesheets/mod.rs
@@ -53,18 +53,18 @@ pub use self::media_rule::MediaRule;
 pub use self::namespace_rule::NamespaceRule;
 pub use self::origin::{Origin, OriginSet, OriginSetIterator, PerOrigin, PerOriginIter};
 pub use self::page_rule::PageRule;
 pub use self::rule_list::{CssRules, CssRulesHelpers};
 pub use self::rule_parser::{InsertRuleContext, State, TopLevelRuleParser};
 pub use self::rules_iterator::{AllRules, EffectiveRules};
 pub use self::rules_iterator::{NestedRuleIterationCondition, RulesIterator};
 pub use self::style_rule::StyleRule;
-pub use self::stylesheet::{AllowImportRules, SanitizationData, SanitizationKind};
 pub use self::stylesheet::{DocumentStyleSheet, Namespaces, Stylesheet};
+pub use self::stylesheet::{SanitizationData, SanitizationKind, AllowImportRules};
 pub use self::stylesheet::{StylesheetContents, StylesheetInDocument, UserAgentStylesheets};
 pub use self::supports_rule::SupportsRule;
 pub use self::viewport_rule::ViewportRule;
 
 /// The CORS mode used for a CSS load.
 #[repr(u8)]
 #[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
 pub enum CorsMode {
--- a/servo/components/style/stylesheets/rule_list.rs
+++ b/servo/components/style/stylesheets/rule_list.rs
@@ -5,17 +5,17 @@
 //! A list of CSS rules.
 
 use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
 use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
 use crate::str::CssStringWriter;
 use crate::stylesheets::loader::StylesheetLoader;
 use crate::stylesheets::rule_parser::{InsertRuleContext, State};
 use crate::stylesheets::stylesheet::StylesheetContents;
-use crate::stylesheets::{AllowImportRules, CssRule, RulesMutateError};
+use crate::stylesheets::{CssRule, RulesMutateError, AllowImportRules};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
 use servo_arc::{Arc, RawOffsetArc};
 use std::fmt::{self, Write};
 
 /// A list of CSS rules.
 #[derive(Debug, ToShmem)]
 pub struct CssRules(pub Vec<CssRule>);
--- a/servo/components/style/traversal.rs
+++ b/servo/components/style/traversal.rs
@@ -689,17 +689,19 @@ where
 
     // We speculatively evaluate any paint worklets during styling.
     // This allows us to run paint worklets in parallel with style and layout.
     // Note that this is wasted effort if the size of the node has
     // changed, but in may cases it won't have.
     if let Some(ref values) = data.styles.primary {
         for image in &values.get_background().background_image.0 {
             let (name, arguments) = match *image {
-                Image::PaintWorklet(ref worklet) => (&worklet.name, &worklet.arguments),
+                Image::PaintWorklet(ref worklet) => {
+                    (&worklet.name, &worklet.arguments)
+                },
                 _ => continue,
             };
             let painter = match context.shared.registered_speculative_painters.get(name) {
                 Some(painter) => painter,
                 None => continue,
             };
             let properties = painter
                 .properties()
@@ -838,17 +840,17 @@ where
     while let Some(p) = parents.pop() {
         for kid in p.traversal_children() {
             if let Some(kid) = kid.as_element() {
                 // We maintain an invariant that, if an element has data, all its
                 // ancestors have data as well.
                 //
                 // By consequence, any element without data has no descendants with
                 // data.
-                if kid.has_data() {
+                if kid.get_data().is_some() {
                     kid.clear_data();
                     parents.push(kid);
                 }
             }
         }
     }
 
     // Make sure not to clear NODE_NEEDS_FRAME on the root.
--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -16,16 +16,17 @@ use crate::values::computed::{Number, Pe
 use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue};
 use crate::values::generics::{font as generics, NonNegative};
 use crate::values::specified::font::{
     self as specified, KeywordInfo, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT,
 };
 use crate::values::specified::length::{FontBaseSize, NoCalcLength};
 use crate::values::CSSFloat;
 use crate::Atom;
+use byteorder::{BigEndian, ByteOrder};
 use cssparser::{serialize_identifier, CssStringWriter, Parser};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use std::fmt::{self, Write};
 use std::hash::{Hash, Hasher};
 #[cfg(feature = "gecko")]
 use std::mem::{self, ManuallyDrop};
 #[cfg(feature = "servo")]
@@ -222,19 +223,17 @@ impl ToCss for FontFamily {
         for family in iter {
             dest.write_str(", ")?;
             family.to_css(dest)?;
         }
         Ok(())
     }
 }
 
-#[derive(
-    Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem,
-)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 /// The name of a font family of choice
 pub struct FamilyName {
     /// Name of the font family
     pub name: Atom,
     /// Syntax of the font family
     pub syntax: FontFamilyNameSyntax,
 }
@@ -267,63 +266,48 @@ impl ToCss for FamilyName {
                     serialize_identifier(ident, dest)?;
                 }
                 Ok(())
             },
         }
     }
 }
 
-#[derive(
-    Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem,
-)]
+#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 /// Font family names must either be given quoted as strings,
 /// or unquoted as a sequence of one or more identifiers.
 #[repr(u8)]
 pub enum FontFamilyNameSyntax {
     /// The family name was specified in a quoted form, e.g. "Font Name"
     /// or 'Font Name'.
     Quoted,
 
     /// The family name was specified in an unquoted form as a sequence of
     /// identifiers.
     Identifiers,
 }
 
-#[derive(
-    Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToComputedValue, ToResolvedValue, ToShmem,
-)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToComputedValue, ToResolvedValue, ToShmem)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize, Hash))]
 /// A set of faces that vary in weight, width or slope.
 pub enum SingleFontFamily {
     /// The name of a font family of choice.
     FamilyName(FamilyName),
     /// Generic family name.
     Generic(GenericFontFamily),
 }
 
 /// A generic font-family name.
 ///
 /// The order here is important, if you change it make sure that
 /// `gfxPlatformFontList.h`s ranged array and `gfxFontFamilyList`'s
 /// sSingleGenerics are updated as well.
 #[derive(
-    Clone,
-    Copy,
-    Debug,
-    Eq,
-    Hash,
-    MallocSizeOf,
-    PartialEq,
-    Parse,
-    ToCss,
-    ToComputedValue,
-    ToResolvedValue,
-    ToShmem,
+    Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, Parse, ToCss, ToComputedValue, ToResolvedValue, ToShmem,
 )]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[repr(u8)]
 #[allow(missing_docs)]
 pub enum GenericFontFamily {
     /// No generic family specified, only for internal usage.
     ///
     /// NOTE(emilio): Gecko code relies on this variant being zero.
@@ -439,19 +423,17 @@ impl SingleFontFamily {
         SingleFontFamily::FamilyName(FamilyName {
             name,
             syntax: family.mSyntax,
         })
     }
 }
 
 #[cfg(feature = "servo")]
-#[derive(
-    Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem,
-)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
 /// A list of SingleFontFamily
 pub struct FontFamilyList(Box<[SingleFontFamily]>);
 
 #[cfg(feature = "gecko")]
 #[derive(Clone, Debug, ToComputedValue, ToResolvedValue)]
 /// A list of SingleFontFamily
 pub enum FontFamilyList {
     /// A strong reference to a Gecko SharedFontList object.
@@ -706,73 +688,44 @@ pub type FontVariationSettings = FontSet
 pub struct FontLanguageOverride(pub u32);
 
 impl FontLanguageOverride {
     #[inline]
     /// Get computed default value of `font-language-override` with 0
     pub fn zero() -> FontLanguageOverride {
         FontLanguageOverride(0)
     }
-
-    /// Returns this value as a `&str`, backed by `storage`.
-    #[inline]
-    pub fn to_str(self, storage: &mut [u8; 4]) -> &str {
-        if self.0 == 0 {
-            return "normal";
-        }
-        *storage = u32::to_be_bytes(self.0);
-        // Safe because we ensure it's ASCII during computing
-        let slice = if cfg!(debug_assertions) {
-            std::str::from_utf8(&storage[..]).unwrap()
-        } else {
-            unsafe { std::str::from_utf8_unchecked(&storage[..]) }
-        };
-        slice.trim_end()
-    }
-
-    /// Parses a str, return `Self::zero()` if the input isn't a valid OpenType
-    /// "language system" tag.
-    #[inline]
-    pub fn from_str(lang: &str) -> Self {
-        if lang.is_empty() || lang.len() > 4 {
-            return Self::zero();
-        }
-        let mut bytes = [b' '; 4];
-        for (byte, lang_byte) in bytes.iter_mut().zip(lang.as_bytes()) {
-            if !lang_byte.is_ascii() {
-                return Self::zero();
-            }
-            *byte = *lang_byte;
-        }
-        Self(u32::from_be_bytes(bytes))
-    }
-
-    /// Unsafe because `Self::to_str` requires the value to represent a UTF-8
-    /// string.
-    #[inline]
-    pub unsafe fn from_u32(value: u32) -> Self {
-        Self(value)
-    }
 }
 
 impl ToCss for FontLanguageOverride {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: fmt::Write,
     {
-        self.to_str(&mut [0; 4]).to_css(dest)
+        use std::str;
+
+        if self.0 == 0 {
+            return dest.write_str("normal");
+        }
+        let mut buf = [0; 4];
+        BigEndian::write_u32(&mut buf, self.0);
+        // Safe because we ensure it's ASCII during computing
+        let slice = if cfg!(debug_assertions) {
+            str::from_utf8(&buf).unwrap()
+        } else {
+            unsafe { str::from_utf8_unchecked(&buf) }
+        };
+        slice.trim_end().to_css(dest)
     }
 }
 
-// FIXME(emilio): Make Gecko use the cbindgen'd fontLanguageOverride, then
-// remove this.
 #[cfg(feature = "gecko")]
 impl From<u32> for FontLanguageOverride {
-    fn from(v: u32) -> Self {
-        unsafe { Self::from_u32(v) }
+    fn from(bits: u32) -> FontLanguageOverride {
+        FontLanguageOverride(bits)
     }
 }
 
 #[cfg(feature = "gecko")]
 impl From<FontLanguageOverride> for u32 {
     fn from(v: FontLanguageOverride) -> u32 {
         v.0
     }
--- a/servo/components/style/values/computed/image.rs
+++ b/servo/components/style/values/computed/image.rs
@@ -8,18 +8,17 @@
 //! [image]: https://drafts.csswg.org/css-images/#image-values
 
 use crate::values::computed::position::Position;
 use crate::values::computed::url::ComputedImageUrl;
 #[cfg(feature = "gecko")]
 use crate::values::computed::NumberOrPercentage;
 use crate::values::computed::{Angle, Color, Context};
 use crate::values::computed::{
-    AngleOrPercentage, LengthPercentage, NonNegativeLength, NonNegativeLengthPercentage,
-    ToComputedValue,
+    AngleOrPercentage, LengthPercentage, NonNegativeLength, NonNegativeLengthPercentage, ToComputedValue,
 };
 use crate::values::generics::image::{self as generic, GradientCompatMode};
 use crate::values::specified::image::LineDirection as SpecifiedLineDirection;
 use crate::values::specified::position::{HorizontalPositionKeyword, VerticalPositionKeyword};
 use std::f32::consts::PI;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 
--- a/servo/components/style/values/computed/length.rs
+++ b/servo/components/style/values/computed/length.rs
@@ -75,58 +75,47 @@ macro_rules! computed_length_percentage_
     ($inner:ty) => {
         /// Returns the used value.
         #[inline]
         pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
             match *self {
                 generics::GenericLengthPercentageOrAuto::Auto => None,
                 generics::GenericLengthPercentageOrAuto::LengthPercentage(ref lp) => {
                     Some(lp.to_used_value(percentage_basis))
-                },
+                }
             }
         }
 
         /// Returns true if the computed value is absolute 0 or 0%.
         #[inline]
         pub fn is_definitely_zero(&self) -> bool {
             use values::generics::length::LengthPercentageOrAuto::*;
             match *self {
                 LengthPercentage(ref l) => l.is_definitely_zero(),
                 Auto => false,
             }
         }
-    };
+    }
 }
 
 /// A computed type for `<length-percentage> | auto`.
 pub type LengthPercentageOrAuto = generics::GenericLengthPercentageOrAuto<LengthPercentage>;
 
 impl LengthPercentageOrAuto {
     /// Clamps the value to a non-negative value.
     pub fn clamp_to_non_negative(self) -> Self {
         use values::generics::length::LengthPercentageOrAuto::*;
         match self {
             LengthPercentage(l) => LengthPercentage(l.clamp_to_non_negative()),
             Auto => Auto,
         }
     }
 
-    /// Convert to have a borrow inside the enum
-    pub fn as_ref(&self) -> generics::GenericLengthPercentageOrAuto<&LengthPercentage> {
-        use values::generics::length::LengthPercentageOrAuto::*;
-        match *self {
-            LengthPercentage(ref lp) => LengthPercentage(lp),
-            Auto => Auto,
-        }
-    }
+    computed_length_percentage_or_auto!(LengthPercentage);
 
-    computed_length_percentage_or_auto!(LengthPercentage);
-}
-
-impl generics::GenericLengthPercentageOrAuto<&LengthPercentage> {
     /// Resolves the percentage.
     #[inline]
     pub fn percentage_relative_to(&self, basis: Length) -> LengthOrAuto {
         use values::generics::length::LengthPercentageOrAuto::*;
         match self {
             LengthPercentage(length_percentage) => {
                 LengthPercentage(length_percentage.percentage_relative_to(basis))
             },
--- a/servo/components/style/values/computed/length_percentage.rs
+++ b/servo/components/style/values/computed/length_percentage.rs
@@ -29,18 +29,18 @@ use crate::values::animated::{Animate, P
 use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
 use crate::values::generics::{calc, NonNegative};
 use crate::values::specified::length::FontBaseSize;
 use crate::values::{specified, CSSFloat};
 use crate::Zero;
 use app_units::Au;
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use serde::{Deserialize, Serialize};
+use std::fmt::{self, Write};
 use std::borrow::Cow;
-use std::fmt::{self, Write};
 use style_traits::values::specified::AllowedNumericType;
 use style_traits::{CssWriter, ToCss};
 
 #[doc(hidden)]
 #[derive(Clone, Copy)]
 #[repr(C)]
 pub struct LengthVariant {
     tag: u8,
@@ -197,19 +197,17 @@ impl LengthPercentage {
     #[inline]
     pub fn zero_percent() -> Self {
         Self::new_percent(Percentage::zero())
     }
 
     fn to_calc_node(&self) -> Cow<CalcNode> {
         match self.unpack() {
             Unpacked::Length(l) => Cow::Owned(CalcNode::Leaf(CalcLengthPercentageLeaf::Length(l))),
-            Unpacked::Percentage(p) => {
-                Cow::Owned(CalcNode::Leaf(CalcLengthPercentageLeaf::Percentage(p)))
-            },
+            Unpacked::Percentage(p) => Cow::Owned(CalcNode::Leaf(CalcLengthPercentageLeaf::Percentage(p))),
             Unpacked::Calc(p) => Cow::Borrowed(&p.node),
         }
     }
 
     /// Constructs a length value.
     #[inline]
     pub fn new_length(length: Length) -> Self {
         let length = Self(LengthPercentageUnion {
@@ -238,47 +236,49 @@ impl LengthPercentage {
     /// Given a `LengthPercentage` value `v`, construct the value representing
     /// `calc(100% - v)`.
     pub fn hundred_percent_minus(v: Self, clamping_mode: AllowedNumericType) -> Self {
         // TODO: This could in theory take ownership of the calc node in `v` if
         // possible instead of cloning.
         let mut node = v.to_calc_node().into_owned();
         node.negate();
 
-        let new_node = CalcNode::Sum(
-            vec![
-                CalcNode::Leaf(CalcLengthPercentageLeaf::Percentage(Percentage::hundred())),
-                node,
-            ]
-            .into(),
-        );
+        let new_node = CalcNode::Sum(vec![
+            CalcNode::Leaf(CalcLengthPercentageLeaf::Percentage(Percentage::hundred())),
+            node,
+        ].into());
 
         Self::new_calc(new_node, clamping_mode)
     }
 
     /// Constructs a `calc()` value.
     #[inline]
-    pub fn new_calc(mut node: CalcNode, clamping_mode: AllowedNumericType) -> Self {
+    pub fn new_calc(
+        mut node: CalcNode,
+        clamping_mode: AllowedNumericType,
+    ) -> Self {
         node.simplify_and_sort();
 
         match node {
             CalcNode::Leaf(l) => {
                 return match l {
                     CalcLengthPercentageLeaf::Length(l) => {
                         Self::new_length(Length::new(clamping_mode.clamp(l.px())))
                     },
                     CalcLengthPercentageLeaf::Percentage(p) => {
                         Self::new_percent(Percentage(clamping_mode.clamp(p.0)))
                     },
                 }
-            },
-            _ => Self::new_calc_unchecked(Box::new(CalcLengthPercentage {
-                clamping_mode,
-                node,
-            })),
+            }
+            _ => {
+                Self::new_calc_unchecked(Box::new(CalcLengthPercentage {
+                    clamping_mode,
+                    node,
+                }))
+            }
         }
     }
 
     /// Private version of new_calc() that constructs a calc() variant without
     /// checking.
     fn new_calc_unchecked(calc: Box<CalcLengthPercentage>) -> Self {
         let ptr = Box::into_raw(calc);
 
@@ -451,17 +451,17 @@ impl LengthPercentage {
     #[inline]
     pub fn clamp_to_non_negative(mut self) -> Self {
         match self.unpack_mut() {
             UnpackedMut::Length(l) => Self::new_length(l.clamp_to_non_negative()),
             UnpackedMut::Percentage(p) => Self::new_percent(p.clamp_to_non_negative()),
             UnpackedMut::Calc(ref mut c) => {
                 c.clamping_mode = AllowedNumericType::NonNegative;
                 self
-            },
+            }
         }
     }
 }
 
 impl PartialEq for LengthPercentage {
     fn eq(&self, other: &Self) -> bool {
         self.unpack() == other.unpack()
     }
@@ -572,27 +572,17 @@ impl<'de> Deserialize<'de> for LengthPer
     {
         Ok(Self::from_serializable(Serializable::deserialize(
             deserializer,
         )?))
     }
 }
 
 /// The leaves of a `<length-percentage>` calc expression.
-#[derive(
-    Clone,
-    Debug,
-    Deserialize,
-    MallocSizeOf,
-    PartialEq,
-    Serialize,
-    ToAnimatedZero,
-    ToCss,
-    ToResolvedValue,
-)]
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, ToAnimatedZero, ToCss, ToResolvedValue)]
 #[allow(missing_docs)]
 #[repr(u8)]
 pub enum CalcLengthPercentageLeaf {
     Length(Length),
     Percentage(Percentage),
 }
 
 impl CalcLengthPercentageLeaf {
@@ -614,20 +604,18 @@ impl PartialOrd for CalcLengthPercentage
 
         match (self, other) {
             (&Length(ref one), &Length(ref other)) => one.partial_cmp(other),
             (&Percentage(ref one), &Percentage(ref other)) => one.partial_cmp(other),
             _ => {
                 match *self {
                     Length(..) | Percentage(..) => {},
                 }
-                unsafe {
-                    debug_unreachable!("Forgot a branch?");
-                }
-            },
+                unsafe { debug_unreachable!("Forgot a branch?"); }
+            }
         }
     }
 }
 
 impl calc::CalcNodeLeaf for CalcLengthPercentageLeaf {
     fn is_negative(&self) -> bool {
         match *self {
             Self::Length(ref l) => l.px() < 0.,
@@ -677,41 +665,36 @@ impl calc::CalcNodeLeaf for CalcLengthPe
         }
     }
 }
 
 /// The computed version of a calc() node for `<length-percentage>` values.
 pub type CalcNode = calc::GenericCalcNode<CalcLengthPercentageLeaf>;
 
 /// The representation of a calc() function with mixed lengths and percentages.
-#[derive(
-    Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue, ToCss,
-)]
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue, ToCss)]
 #[repr(C)]
 pub struct CalcLengthPercentage {
     #[animation(constant)]
     #[css(skip)]
     clamping_mode: AllowedNumericType,
     node: CalcNode,
 }
 
 impl CalcLengthPercentage {
     /// Resolves the percentage.
     #[inline]
     fn resolve(&self, basis: Length) -> Length {
         // unwrap() is fine because the conversion below is infallible.
-        let px = self
-            .node
-            .resolve(|l| {
-                Ok(match *l {
-                    CalcLengthPercentageLeaf::Length(l) => l.px(),
-                    CalcLengthPercentageLeaf::Percentage(ref p) => basis.px() * p.0,
-                })
+        let px = self.node.resolve(|l| {
+            Ok(match *l {
+                CalcLengthPercentageLeaf::Length(l) => l.px(),
+                CalcLengthPercentageLeaf::Percentage(ref p) => basis.px() * p.0,
             })
-            .unwrap();
+        }).unwrap();
         Length::new(self.clamping_mode.clamp(px))
     }
 }
 
 // NOTE(emilio): We don't compare `clamping_mode` since we want to preserve the
 // invariant that `from_computed_value(length).to_computed_value(..) == length`.
 //
 // Right now for e.g. a non-negative length, we set clamping_mode to `All`
@@ -738,26 +721,34 @@ impl specified::CalcLengthPercentage {
         base_size: FontBaseSize,
     ) -> LengthPercentage
     where
         F: Fn(Length) -> Length,
     {
         use crate::values::specified::calc::Leaf;
         use crate::values::specified::length::NoCalcLength;
 
-        let node = self.node.map_leaves(|leaf| match *leaf {
-            Leaf::Percentage(p) => CalcLengthPercentageLeaf::Percentage(Percentage(p)),
-            Leaf::Length(l) => CalcLengthPercentageLeaf::Length(match l {
-                NoCalcLength::Absolute(ref abs) => zoom_fn(abs.to_computed_value(context)),
-                NoCalcLength::FontRelative(ref fr) => fr.to_computed_value(context, base_size),
-                other => other.to_computed_value(context),
-            }),
-            Leaf::Number(..) | Leaf::Angle(..) | Leaf::Time(..) => {
-                unreachable!("Shouldn't have parsed")
-            },
+        let node = self.node.map_leaves(|leaf| {
+            match *leaf {
+                Leaf::Percentage(p) => CalcLengthPercentageLeaf::Percentage(Percentage(p)),
+                Leaf::Length(l) => {
+                    CalcLengthPercentageLeaf::Length(match l {
+                        NoCalcLength::Absolute(ref abs) => {
+                            zoom_fn(abs.to_computed_value(context))
+                        },
+                        NoCalcLength::FontRelative(ref fr) => {
+                            fr.to_computed_value(context, base_size)
+                        },
+                        other => other.to_computed_value(context),
+                    })
+                },
+                Leaf::Number(..) |
+                Leaf::Angle(..) |
+                Leaf::Time(..) => unreachable!("Shouldn't have parsed"),
+            }
         });
 
         LengthPercentage::new_calc(node, self.clamping_mode)
     }
 
     /// Compute font-size or line-height taking into account text-zoom if necessary.
     pub fn to_computed_value_zoomed(
         &self,
@@ -792,22 +783,22 @@ impl specified::CalcLengthPercentage {
 
     #[inline]
     fn from_computed_value(computed: &CalcLengthPercentage) -> Self {
         use crate::values::specified::calc::Leaf;
         use crate::values::specified::length::NoCalcLength;
 
         specified::CalcLengthPercentage {
             clamping_mode: computed.clamping_mode,
-            node: computed.node.map_leaves(|l| match l {
-                CalcLengthPercentageLeaf::Length(ref l) => {
-                    Leaf::Length(NoCalcLength::from_px(l.px()))
-                },
-                CalcLengthPercentageLeaf::Percentage(ref p) => Leaf::Percentage(p.0),
-            }),
+            node: computed.node.map_leaves(|l| {
+                match l {
+                    CalcLengthPercentageLeaf::Length(ref l) => Leaf::Length(NoCalcLength::from_px(l.px())),
+                    CalcLengthPercentageLeaf::Percentage(ref p) => Leaf::Percentage(p.0),
+                }
+            })
         }
     }
 }
 
 /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
 /// https://drafts.csswg.org/css-values-4/#combine-math
 /// https://drafts.csswg.org/css-values-4/#combine-mixed
 impl Animate for LengthPercentage {
@@ -823,20 +814,17 @@ impl Animate for LengthPercentage {
             _ => {
                 let mut one = self.to_calc_node().into_owned();
                 let mut other = other.to_calc_node().into_owned();
                 let (l, r) = procedure.weights();
 
                 one.mul_by(l as f32);
                 other.mul_by(r as f32);
 
-                Self::new_calc(
-                    CalcNode::Sum(vec![one, other].into()),
-                    AllowedNumericType::All,
-                )
+                Self::new_calc(CalcNode::Sum(vec![one, other].into()), AllowedNumericType::All)
             },
         })
     }
 }
 
 /// A wrapper of LengthPercentage, whose value must be >= 0.
 pub type NonNegativeLengthPercentage = NonNegative<LengthPercentage>;
 
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -17,16 +17,18 @@ use super::{CSSFloat, CSSInteger};
 use crate::context::QuirksMode;
 use crate::font_metrics::{get_metrics_provider_for_product, FontMetricsProvider};
 use crate::media_queries::Device;
 #[cfg(feature = "gecko")]
 use crate::properties;
 use crate::properties::{ComputedValues, LonghandId, StyleBuilder};
 use crate::rule_cache::RuleCacheConditions;
 use crate::{ArcSlice, Atom};
+#[cfg(feature = "servo")]
+use crate::Prefix;
 use euclid::default::Size2D;
 use servo_arc::Arc;
 use std::cell::RefCell;
 use std::cmp;
 use std::f32;
 
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignContent, AlignItems, JustifyContent, JustifyItems, SelfAlignment};
@@ -494,19 +496,17 @@ trivial_to_computed_value!(bool);
 trivial_to_computed_value!(f32);
 trivial_to_computed_value!(i32);
 trivial_to_computed_value!(u8);
 trivial_to_computed_value!(u16);
 trivial_to_computed_value!(u32);
 trivial_to_computed_value!(usize);
 trivial_to_computed_value!(Atom);
 #[cfg(feature = "servo")]
-trivial_to_computed_value!(html5ever::Namespace);
-#[cfg(feature = "servo")]
-trivial_to_computed_value!(html5ever::Prefix);
+trivial_to_computed_value!(Prefix);
 trivial_to_computed_value!(String);
 trivial_to_computed_value!(Box<str>);
 trivial_to_computed_value!(crate::OwnedStr);
 trivial_to_computed_value!(style_traits::values::specified::AllowedNumericType);
 
 #[allow(missing_docs)]
 #[derive(
     Animate,
--- a/servo/components/style/values/computed/position.rs
+++ b/servo/components/style/values/computed/position.rs
@@ -56,15 +56,15 @@ impl ToCss for Position {
         self.vertical.to_css(dest)
     }
 }
 
 impl GenericPositionComponent for LengthPercentage {
     fn is_center(&self) -> bool {
         match self.to_percentage() {
             Some(Percentage(per)) => per == 0.5,
-            _ => false,
+            _ => false
         }
     }
 }
 
 /// A computed value for the `z-index` property.
 pub type ZIndex = GenericZIndex<Integer>;
--- a/servo/components/style/values/generics/basic_shape.rs
+++ b/servo/components/style/values/generics/basic_shape.rs
@@ -109,20 +109,17 @@ impl Default for ShapeBox {
 #[repr(u8)]
 pub enum GenericClipPath<BasicShape, U> {
     #[animation(error)]
     None,
     #[animation(error)]
     Url(U),
     #[css(function)]
     Path(Path),
-    Shape(
-        Box<BasicShape>,
-        #[css(skip_if = "is_default")] ShapeGeometryBox,
-    ),
+    Shape(Box<BasicShape>, #[css(skip_if = "is_default")] ShapeGeometryBox),
     #[animation(error)]
     Box(ShapeGeometryBox),
 }
 
 pub use self::GenericClipPath as ClipPath;
 
 /// A value for the `shape-outside` property.
 #[allow(missing_docs)]
--- a/servo/components/style/values/generics/calc.rs
+++ b/servo/components/style/values/generics/calc.rs
@@ -2,35 +2,24 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 //! [Calc expressions][calc].
 //!
 //! [calc]: https://drafts.csswg.org/css-values/#calc-notation
 
 use crate::Zero;
-use smallvec::SmallVec;
+use style_traits::{CssWriter, ToCss};
 use std::fmt::{self, Write};
+use std::{cmp, mem};
 use std::ops::Add;
-use std::{cmp, mem};
-use style_traits::{CssWriter, ToCss};
+use smallvec::SmallVec;
 
 /// Whether we're a `min` or `max` function.
-#[derive(
-    Clone,
-    Copy,
-    Debug,
-    Deserialize,
-    MallocSizeOf,
-    PartialEq,
-    Serialize,
-    ToAnimatedZero,
-    ToResolvedValue,
-    ToShmem,
-)]
+#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, ToAnimatedZero, ToResolvedValue, ToShmem)]
 #[repr(u8)]
 pub enum MinMaxOp {
     /// `min()`
     Min,
     /// `max()`
     Max,
 }
 
@@ -56,27 +45,17 @@ pub enum SortKey {
     Other,
 }
 
 /// A generic node in a calc expression.
 ///
 /// FIXME: This would be much more elegant if we used `Self` in the types below,
 /// but we can't because of https://github.com/serde-rs/serde/issues/1565.
 #[repr(u8)]
-#[derive(
-    Clone,
-    Debug,
-    Deserialize,
-    MallocSizeOf,
-    PartialEq,
-    Serialize,
-    ToAnimatedZero,
-    ToResolvedValue,
-    ToShmem,
-)]
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, ToAnimatedZero, ToResolvedValue, ToShmem)]
 pub enum GenericCalcNode<L> {
     /// A leaf node.
     Leaf(L),
     /// A sum node, representing `a + b + c` where a, b, and c are the
     /// arguments.
     Sum(crate::OwnedSlice<GenericCalcNode<L>>),
     /// A `min` or `max` function.
     MinMax(crate::OwnedSlice<GenericCalcNode<L>>, MinMaxOp),
@@ -89,17 +68,17 @@ pub enum GenericCalcNode<L> {
         /// The maximum value.
         max: Box<GenericCalcNode<L>>,
     },
 }
 
 pub use self::GenericCalcNode as CalcNode;
 
 /// A trait that represents all the stuff a valid leaf of a calc expression.
-pub trait CalcNodeLeaf: Clone + Sized + PartialOrd + PartialEq + ToCss {
+pub trait CalcNodeLeaf : Clone + Sized + PartialOrd + PartialEq + ToCss {
     /// Whether this value is known-negative.
     fn is_negative(&self) -> bool;
 
     /// Tries to merge one sum to another, that is, perform `x` + `y`.
     fn try_sum_in_place(&mut self, other: &Self) -> Result<(), ()>;
 
     /// Multiplies the leaf by a given scalar number.
     fn mul_by(&mut self, scalar: f32);
@@ -127,19 +106,17 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
             Self::Leaf(ref l) => l.sort_key(),
             _ => SortKey::Other,
         }
     }
 
     /// Tries to merge one sum to another, that is, perform `x` + `y`.
     fn try_sum_in_place(&mut self, other: &Self) -> Result<(), ()> {
         match (self, other) {
-            (&mut CalcNode::Leaf(ref mut one), &CalcNode::Leaf(ref other)) => {
-                one.try_sum_in_place(other)
-            },
+            (&mut CalcNode::Leaf(ref mut one), &CalcNode::Leaf(ref other)) => one.try_sum_in_place(other),
             _ => Err(()),
         }
     }
 
     /// Convert this `CalcNode` into a `CalcNode` with a different leaf kind.
     pub fn map_leaves<O, F>(&self, mut map: F) -> CalcNode<O>
     where
         O: CalcNodeLeaf,
@@ -157,45 +134,35 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
             children: &[CalcNode<L>],
             map: &mut F,
         ) -> crate::OwnedSlice<CalcNode<O>>
         where
             L: CalcNodeLeaf,
             O: CalcNodeLeaf,
             F: FnMut(&L) -> O,
         {
-            children
-                .iter()
-                .map(|c| c.map_leaves_internal(map))
-                .collect()
+            children.iter().map(|c| c.map_leaves_internal(map)).collect()
         }
 
         match *self {
             Self::Leaf(ref l) => CalcNode::Leaf(map(l)),
             Self::Sum(ref c) => CalcNode::Sum(map_children(c, map)),
             Self::MinMax(ref c, op) => CalcNode::MinMax(map_children(c, map), op),
-            Self::Clamp {
-                ref min,
-                ref center,
-                ref max,
-            } => {
+            Self::Clamp { ref min, ref center, ref max } => {
                 let min = Box::new(min.map_leaves_internal(map));
                 let center = Box::new(center.map_leaves_internal(map));
                 let max = Box::new(max.map_leaves_internal(map));
                 CalcNode::Clamp { min, center, max }
-            },
+            }
         }
     }
 
     /// Resolves the expression returning a value of `O`, given a function to
     /// turn a leaf into the relevant value.
-    pub fn resolve<O>(
-        &self,
-        mut leaf_to_output_fn: impl FnMut(&L) -> Result<O, ()>,
-    ) -> Result<O, ()>
+    pub fn resolve<O>(&self, mut leaf_to_output_fn: impl FnMut(&L) -> Result<O, ()>) -> Result<O, ()>
     where
         O: PartialOrd + PartialEq + Add<Output = O> + Zero,
     {
         self.resolve_internal(&mut leaf_to_output_fn)
     }
 
     fn resolve_internal<O, F>(&self, leaf_to_output_fn: &mut F) -> Result<O, ()>
     where
@@ -220,21 +187,17 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
                         MinMaxOp::Max => candidate > result,
                     };
                     if candidate_wins {
                         result = candidate;
                     }
                 }
                 result
             },
-            Self::Clamp {
-                ref min,
-                ref center,
-                ref max,
-            } => {
+            Self::Clamp { ref min, ref center, ref max } => {
                 let min = min.resolve_internal(leaf_to_output_fn)?;
                 let center = center.resolve_internal(leaf_to_output_fn)?;
                 let max = max.resolve_internal(leaf_to_output_fn)?;
 
                 let mut result = center;
                 if result > max {
                     result = max;
                 }
@@ -464,17 +427,17 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
                     replace_self_with!(&mut children[0]);
                 } else {
                     // Else put our simplified children back.
                     mem::replace(children_slot, children.into_boxed_slice().into());
                 }
             },
             Self::Leaf(ref mut l) => {
                 l.simplify();
-            },
+            }
         }
     }
 
     /// Simplifies and sorts the kids in the whole calculation subtree.
     pub fn simplify_and_sort(&mut self) {
         self.visit_depth_first(|node| node.simplify_and_sort_direct_children())
     }
 
--- a/servo/components/style/values/generics/counters.rs
+++ b/servo/components/style/values/generics/counters.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 //! Generic types for counters-related CSS values.
 
 #[cfg(feature = "servo")]
 use crate::computed_values::list_style_type::T as ListStyleType;
 #[cfg(feature = "gecko")]
 use crate::values::generics::CounterStyle;
-#[cfg(any(feature = "gecko", feature = "servo-layout-2020"))]
+#[cfg(feature = "gecko")]
 use crate::values::specified::Attr;
 use crate::values::CustomIdent;
 use std::ops::Deref;
 
 /// A name / value pair for counters.
 #[derive(
     Clone,
     Debug,
@@ -207,15 +207,15 @@ pub enum GenericContentItem<ImageUrl> {
     /// `no-open-quote`.
     NoOpenQuote,
     /// `no-close-quote`.
     NoCloseQuote,
     /// `-moz-alt-content`.
     #[cfg(feature = "gecko")]
     MozAltContent,
     /// `attr([namespace? `|`]? ident)`
-    #[cfg(any(feature = "gecko", feature = "servo-layout-2020"))]
+    #[cfg(feature = "gecko")]
     Attr(Attr),
     /// `url(url)`
     Url(ImageUrl),
 }
 
 pub use self::GenericContentItem as ContentItem;
--- a/servo/components/style/values/generics/image.rs
+++ b/servo/components/style/values/generics/image.rs
@@ -336,68 +336,49 @@ where
     AoP: ToCss,
     C: ToCss,
 {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: Write,
     {
         let (compat_mode, repeating) = match *self {
-            Gradient::Linear {
-                compat_mode,
-                repeating,
-                ..
-            } => (compat_mode, repeating),
-            Gradient::Radial {
-                compat_mode,
-                repeating,
-                ..
-            } => (compat_mode, repeating),
+            Gradient::Linear { compat_mode, repeating, .. } => (compat_mode, repeating),
+            Gradient::Radial { compat_mode, repeating, .. } => (compat_mode, repeating),
             Gradient::Conic { repeating, .. } => (GradientCompatMode::Modern, repeating),
         };
 
         match compat_mode {
             GradientCompatMode::WebKit => dest.write_str("-webkit-")?,
             GradientCompatMode::Moz => dest.write_str("-moz-")?,
             _ => {},
         }
 
         if repeating {
             dest.write_str("repeating-")?;
         }
 
         match *self {
-            Gradient::Linear {
-                ref direction,
-                ref items,
-                compat_mode,
-                ..
-            } => {
+            Gradient::Linear { ref direction, ref items, compat_mode, .. } => {
                 dest.write_str("linear-gradient(")?;
                 let mut skip_comma = if !direction.points_downwards(compat_mode) {
                     direction.to_css(dest, compat_mode)?;
                     false
                 } else {
                     true
                 };
                 for item in &**items {
                     if !skip_comma {
                         dest.write_str(", ")?;
                     }
                     skip_comma = false;
                     item.to_css(dest)?;
                 }
             },
-            Gradient::Radial {
-                ref shape,
-                ref position,
-                ref items,
-                compat_mode,
-                ..
-            } => {
+            Gradient::Radial { ref shape, ref position, ref items, compat_mode, .. } => {
                 dest.write_str("radial-gradient(")?;
                 let omit_shape = match *shape {
                     EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::Cover)) |
                     EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::FarthestCorner)) => true,
                     _ => false,
                 };
                 let omit_position = position.is_center();
                 if compat_mode == GradientCompatMode::Modern {
@@ -426,22 +407,17 @@ where
                 for item in &**items {
                     if !skip_comma {
                         dest.write_str(", ")?;
                     }
                     skip_comma = false;
                     item.to_css(dest)?;
                 }
             },
-            Gradient::Conic {
-                ref angle,
-                ref position,
-                ref items,
-                ..
-            } => {
+            Gradient::Conic { ref angle, ref position, ref items, .. } => {
                 dest.write_str("conic-gradient(")?;
                 let omit_angle = angle.is_zero();
                 let omit_position = position.is_center();
                 if !omit_angle {
                     dest.write_str("from ")?;
                     angle.to_css(dest)?;
                     if !omit_position {
                         dest.write_str(" ")?;
--- a/servo/components/style/values/generics/transform.rs
+++ b/servo/components/style/values/generics/transform.rs
@@ -6,16 +6,17 @@
 
 use crate::values::computed::length::Length as ComputedLength;
 use crate::values::computed::length::LengthPercentage as ComputedLengthPercentage;
 use crate::values::specified::angle::Angle as SpecifiedAngle;
 use crate::values::specified::length::Length as SpecifiedLength;
 use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
 use crate::values::{computed, CSSFloat};
 use crate::Zero;
+use app_units::Au;
 use euclid;
 use euclid::default::{Rect, Transform3D};
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 
 /// A generic 2D transformation matrix.
 #[allow(missing_docs)]
 #[derive(
@@ -323,79 +324,76 @@ where
             _ => false,
         }
     }
 }
 
 /// Convert a length type into the absolute lengths.
 pub trait ToAbsoluteLength {
     /// Returns the absolute length as pixel value.
-    fn to_pixel_length(&self, containing_len: Option<ComputedLength>) -> Result<CSSFloat, ()>;
+    fn to_pixel_length(&self, containing_len: Option<Au>) -> Result<CSSFloat, ()>;
 }
 
 impl ToAbsoluteLength for SpecifiedLength {
     // This returns Err(()) if there is any relative length or percentage. We use this when
     // parsing a transform list of DOMMatrix because we want to return a DOM Exception
     // if there is relative length.
     #[inline]
-    fn to_pixel_length(&self, _containing_len: Option<ComputedLength>) -> Result<CSSFloat, ()> {
+    fn to_pixel_length(&self, _containing_len: Option<Au>) -> Result<CSSFloat, ()> {
         match *self {
             SpecifiedLength::NoCalc(len) => len.to_computed_pixel_length_without_context(),
             SpecifiedLength::Calc(ref calc) => calc.to_computed_pixel_length_without_context(),
         }
     }
 }
 
 impl ToAbsoluteLength for SpecifiedLengthPercentage {
     // This returns Err(()) if there is any relative length or percentage. We use this when
     // parsing a transform list of DOMMatrix because we want to return a DOM Exception
     // if there is relative length.
     #[inline]
-    fn to_pixel_length(&self, _containing_len: Option<ComputedLength>) -> Result<CSSFloat, ()> {
+    fn to_pixel_length(&self, _containing_len: Option<Au>) -> Result<CSSFloat, ()> {
         use self::SpecifiedLengthPercentage::*;
         match *self {
             Length(len) => len.to_computed_pixel_length_without_context(),
             Calc(ref calc) => calc.to_computed_pixel_length_without_context(),
             Percentage(..) => Err(()),
         }
     }
 }
 
 impl ToAbsoluteLength for ComputedLength {
     #[inline]
-    fn to_pixel_length(&self, _containing_len: Option<ComputedLength>) -> Result<CSSFloat, ()> {
+    fn to_pixel_length(&self, _containing_len: Option<Au>) -> Result<CSSFloat, ()> {
         Ok(self.px())
     }
 }
 
 impl ToAbsoluteLength for ComputedLengthPercentage {
     #[inline]
-    fn to_pixel_length(&self, containing_len: Option<ComputedLength>) -> Result<CSSFloat, ()> {
+    fn to_pixel_length(&self, containing_len: Option<Au>) -> Result<CSSFloat, ()> {
         match containing_len {
-            Some(relative_len) => Ok(self.resolve(relative_len).px()),
+            Some(relative_len) => Ok(self.to_pixel_length(relative_len).px()),
             // If we don't have reference box, we cannot resolve the used value,
             // so only retrieve the length part. This will be used for computing
             // distance without any layout info.
             //
             // FIXME(emilio): This looks wrong.
             None => Ok(self.resolve(Zero::zero()).px()),
         }
     }
 }
 
 /// Support the conversion to a 3d matrix.
 pub trait ToMatrix {
     /// Check if it is a 3d transform function.
     fn is_3d(&self) -> bool;
 
     /// Return the equivalent 3d matrix.
-    fn to_3d_matrix(
-        &self,
-        reference_box: Option<&Rect<ComputedLength>>,
-    ) -> Result<Transform3D<f64>, ()>;
+    fn to_3d_matrix(&self, reference_box: Option<&Rect<Au>>) -> Result<Transform3D<f64>, ()>;
 }
 
 /// A little helper to deal with both specified and computed angles.
 pub trait ToRadians {
     /// Return the radians value as a 64-bit floating point value.
     fn radians64(&self) -> f64;
 }
 
@@ -431,20 +429,17 @@ where
         }
     }
 
     /// If |reference_box| is None, we will drop the percent part from translate because
     /// we cannot resolve it without the layout info, for computed TransformOperation.
     /// However, for specified TransformOperation, we will return Err(()) if there is any relative
     /// lengths because the only caller, DOMMatrix, doesn't accept relative lengths.
     #[inline]
-    fn to_3d_matrix(
-        &self,
-        reference_box: Option<&Rect<ComputedLength>>,
-    ) -> Result<Transform3D<f64>, ()> {
+    fn to_3d_matrix(&self, reference_box: Option<&Rect<Au>>) -> Result<Transform3D<f64>, ()> {
         use self::TransformOperation::*;
         use std::f64;
 
         const TWO_PI: f64 = 2.0f64 * f64::consts::PI;
         let reference_width = reference_box.map(|v| v.size.width);
         let reference_height = reference_box.map(|v| v.size.height);
         let matrix = match *self {
             Rotate3D(ax, ay, az, theta) => {
@@ -537,17 +532,17 @@ impl<T> Transform<T> {
 
 impl<T: ToMatrix> Transform<T> {
     /// Return the equivalent 3d matrix of this transform list.
     /// We return a pair: the first one is the transform matrix, and the second one
     /// indicates if there is any 3d transform function in this transform list.
     #[cfg_attr(rustfmt, rustfmt_skip)]
     pub fn to_transform_3d_matrix(
         &self,
-        reference_box: Option<&Rect<ComputedLength>>
+        reference_box: Option<&Rect<Au>>
     ) -> Result<(Transform3D<CSSFloat>, bool), ()> {
         let cast_3d_transform = |m: Transform3D<f64>| -> Transform3D<CSSFloat> {
             use std::{f32, f64};
             let cast = |v: f64| { v.min(f32::MAX as f64).max(f32::MIN as f64) as f32 };
             Transform3D::row_major(
                 cast(m.m11), cast(m.m12), cast(m.m13), cast(m.m14),
                 cast(m.m21), cast(m.m22), cast(m.m23), cast(m.m24),
                 cast(m.m31), cast(m.m32), cast(m.m33), cast(m.m34),
@@ -557,17 +552,17 @@ impl<T: ToMatrix> Transform<T> {
 
         let (m, is_3d) = self.to_transform_3d_matrix_f64(reference_box)?;
         Ok((cast_3d_transform(m), is_3d))
     }
 
     /// Same as Transform::to_transform_3d_matrix but a f64 version.
     pub fn to_transform_3d_matrix_f64(
         &self,
-        reference_box: Option<&Rect<ComputedLength>>,
+        reference_box: Option<&Rect<Au>>,
     ) -> Result<(Transform3D<f64>, bool), ()> {
         // We intentionally use Transform3D<f64> during computation to avoid error propagation
         // because using f32 to compute triangle functions (e.g. in create_rotation()) is not
         // accurate enough. In Gecko, we also use "double" to compute the triangle functions.
         // Therefore, let's use Transform3D<f64> during matrix computation and cast it into f32
         // in the end.
         let mut transform = Transform3D::<f64>::identity();
         let mut contain_3d = false;
--- a/servo/components/style/values/resolved/mod.rs
+++ b/servo/components/style/values/resolved/mod.rs
@@ -74,18 +74,16 @@ trivial_to_resolved_value!(Box<str>);
 trivial_to_resolved_value!(crate::OwnedStr);
 trivial_to_resolved_value!(cssparser::RGBA);
 trivial_to_resolved_value!(crate::Atom);
 trivial_to_resolved_value!(app_units::Au);
 trivial_to_resolved_value!(computed::url::ComputedUrl);
 #[cfg(feature = "gecko")]
 trivial_to_resolved_value!(computed::url::ComputedImageUrl);
 #[cfg(feature = "servo")]
-trivial_to_resolved_value!(html5ever::Namespace);
-#[cfg(feature = "servo")]
 trivial_to_resolved_value!(html5ever::Prefix);
 trivial_to_resolved_value!(computed::LengthPercentage);
 trivial_to_resolved_value!(style_traits::values::specified::AllowedNumericType);
 
 impl<A, B> ToResolvedValue for (A, B)
 where
     A: ToResolvedValue,
     B: ToResolvedValue,
--- a/servo/components/style/values/specified/basic_shape.rs
+++ b/servo/components/style/values/specified/basic_shape.rs
@@ -121,17 +121,22 @@ impl Parse for ClipPath {
                 return Ok(ClipPath::Path(p));
             }
         }
 
         if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
             return Ok(ClipPath::Url(url));
         }
 
-        parse_shape_or_box(context, input, ClipPath::Shape, ClipPath::Box)
+        parse_shape_or_box(
+            context,
+            input,
+            ClipPath::Shape,
+            ClipPath::Box,
+        )
     }
 }
 
 impl Parse for ShapeOutside {
     #[inline]
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
@@ -142,17 +147,22 @@ impl Parse for ShapeOutside {
             return Ok(ShapeOutside::None);
         }
 
         if let Ok(image) = input.try(|i| Image::parse_with_cors_anonymous(context, i)) {
             debug_assert_ne!(image, Image::None);
             return Ok(ShapeOutside::Image(image));
         }
 
-        parse_shape_or_box(context, input, ShapeOutside::Shape, ShapeOutside::Box)
+        parse_shape_or_box(
+            context,
+            input,
+            ShapeOutside::Shape,
+            ShapeOutside::Box,
+        )
     }
 }
 
 impl Parse for BasicShape {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
--- a/servo/components/style/values/specified/calc.rs
+++ b/servo/components/style/values/specified/calc.rs
@@ -10,18 +10,18 @@ use crate::parser::ParserContext;
 use crate::values::generics::calc as generic;
 use crate::values::generics::calc::{MinMaxOp, SortKey};
 use crate::values::specified::length::ViewportPercentageLength;
 use crate::values::specified::length::{AbsoluteLength, FontRelativeLength, NoCalcLength};
 use crate::values::specified::{self, Angle, Time};
 use crate::values::{CSSFloat, CSSInteger};
 use cssparser::{AngleOrNumber, CowRcStr, NumberOrPercentage, Parser, Token};
 use smallvec::SmallVec;
+use std::fmt::{self, Write};
 use std::cmp;
-use std::fmt::{self, Write};
 use style_traits::values::specified::AllowedNumericType;
 use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
 
 /// The name of the mathematical function that we're parsing.
 #[derive(Clone, Copy, Debug)]
 pub enum MathFunction {
     /// `calc()`: https://drafts.csswg.org/css-values-4/#funcdef-calc
     Calc,
@@ -111,29 +111,28 @@ impl PartialOrd for Leaf {
             (&Percentage(ref one), &Percentage(ref other)) => one.partial_cmp(other),
             (&Angle(ref one), &Angle(ref other)) => one.degrees().partial_cmp(&other.degrees()),
             (&Time(ref one), &Time(ref other)) => one.seconds().partial_cmp(&other.seconds()),
             (&Number(ref one), &Number(ref other)) => one.partial_cmp(other),
             _ => {
                 match *self {
                     Length(..) | Percentage(..) | Angle(..) | Time(..) | Number(..) => {},
                 }
-                unsafe {
-                    debug_unreachable!("Forgot a branch?");
-                }
-            },
+                unsafe { debug_unreachable!("Forgot a branch?"); }
+            }
         }
     }
 }
 
 impl generic::CalcNodeLeaf for Leaf {
     fn is_negative(&self) -> bool {
         match *self {
             Self::Length(ref l) => l.is_negative(),
-            Self::Percentage(n) | Self::Number(n) => n < 0.,
+            Self::Percentage(n) |
+            Self::Number(n) => n < 0.,
             Self::Angle(ref a) => a.degrees() < 0.,
             Self::Time(ref t) => t.seconds() < 0.,
         }
     }
 
     fn mul_by(&mut self, scalar: f32) {
         match *self {
             Self::Length(ref mut l) => {
@@ -211,20 +210,18 @@ impl generic::CalcNodeLeaf for Leaf {
             },
             (&mut Length(ref mut one), &Length(ref other)) => {
                 *one = one.try_sum(other)?;
             },
             _ => {
                 match *other {
                     Number(..) | Percentage(..) | Angle(..) | Time(..) | Length(..) => {},
                 }
-                unsafe {
-                    debug_unreachable!();
-                }
-            },
+                unsafe { debug_unreachable!(); }
+            }
         }
 
         Ok(())
     }
 }
 
 /// A calc node representation for specified values.
 pub type CalcNode = generic::GenericCalcNode<Leaf>;
@@ -250,44 +247,42 @@ impl CalcNode {
                 },
                 CalcUnit::Length,
             ) |
             (
                 &Token::Dimension {
                     value, ref unit, ..
                 },
                 CalcUnit::LengthPercentage,
-            ) => match NoCalcLength::parse_dimension(context, value, unit) {
-                Ok(l) => Ok(CalcNode::Leaf(Leaf::Length(l))),
-                Err(()) => Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
+            ) => {
+                match NoCalcLength::parse_dimension(context, value, unit) {
+                    Ok(l) => Ok(CalcNode::Leaf(Leaf::Length(l))),
+                    Err(()) => Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
+                }
             },
             (
                 &Token::Dimension {
                     value, ref unit, ..
                 },
                 CalcUnit::Angle,
             ) => {
                 match Angle::parse_dimension(value, unit, /* from_calc = */ true) {
                     Ok(a) => Ok(CalcNode::Leaf(Leaf::Angle(a))),
-                    Err(()) => {
-                        Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
-                    },
+                    Err(()) => Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
                 }
             },
             (
                 &Token::Dimension {
                     value, ref unit, ..
                 },
                 CalcUnit::Time,
             ) => {
                 match Time::parse_dimension(value, unit, /* from_calc = */ true) {
                     Ok(t) => Ok(CalcNode::Leaf(Leaf::Time(t))),
-                    Err(()) => {
-                        Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
-                    },
+                    Err(()) => Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
                 }
             },
             (&Token::Percentage { unit_value, .. }, CalcUnit::LengthPercentage) |
             (&Token::Percentage { unit_value, .. }, CalcUnit::Percentage) => {
                 Ok(CalcNode::Leaf(Leaf::Percentage(unit_value)))
             },
             (&Token::ParenthesisBlock, _) => input.parse_nested_block(|input| {
                 CalcNode::parse_argument(context, input, expected_unit)
@@ -328,19 +323,20 @@ impl CalcNode {
                     })
                 },
                 MathFunction::Min | MathFunction::Max => {
                     // TODO(emilio): The common case for parse_comma_separated
                     // is just one element, but for min / max is two, really...
                     //
                     // Consider adding an API to cssparser to specify the
                     // initial vector capacity?
-                    let arguments = input.parse_comma_separated(|input| {
-                        Self::parse_argument(context, input, expected_unit)
-                    })?;
+                    let arguments = input
+                        .parse_comma_separated(|input| {
+                            Self::parse_argument(context, input, expected_unit)
+                        })?;
 
                     let op = match function {
                         MathFunction::Min => MinMaxOp::Min,
                         MathFunction::Max => MinMaxOp::Max,
                         _ => unreachable!(),
                     };
 
                     Ok(Self::MinMax(arguments.into(), op))
@@ -473,45 +469,53 @@ impl CalcNode {
         Ok(CalcLengthPercentage {
             clamping_mode,
             node: self,
         })
     }
 
     /// Tries to simplify this expression into a `<time>` value.
     fn to_time(&self) -> Result<Time, ()> {
-        let seconds = self.resolve(|leaf| match *leaf {
-            Leaf::Time(ref t) => Ok(t.seconds()),
-            _ => Err(()),
+        let seconds = self.resolve(|leaf| {
+            match *leaf {
+                Leaf::Time(ref t) => Ok(t.seconds()),
+                _ => Err(()),
+            }
         })?;
         Ok(Time::from_calc(seconds))
     }
 
     /// Tries to simplify this expression into an `Angle` value.
     fn to_angle(&self) -> Result<Angle, ()> {
-        let degrees = self.resolve(|leaf| match *leaf {
-            Leaf::Angle(ref angle) => Ok(angle.degrees()),
-            _ => Err(()),
+        let degrees = self.resolve(|leaf| {
+            match *leaf {
+                Leaf::Angle(ref angle) => Ok(angle.degrees()),
+                _ => Err(()),
+            }
         })?;
         Ok(Angle::from_calc(degrees))
     }
 
     /// Tries to simplify this expression into a `<number>` value.
     fn to_number(&self) -> Result<CSSFloat, ()> {
-        self.resolve(|leaf| match *leaf {
-            Leaf::Number(n) => Ok(n),
-            _ => Err(()),
+        self.resolve(|leaf| {
+            match *leaf {
+                Leaf::Number(n) => Ok(n),
+                _ => Err(()),
+            }
         })
     }
 
     /// Tries to simplify this expression into a `<percentage>` value.
     fn to_percentage(&self) -> Result<CSSFloat, ()> {
-        self.resolve(|leaf| match *leaf {
-            Leaf::Percentage(p) => Ok(p),
-            _ => Err(()),
+        self.resolve(|leaf| {
+            match *leaf {
+                Leaf::Percentage(p) => Ok(p),
+                _ => Err(()),
+            }
         })
     }
 
     /// Given a function name, and the location from where the token came from,
     /// return a mathematical function corresponding to that name or an error.
     #[inline]
     pub fn math_function<'i>(
         name: &CowRcStr<'i>,
--- a/servo/components/style/values/specified/counters.rs
+++ b/servo/components/style/values/specified/counters.rs
@@ -7,17 +7,17 @@
 #[cfg(feature = "servo")]
 use crate::computed_values::list_style_type::T as ListStyleType;
 use crate::parser::{Parse, ParserContext};
 use crate::values::generics::counters as generics;
 use crate::values::generics::counters::CounterPair;
 #[cfg(feature = "gecko")]
 use crate::values::generics::CounterStyle;
 use crate::values::specified::url::SpecifiedImageUrl;
-#[cfg(any(feature = "gecko", feature = "servo-layout-2020"))]
+#[cfg(feature = "gecko")]
 use crate::values::specified::Attr;
 use crate::values::specified::Integer;
 use crate::values::CustomIdent;
 use cssparser::{Parser, Token};
 use selectors::parser::SelectorParseErrorKind;
 use style_traits::{ParseError, StyleParseErrorKind};
 
 /// A specified value for the `counter-increment` property.
@@ -129,17 +129,17 @@ impl Parse for Content {
             .is_ok()
         {
             return Ok(generics::Content::None);
         }
 
         let mut content = vec![];
         let mut has_alt_content = false;
         loop {
-            #[cfg(any(feature = "gecko", feature = "servo-layout-2020"))]
+            #[cfg(feature = "gecko")]
             {
                 if let Ok(url) = input.try(|i| SpecifiedImageUrl::parse(context, i)) {
                     content.push(generics::ContentItem::Url(url));
                     continue;
                 }
             }
             match input.next() {
                 Ok(&Token::QuotedString(ref value)) => {
@@ -158,17 +158,17 @@ impl Parse for Content {
                         "counters" => input.parse_nested_block(|input| {
                             let location = input.current_source_location();
                             let name = CustomIdent::from_ident(location, input.expect_ident()?, &[])?;
                             input.expect_comma()?;
                             let separator = input.expect_string()?.as_ref().to_owned().into();
                             let style = Content::parse_counter_style(context, input);
                             Ok(generics::ContentItem::Counters(name, separator, style))
                         }),
-                        #[cfg(any(feature = "gecko", feature = "servo-layout-2020"))]
+                        #[cfg(feature = "gecko")]
                         "attr" => input.parse_nested_block(|input| {
                             Ok(generics::ContentItem::Attr(Attr::parse_function(context, input)?))
                         }),
                         _ => {
                             let name = name.clone();
                             return Err(input.new_custom_error(
                                 StyleParseErrorKind::UnexpectedFunction(name),
                             ))
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -15,16 +15,17 @@ use crate::values::computed::{CSSPixelLe
 use crate::values::generics::font::VariationValue;
 use crate::values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag};
 use crate::values::generics::NonNegative;
 use crate::values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX};
 use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage};
 use crate::values::specified::{NoCalcLength, NonNegativeNumber, Number, Percentage};
 use crate::values::CustomIdent;
 use crate::Atom;
+use byteorder::{BigEndian, ByteOrder};
 use cssparser::{Parser, Token};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use std::fmt::{self, Write};
 use style_traits::values::SequenceWriter;
 use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
 use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
 
@@ -55,17 +56,17 @@ macro_rules! system_font_methods {
         /// Retreive a SystemFont from the specified value.
         pub fn get_system(&self) -> Option<SystemFont> {
             if let $ty::System(s) = *self {
                 Some(s)
             } else {
                 None
             }
         }
-    };
+    }
 }
 
 const DEFAULT_SCRIPT_MIN_SIZE_PT: u32 = 8;
 const DEFAULT_SCRIPT_SIZE_MULTIPLIER: f64 = 0.71;
 
 /// The minimum font-weight value per:
 ///
 /// https://drafts.csswg.org/css-fonts-4/#font-weight-numeric-values
@@ -2041,19 +2042,29 @@ impl FontLanguageOverride {
         FontLanguageOverride::Normal
     }
 
     /// The ToComputedValue implementation for non-system-font
     /// FontLanguageOverride, used for @font-face descriptors.
     #[inline]
     pub fn compute_non_system(&self) -> computed::FontLanguageOverride {
         match *self {
-            FontLanguageOverride::Normal => computed::FontLanguageOverride::zero(),
+            FontLanguageOverride::Normal => computed::FontLanguageOverride(0),
             FontLanguageOverride::Override(ref lang) => {
-                computed::FontLanguageOverride::from_str(lang)
+                if lang.is_empty() || lang.len() > 4 {
+                    return computed::FontLanguageOverride(0);
+                }
+                let mut bytes = [b' '; 4];
+                for (byte, lang_byte) in bytes.iter_mut().zip(lang.as_bytes()) {
+                    if !lang_byte.is_ascii() {
+                        return computed::FontLanguageOverride(0);
+                    }
+                    *byte = *lang_byte;
+                }
+                computed::FontLanguageOverride(BigEndian::read_u32(&bytes))
             },
             FontLanguageOverride::System(..) => unreachable!(),
         }
     }
 
     system_font_methods!(FontLanguageOverride, font_language_override);
 }
 
@@ -2064,20 +2075,29 @@ impl ToComputedValue for FontLanguageOve
     fn to_computed_value(&self, context: &Context) -> computed::FontLanguageOverride {
         match *self {
             FontLanguageOverride::System(_) => self.compute_system(context),
             _ => self.compute_non_system(),
         }
     }
     #[inline]
     fn from_computed_value(computed: &computed::FontLanguageOverride) -> Self {
-        if *computed == computed::FontLanguageOverride::zero() {
+        if computed.0 == 0 {
             return FontLanguageOverride::Normal;
         }
-        FontLanguageOverride::Override(computed.to_str(&mut [0; 4]).into())
+        let mut buf = [0; 4];
+        BigEndian::write_u32(&mut buf, computed.0);
+        FontLanguageOverride::Override(
+            if cfg!(debug_assertions) {
+                String::from_utf8(buf.to_vec()).unwrap()
+            } else {
+                unsafe { String::from_utf8_unchecked(buf.to_vec()) }
+            }
+            .into_boxed_str(),
+        )
     }
 }
 
 impl Parse for FontLanguageOverride {
     /// normal | <string>
     fn parse<'i, 't>(
         _: &ParserContext,
         input: &mut Parser<'i, 't>,
--- a/servo/components/style/values/specified/image.rs
+++ b/servo/components/style/values/specified/image.rs
@@ -14,18 +14,17 @@ use crate::values::generics::image::{
     self as generic, Circle, Ellipse, GradientCompatMode, ShapeExtent,
 };
 use crate::values::generics::position::Position as GenericPosition;
 use crate::values::generics::NonNegative;
 use crate::values::specified::position::{HorizontalPositionKeyword, VerticalPositionKeyword};
 use crate::values::specified::position::{Position, PositionComponent, Side};
 use crate::values::specified::url::SpecifiedImageUrl;
 use crate::values::specified::{
-    Angle, AngleOrPercentage, Color, Length, LengthPercentage, NonNegativeLength,
-    NonNegativeLengthPercentage,
+    Angle, AngleOrPercentage, Color, Length, LengthPercentage, NonNegativeLength, NonNegativeLengthPercentage,
 };
 use crate::values::specified::{Number, NumberOrPercentage, Percentage};
 use crate::Atom;
 use cssparser::{Delimiter, Parser, Token};
 use selectors::parser::SelectorParseErrorKind;
 #[cfg(feature = "servo")]
 use servo_url::ServoUrl;
 use std::cmp::Ordering;
@@ -47,26 +46,16 @@ pub type Gradient = generic::Gradient<
     Position,
     Angle,
     AngleOrPercentage,
     Color,
 >;
 
 type LengthPercentageItemList = crate::OwnedSlice<generic::GradientItem<Color, LengthPercentage>>;
 
-#[cfg(feature = "gecko")]
-fn conic_gradients_enabled() -> bool {
-    static_prefs::pref!("layout.css.conic-gradient.enabled")
-}
-
-#[cfg(feature = "servo")]
-fn conic_gradients_enabled() -> bool {
-    false
-}
-
 impl SpecifiedValueInfo for Gradient {
     const SUPPORTED_TYPES: u8 = CssType::GRADIENT;
 
     fn collect_completion_keywords(f: KeywordsCollectFn) {
         // This list here should keep sync with that in Gradient::parse.
         f(&[
             "linear-gradient",
             "-webkit-linear-gradient",
@@ -78,18 +67,21 @@ impl SpecifiedValueInfo for Gradient {
             "-webkit-radial-gradient",
             "-moz-radial-gradient",
             "repeating-radial-gradient",
             "-webkit-repeating-radial-gradient",
             "-moz-repeating-radial-gradient",
             "-webkit-gradient",
         ]);
 
-        if conic_gradients_enabled() {
-            f(&["conic-gradient", "repeating-conic-gradient"]);
+        if static_prefs::pref!("layout.css.conic-gradient.enabled") {
+            f(&[
+                "conic-gradient",
+                "repeating-conic-gradient",
+            ]);
         }
     }
 }
 
 /// A specified gradient line direction.
 ///
 /// FIXME(emilio): This should be generic over Angle.
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
@@ -245,20 +237,20 @@ impl Parse for Gradient {
             },
             "-webkit-repeating-radial-gradient" => {
                 (Shape::Radial, true, GradientCompatMode::WebKit)
             },
             #[cfg(feature = "gecko")]
             "-moz-repeating-radial-gradient" => {
                 (Shape::Radial, true, GradientCompatMode::Moz)
             },
-            "conic-gradient" if conic_gradients_enabled() => {
+            "conic-gradient" if static_prefs::pref!("layout.css.conic-gradient.enabled") => {
                 (Shape::Conic, false, GradientCompatMode::Modern)
             },
-            "repeating-conic-gradient" if conic_gradients_enabled() => {
+            "repeating-conic-gradient" if static_prefs::pref!("layout.css.conic-gradient.enabled") => {
                 (Shape::Conic, true, GradientCompatMode::Modern)
             },
             "-webkit-gradient" => {
                 return input.parse_nested_block(|i| {
                     Self::parse_webkit_gradient_argument(context, i)
                 });
             },
             _ => {
@@ -530,18 +522,17 @@ impl Gradient {
         Ok(items.into())
     }
 
     /// Not used for -webkit-gradient syntax and conic-gradient
     fn parse_stops<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<LengthPercentageItemList, ParseError<'i>> {
-        let items =
-            generic::GradientItem::parse_comma_separated(context, input, LengthPercentage::parse)?;
+        let items = generic::GradientItem::parse_comma_separated(context, input, LengthPercentage::parse)?;
         if items.len() < 2 {
             return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
         }
         Ok(items)
     }
 
     /// Parses a linear gradient.
     /// GradientCompatMode can change during `-moz-` prefixed gradient parsing if it come across a `to` keyword.
@@ -637,21 +628,17 @@ impl Gradient {
             Position::parse(context, i)
         });
         if angle.is_ok() || position.is_ok() {
             input.expect_comma()?;
         }
 
         let angle = angle.unwrap_or(Angle::zero());
         let position = position.unwrap_or(Position::center());
-        let items = generic::GradientItem::parse_comma_separated(
-            context,
-            input,
-            AngleOrPercentage::parse_with_unitless,
-        )?;
+        let items = generic::GradientItem::parse_comma_separated(context, input, AngleOrPercentage::parse_with_unitless)?;
 
         if items.len() < 2 {
             return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
         }
 
         Ok(Gradient::Conic {
             angle,
             position,
@@ -861,18 +848,17 @@ impl ShapeExtent {
         }
     }
 }
 
 impl<T> generic::GradientItem<Color, T> {
     fn parse_comma_separated<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
-        parse_position: impl for<'i1, 't1> Fn(&ParserContext, &mut Parser<'i1, 't1>) -> Result<T, ParseError<'i1>>
-            + Copy,
+        parse_position: impl for<'i1, 't1> Fn(&ParserContext, &mut Parser<'i1, 't1>) -> Result<T, ParseError<'i1>> + Copy,
     ) -> Result<crate::OwnedSlice<Self>, ParseError<'i>> {
         let mut items = Vec::new();
         let mut seen_stop = false;
 
         loop {
             input.parse_until_before(Delimiter::Comma, |input| {
                 if seen_stop {
                     if let Ok(hint) = input.try(|i| parse_position(context, i)) {
@@ -915,20 +901,17 @@ impl<T> generic::GradientItem<Color, T> 
         Ok(items.into())
     }
 }
 
 impl<T> generic::ColorStop<Color, T> {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
-        parse_position: impl for<'i1, 't1> Fn(
-            &ParserContext,
-            &mut Parser<'i1, 't1>,
-        ) -> Result<T, ParseError<'i1>>,
+        parse_position: impl for<'i1, 't1> Fn(&ParserContext, &mut Parser<'i1, 't1>) -> Result<T, ParseError<'i1>>,
     ) -> Result<Self, ParseError<'i>> {
         Ok(generic::ColorStop {
             color: Color::parse(context, input)?,
             position: input.try(|i| parse_position(context, i)).ok(),
         })
     }
 }
 
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -23,18 +23,18 @@ use crate::Zero;
 use app_units::Au;
 use cssparser::{Parser, Token};
 use euclid::default::Size2D;
 use std::cmp;
 use std::ops::{Add, Mul};
 use style_traits::values::specified::AllowedNumericType;
 use style_traits::{ParseError, SpecifiedValueInfo, StyleParseErrorKind};
 
+pub use super::image::{EndingShape as GradientEndingShape, Gradient};
 pub use super::image::Image;
-pub use super::image::{EndingShape as GradientEndingShape, Gradient};
 pub use crate::values::specified::calc::CalcLengthPercentage;
 
 /// Number of app units per pixel
 pub const AU_PER_PX: CSSFloat = 60.;
 /// Number of app units per inch
 pub const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
 /// Number of app units per centimeter
 pub const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -75,22 +75,22 @@ pub use self::percentage::Percentage;
 pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, PositionOrAuto};
 pub use self::position::{PositionComponent, ZIndex};
 pub use self::rect::NonNegativeLengthOrNumberRect;
 pub use self::resolution::Resolution;
 pub use self::svg::MozContextProperties;
 pub use self::svg::{SVGLength, SVGOpacity, SVGPaint};
 pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
 pub use self::svg_path::SVGPathData;
-pub use self::text::TextAlignLast;
 pub use self::text::TextUnderlinePosition;
 pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign};
 pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
 pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
 pub use self::text::{TextDecorationLength, TextDecorationSkipInk, TextTransform};
+pub use self::text::TextAlignLast;
 pub use self::time::Time;
 pub use self::transform::{Rotate, Scale, Transform};
 pub use self::transform::{TransformOrigin, TransformStyle, Translate};
 #[cfg(feature = "gecko")]
 pub use self::ui::CursorImage;
 pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect};
 pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
 
--- a/servo/components/style/values/specified/svg.rs
+++ b/servo/components/style/values/specified/svg.rs
@@ -141,23 +141,18 @@ pub struct SVGPaintOrder(pub u8);
 impl SVGPaintOrder {
     /// Get default `paint-order` with `0`
     pub fn normal() -> Self {
         SVGPaintOrder(0)
     }
 
     /// Get variant of `paint-order`
     pub fn order_at(&self, pos: u8) -> PaintOrder {
-        match (self.0 >> pos * PAINT_ORDER_SHIFT) & PAINT_ORDER_MASK {
-            0 => PaintOrder::Normal,
-            1 => PaintOrder::Fill,
-            2 => PaintOrder::Stroke,
-            3 => PaintOrder::Markers,
-            _ => unreachable!("this cannot happen"),
-        }
+        // Safe because PaintOrder covers all possible patterns.
+        unsafe { std::mem::transmute((self.0 >> pos * PAINT_ORDER_SHIFT) & PAINT_ORDER_MASK) }
     }
 }
 
 impl Parse for SVGPaintOrder {
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<SVGPaintOrder, ParseError<'i>> {
--- a/servo/components/style/values/specified/svg_path.rs
+++ b/servo/components/style/values/specified/svg_path.rs
@@ -30,17 +30,18 @@ use style_traits::{CssWriter, ParseError
     ToComputedValue,
     ToResolvedValue,
     ToShmem,
 )]
 #[repr(C)]
 pub struct SVGPathData(
     // TODO(emilio): Should probably measure this somehow only from the
     // specified values.
-    #[ignore_malloc_size_of = "Arc"] pub crate::ArcSlice<PathCommand>,
+    #[ignore_malloc_size_of = "Arc"]
+    pub crate::ArcSlice<PathCommand>,
 );
 
 impl SVGPathData {
     /// Get the array of PathCommand.
     #[inline]
     pub fn commands(&self) -> &[PathCommand] {
         &self.0
     }
@@ -535,27 +536,17 @@ impl CoordPair {
     #[inline]
     pub fn new(x: CSSFloat, y: CSSFloat) -> Self {
         CoordPair(x, y)
     }
 }
 
 /// The EllipticalArc flag type.
 #[derive(
-    Clone,
-    Copy,
-    Debug,
-    Deserialize,
-    MallocSizeOf,
-    PartialEq,
-    Serialize,
-    SpecifiedValueInfo,
-    ToComputedValue,
-    ToResolvedValue,
-    ToShmem,
+    Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem,
 )]
 #[repr(C)]
 pub struct ArcFlag(bool);
 
 impl ToCss for ArcFlag {
     #[inline]
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
--- a/servo/components/style/values/specified/text.rs
+++ b/servo/components/style/values/specified/text.rs
@@ -117,28 +117,17 @@ impl ToComputedValue for LineHeight {
             GenericLineHeight::Length(ref length) => {
                 GenericLineHeight::Length(NoCalcLength::from_computed_value(&length.0).into())
             },
         }
     }
 }
 
 /// A generic value for the `text-overflow` property.
-#[derive(
-    Clone,
-    Debug,
-    Eq,
-    MallocSizeOf,
-    PartialEq,
-    SpecifiedValueInfo,
-    ToComputedValue,
-    ToCss,
-    ToResolvedValue,
-    ToShmem,
-)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
 #[repr(C, u8)]
 pub enum TextOverflowSide {
     /// Clip inline content.
     Clip,
     /// Render ellipsis to represent clipped inline content.
     Ellipsis,
     /// Render a given string to represent clipped inline content.
     String(crate::OwnedStr),
@@ -223,17 +212,17 @@ impl ToComputedValue for TextOverflow {
                 first: computed.first.clone(),
                 second: Some(computed.second.clone()),
             }
         }
     }
 }
 
 bitflags! {
-    #[derive(MallocSizeOf, Serialize, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
+    #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
     #[value_info(other_values = "none,underline,overline,line-through,blink")]
     #[repr(C)]
     /// Specified keyword values for the text-decoration-line property.
     pub struct TextDecorationLine: u8 {
         /// No text decoration line is specified.
         const NONE = 0;
         /// underline
         const UNDERLINE = 1 << 0;
@@ -250,22 +239,16 @@ bitflags! {
         ///
         /// For example, this gives <a href=foo><font color="red">text</font></a>
         /// a red text decoration
         #[cfg(feature = "gecko")]
         const COLOR_OVERRIDE = 0x10;
     }
 }
 
-impl Default for TextDecorationLine {
-    fn default() -> Self {
-        TextDecorationLine::NONE
-    }
-}
-
 impl Parse for TextDecorationLine {
     /// none | [ underline || overline || line-through || blink ]
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         let mut result = TextDecorationLine::empty();
 
@@ -693,29 +676,17 @@ pub enum TextEmphasisStyle {
     },
     /// `none`
     None,
     /// `<string>` (of which only the first grapheme cluster will be used).
     String(crate::OwnedStr),
 }
 
 /// Fill mode for the text-emphasis-style property
-#[derive(
-    Clone,
-    Copy,
-    Debug,
-    MallocSizeOf,
-    Parse,
-    PartialEq,
-    SpecifiedValueInfo,
-    ToCss,
-    ToComputedValue,
-    ToResolvedValue,
-    ToShmem,
-)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToComputedValue, ToResolvedValue, ToShmem)]
 #[repr(u8)]
 pub enum TextEmphasisFillMode {
     /// `filled`
     Filled,
     /// `open`
     Open,
 }
 
--- a/servo/components/style/values/specified/ui.rs
+++ b/servo/components/style/values/specified/ui.rs
@@ -53,22 +53,17 @@ impl Parse for CursorImage {
         let mut hotspot_y = Number::zero();
 
         if let Ok(x) = input.try(|input| Number::parse(context, input)) {
             has_hotspot = true;
             hotspot_x = x;
             hotspot_y = Number::parse(context, input)?;
         }
 
-        Ok(Self {
-            url,
-            has_hotspot,
-            hotspot_x,
-            hotspot_y,
-        })
+        Ok(Self { url, has_hotspot, hotspot_x, hotspot_y })
     }
 }
 
 /// Specified value of `-moz-force-broken-image-icon`
 #[derive(
     Clone,
     Copy,
     Debug,
--- a/servo/components/style_derive/to_computed_value.rs
+++ b/servo/components/style_derive/to_computed_value.rs
@@ -97,38 +97,27 @@ pub fn derive_to_value(
         } else {
             quote! { std::clone::Clone::clone(from) }
         };
 
         (to_body, from_body)
     } else {
         let to_body = cg::fmap_match(&input, bind_style, |binding| {
             let attrs = binding_attrs(&binding);
-            assert!(
-                !attrs.no_field_bound,
-                "It doesn't make sense on a generic implementation"
-            );
+            assert!(!attrs.no_field_bound, "It doesn't make sense on a generic implementation");
             if attrs.field_bound {
                 add_field_bound(&binding);
             }
             call_to(&binding)
         });
 
         let from_body = cg::fmap_match(&input, bind_style, |binding| call_from(&binding));
 
-        let self_ = if moves {
-            quote! { self }
-        } else {
-            quote! { *self }
-        };
-        let from_ = if moves {
-            quote! { from }
-        } else {
-            quote! { *from }
-        };
+        let self_ = if moves { quote! { self } } else { quote! { *self } };
+        let from_ = if moves { quote! { from } } else { quote! { *from } };
 
         let to_body = quote! {
             match #self_ {
                 #to_body
             }
         };
 
         let from_body = quote! {
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -295,17 +295,17 @@ pub extern "C" fn Servo_TraverseSubtree(
         element.has_animation_only_dirty_descendants() || element.has_animation_restyle_hints();
 
     let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     debug_assert!(!per_doc_data.stylist.stylesheets_have_changed());
 
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
 
-    let was_initial_style = !element.has_data();
+    let was_initial_style = element.get_data().is_none();
 
     if needs_animation_only_restyle {
         debug!(
             "Servo_TraverseSubtree doing animation-only restyle (aodd={})",
             element.has_animation_only_dirty_descendants()
         );
         traverse_subtree(
             element,
@@ -3713,17 +3713,17 @@ pub extern "C" fn Servo_ComputedValues_R
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_SetExplicitStyle(element: &RawGeckoElement, style: &ComputedValues) {
     let element = GeckoElement(element);
     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.has_data());
+    debug_assert!(element.get_data().is_none());
     let mut data = unsafe { element.ensure_data() };
     data.styles.primary = Some(unsafe { ArcBorrow::from_ref(style) }.clone_arc());
 }
 
 fn get_pseudo_style(
     guard: &SharedRwLockReadGuard,
     element: GeckoElement,
     pseudo: &PseudoElement,