servo: Merge #20519 - Use Servo data to back @font-face rule in Gecko (from upsuper:font-face-rule); r=emilio
authorXidorn Quan <me@upsuper.org>
Tue, 03 Apr 2018 19:33:59 -0400
changeset 411641 aab637e75538c977a5fe2793c3e2655abb818efc
parent 411640 7d7ad254494eee551d26aafb9fc44906679480e6
child 411642 233075da24e319daf7fdfa568812fed60c091539
push id101712
push userebalazs@mozilla.com
push dateWed, 04 Apr 2018 09:52:15 +0000
treeherdermozilla-inbound@dd31fb345c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1449087
milestone61.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
servo: Merge #20519 - Use Servo data to back @font-face rule in Gecko (from upsuper:font-face-rule); r=emilio This is the Servo side change of [bug 1449087](https://bugzilla.mozilla.org/show_bug.cgi?id=1449087). Source-Repo: https://github.com/servo/servo Source-Revision: 34b13dac66b48790003ccd069f4636f1def77e7d
servo/components/style/font_face.rs
servo/components/style/gecko/arc_types.rs
servo/components/style/gecko/generated/bindings.rs
servo/components/style/gecko/generated/structs.rs
servo/components/style/gecko/rules.rs
servo/components/style/gecko_bindings/sugar/refptr.rs
servo/components/style/stylesheets/font_face_rule.rs
servo/components/style/stylesheets/mod.rs
servo/components/style/stylist.rs
servo/ports/geckolib/glue.rs
--- a/servo/components/style/font_face.rs
+++ b/servo/components/style/font_face.rs
@@ -8,27 +8,27 @@
 
 #![deny(missing_docs)]
 
 #[cfg(feature = "gecko")]
 use computed_values::{font_stretch, font_style, font_weight};
 use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
 use cssparser::{SourceLocation, CowRcStr};
 use error_reporting::{ContextualParseError, ParseErrorReporter};
-#[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors;
 #[cfg(feature = "gecko")] use cssparser::UnicodeRange;
 use parser::{ParserContext, ParserErrorContext, Parse};
 #[cfg(feature = "gecko")]
 use properties::longhands::font_language_override;
 use selectors::parser::SelectorParseErrorKind;
 use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
 use std::fmt::{self, Write};
 use str::CssStringWriter;
 use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError};
 use style_traits::{StyleParseErrorKind, ToCss};
+use style_traits::values::SequenceWriter;
 use values::computed::font::FamilyName;
 #[cfg(feature = "gecko")]
 use values::specified::font::{SpecifiedFontFeatureSettings, SpecifiedFontVariationSettings};
 use values::specified::url::SpecifiedUrl;
 
 /// A source for a font-face rule.
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[derive(Clone, Debug, Eq, PartialEq, ToCss)]
@@ -44,25 +44,41 @@ impl OneOrMoreSeparated for Source {
     type S = Comma;
 }
 
 /// A `UrlSource` represents a font-face source that has been specified with a
 /// `url()` function.
 ///
 /// <https://drafts.csswg.org/css-fonts/#src-desc>
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
+#[derive(Clone, Debug, Eq, PartialEq)]
 pub struct UrlSource {
     /// The specified url.
     pub url: SpecifiedUrl,
     /// The format hints specified with the `format()` function.
-    #[css(skip)]
     pub format_hints: Vec<String>,
 }
 
+impl ToCss for UrlSource {
+    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
+        self.url.to_css(dest)?;
+        if !self.format_hints.is_empty() {
+            dest.write_str(" format(")?;
+            {
+                let mut writer = SequenceWriter::new(dest, ", ");
+                for hint in self.format_hints.iter() {
+                    writer.item(hint)?;
+                }
+            }
+            dest.write_char(')')?;
+        }
+        Ok(())
+    }
+}
+
 /// A font-display value for a @font-face rule.
 /// The font-display descriptor determines how a font face is displayed based
 /// on whether and when it is downloaded and ready to use.
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
 #[derive(ToComputedValue, ToCss)]
 pub enum FontDisplay {
@@ -249,51 +265,36 @@ macro_rules! font_face_descriptors_commo
                 #[$doc]
                 pub $ident: Option<$ty>,
             )*
             /// Line and column of the @font-face rule source code.
             pub source_location: SourceLocation,
         }
 
         impl FontFaceRuleData {
-            fn empty(location: SourceLocation) -> Self {
+            /// Create an empty font-face rule
+            pub fn empty(location: SourceLocation) -> Self {
                 FontFaceRuleData {
                     $(
                         $ident: None,
                     )*
                     source_location: location,
                 }
             }
 
-            /// Convert to Gecko types
-            #[cfg(feature = "gecko")]
-            pub fn set_descriptors(self, descriptors: &mut CSSFontFaceDescriptors) {
-                $(
-                    if let Some(value) = self.$ident {
-                        descriptors.$gecko_ident.set_from(value)
-                    }
-                )*
-                // Leave unset descriptors to eCSSUnit_Null,
-                // FontFaceSet::FindOrCreateUserFontEntryFromFontFace does the defaulting
-                // to initial values.
-            }
-        }
-
-        impl ToCssWithGuard for FontFaceRuleData {
-            // Serialization of FontFaceRule is not specced.
-            fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
-                dest.write_str("@font-face {\n")?;
+            /// Serialization of declarations in the FontFaceRule
+            pub fn decl_to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
                 $(
                     if let Some(ref value) = self.$ident {
                         dest.write_str(concat!("  ", $name, ": "))?;
                         ToCss::to_css(value, &mut CssWriter::new(dest))?;
                         dest.write_str(";\n")?;
                     }
                 )*
-                dest.write_str("}")
+                Ok(())
             }
         }
 
        impl<'a, 'b, 'i> DeclarationParser<'i> for FontFaceRuleParser<'a, 'b> {
            type Declaration = ();
            type Error = StyleParseErrorKind<'i>;
 
            fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>)
@@ -312,16 +313,25 @@ macro_rules! font_face_descriptors_commo
                     _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
                 }
                 Ok(())
             }
         }
     }
 }
 
+impl ToCssWithGuard for FontFaceRuleData {
+    // Serialization of FontFaceRule is not specced.
+    fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
+        dest.write_str("@font-face {\n")?;
+        self.decl_to_css(dest)?;
+        dest.write_str("}")
+    }
+}
+
 macro_rules! font_face_descriptors {
     (
         mandatory descriptors = [
             $( #[$m_doc: meta] $m_name: tt $m_ident: ident / $m_gecko_ident: ident: $m_ty: ty, )*
         ]
         optional descriptors = [
             $( #[$o_doc: meta] $o_name: tt $o_ident: ident / $o_gecko_ident: ident: $o_ty: ty, )*
         ]
--- a/servo/components/style/gecko/arc_types.rs
+++ b/servo/components/style/gecko/arc_types.rs
@@ -3,33 +3,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! This file lists all arc FFI types and defines corresponding addref
 //! and release functions. This list corresponds to ServoArcTypeList.h
 //! file in Gecko.
 
 #![allow(non_snake_case, missing_docs)]
 
-use gecko_bindings::bindings::{RawServoFontFeatureValuesRule, RawServoImportRule, RawServoSupportsRule};
-use gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframesRule};
+use gecko_bindings::bindings::{RawServoFontFeatureValuesRule, RawServoImportRule};
+use gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframesRule, RawServoSupportsRule};
 use gecko_bindings::bindings::{RawServoMediaRule, RawServoNamespaceRule, RawServoPageRule};
 use gecko_bindings::bindings::{RawServoRuleNode, RawServoRuleNodeStrong, RawServoDocumentRule};
 use gecko_bindings::bindings::ServoCssRules;
-use gecko_bindings::structs::{RawServoAnimationValue, RawServoDeclarationBlock, RawServoStyleRule};
-use gecko_bindings::structs::{RawServoMediaList, RawServoStyleSheetContents};
+use gecko_bindings::structs::{RawServoAnimationValue, RawServoDeclarationBlock, RawServoFontFaceRule};
+use gecko_bindings::structs::{RawServoMediaList, RawServoStyleRule, RawServoStyleSheetContents};
 use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI, Strong};
 use media_queries::MediaList;
 use properties::{ComputedValues, PropertyDeclarationBlock};
 use properties::animated_properties::AnimationValue;
 use rule_tree::StrongRuleNode;
 use servo_arc::{Arc, ArcBorrow};
 use shared_lock::Locked;
 use std::{mem, ptr};
 use stylesheets::{CssRules, StylesheetContents, StyleRule, ImportRule, KeyframesRule, MediaRule};
-use stylesheets::{FontFeatureValuesRule, NamespaceRule, PageRule, SupportsRule, DocumentRule};
+use stylesheets::{FontFaceRule, FontFeatureValuesRule, NamespaceRule, PageRule, SupportsRule, DocumentRule};
 use stylesheets::keyframes_rule::Keyframe;
 
 macro_rules! impl_arc_ffi {
     ($servo_type:ty => $gecko_type:ty [$addref:ident, $release:ident]) => {
         unsafe impl HasFFI for $servo_type {
             type FFIType = $gecko_type;
         }
         unsafe impl HasArcFFI for $servo_type {}
@@ -86,16 +86,19 @@ impl_arc_ffi!(Locked<SupportsRule> => Ra
               [Servo_SupportsRule_AddRef, Servo_SupportsRule_Release]);
 
 impl_arc_ffi!(Locked<DocumentRule> => RawServoDocumentRule
               [Servo_DocumentRule_AddRef, Servo_DocumentRule_Release]);
 
 impl_arc_ffi!(Locked<FontFeatureValuesRule> => RawServoFontFeatureValuesRule
               [Servo_FontFeatureValuesRule_AddRef, Servo_FontFeatureValuesRule_Release]);
 
+impl_arc_ffi!(Locked<FontFaceRule> => RawServoFontFaceRule
+              [Servo_FontFaceRule_AddRef, Servo_FontFaceRule_Release]);
+
 // RuleNode is a Arc-like type but it does not use Arc.
 
 impl StrongRuleNode {
     pub fn into_strong(self) -> RawServoRuleNodeStrong {
         let ptr = self.ptr();
         mem::forget(self);
         unsafe { mem::transmute(ptr) }
     }
--- a/servo/components/style/gecko/generated/bindings.rs
+++ b/servo/components/style/gecko/generated/bindings.rs
@@ -33,16 +33,17 @@ use gecko_bindings::structs::RawGeckoDoc
 use gecko_bindings::structs::RawGeckoElement;
 use gecko_bindings::structs::Element;
 use gecko_bindings::structs::RawGeckoKeyframeList;
 use gecko_bindings::structs::RawGeckoPropertyValuePairList;
 use gecko_bindings::structs::RawGeckoComputedKeyframeValuesList;
 use gecko_bindings::structs::RawGeckoFontFaceRuleList;
 use gecko_bindings::structs::RawGeckoNode;
 use gecko_bindings::structs::RawServoAnimationValue;
+use gecko_bindings::structs::RawServoFontFaceRule;
 use gecko_bindings::structs::RawGeckoServoAnimationValueList;
 use gecko_bindings::structs::RawServoMediaList;
 use gecko_bindings::structs::RawServoStyleSheetContents;
 use gecko_bindings::structs::RawServoDeclarationBlock;
 use gecko_bindings::structs::RawServoStyleRule;
 use gecko_bindings::structs::RawGeckoPresContext;
 use gecko_bindings::structs::RawGeckoPresContextOwned;
 use gecko_bindings::structs::RawGeckoStyleAnimationList;
@@ -72,17 +73,16 @@ use gecko_bindings::structs::ServoStyleS
 use gecko_bindings::structs::SheetParsingMode;
 use gecko_bindings::structs::StyleBasicShapeType;
 use gecko_bindings::structs::StyleShapeSource;
 use gecko_bindings::structs::StyleTransition;
 use gecko_bindings::structs::gfxFontFeatureValueSet;
 use gecko_bindings::structs::nsCSSCounterDesc;
 use gecko_bindings::structs::nsCSSCounterStyleRule;
 use gecko_bindings::structs::nsCSSFontDesc;
-use gecko_bindings::structs::nsCSSFontFaceRule;
 use gecko_bindings::structs::nsCSSKeyword;
 use gecko_bindings::structs::nsCSSPropertyID;
 use gecko_bindings::structs::nsCSSPropertyIDSet;
 use gecko_bindings::structs::nsCSSRect;
 use gecko_bindings::structs::nsCSSShadowArray;
 use gecko_bindings::structs::nsCSSUnit;
 use gecko_bindings::structs::nsCSSValue;
 use gecko_bindings::structs::nsCSSValueSharedList;
@@ -425,16 +425,19 @@ pub type RawServoFontFeatureValuesRuleBo
 pub type RawServoFontFeatureValuesRuleBorrowedOrNull<'a> = Option<&'a RawServoFontFeatureValuesRule>;
 enum RawServoFontFeatureValuesRuleVoid { }
 pub struct RawServoFontFeatureValuesRule(RawServoFontFeatureValuesRuleVoid);
 pub type RawServoRuleNodeStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoRuleNode>;
 pub type RawServoRuleNodeBorrowed<'a> = &'a RawServoRuleNode;
 pub type RawServoRuleNodeBorrowedOrNull<'a> = Option<&'a RawServoRuleNode>;
 enum RawServoRuleNodeVoid { }
 pub struct RawServoRuleNode(RawServoRuleNodeVoid);
+pub type RawServoFontFaceRuleStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoFontFaceRule>;
+pub type RawServoFontFaceRuleBorrowed<'a> = &'a RawServoFontFaceRule;
+pub type RawServoFontFaceRuleBorrowedOrNull<'a> = Option<&'a RawServoFontFaceRule>;
 
 extern "C" {
     pub fn Gecko_EnsureTArrayCapacity(
         aArray: *mut ::std::os::raw::c_void,
         aCapacity: usize,
         aElementSize: usize,
     );
 }
@@ -537,16 +540,22 @@ extern "C" {
 }
 extern "C" {
     pub fn Servo_RuleNode_AddRef(ptr: RawServoRuleNodeBorrowed);
 }
 extern "C" {
     pub fn Servo_RuleNode_Release(ptr: RawServoRuleNodeBorrowed);
 }
 extern "C" {
+    pub fn Servo_FontFaceRule_AddRef(ptr: RawServoFontFaceRuleBorrowed);
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_Release(ptr: RawServoFontFaceRuleBorrowed);
+}
+extern "C" {
     pub fn Servo_StyleSet_Drop(ptr: RawServoStyleSetOwned);
 }
 extern "C" {
     pub fn Servo_AuthorStyles_Drop(ptr: RawServoAuthorStylesOwned);
 }
 extern "C" {
     pub fn Servo_SelectorList_Drop(ptr: RawServoSelectorListOwned);
 }
@@ -1559,31 +1568,16 @@ extern "C" {
 }
 extern "C" {
     pub fn Gecko_CSSKeywordString(
         keyword: nsCSSKeyword,
         len: *mut u32,
     ) -> *const ::std::os::raw::c_char;
 }
 extern "C" {
-    pub fn Gecko_CSSFontFaceRule_Create(line: u32, column: u32) -> *mut nsCSSFontFaceRule;
-}
-extern "C" {
-    pub fn Gecko_CSSFontFaceRule_Clone(rule: *const nsCSSFontFaceRule) -> *mut nsCSSFontFaceRule;
-}
-extern "C" {
-    pub fn Gecko_CSSFontFaceRule_GetCssText(rule: *const nsCSSFontFaceRule, result: *mut nsAString);
-}
-extern "C" {
-    pub fn Gecko_CSSFontFaceRule_AddRef(aPtr: *mut nsCSSFontFaceRule);
-}
-extern "C" {
-    pub fn Gecko_CSSFontFaceRule_Release(aPtr: *mut nsCSSFontFaceRule);
-}
-extern "C" {
     pub fn Gecko_CSSCounterStyle_Create(name: *mut nsAtom) -> *mut nsCSSCounterStyleRule;
 }
 extern "C" {
     pub fn Gecko_CSSCounterStyle_Clone(
         rule: *const nsCSSCounterStyleRule,
     ) -> *mut nsCSSCounterStyleRule;
 }
 extern "C" {
@@ -2457,17 +2451,28 @@ extern "C" {
         rule: RawServoFontFeatureValuesRuleBorrowed,
         result: *mut nsAString,
     );
 }
 extern "C" {
     pub fn Servo_CssRules_GetFontFaceRuleAt(
         rules: ServoCssRulesBorrowed,
         index: u32,
-    ) -> *mut nsCSSFontFaceRule;
+        line: *mut u32,
+        column: *mut u32,
+    ) -> RawServoFontFaceRuleStrong;
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_Debug(rule: RawServoFontFaceRuleBorrowed, result: *mut nsACString);
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_GetCssText(
+        rule: RawServoFontFaceRuleBorrowed,
+        result: *mut nsAString,
+    );
 }
 extern "C" {
     pub fn Servo_CssRules_GetCounterStyleRuleAt(
         rules: ServoCssRulesBorrowed,
         index: u32,
     ) -> *mut nsCSSCounterStyleRule;
 }
 extern "C" {
@@ -2608,16 +2613,74 @@ extern "C" {
 }
 extern "C" {
     pub fn Servo_FontFeatureValuesRule_GetValueText(
         rule: RawServoFontFeatureValuesRuleBorrowed,
         result: *mut nsAString,
     );
 }
 extern "C" {
+    pub fn Servo_FontFaceRule_CreateEmpty() -> RawServoFontFaceRuleStrong;
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_Clone(
+        rule: RawServoFontFaceRuleBorrowed,
+    ) -> RawServoFontFaceRuleStrong;
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_GetSourceLocation(
+        rule: RawServoFontFaceRuleBorrowed,
+        line: *mut u32,
+        column: *mut u32,
+    );
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_Length(rule: RawServoFontFaceRuleBorrowed) -> u32;
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_IndexGetter(
+        rule: RawServoFontFaceRuleBorrowed,
+        index: u32,
+    ) -> nsCSSFontDesc;
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_GetDeclCssText(
+        rule: RawServoFontFaceRuleBorrowed,
+        result: *mut nsAString,
+    );
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_GetDescriptor(
+        rule: RawServoFontFaceRuleBorrowed,
+        desc: nsCSSFontDesc,
+        result: nsCSSValueBorrowedMut,
+    );
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_GetDescriptorCssText(
+        rule: RawServoFontFaceRuleBorrowed,
+        desc: nsCSSFontDesc,
+        result: *mut nsAString,
+    );
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_SetDescriptor(
+        rule: RawServoFontFaceRuleBorrowed,
+        desc: nsCSSFontDesc,
+        value: *const nsACString,
+        data: *mut RawGeckoURLExtraData,
+    ) -> bool;
+}
+extern "C" {
+    pub fn Servo_FontFaceRule_ResetDescriptor(
+        rule: RawServoFontFaceRuleBorrowed,
+        desc: nsCSSFontDesc,
+    );
+}
+extern "C" {
     pub fn Servo_ParseProperty(
         property: nsCSSPropertyID,
         value: *const nsACString,
         data: *mut RawGeckoURLExtraData,
         parsing_mode: ParsingMode,
         quirks_mode: nsCompatibility,
         loader: *mut Loader,
     ) -> RawServoDeclarationBlockStrong;
@@ -3261,24 +3324,16 @@ extern "C" {
     pub fn Servo_ParseCounterStyleDescriptor(
         aDescriptor: nsCSSCounterDesc,
         aValue: *const nsACString,
         aURLExtraData: *mut RawGeckoURLExtraData,
         aResult: *mut nsCSSValue,
     ) -> bool;
 }
 extern "C" {
-    pub fn Servo_ParseFontDescriptor(
-        desc_id: nsCSSFontDesc,
-        value: *const nsAString,
-        data: *mut RawGeckoURLExtraData,
-        arg1: nsCSSValueBorrowedMut,
-    ) -> bool;
-}
-extern "C" {
     pub fn Servo_ParseFontShorthandForMatching(
         value: *const nsAString,
         data: *mut RawGeckoURLExtraData,
         family: *mut RefPtr<SharedFontList>,
         style: nsCSSValueBorrowedMut,
         stretch: nsCSSValueBorrowedMut,
         weight: nsCSSValueBorrowedMut,
     ) -> bool;
--- a/servo/components/style/gecko/generated/structs.rs
+++ b/servo/components/style/gecko/generated/structs.rs
@@ -13373,171 +13373,16 @@ pub mod root {
                 )
             );
         }
         impl Clone for ServoTraversalStatistics {
             fn clone(&self) -> Self {
                 *self
             }
         }
-        #[repr(C)]
-        #[derive(Debug)]
-        pub struct CSSFontFaceDescriptors {
-            pub mFamily: root::nsCSSValue,
-            pub mStyle: root::nsCSSValue,
-            pub mWeight: root::nsCSSValue,
-            pub mStretch: root::nsCSSValue,
-            pub mSrc: root::nsCSSValue,
-            pub mUnicodeRange: root::nsCSSValue,
-            pub mFontFeatureSettings: root::nsCSSValue,
-            pub mFontVariationSettings: root::nsCSSValue,
-            pub mFontLanguageOverride: root::nsCSSValue,
-            pub mDisplay: root::nsCSSValue,
-        }
-        extern "C" {
-            #[link_name = "\u{1}_ZN7mozilla22CSSFontFaceDescriptors6FieldsE"]
-            pub static mut CSSFontFaceDescriptors_Fields: [*const root::nsCSSValue; 0usize];
-        }
-        #[test]
-        fn bindgen_test_layout_CSSFontFaceDescriptors() {
-            assert_eq!(
-                ::std::mem::size_of::<CSSFontFaceDescriptors>(),
-                160usize,
-                concat!("Size of: ", stringify!(CSSFontFaceDescriptors))
-            );
-            assert_eq!(
-                ::std::mem::align_of::<CSSFontFaceDescriptors>(),
-                8usize,
-                concat!("Alignment of ", stringify!(CSSFontFaceDescriptors))
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mFamily as *const _ as usize
-                },
-                0usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mFamily)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mStyle as *const _ as usize
-                },
-                16usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mStyle)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mWeight as *const _ as usize
-                },
-                32usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mWeight)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mStretch as *const _ as usize
-                },
-                48usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mStretch)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mSrc as *const _ as usize
-                },
-                64usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mSrc)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mUnicodeRange as *const _
-                        as usize
-                },
-                80usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mUnicodeRange)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mFontFeatureSettings
-                        as *const _ as usize
-                },
-                96usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mFontFeatureSettings)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mFontVariationSettings
-                        as *const _ as usize
-                },
-                112usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mFontVariationSettings)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mFontLanguageOverride
-                        as *const _ as usize
-                },
-                128usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mFontLanguageOverride)
-                )
-            );
-            assert_eq!(
-                unsafe {
-                    &(*(::std::ptr::null::<CSSFontFaceDescriptors>())).mDisplay as *const _ as usize
-                },
-                144usize,
-                concat!(
-                    "Offset of field: ",
-                    stringify!(CSSFontFaceDescriptors),
-                    "::",
-                    stringify!(mDisplay)
-                )
-            );
-        }
         pub mod intl {
             #[allow(unused_imports)]
             use self::super::super::super::root;
             #[repr(C)]
             #[derive(Debug)]
             pub struct LineBreaker {
                 pub mRefCnt: root::nsAutoRefCnt,
             }
@@ -23539,16 +23384,26 @@ pub mod root {
     pub struct RawServoMediaList {
         _unused: [u8; 0],
     }
     impl Clone for RawServoMediaList {
         fn clone(&self) -> Self {
             *self
         }
     }
+    #[repr(C)]
+    #[derive(Debug, Copy)]
+    pub struct RawServoFontFaceRule {
+        _unused: [u8; 0],
+    }
+    impl Clone for RawServoFontFaceRule {
+        fn clone(&self) -> Self {
+            *self
+        }
+    }
     pub mod nsStyleTransformMatrix {
         #[allow(unused_imports)]
         use self::super::super::root;
         #[repr(u8)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum MatrixTransformOperator {
             Interpolate = 0,
             Accumulate = 1,
@@ -23622,16 +23477,59 @@ pub mod root {
     pub type RawGeckoFontFaceRuleListBorrowedMut = *mut root::RawGeckoFontFaceRuleList;
     pub type RawGeckoAnimationPropertySegmentBorrowed =
         *const root::RawGeckoAnimationPropertySegment;
     pub type RawGeckoComputedTimingBorrowed = *const root::RawGeckoComputedTiming;
     pub type RawGeckoServoStyleRuleListBorrowedMut = *mut root::RawGeckoServoStyleRuleList;
     pub type RawGeckoCSSPropertyIDListBorrowed = *const root::RawGeckoCSSPropertyIDList;
     pub type RawGeckoStyleChildrenIteratorBorrowedMut = *mut root::RawGeckoStyleChildrenIterator;
     #[repr(C)]
+    #[derive(Debug)]
+    pub struct nsFontFaceRuleContainer {
+        pub mRule: root::RefPtr<root::RawServoFontFaceRule>,
+        pub mSheetType: root::mozilla::SheetType,
+    }
+    #[test]
+    fn bindgen_test_layout_nsFontFaceRuleContainer() {
+        assert_eq!(
+            ::std::mem::size_of::<nsFontFaceRuleContainer>(),
+            16usize,
+            concat!("Size of: ", stringify!(nsFontFaceRuleContainer))
+        );
+        assert_eq!(
+            ::std::mem::align_of::<nsFontFaceRuleContainer>(),
+            8usize,
+            concat!("Alignment of ", stringify!(nsFontFaceRuleContainer))
+        );
+        assert_eq!(
+            unsafe {
+                &(*(::std::ptr::null::<nsFontFaceRuleContainer>())).mRule as *const _ as usize
+            },
+            0usize,
+            concat!(
+                "Offset of field: ",
+                stringify!(nsFontFaceRuleContainer),
+                "::",
+                stringify!(mRule)
+            )
+        );
+        assert_eq!(
+            unsafe {
+                &(*(::std::ptr::null::<nsFontFaceRuleContainer>())).mSheetType as *const _ as usize
+            },
+            8usize,
+            concat!(
+                "Offset of field: ",
+                stringify!(nsFontFaceRuleContainer),
+                "::",
+                stringify!(mSheetType)
+            )
+        );
+    }
+    #[repr(C)]
     #[derive(Debug, Copy)]
     pub struct nsDOMStyleSheetSetList {
         _unused: [u8; 0],
     }
     impl Clone for nsDOMStyleSheetSetList {
         fn clone(&self) -> Self {
             *self
         }
@@ -39868,150 +39766,16 @@ pub mod root {
                 "Offset of field: ",
                 stringify!(nsCSSCounterStyleRule),
                 "::",
                 stringify!(mGeneration)
             )
         );
     }
     #[repr(C)]
-    #[derive(Debug)]
-    pub struct nsCSSFontFaceStyleDecl {
-        pub _base: root::nsICSSDeclaration,
-        pub mDescriptors: root::mozilla::CSSFontFaceDescriptors,
-    }
-    #[test]
-    fn bindgen_test_layout_nsCSSFontFaceStyleDecl() {
-        assert_eq!(
-            ::std::mem::size_of::<nsCSSFontFaceStyleDecl>(),
-            192usize,
-            concat!("Size of: ", stringify!(nsCSSFontFaceStyleDecl))
-        );
-        assert_eq!(
-            ::std::mem::align_of::<nsCSSFontFaceStyleDecl>(),
-            8usize,
-            concat!("Alignment of ", stringify!(nsCSSFontFaceStyleDecl))
-        );
-        assert_eq!(
-            unsafe {
-                &(*(::std::ptr::null::<nsCSSFontFaceStyleDecl>())).mDescriptors as *const _ as usize
-            },
-            32usize,
-            concat!(
-                "Offset of field: ",
-                stringify!(nsCSSFontFaceStyleDecl),
-                "::",
-                stringify!(mDescriptors)
-            )
-        );
-    }
-    #[repr(C)]
-    #[derive(Debug)]
-    pub struct nsCSSFontFaceRule {
-        pub _base: root::mozilla::css::Rule,
-        pub mDecl: root::nsCSSFontFaceStyleDecl,
-    }
-    #[repr(C)]
-    #[derive(Debug, Copy)]
-    pub struct nsCSSFontFaceRule_cycleCollection {
-        pub _base: root::mozilla::css::Rule_cycleCollection,
-    }
-    #[test]
-    fn bindgen_test_layout_nsCSSFontFaceRule_cycleCollection() {
-        assert_eq!(
-            ::std::mem::size_of::<nsCSSFontFaceRule_cycleCollection>(),
-            16usize,
-            concat!("Size of: ", stringify!(nsCSSFontFaceRule_cycleCollection))
-        );
-        assert_eq!(
-            ::std::mem::align_of::<nsCSSFontFaceRule_cycleCollection>(),
-            8usize,
-            concat!(
-                "Alignment of ",
-                stringify!(nsCSSFontFaceRule_cycleCollection)
-            )
-        );
-    }
-    impl Clone for nsCSSFontFaceRule_cycleCollection {
-        fn clone(&self) -> Self {
-            *self
-        }
-    }
-    extern "C" {
-        #[link_name = "\u{1}_ZN17nsCSSFontFaceRule21_cycleCollectorGlobalE"]
-        pub static mut nsCSSFontFaceRule__cycleCollectorGlobal:
-            root::nsCSSFontFaceRule_cycleCollection;
-    }
-    #[test]
-    fn bindgen_test_layout_nsCSSFontFaceRule() {
-        assert_eq!(
-            ::std::mem::size_of::<nsCSSFontFaceRule>(),
-            256usize,
-            concat!("Size of: ", stringify!(nsCSSFontFaceRule))
-        );
-        assert_eq!(
-            ::std::mem::align_of::<nsCSSFontFaceRule>(),
-            8usize,
-            concat!("Alignment of ", stringify!(nsCSSFontFaceRule))
-        );
-        assert_eq!(
-            unsafe { &(*(::std::ptr::null::<nsCSSFontFaceRule>())).mDecl as *const _ as usize },
-            64usize,
-            concat!(
-                "Offset of field: ",
-                stringify!(nsCSSFontFaceRule),
-                "::",
-                stringify!(mDecl)
-            )
-        );
-    }
-    #[repr(C)]
-    #[derive(Debug)]
-    pub struct nsFontFaceRuleContainer {
-        pub mRule: root::RefPtr<root::nsCSSFontFaceRule>,
-        pub mSheetType: root::mozilla::SheetType,
-    }
-    #[test]
-    fn bindgen_test_layout_nsFontFaceRuleContainer() {
-        assert_eq!(
-            ::std::mem::size_of::<nsFontFaceRuleContainer>(),
-            16usize,
-            concat!("Size of: ", stringify!(nsFontFaceRuleContainer))
-        );
-        assert_eq!(
-            ::std::mem::align_of::<nsFontFaceRuleContainer>(),
-            8usize,
-            concat!("Alignment of ", stringify!(nsFontFaceRuleContainer))
-        );
-        assert_eq!(
-            unsafe {
-                &(*(::std::ptr::null::<nsFontFaceRuleContainer>())).mRule as *const _ as usize
-            },
-            0usize,
-            concat!(
-                "Offset of field: ",
-                stringify!(nsFontFaceRuleContainer),
-                "::",
-                stringify!(mRule)
-            )
-        );
-        assert_eq!(
-            unsafe {
-                &(*(::std::ptr::null::<nsFontFaceRuleContainer>())).mSheetType as *const _ as usize
-            },
-            8usize,
-            concat!(
-                "Offset of field: ",
-                stringify!(nsFontFaceRuleContainer),
-                "::",
-                stringify!(mSheetType)
-            )
-        );
-    }
-    #[repr(C)]
     #[derive(Debug, Copy)]
     pub struct nsHtml5StringParser {
         _unused: [u8; 0],
     }
     impl Clone for nsHtml5StringParser {
         fn clone(&self) -> Self {
             *self
         }
@@ -47142,16 +46906,35 @@ pub mod root {
             8usize,
             concat!(
                 "Alignment of template specialization: ",
                 stringify!(root::nsTArray<*mut root::nsISupports>)
             )
         );
     }
     #[test]
+    fn __bindgen_test_layout_RefPtr_open0_RawServoFontFaceRule_close0_instantiation() {
+        assert_eq!(
+            ::std::mem::size_of::<root::RefPtr<root::RawServoFontFaceRule>>(),
+            8usize,
+            concat!(
+                "Size of template specialization: ",
+                stringify!(root::RefPtr<root::RawServoFontFaceRule>)
+            )
+        );
+        assert_eq!(
+            ::std::mem::align_of::<root::RefPtr<root::RawServoFontFaceRule>>(),
+            8usize,
+            concat!(
+                "Alignment of template specialization: ",
+                stringify!(root::RefPtr<root::RawServoFontFaceRule>)
+            )
+        );
+    }
+    #[test]
     fn __bindgen_test_layout_RefPtr_open0_RawServoAnimationValue_close0_instantiation_1() {
         assert_eq!(
             ::std::mem::size_of::<root::RefPtr<root::RawServoAnimationValue>>(),
             8usize,
             concat!(
                 "Size of template specialization: ",
                 stringify!(root::RefPtr<root::RawServoAnimationValue>)
             )
@@ -49301,35 +49084,16 @@ pub mod root {
             8usize,
             concat!(
                 "Alignment of template specialization: ",
                 stringify!(root::RefPtr<root::nsAtom>)
             )
         );
     }
     #[test]
-    fn __bindgen_test_layout_RefPtr_open0_nsCSSFontFaceRule_close0_instantiation() {
-        assert_eq!(
-            ::std::mem::size_of::<root::RefPtr<root::nsCSSFontFaceRule>>(),
-            8usize,
-            concat!(
-                "Size of template specialization: ",
-                stringify!(root::RefPtr<root::nsCSSFontFaceRule>)
-            )
-        );
-        assert_eq!(
-            ::std::mem::align_of::<root::RefPtr<root::nsCSSFontFaceRule>>(),
-            8usize,
-            concat!(
-                "Alignment of template specialization: ",
-                stringify!(root::RefPtr<root::nsCSSFontFaceRule>)
-            )
-        );
-    }
-    #[test]
     fn __bindgen_test_layout_nsRefPtrHashKey_open0_nsAtom_close0_instantiation_5() {
         assert_eq!(
             ::std::mem::size_of::<root::nsRefPtrHashKey<root::nsAtom>>(),
             16usize,
             concat!(
                 "Size of template specialization: ",
                 stringify!(root::nsRefPtrHashKey<root::nsAtom>)
             )
--- a/servo/components/style/gecko/rules.rs
+++ b/servo/components/style/gecko/rules.rs
@@ -3,50 +3,47 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Bindings for CSS Rule objects
 
 use byteorder::{BigEndian, WriteBytesExt};
 use computed_values::{font_stretch, font_style, font_weight};
 use counter_style::{self, CounterBound};
 use cssparser::UnicodeRange;
-use font_face::{FontFaceRuleData, Source, FontDisplay, FontWeight};
+use font_face::{Source, FontDisplay, FontWeight};
 use gecko_bindings::bindings;
-use gecko_bindings::structs::{self, nsCSSFontFaceRule, nsCSSValue};
+use gecko_bindings::structs::{self, nsCSSValue};
 use gecko_bindings::structs::{nsCSSCounterDesc, nsCSSCounterStyleRule};
 use gecko_bindings::sugar::ns_css_value::ToNsCssValue;
 use gecko_bindings::sugar::refptr::{RefPtr, UniqueRefPtr};
 use nsstring::nsString;
 use properties::longhands::font_language_override;
 use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard};
 use std::fmt::{self, Write};
 use std::str;
 use str::CssStringWriter;
 use values::computed::font::FamilyName;
 use values::generics::font::FontTag;
 use values::specified::font::{SpecifiedFontVariationSettings, SpecifiedFontFeatureSettings};
 
-/// A @font-face rule
-pub type FontFaceRule = RefPtr<nsCSSFontFaceRule>;
-
-impl ToNsCssValue for FamilyName {
+impl<'a> ToNsCssValue for &'a FamilyName {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
         nscssvalue.set_string_from_atom(&self.name)
     }
 }
 
 impl ToNsCssValue for font_weight::T {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
         nscssvalue.set_integer(self.0 as i32)
     }
 }
 
-impl ToNsCssValue for FontWeight {
+impl<'a> ToNsCssValue for &'a FontWeight {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
-        match self {
+        match *self {
             FontWeight::Normal =>
                 nscssvalue.set_enum(structs::NS_STYLE_FONT_WEIGHT_NORMAL as i32),
             FontWeight::Bold =>
                 nscssvalue.set_enum(structs::NS_STYLE_FONT_WEIGHT_BOLD as i32),
             FontWeight::Weight(weight) => nscssvalue.set_integer(weight.0 as i32),
         }
     }
 }
@@ -54,49 +51,49 @@ impl ToNsCssValue for FontWeight {
 impl ToNsCssValue for FontTag {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
         let mut raw = [0u8; 4];
         (&mut raw[..]).write_u32::<BigEndian>(self.0).unwrap();
         nscssvalue.set_string(str::from_utf8(&raw).unwrap());
     }
 }
 
-impl ToNsCssValue for SpecifiedFontFeatureSettings {
+impl<'a> ToNsCssValue for &'a SpecifiedFontFeatureSettings {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
         if self.0.is_empty() {
             nscssvalue.set_normal();
             return;
         }
 
-        nscssvalue.set_pair_list(self.0.into_iter().map(|entry| {
+        nscssvalue.set_pair_list(self.0.iter().map(|entry| {
             let mut index = nsCSSValue::null();
             index.set_integer(entry.value.value());
             (entry.tag.into(), index)
         }))
     }
 }
 
-impl ToNsCssValue for SpecifiedFontVariationSettings {
+impl<'a> ToNsCssValue for &'a SpecifiedFontVariationSettings {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
         if self.0.is_empty() {
             nscssvalue.set_normal();
             return;
         }
 
-        nscssvalue.set_pair_list(self.0.into_iter().map(|entry| {
+        nscssvalue.set_pair_list(self.0.iter().map(|entry| {
             let mut value = nsCSSValue::null();
             value.set_number(entry.value.into());
             (entry.tag.into(), value)
         }))
     }
 }
 
-impl ToNsCssValue for font_language_override::SpecifiedValue {
+impl<'a> ToNsCssValue for &'a font_language_override::SpecifiedValue {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
-        match self {
+        match *self {
             font_language_override::SpecifiedValue::Normal => nscssvalue.set_normal(),
             font_language_override::SpecifiedValue::Override(ref lang) => nscssvalue.set_string(&*lang),
             // This path is unreachable because the descriptor is only specified by the user.
             font_language_override::SpecifiedValue::System(_) => unreachable!(),
         }
     }
 }
 
@@ -104,19 +101,19 @@ macro_rules! map_enum {
     (
         $(
             $prop:ident {
                 $($servo:ident => $gecko:ident,)+
             }
         )+
     ) => {
         $(
-            impl ToNsCssValue for $prop::T {
+            impl<'a> ToNsCssValue for &'a $prop::T {
                 fn convert(self, nscssvalue: &mut nsCSSValue) {
-                    nscssvalue.set_enum(match self {
+                    nscssvalue.set_enum(match *self {
                         $( $prop::T::$servo => structs::$gecko as i32, )+
                     })
                 }
             }
         )+
     }
 }
 
@@ -135,105 +132,71 @@ map_enum! {
         SemiCondensed   => NS_FONT_STRETCH_SEMI_CONDENSED,
         SemiExpanded    => NS_FONT_STRETCH_SEMI_EXPANDED,
         Expanded        => NS_FONT_STRETCH_EXPANDED,
         ExtraExpanded   => NS_FONT_STRETCH_EXTRA_EXPANDED,
         UltraExpanded   => NS_FONT_STRETCH_ULTRA_EXPANDED,
     }
 }
 
-impl ToNsCssValue for Vec<Source> {
+impl<'a> ToNsCssValue for &'a Vec<Source> {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
         let src_len = self.iter().fold(0, |acc, src| {
             acc + match *src {
                 // Each format hint takes one position in the array of mSrc.
                 Source::Url(ref url) => url.format_hints.len() + 1,
                 Source::Local(_) => 1,
             }
         });
         let mut target_srcs =
             nscssvalue.set_array(src_len as i32).as_mut_slice().iter_mut();
         macro_rules! next { () => {
             target_srcs.next().expect("Length of target_srcs should be enough")
         } }
-        for src in self.into_iter() {
-            match src {
-                Source::Url(url) => {
+        for src in self.iter() {
+            match *src {
+                Source::Url(ref url) => {
                     next!().set_url(&url.url);
                     for hint in url.format_hints.iter() {
                         next!().set_font_format(&hint);
                     }
                 }
-                Source::Local(family) => {
+                Source::Local(ref family) => {
                     next!().set_local_font(&family.name);
                 }
             }
         }
         debug_assert!(target_srcs.next().is_none(), "Should have filled all slots");
     }
 }
 
-impl ToNsCssValue for Vec<UnicodeRange> {
+impl<'a> ToNsCssValue for &'a Vec<UnicodeRange> {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
         let target_ranges = nscssvalue
             .set_array((self.len() * 2) as i32)
             .as_mut_slice().chunks_mut(2);
         for (range, target) in self.iter().zip(target_ranges) {
             target[0].set_integer(range.start as i32);
             target[1].set_integer(range.end as i32);
         }
     }
 }
 
-impl ToNsCssValue for FontDisplay {
+impl<'a> ToNsCssValue for &'a FontDisplay {
     fn convert(self, nscssvalue: &mut nsCSSValue) {
-        nscssvalue.set_enum(match self {
+        nscssvalue.set_enum(match *self {
             FontDisplay::Auto => structs::NS_FONT_DISPLAY_AUTO,
             FontDisplay::Block => structs::NS_FONT_DISPLAY_BLOCK,
             FontDisplay::Swap => structs::NS_FONT_DISPLAY_SWAP,
             FontDisplay::Fallback => structs::NS_FONT_DISPLAY_FALLBACK,
             FontDisplay::Optional => structs::NS_FONT_DISPLAY_OPTIONAL,
         } as i32)
     }
 }
 
-impl FontFaceRule {
-    /// Ask Gecko to deep clone the nsCSSFontFaceRule, and then construct
-    /// a FontFaceRule object from it.
-    pub fn deep_clone_from_gecko(&self) -> FontFaceRule {
-        let result = unsafe {
-            UniqueRefPtr::from_addrefed(
-                bindings::Gecko_CSSFontFaceRule_Clone(self.get()))
-        };
-        result.get()
-    }
-}
-
-impl From<FontFaceRuleData> for FontFaceRule {
-    fn from(data: FontFaceRuleData) -> FontFaceRule {
-        let mut result = unsafe {
-            UniqueRefPtr::from_addrefed(bindings::Gecko_CSSFontFaceRule_Create(
-                data.source_location.line as u32, data.source_location.column as u32
-            ))
-        };
-        data.set_descriptors(&mut result.mDecl.mDescriptors);
-        result.get()
-    }
-}
-
-impl ToCssWithGuard for FontFaceRule {
-    fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
-        let mut css_text = nsString::new();
-        unsafe {
-            bindings::Gecko_CSSFontFaceRule_GetCssText(self.get(), &mut *css_text);
-        }
-        write!(dest, "{}", css_text)
-    }
-}
-
 /// A @counter-style rule
 pub type CounterStyleRule = RefPtr<nsCSSCounterStyleRule>;
 
 impl CounterStyleRule {
     /// Ask Gecko to deep clone the nsCSSCounterStyleRule, and then construct
     /// a CounterStyleRule object from it.
     pub fn deep_clone_from_gecko(&self) -> CounterStyleRule {
         let result = unsafe {
--- a/servo/components/style/gecko_bindings/sugar/refptr.rs
+++ b/servo/components/style/gecko_bindings/sugar/refptr.rs
@@ -255,18 +255,16 @@ macro_rules! impl_refcount {
             }
             unsafe fn release(&self) {
                 ::gecko_bindings::bindings::$release(self as *const _ as *mut _)
             }
         }
     );
 }
 
-impl_refcount!(::gecko_bindings::structs::nsCSSFontFaceRule,
-               Gecko_CSSFontFaceRule_AddRef, Gecko_CSSFontFaceRule_Release);
 impl_refcount!(::gecko_bindings::structs::nsCSSCounterStyleRule,
                Gecko_CSSCounterStyleRule_AddRef, Gecko_CSSCounterStyleRule_Release);
 
 // Companion of NS_DECL_THREADSAFE_FFI_REFCOUNTING.
 //
 // Gets you a free RefCounted impl implemented via FFI.
 macro_rules! impl_threadsafe_refcount {
     ($t:ty, $addref:ident, $release:ident) => (
--- a/servo/components/style/stylesheets/font_face_rule.rs
+++ b/servo/components/style/stylesheets/font_face_rule.rs
@@ -1,24 +1,7 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-// TODO(emilio): unify this, components/style/font_face.rs, and
-// components/style/gecko/rules.rs
 #![allow(missing_docs)]
 
-#[cfg(feature = "servo")]
 pub use font_face::FontFaceRuleData as FontFaceRule;
-#[cfg(feature = "gecko")]
-pub use gecko::rules::FontFaceRule;
-
-impl FontFaceRule {
-    #[cfg(feature = "servo")]
-    pub fn clone_conditionally_gecko_or_servo(&self) -> FontFaceRule {
-        self.clone()
-    }
-
-    #[cfg(feature = "gecko")]
-    pub fn clone_conditionally_gecko_or_servo(&self) -> FontFaceRule {
-        self.deep_clone_from_gecko()
-    }
-}
--- a/servo/components/style/stylesheets/mod.rs
+++ b/servo/components/style/stylesheets/mod.rs
@@ -301,18 +301,17 @@ impl DeepCloneWithLock for CssRule {
             },
             CssRule::Media(ref arc) => {
                 let rule = arc.read_with(guard);
                 CssRule::Media(Arc::new(
                     lock.wrap(rule.deep_clone_with_lock(lock, guard, params))))
             },
             CssRule::FontFace(ref arc) => {
                 let rule = arc.read_with(guard);
-                CssRule::FontFace(Arc::new(lock.wrap(
-                    rule.clone_conditionally_gecko_or_servo())))
+                CssRule::FontFace(Arc::new(lock.wrap(rule.clone())))
             },
             CssRule::FontFeatureValues(ref arc) => {
                 let rule = arc.read_with(guard);
                 CssRule::FontFeatureValues(Arc::new(lock.wrap(rule.clone())))
             },
             CssRule::CounterStyle(ref arc) => {
                 let rule = arc.read_with(guard);
                 CssRule::CounterStyle(Arc::new(lock.wrap(
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -1607,17 +1607,17 @@ pub struct ExtraStyleData {
     pub counter_styles: PrecomputedHashMap<Atom, Arc<Locked<CounterStyleRule>>>,
 
     /// A map of effective page rules.
     #[cfg(feature = "gecko")]
     pub pages: Vec<Arc<Locked<PageRule>>>,
 }
 
 // FIXME(emilio): This is kind of a lie, and relies on us not cloning
-// nsCSSFontFaceRules or nsCSSCounterStyleRules OMT (which we don't).
+// nsCSSCounterStyleRules OMT (which we don't).
 #[cfg(feature = "gecko")]
 unsafe impl Sync for ExtraStyleData {}
 #[cfg(feature = "gecko")]
 unsafe impl Send for ExtraStyleData {}
 
 #[cfg(feature = "gecko")]
 impl ExtraStyleData {
     /// Add the given @font-face rule.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use cssparser::{ParseErrorKind, Parser, ParserInput};
+use cssparser::{ParseErrorKind, Parser, ParserInput, SourceLocation};
 use cssparser::ToCss as ParserToCss;
 use env_logger::Builder;
 use malloc_size_of::MallocSizeOfOps;
 use selectors::NthIndexCache;
 use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
 use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
 use smallvec::SmallVec;
 use std::cell::RefCell;
@@ -36,16 +36,17 @@ use style::gecko::traversal::RecalcStyle
 use style::gecko::wrapper::{GeckoElement, GeckoNode};
 use style::gecko_bindings::bindings;
 use style::gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoElementBorrowedOrNull, RawGeckoNodeBorrowed};
 use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut};
 use style::gecko_bindings::bindings::{RawServoAuthorStyles, RawServoAuthorStylesBorrowed};
 use style::gecko_bindings::bindings::{RawServoAuthorStylesBorrowedMut, RawServoAuthorStylesOwned};
 use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
 use style::gecko_bindings::bindings::{RawServoDocumentRule, RawServoDocumentRuleBorrowed};
+use style::gecko_bindings::bindings::{RawServoFontFaceRuleBorrowed, RawServoFontFaceRuleStrong};
 use style::gecko_bindings::bindings::{RawServoFontFeatureValuesRule, RawServoFontFeatureValuesRuleBorrowed};
 use style::gecko_bindings::bindings::{RawServoImportRule, RawServoImportRuleBorrowed};
 use style::gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframeBorrowed, RawServoKeyframeStrong};
 use style::gecko_bindings::bindings::{RawServoKeyframesRule, RawServoKeyframesRuleBorrowed};
 use style::gecko_bindings::bindings::{RawServoMediaListBorrowed, RawServoMediaListStrong};
 use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed};
 use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
 use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
@@ -86,27 +87,28 @@ use style::gecko_bindings::bindings::nsC
 use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
 use style::gecko_bindings::bindings::nsTimingFunctionBorrowed;
 use style::gecko_bindings::bindings::nsTimingFunctionBorrowedMut;
 use style::gecko_bindings::structs;
 use style::gecko_bindings::structs::{CallerType, CSSPseudoElementType, CompositeOperation};
 use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
 use style::gecko_bindings::structs::{RawServoStyleRule, ComputedStyleStrong, RustString};
 use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetParsingMode, nsAtom, nsCSSPropertyID};
-use style::gecko_bindings::structs::{nsCSSFontDesc, nsCSSFontFaceRule, nsCSSCounterStyleRule};
+use style::gecko_bindings::structs::{nsCSSFontDesc, nsCSSCounterStyleRule};
 use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, PropertyValuePair};
 use style::gecko_bindings::structs::AtomArray;
 use style::gecko_bindings::structs::IterationCompositeOperation;
 use style::gecko_bindings::structs::MallocSizeOf as GeckoMallocSizeOf;
 use style::gecko_bindings::structs::OriginFlags;
 use style::gecko_bindings::structs::OriginFlags_Author;
 use style::gecko_bindings::structs::OriginFlags_User;
 use style::gecko_bindings::structs::OriginFlags_UserAgent;
 use style::gecko_bindings::structs::RawGeckoGfxMatrix4x4;
 use style::gecko_bindings::structs::RawGeckoPresContextOwned;
+use style::gecko_bindings::structs::RawServoFontFaceRule;
 use style::gecko_bindings::structs::RawServoSelectorList;
 use style::gecko_bindings::structs::RawServoSourceSizeList;
 use style::gecko_bindings::structs::SeenPtrs;
 use style::gecko_bindings::structs::ServoElementSnapshotTable;
 use style::gecko_bindings::structs::ServoStyleSetSizes;
 use style::gecko_bindings::structs::ServoTraversalFlags;
 use style::gecko_bindings::structs::StyleRuleInclusion;
 use style::gecko_bindings::structs::URLExtraData;
@@ -135,18 +137,18 @@ use style::properties::animated_properti
 use style::properties::animated_properties::compare_property_priority;
 use style::rule_cache::RuleCacheConditions;
 use style::rule_tree::{CascadeLevel, StrongRuleNode, StyleSource};
 use style::selector_parser::{PseudoElementCascadeType, SelectorImpl};
 use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
 use style::string_cache::{Atom, WeakAtom};
 use style::style_adjuster::StyleAdjuster;
 use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers, DocumentRule};
-use style::stylesheets::{FontFeatureValuesRule, ImportRule, KeyframesRule, MediaRule};
-use style::stylesheets::{NamespaceRule, Origin, OriginSet, PageRule, StyleRule};
+use style::stylesheets::{FontFaceRule, FontFeatureValuesRule, ImportRule, KeyframesRule};
+use style::stylesheets::{MediaRule, NamespaceRule, Origin, OriginSet, PageRule, StyleRule};
 use style::stylesheets::{StylesheetContents, SupportsRule};
 use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
 use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
 use style::stylesheets::supports_rule::parse_condition_or_declaration;
 use style::stylist::{add_size_of_ua_cache, AuthorStylesEnabled, RuleInclusion, Stylist};
 use style::thread_state;
 use style::timer::Timer;
 use style::traversal::DomTraversal;
@@ -1741,16 +1743,22 @@ impl_group_rule_funcs! { (Document, Docu
 }
 
 impl_basic_rule_funcs! { (FontFeatureValues, FontFeatureValuesRule, RawServoFontFeatureValuesRule),
     getter: Servo_CssRules_GetFontFeatureValuesRuleAt,
     debug: Servo_FontFeatureValuesRule_Debug,
     to_css: Servo_FontFeatureValuesRule_GetCssText,
 }
 
+impl_basic_rule_funcs! { (FontFace, FontFaceRule, RawServoFontFaceRule),
+    getter: Servo_CssRules_GetFontFaceRuleAt,
+    debug: Servo_FontFaceRule_Debug,
+    to_css: Servo_FontFaceRule_GetCssText,
+}
+
 macro_rules! impl_getter_for_embedded_rule {
     ($getter:ident: $name:ident -> $ty:ty) => {
         #[no_mangle]
         pub extern "C" fn $getter(rules: ServoCssRulesBorrowed, index: u32) -> *mut $ty
         {
             let global_style_data = &*GLOBAL_STYLE_DATA;
             let guard = global_style_data.shared_lock.read();
             let rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard);
@@ -1758,18 +1766,16 @@ macro_rules! impl_getter_for_embedded_ru
                 CssRule::$name(ref rule) => rule.read_with(&guard).get(),
                 _ => unreachable!(concat!(stringify!($getter), " should only be called on a ",
                                           stringify!($name), " rule")),
             }
         }
     }
 }
 
-impl_getter_for_embedded_rule!(Servo_CssRules_GetFontFaceRuleAt:
-                               FontFace -> nsCSSFontFaceRule);
 impl_getter_for_embedded_rule!(Servo_CssRules_GetCounterStyleRuleAt:
                                CounterStyle -> nsCSSCounterStyleRule);
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
     read_locked_arc(rule, |rule: &StyleRule| {
         rule.block.clone().into_strong()
     })
@@ -2179,16 +2185,265 @@ pub extern "C" fn Servo_FontFeatureValue
     result: *mut nsAString,
 ) {
     read_locked_arc(rule, |rule: &FontFeatureValuesRule| {
         rule.value_to_css(&mut CssWriter::new(unsafe { result.as_mut().unwrap() })).unwrap();
     })
 }
 
 #[no_mangle]
+pub extern "C" fn Servo_FontFaceRule_CreateEmpty() -> RawServoFontFaceRuleStrong {
+    let global_style_data = &*GLOBAL_STYLE_DATA;
+    // XXX This is not great. We should split FontFace descriptor data
+    // from the rule, so that we don't need to create the rule like this
+    // and the descriptor data itself can be hold in UniquePtr from the
+    // Gecko side. See bug 1450904.
+    Arc::new(global_style_data.shared_lock.wrap(FontFaceRule::empty(SourceLocation {
+        line: 0,
+        column: 0,
+    }))).into_strong()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_Clone(
+    rule: RawServoFontFaceRuleBorrowed,
+) -> RawServoFontFaceRuleStrong {
+    let clone = read_locked_arc(rule, |rule: &FontFaceRule| rule.clone());
+    let global_style_data = &*GLOBAL_STYLE_DATA;
+    Arc::new(global_style_data.shared_lock.wrap(clone)).into_strong()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_GetSourceLocation(
+    rule: RawServoFontFaceRuleBorrowed,
+    line: *mut u32,
+    column: *mut u32,
+) {
+    read_locked_arc(rule, |rule: &FontFaceRule| {
+        let location = rule.source_location;
+        *line.as_mut().unwrap() = location.line as u32;
+        *column.as_mut().unwrap() = location.column as u32;
+    });
+}
+
+macro_rules! apply_font_desc_list {
+    ($apply_macro:ident) => {
+        $apply_macro! {
+            valid: [
+                eCSSFontDesc_Family => family,
+                eCSSFontDesc_Style => style,
+                eCSSFontDesc_Weight => weight,
+                eCSSFontDesc_Stretch => stretch,
+                eCSSFontDesc_Src => sources,
+                eCSSFontDesc_UnicodeRange => unicode_range,
+                eCSSFontDesc_FontFeatureSettings => feature_settings,
+                eCSSFontDesc_FontVariationSettings => variation_settings,
+                eCSSFontDesc_FontLanguageOverride => language_override,
+                eCSSFontDesc_Display => display,
+            ]
+            invalid: [
+                eCSSFontDesc_UNKNOWN,
+                eCSSFontDesc_COUNT,
+            ]
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_Length(
+    rule: RawServoFontFaceRuleBorrowed,
+) -> u32 {
+    read_locked_arc(rule, |rule: &FontFaceRule| {
+        let mut result = 0;
+        macro_rules! count_values {
+            (
+                valid: [$($v_enum_name:ident => $field:ident,)*]
+                invalid: [$($i_enum_name:ident,)*]
+            ) => {
+                $(if rule.$field.is_some() {
+                    result += 1;
+                })*
+            }
+        }
+        apply_font_desc_list!(count_values);
+        result
+    })
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_IndexGetter(
+    rule: RawServoFontFaceRuleBorrowed,
+    index: u32,
+) -> nsCSSFontDesc {
+    read_locked_arc(rule, |rule: &FontFaceRule| {
+        let mut count = 0;
+        macro_rules! lookup_index {
+            (
+                valid: [$($v_enum_name:ident => $field:ident,)*]
+                invalid: [$($i_enum_name:ident,)*]
+            ) => {
+                $(if rule.$field.is_some() {
+                    count += 1;
+                    if count - 1 == index {
+                        return nsCSSFontDesc::$v_enum_name;
+                    }
+                })*
+            }
+        }
+        apply_font_desc_list!(lookup_index);
+        return nsCSSFontDesc::eCSSFontDesc_UNKNOWN;
+    })
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_GetDeclCssText(
+    rule: RawServoFontFaceRuleBorrowed,
+    result: *mut nsAString,
+) {
+    read_locked_arc(rule, |rule: &FontFaceRule| {
+        rule.decl_to_css(result.as_mut().unwrap()).unwrap();
+    })
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_GetDescriptor(
+    rule: RawServoFontFaceRuleBorrowed,
+    desc: nsCSSFontDesc,
+    result: nsCSSValueBorrowedMut,
+) {
+    read_locked_arc(rule, |rule: &FontFaceRule| {
+        macro_rules! to_css_value {
+            (
+                valid: [$($v_enum_name:ident => $field:ident,)*]
+                invalid: [$($i_enum_name:ident,)*]
+            ) => {
+                match desc {
+                    $(
+                        nsCSSFontDesc::$v_enum_name => {
+                            if let Some(ref value) = rule.$field {
+                                result.set_from(value);
+                            }
+                        }
+                    )*
+                    $(
+                        nsCSSFontDesc::$i_enum_name => {
+                            debug_assert!(false, "not a valid font descriptor");
+                        }
+                    )*
+                }
+            }
+        }
+        apply_font_desc_list!(to_css_value)
+    })
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_GetDescriptorCssText(
+    rule: RawServoFontFaceRuleBorrowed,
+    desc: nsCSSFontDesc,
+    result: *mut nsAString,
+) {
+    read_locked_arc(rule, |rule: &FontFaceRule| {
+        let mut writer = CssWriter::new(result.as_mut().unwrap());
+        macro_rules! to_css_text {
+            (
+                valid: [$($v_enum_name:ident => $field:ident,)*]
+                invalid: [$($i_enum_name:ident,)*]
+            ) => {
+                match desc {
+                    $(
+                        nsCSSFontDesc::$v_enum_name => {
+                            if let Some(ref value) = rule.$field {
+                                value.to_css(&mut writer).unwrap();
+                            }
+                        }
+                    )*
+                    $(
+                        nsCSSFontDesc::$i_enum_name => {
+                            debug_assert!(false, "not a valid font descriptor");
+                        }
+                    )*
+                }
+            }
+        }
+        apply_font_desc_list!(to_css_text)
+    })
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_SetDescriptor(
+    rule: RawServoFontFaceRuleBorrowed,
+    desc: nsCSSFontDesc,
+    value: *const nsACString,
+    data: *mut URLExtraData,
+) -> bool {
+    let value = value.as_ref().unwrap().as_str_unchecked();
+    let mut input = ParserInput::new(&value);
+    let mut parser = Parser::new(&mut input);
+    let url_data = RefPtr::from_ptr_ref(&data);
+    let context = ParserContext::new(
+        Origin::Author,
+        url_data,
+        Some(CssRuleType::FontFace),
+        ParsingMode::DEFAULT,
+        QuirksMode::NoQuirks,
+    );
+
+    write_locked_arc(rule, |rule: &mut FontFaceRule| {
+        macro_rules! to_css_text {
+            (
+                valid: [$($v_enum_name:ident => $field:ident,)*]
+                invalid: [$($i_enum_name:ident,)*]
+            ) => {
+                match desc {
+                    $(
+                        nsCSSFontDesc::$v_enum_name => {
+                            if let Ok(value) = parser.parse_entirely(|i| Parse::parse(&context, i)) {
+                                rule.$field = Some(value);
+                                true
+                            } else {
+                                false
+                            }
+                        }
+                    )*
+                    $(
+                        nsCSSFontDesc::$i_enum_name => {
+                            debug_assert!(false, "not a valid font descriptor");
+                            false
+                        }
+                    )*
+                }
+            }
+        }
+        apply_font_desc_list!(to_css_text)
+    })
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_FontFaceRule_ResetDescriptor(
+    rule: RawServoFontFaceRuleBorrowed,
+    desc: nsCSSFontDesc,
+) {
+    write_locked_arc(rule, |rule: &mut FontFaceRule| {
+        macro_rules! reset_desc {
+            (
+                valid: [$($v_enum_name:ident => $field:ident,)*]
+                invalid: [$($i_enum_name:ident,)*]
+            ) => {
+                match desc {
+                    $(nsCSSFontDesc::$v_enum_name => rule.$field = None,)*
+                    $(nsCSSFontDesc::$i_enum_name => debug_assert!(false, "not a valid font descriptor"),)*
+                }
+            }
+        }
+        apply_font_desc_list!(reset_desc)
+    })
+}
+
+#[no_mangle]
 pub unsafe extern "C" fn Servo_ComputedValues_GetForAnonymousBox(
     parent_style_or_null: ComputedStyleBorrowedOrNull,
     pseudo_tag: *mut nsAtom,
     raw_data: RawServoStyleSetBorrowed,
 ) -> ComputedStyleStrong {
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
     let guards = StylesheetGuards::same(&guard);
@@ -4325,35 +4580,32 @@ pub unsafe extern "C" fn Servo_StyleSet_
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_GetFontFaceRules(
     raw_data: RawServoStyleSetBorrowed,
     rules: RawGeckoFontFaceRuleListBorrowedMut,
 ) {
     let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     debug_assert_eq!(rules.len(), 0);
 
-    let global_style_data = &*GLOBAL_STYLE_DATA;
-    let guard = global_style_data.shared_lock.read();
-
     let len: u32 = data
         .stylist
         .iter_extra_data_origins()
         .map(|(d, _)| d.font_faces.len() as u32)
         .sum();
 
     // Reversed iterator because Gecko expects rules to appear sorted
     // UserAgent first, Author last.
     let font_face_iter = data
         .stylist
         .iter_extra_data_origins_rev()
         .flat_map(|(d, o)| d.font_faces.iter().zip(iter::repeat(o)));
 
     unsafe { rules.set_len(len) };
     for (src, dest) in font_face_iter.zip(rules.iter_mut()) {
-        dest.mRule = src.0.read_with(&guard).clone().forget();
+        dest.mRule.set_arc_leaky(src.0.clone());
         dest.mSheetType = src.1.into();
     }
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_GetCounterStyleRule(
     raw_data: RawServoStyleSetBorrowed,
     name: *mut nsAtom,
@@ -4843,93 +5095,16 @@ pub extern "C" fn Servo_ParseTransformIn
 
     let result = unsafe { result.as_mut() }.expect("not a valid matrix");
     let contain_3d = unsafe { contain_3d.as_mut() }.expect("not a valid bool");
     *result = m.to_row_major_array();
     *contain_3d = is_3d;
     true
 }
 
-// https://drafts.csswg.org/css-font-loading/#dom-fontface-fontface
-#[no_mangle]
-pub extern "C" fn Servo_ParseFontDescriptor(
-    desc_id: nsCSSFontDesc,
-    value: *const nsAString,
-    data: *mut URLExtraData,
-    result: nsCSSValueBorrowedMut,
-) -> bool {
-    use cssparser::UnicodeRange;
-    use self::nsCSSFontDesc::*;
-    use style::computed_values::{font_stretch, font_style};
-    use style::font_face::{FontDisplay, FontWeight, Source};
-    use style::properties::longhands::font_language_override;
-    use style::values::computed::font::FamilyName;
-    use style::values::specified::font::{SpecifiedFontFeatureSettings, SpecifiedFontVariationSettings};
-
-    let string = unsafe { (*value).to_string() };
-    let mut input = ParserInput::new(&string);
-    let mut parser = Parser::new(&mut input);
-    let url_data = unsafe { RefPtr::from_ptr_ref(&data) };
-    let context = ParserContext::new(
-        Origin::Author,
-        url_data,
-        Some(CssRuleType::FontFace),
-        ParsingMode::DEFAULT,
-        QuirksMode::NoQuirks,
-    );
-
-    macro_rules! parse_font_desc {
-        (
-            valid = [ $( $v_enum_name: ident / $t: ty, )* ]
-            invalid = [ $( $i_enum_name: ident, )* ]
-        ) => {
-            match desc_id {
-                $(
-                    $v_enum_name => {
-                        let f = match parser.parse_entirely(|i| <$t as Parse>::parse(&context, i)) {
-                            Ok(f) => f,
-                            Err(..) => return false,
-                        };
-                        result.set_from(f);
-                    },
-                )*
-                $(
-                    $i_enum_name => {
-                        debug_assert!(false, "$i_enum_name is not a valid font descriptor");
-                        return false;
-                    },
-                )*
-            }
-        }
-    }
-
-    // We implement the parser of each arm according to the implementation of @font-face rule.
-    // see component/style/font_face.rs for more detail.
-    parse_font_desc!(
-        valid = [
-            eCSSFontDesc_Family / FamilyName,
-            eCSSFontDesc_Style / font_style::T,
-            eCSSFontDesc_Weight / FontWeight,
-            eCSSFontDesc_Stretch / font_stretch::T,
-            eCSSFontDesc_Src / Vec<Source>,
-            eCSSFontDesc_UnicodeRange / Vec<UnicodeRange>,
-            eCSSFontDesc_FontFeatureSettings / SpecifiedFontFeatureSettings,
-            eCSSFontDesc_FontVariationSettings / SpecifiedFontVariationSettings,
-            eCSSFontDesc_FontLanguageOverride / font_language_override::SpecifiedValue,
-            eCSSFontDesc_Display / FontDisplay,
-        ]
-        invalid = [
-            eCSSFontDesc_UNKNOWN,
-            eCSSFontDesc_COUNT,
-        ]
-    );
-
-    true
-}
-
 #[no_mangle]
 pub extern "C" fn Servo_ParseFontShorthandForMatching(
     value: *const nsAString,
     data: *mut URLExtraData,
     family: *mut structs::RefPtr<structs::SharedFontList>,
     style: nsCSSValueBorrowedMut,
     stretch: nsCSSValueBorrowedMut,
     weight: nsCSSValueBorrowedMut
@@ -4957,21 +5132,21 @@ pub extern "C" fn Servo_ParseFontShortha
 
     // The system font is not acceptable, so we return false.
     let family = unsafe { &mut *family };
     match font.font_family {
         FontFamily::Values(list) => family.set_move(list.0),
         FontFamily::System(_) => return false,
     }
     style.set_from(match font.font_style {
-        font_style::SpecifiedValue::Keyword(kw) => kw,
+        font_style::SpecifiedValue::Keyword(ref kw) => kw,
         font_style::SpecifiedValue::System(_) => return false,
     });
     stretch.set_from(match font.font_stretch {
-        font_stretch::SpecifiedValue::Keyword(kw) => kw,
+        font_stretch::SpecifiedValue::Keyword(ref kw) => kw,
         font_stretch::SpecifiedValue::System(_) => return false,
     });
     match font.font_weight {
         FontWeight::Weight(w) => weight.set_from(w),
         FontWeight::Normal => weight.set_enum(structs::NS_STYLE_FONT_WEIGHT_NORMAL as i32),
         FontWeight::Bold => weight.set_enum(structs::NS_STYLE_FONT_WEIGHT_BOLD as i32),
         // Resolve relative font weights against the initial of font-weight
         // (normal, which is equivalent to 400).