Bug 1543837 - Fix servo build and appease tidy.
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 11 Apr 2019 23:55:42 +0200
changeset 469149 6873807a36e8200a7b545d63d6fbfb37316a8dad
parent 469148 ee6cfdd22388644a6e49baf1a47de29b8ef651e7
child 469150 c1f7767c6896d6d3e4c40b3f32244822fca0bfda
push id112769
push usercsabou@mozilla.com
push dateFri, 12 Apr 2019 03:51:12 +0000
treeherdermozilla-inbound@9ab47be2e004 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1543837
milestone68.0a1
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
Bug 1543837 - Fix servo build and appease tidy.
servo/components/style/Cargo.toml
servo/components/style/font_metrics.rs
servo/components/style/gecko/url.rs
servo/components/style/properties/declaration_block.rs
servo/components/style/properties/longhands/font.mako.rs
servo/components/style/servo/selector_parser.rs
servo/components/style/servo/url.rs
servo/components/style/shared_lock.rs
servo/components/style/stylesheets/mod.rs
servo/components/style/values/computed/font.rs
servo/components/style/values/generics/grid.rs
servo/components/style/values/generics/image.rs
servo/components/style/values/resolved/mod.rs
servo/components/style/values/specified/font.rs
servo/components/to_shmem/Cargo.toml
servo/components/to_shmem/lib.rs
servo/components/to_shmem_derive/to_shmem.rs
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -15,17 +15,17 @@ name = "style"
 path = "lib.rs"
 doctest = false
 
 [features]
 gecko = ["nsstring", "style_traits/gecko", "fallible/known_system_malloc"]
 use_bindgen = ["bindgen", "regex", "toml"]
 servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5ever",
          "cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union",
-         "servo_url", "string_cache", "crossbeam-channel"]
+         "servo_url", "string_cache", "crossbeam-channel", "to_shmem/servo", "servo_arc/servo"]
 gecko_debug = []
 
 [dependencies]
 app_units = "0.7"
 arrayvec = "0.4.6"
 atomic_refcell = "0.1"
 bitflags = "1.0"
 byteorder = "1.0"
--- a/servo/components/style/font_metrics.rs
+++ b/servo/components/style/font_metrics.rs
@@ -65,17 +65,17 @@ pub trait FontMetricsProvider {
 pub struct ServoMetricsProvider;
 
 #[cfg(feature = "servo")]
 impl FontMetricsProvider for ServoMetricsProvider {
     fn create_from(_: &SharedStyleContext) -> Self {
         ServoMetricsProvider
     }
 
-    fn get_size(&self, _font_name: &Atom, _font_family: u8) -> Au {
+    fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Au {
         unreachable!("Dummy provider should never be used to compute font size")
     }
 }
 
 // Servo's font metrics provider will probably not live in this crate, so this will
 // have to be replaced with something else (perhaps a trait method on TElement)
 // when we get there
 
--- a/servo/components/style/gecko/url.rs
+++ b/servo/components/style/gecko/url.rs
@@ -118,17 +118,17 @@ impl MallocSizeOf for CssUrl {
         // We ignore `extra_data`, because RefPtr is tricky, and there aren't
         // many of them in practise (sharing is common).
 
         0
     }
 }
 
 /// A key type for URL_VALUE_TABLE.
-#[derive(Hash, PartialEq, Eq)]
+#[derive(Eq, Hash, PartialEq)]
 struct CssUrlDataKey(*const CssUrlData);
 
 unsafe impl Sync for CssUrlDataKey {}
 unsafe impl Send for CssUrlDataKey {}
 
 /// The source of a Gecko URLValue object for a SpecifiedUrl.
 #[derive(Clone, Debug)]
 pub enum URLValueSource {
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -20,17 +20,17 @@ use smallvec::SmallVec;
 use std::fmt::{self, Write};
 use std::iter::{DoubleEndedIterator, Zip};
 use std::slice::Iter;
 use crate::str::{CssString, CssStringBorrow, CssStringWriter};
 use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
 use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
 use super::*;
 use crate::values::computed::Context;
-use crate::selector_parser::{SelectorImpl};
+use crate::selector_parser::SelectorImpl;
 use selectors::SelectorList;
 
 /// The animation rules.
 ///
 /// The first one is for Animation cascade level, and the second one is for
 /// Transition cascade level.
 pub struct AnimationRules(pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
                           pub Option<Arc<Locked<PropertyDeclarationBlock>>>);
--- a/servo/components/style/properties/longhands/font.mako.rs
+++ b/servo/components/style/properties/longhands/font.mako.rs
@@ -490,18 +490,17 @@ https://drafts.csswg.org/css-fonts-4/#lo
 % else:
     pub mod system_font {
         use cssparser::Parser;
 
         // We don't parse system fonts, but in the interest of not littering
         // a lot of code with `if product == gecko` conditionals, we have a
         // dummy system font module that does nothing
 
-        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, SpecifiedValueInfo, ToCss)]
-        #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
+        #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
         /// void enum for system font, can never exist
         pub enum SystemFont {}
         impl SystemFont {
             pub fn parse(_: &mut Parser) -> Result<Self, ()> {
                 Err(())
             }
         }
     }
--- a/servo/components/style/servo/selector_parser.rs
+++ b/servo/components/style/servo/selector_parser.rs
@@ -24,18 +24,17 @@ use selectors::visitor::SelectorVisitor;
 use std::fmt;
 use std::mem;
 use std::ops::{Deref, DerefMut};
 use style_traits::{ParseError, StyleParseErrorKind};
 
 /// A pseudo-element, both public and private.
 ///
 /// NB: If you add to this list, be sure to update `each_simple_pseudo_element` too.
-#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 #[allow(missing_docs)]
 #[repr(usize)]
 pub enum PseudoElement {
     // Eager pseudos. Keep these first so that eager_index() works.
     After = 0,
     Before,
     Selection,
     // If/when :first-letter is added, update is_first_letter accordingly.
@@ -260,18 +259,17 @@ impl PseudoElement {
     }
 }
 
 /// The type used for storing `:lang` arguments.
 pub type Lang = Box<str>;
 
 /// A non tree-structural pseudo-class.
 /// See https://drafts.csswg.org/selectors-4/#structural-pseudos
-#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 #[allow(missing_docs)]
 pub enum NonTSPseudoClass {
     Active,
     AnyLink,
     Checked,
     Disabled,
     Enabled,
     Focus,
--- a/servo/components/style/servo/url.rs
+++ b/servo/components/style/servo/url.rs
@@ -7,31 +7,31 @@
 use crate::parser::{Parse, ParserContext};
 use cssparser::Parser;
 use servo_url::ServoUrl;
 use std::fmt::{self, Write};
 // Note: We use std::sync::Arc rather than servo_arc::Arc here because the
 // nonzero optimization is important in keeping the size of SpecifiedUrl below
 // the threshold.
 use crate::values::computed::{Context, ToComputedValue};
-use std::sync::Arc;
+use servo_arc::Arc;
 use style_traits::{CssWriter, ParseError, ToCss};
 
 /// A CSS url() value for servo.
 ///
 /// Servo eagerly resolves SpecifiedUrls, which it can then take advantage of
 /// when computing values. In contrast, Gecko uses a different URL backend, so
 /// eagerly resolving with rust-url would be duplicated work.
 ///
 /// However, this approach is still not necessarily optimal: See
 /// <https://bugzilla.mozilla.org/show_bug.cgi?id=1347435#c6>
 ///
 /// TODO(emilio): This should be shrunk by making CssUrl a wrapper type of an
 /// arc, and keep the serialization in that Arc. See gecko/url.rs for example.
-#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, SpecifiedValueInfo)]
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, SpecifiedValueInfo, ToShmem)]
 pub struct CssUrl {
     /// The original URI. This might be optional since we may insert computed
     /// values of images into the cascade directly, and we don't bother to
     /// convert their serialization.
     ///
     /// Refcounted since cloning this should be cheap and data: uris can be
     /// really large.
     #[ignore_malloc_size_of = "Arc"]
--- a/servo/components/style/shared_lock.rs
+++ b/servo/components/style/shared_lock.rs
@@ -10,17 +10,16 @@ use crate::stylesheets::Origin;
 use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
 #[cfg(feature = "servo")]
 use parking_lot::RwLock;
 use servo_arc::Arc;
 use std::cell::UnsafeCell;
 use std::fmt;
 #[cfg(feature = "servo")]
 use std::mem;
-#[cfg(feature = "gecko")]
 use std::mem::ManuallyDrop;
 #[cfg(feature = "gecko")]
 use std::ptr;
 use to_shmem::{SharedMemoryBuilder, ToShmem};
 
 /// A shared read/write lock that can protect multiple objects.
 ///
 /// In Gecko builds, we don't need the blocking behavior, just the safety. As
@@ -119,21 +118,17 @@ pub struct SharedRwLockReadGuard<'a>(&'a
 /// Proof that a shared lock was obtained for reading (gecko).
 #[cfg(feature = "gecko")]
 pub struct SharedRwLockReadGuard<'a>(Option<AtomicRef<'a, SomethingZeroSizedButTyped>>);
 #[cfg(feature = "servo")]
 impl<'a> Drop for SharedRwLockReadGuard<'a> {
     fn drop(&mut self) {
         // Unsafe: self.lock is private to this module, only ever set after `read()`,
         // and never copied or cloned (see `compile_time_assert` below).
-        if let Some(arc) = self.0.arc {
-            unsafe {
-                arc.force_unlock_read();
-            }
-        }
+        unsafe { self.0.arc.force_unlock_read() }
     }
 }
 
 /// Proof that a shared lock was obtained for writing (servo).
 #[cfg(feature = "servo")]
 pub struct SharedRwLockWriteGuard<'a>(&'a SharedRwLock);
 /// Proof that a shared lock was obtained for writing (gecko).
 #[cfg(feature = "gecko")]
@@ -161,22 +156,16 @@ unsafe impl<T: Send + Sync> Sync for Loc
 impl<T: fmt::Debug> fmt::Debug for Locked<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let guard = self.shared_lock.read();
         self.read_with(&guard).fmt(f)
     }
 }
 
 impl<T> Locked<T> {
-    #[cfg(feature = "servo")]
-    #[inline]
-    fn is_read_only_lock(&self) -> bool {
-        false
-    }
-
     #[cfg(feature = "gecko")]
     #[inline]
     fn is_read_only_lock(&self) -> bool {
         self.shared_lock.cell.is_none()
     }
 
     #[cfg(feature = "servo")]
     fn same_lock_as(&self, lock: &SharedRwLock) -> bool {
@@ -194,20 +183,24 @@ impl<T> Locked<T> {
             derefed_guard
                 .map(|guard| guard as *const _ as *mut _)
                 .unwrap_or(ptr::null_mut()),
         )
     }
 
     /// Access the data for reading.
     pub fn read_with<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a T {
+        #[cfg(feature = "gecko")]
         assert!(
             self.is_read_only_lock() || self.same_lock_as(guard.0.as_ref().map(|r| &**r)),
             "Locked::read_with called with a guard from an unrelated SharedRwLock"
         );
+        #[cfg(not(feature = "gecko"))]
+        assert!(self.same_lock_as(&guard.0));
+
         let ptr = self.data.get();
 
         // Unsafe:
         //
         // * The guard guarantees that the lock is taken for reading,
         //   and we’ve checked that it’s the correct lock.
         // * The returned reference borrows *both* the data and the guard,
         //   so that it can outlive neither.
@@ -218,20 +211,24 @@ impl<T> Locked<T> {
     #[cfg(feature = "gecko")]
     pub unsafe fn read_unchecked<'a>(&'a self) -> &'a T {
         let ptr = self.data.get();
         &*ptr
     }
 
     /// Access the data for writing.
     pub fn write_with<'a>(&'a self, guard: &'a mut SharedRwLockWriteGuard) -> &'a mut T {
+        #[cfg(feature = "gecko")]
         assert!(
             !self.is_read_only_lock() && self.same_lock_as(Some(&guard.0)),
             "Locked::write_with called with a guard from a read only or unrelated SharedRwLock"
         );
+        #[cfg(not(feature = "gecko"))]
+        assert!(self.same_lock_as(&guard.0));
+
         let ptr = self.data.get();
 
         // Unsafe:
         //
         // * The guard guarantees that the lock is taken for writing,
         //   and we’ve checked that it’s the correct lock.
         // * The returned reference borrows *both* the data and the guard,
         //   so that it can outlive neither.
--- a/servo/components/style/stylesheets/mod.rs
+++ b/servo/components/style/stylesheets/mod.rs
@@ -34,16 +34,17 @@ use crate::str::CssStringWriter;
 use cssparser::{parse_one_rule, Parser, ParserInput};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
 use servo_arc::Arc;
 use std::fmt;
 #[cfg(feature = "gecko")]
 use std::mem::{self, ManuallyDrop};
 use style_traits::ParsingMode;
+#[cfg(feature = "gecko")]
 use to_shmem::{SharedMemoryBuilder, ToShmem};
 
 pub use self::counter_style_rule::CounterStyleRule;
 pub use self::document_rule::DocumentRule;
 pub use self::font_face_rule::FontFaceRule;
 pub use self::font_feature_values_rule::FontFeatureValuesRule;
 pub use self::import_rule::ImportRule;
 pub use self::keyframes_rule::KeyframesRule;
--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -24,16 +24,17 @@ use cssparser::{serialize_identifier, Cs
 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")]
 use std::slice;
 use style_traits::{CssWriter, ParseError, ToCss};
+#[cfg(feature = "gecko")]
 use to_shmem::{SharedMemoryBuilder, ToShmem};
 
 pub use crate::values::computed::Length as MozScriptMinSize;
 pub use crate::values::specified::font::{FontSynthesis, MozScriptSizeMultiplier};
 pub use crate::values::specified::font::{XLang, XTextZoom};
 
 /// A value for the font-weight property per:
 ///
@@ -279,32 +280,35 @@ pub enum FontFamilyNameSyntax {
     /// 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, ToResolvedValue)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, 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, ToResolvedValue)]
+#[derive(
+    Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, Parse, ToCss, 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.
     #[css(skip)]
     None,
     Serif,
     SansSerif,
@@ -368,33 +372,62 @@ impl SingleFontFamily {
             FontFamilyNameSyntax::Identifiers
         };
         Ok(SingleFontFamily::FamilyName(FamilyName {
             name: Atom::from(value),
             syntax,
         }))
     }
 
+    #[cfg(feature = "servo")]
+    /// Get the corresponding font-family with Atom
+    pub fn from_atom(input: Atom) -> SingleFontFamily {
+        match input {
+            atom!("serif") => return SingleFontFamily::Generic(GenericFontFamily::Serif),
+            atom!("sans-serif") => return SingleFontFamily::Generic(GenericFontFamily::SansSerif),
+            atom!("cursive") => return SingleFontFamily::Generic(GenericFontFamily::Cursive),
+            atom!("fantasy") => return SingleFontFamily::Generic(GenericFontFamily::Fantasy),
+            atom!("monospace") => return SingleFontFamily::Generic(GenericFontFamily::Monospace),
+            _ => {},
+        }
+
+        match_ignore_ascii_case! { &input,
+            "serif" => return SingleFontFamily::Generic(GenericFontFamily::Serif),
+            "sans-serif" => return SingleFontFamily::Generic(GenericFontFamily::SansSerif),
+            "cursive" => return SingleFontFamily::Generic(GenericFontFamily::Cursive),
+            "fantasy" => return SingleFontFamily::Generic(GenericFontFamily::Fantasy),
+            "monospace" => return SingleFontFamily::Generic(GenericFontFamily::Monospace),
+            _ => {}
+        }
+
+        // We don't know if it's quoted or not. So we set it to
+        // quoted by default.
+        SingleFontFamily::FamilyName(FamilyName {
+            name: input,
+            syntax: FontFamilyNameSyntax::Quoted,
+        })
+    }
+
     #[cfg(feature = "gecko")]
     /// Get the corresponding font-family with family name
     fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily {
         if family.mName.mRawPtr.is_null() {
             debug_assert_ne!(family.mGeneric, GenericFontFamily::None);
             return SingleFontFamily::Generic(family.mGeneric);
         }
         let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
         SingleFontFamily::FamilyName(FamilyName {
             name,
             syntax: family.mSyntax,
         })
     }
 }
 
 #[cfg(feature = "servo")]
-#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)]
 /// A list of SingleFontFamily
 pub struct FontFamilyList(Box<[SingleFontFamily]>);
 
 #[cfg(feature = "gecko")]
 #[derive(Clone, Debug)]
 /// A list of SingleFontFamily
 pub enum FontFamilyList {
     /// A strong reference to a Gecko SharedFontList object.
@@ -496,17 +529,17 @@ impl FontFamilyList {
         }
     }
 
     /// Return the generic ID if it is a single generic font
     pub fn single_generic(&self) -> Option<GenericFontFamily> {
         let mut iter = self.iter();
         if let Some(SingleFontFamily::Generic(f)) = iter.next() {
             if iter.next().is_none() {
-                return Some(f);
+                return Some(f.clone());
             }
         }
         None
     }
 
     /// Return a reference to the Gecko SharedFontList.
     #[cfg(feature = "gecko")]
     pub fn shared_font_list(&self) -> &RefPtr<structs::SharedFontList> {
--- a/servo/components/style/values/generics/grid.rs
+++ b/servo/components/style/values/generics/grid.rs
@@ -552,17 +552,17 @@ pub enum TrackListType {
     /// Note that this is a subset of the normal `<track-list>`, and so it could be used in place
     /// of the latter.
     Explicit,
 }
 
 /// A grid `<track-list>` type.
 ///
 /// <https://drafts.csswg.org/css-grid/#typedef-track-list>
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem, ToResolvedValue)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToResolvedValue, ToShmem)]
 pub struct TrackList<LengthPercentage, Integer> {
     /// The type of this `<track-list>` (auto, explicit or general).
     ///
     /// In order to avoid parsing the same value multiple times, this does a single traversal
     /// and arrives at the type of value it has parsed (or bails out gracefully with an error).
     #[css(skip)]
     pub list_type: TrackListType,
     /// A vector of `<track-size> | <track-repeat>` values.
--- a/servo/components/style/values/generics/image.rs
+++ b/servo/components/style/values/generics/image.rs
@@ -152,17 +152,17 @@ pub struct ColorStop<Color, LengthPercen
     pub color: Color,
     /// The position of this stop.
     pub position: Option<LengthPercentage>,
 }
 
 /// Specified values for a paint worklet.
 /// <https://drafts.css-houdini.org/css-paint-api/>
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
-#[derive(Clone, Debug, PartialEq, ToComputedValue)]
+#[derive(Clone, Debug, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
 pub struct PaintWorklet {
     /// The name the worklet was registered with.
     pub name: Atom,
     /// The arguments for the worklet.
     /// TODO: store a parsed representation of the arguments.
     #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
     pub arguments: Vec<Arc<custom_properties::SpecifiedValue>>,
 }
--- a/servo/components/style/values/resolved/mod.rs
+++ b/servo/components/style/values/resolved/mod.rs
@@ -60,25 +60,26 @@ macro_rules! trivial_to_resolved_value {
 trivial_to_resolved_value!(());
 trivial_to_resolved_value!(bool);
 trivial_to_resolved_value!(f32);
 trivial_to_resolved_value!(i32);
 trivial_to_resolved_value!(u8);
 trivial_to_resolved_value!(i8);
 trivial_to_resolved_value!(u16);
 trivial_to_resolved_value!(u32);
-#[cfg(feature = "servo")]
-trivial_to_resolved_value!(Prefix);
 trivial_to_resolved_value!(String);
 trivial_to_resolved_value!(Box<str>);
 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::Prefix);
 
 impl<A, B> ToResolvedValue for (A, B)
 where
     A: ToResolvedValue,
     B: ToResolvedValue,
 {
     type ResolvedValue = (
         <A as ToResolvedValue>::ResolvedValue,
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -1187,17 +1187,17 @@ impl Parse for FontVariantAlternates {
 macro_rules! impl_variant_east_asian {
     {
         $(
             $(#[$($meta:tt)+])*
             $ident:ident / $css:expr => $gecko:ident = $value:expr,
         )+
     } => {
         bitflags! {
-            #[derive(MallocSizeOf, ToShmem, ToResolvedValue)]
+            #[derive(MallocSizeOf, ToResolvedValue, ToShmem)]
             /// Vairants for east asian variant
             pub struct VariantEastAsian: u16 {
                 /// None of the features
                 const NORMAL = 0;
                 $(
                     $(#[$($meta)+])*
                     const $ident = $value;
                 )+
--- a/servo/components/to_shmem/Cargo.toml
+++ b/servo/components/to_shmem/Cargo.toml
@@ -5,18 +5,19 @@ authors = ["The Servo Project Developers
 license = "MPL-2.0"
 publish = false
 
 [lib]
 name = "to_shmem"
 path = "lib.rs"
 
 [features]
-servo = ["serde", "cssparser/serde"]
+servo = ["serde", "cssparser/serde", "string_cache"]
 gecko = []
 
 [dependencies]
 cssparser = "0.25"
-serde = {version = "1.0", optional = true}
+serde = { version = "1.0", optional = true }
 servo_arc = { path = "../servo_arc" }
 smallbitvec = "2.1.1"
 smallvec = "0.6.6"
+string_cache = { version = "0.7", optional = true }
 thin-slice = "0.1.0"
--- a/servo/components/to_shmem/lib.rs
+++ b/servo/components/to_shmem/lib.rs
@@ -11,16 +11,18 @@
 
 #![crate_name = "to_shmem"]
 #![crate_type = "rlib"]
 
 extern crate cssparser;
 extern crate servo_arc;
 extern crate smallbitvec;
 extern crate smallvec;
+#[cfg(feature = "string_cache")]
+extern crate string_cache;
 extern crate thin_slice;
 
 use servo_arc::{Arc, ThinArc};
 use smallbitvec::{InternalStorage, SmallBitVec};
 use smallvec::{Array, SmallVec};
 use std::alloc::Layout;
 #[cfg(debug_assertions)]
 use std::any::TypeId;
@@ -188,26 +190,28 @@ pub trait ToShmem: Sized {
     ///
     /// The return type is wrapped in ManuallyDrop to make it harder to
     /// accidentally invoke the destructor of the value that is produced.
     fn to_shmem(&self, builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self>;
 }
 
 #[macro_export]
 macro_rules! impl_trivial_to_shmem {
-    ($($ty:ty),*) => {$(
-        impl $crate::ToShmem for $ty {
-            fn to_shmem(
-                &self,
-                _builder: &mut $crate::SharedMemoryBuilder,
-            ) -> ::std::mem::ManuallyDrop<Self> {
-                ::std::mem::ManuallyDrop::new(*self)
+    ($($ty:ty),*) => {
+        $(
+            impl $crate::ToShmem for $ty {
+                fn to_shmem(
+                    &self,
+                    _builder: &mut $crate::SharedMemoryBuilder,
+                ) -> ::std::mem::ManuallyDrop<Self> {
+                    ::std::mem::ManuallyDrop::new(*self)
+                }
             }
-        }
-    )*};
+        )*
+    };
 }
 
 impl_trivial_to_shmem!(
     (),
     bool,
     f32,
     f64,
     i8,
@@ -517,8 +521,22 @@ impl ToShmem for SmallBitVec {
                     InternalStorage::Spilled(dest_slice)
                 }
             },
             InternalStorage::Inline(x) => InternalStorage::Inline(x),
         };
         ManuallyDrop::new(unsafe { SmallBitVec::from_storage(storage) })
     }
 }
+
+#[cfg(feature = "string_cache")]
+impl<Static: string_cache::StaticAtomSet> ToShmem for string_cache::Atom<Static> {
+    fn to_shmem(&self, _: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
+        // NOTE(emilio): In practice, this can be implemented trivially if
+        // string_cache could expose the implementation detail of static atoms
+        // being an index into the static table (and panicking in the
+        // non-static, non-inline cases).
+        unimplemented!(
+            "If servo wants to share stylesheets across processes, \
+             then ToShmem for Atom needs to be implemented"
+        )
+    }
+}
--- a/servo/components/to_shmem_derive/to_shmem.rs
+++ b/servo/components/to_shmem_derive/to_shmem.rs
@@ -35,17 +35,17 @@ pub fn derive(mut input: syn::DeriveInpu
         }
     });
 
     let name = &input.ident;
     let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
 
     quote! {
         impl #impl_generics ::to_shmem::ToShmem for #name #ty_generics #where_clause {
-            #[allow(unused_variables)]
+            #[allow(unused_variables, unreachable_code)]
             fn to_shmem(
                 &self,
                 builder: &mut ::to_shmem::SharedMemoryBuilder,
             ) -> ::std::mem::ManuallyDrop<Self> {
                 ::std::mem::ManuallyDrop::new(
                     match *self {
                         #match_body
                     }