servo: Merge #15900 - Process css animations for gecko (from hiikezoe:process-css-animations); r=heycam
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Thu, 09 Mar 2017 20:23:21 -0800
changeset 346893 8993adab1cd631a16d872a9c6db4ae3b2302cab5
parent 346892 f04955ea1c7a7acdfaa0cfbb1a0c1f19cfa1b1d1
child 346894 d6ab48ced3b85d7e8b2de403dc32bbeaaaae1870
push id31480
push usercbook@mozilla.com
push dateFri, 10 Mar 2017 10:37:06 +0000
treeherdermozilla-central@e18d3dd20e8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
milestone55.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 #15900 - Process css animations for gecko (from hiikezoe:process-css-animations); r=heycam <!-- Please describe your changes on the following line: --> This is a PR for https://bugzilla.mozilla.org/show_bug.cgi?id=1341985 . --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [X] These changes do not require tests because it's for stylo <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 63bed270734aee1956d1c1ec131aa1de9d5bb5a0
servo/components/script/layout_wrapper.rs
servo/components/style/build_gecko.rs
servo/components/style/context.rs
servo/components/style/dom.rs
servo/components/style/gecko/selector_parser.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/gecko_bindings/bindings.rs
servo/components/style/gecko_bindings/structs_debug.rs
servo/components/style/gecko_bindings/structs_release.rs
servo/components/style/matching.rs
servo/components/style/properties/gecko.mako.rs
servo/ports/geckolib/glue.rs
--- a/servo/components/script/layout_wrapper.rs
+++ b/servo/components/script/layout_wrapper.rs
@@ -441,16 +441,24 @@ impl<'le> TElement for ServoLayoutElemen
 
     unsafe fn set_selector_flags(&self, flags: ElementSelectorFlags) {
         self.element.insert_selector_flags(flags);
     }
 
     fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool {
         self.element.has_selector_flags(flags)
     }
+
+    fn update_animations(&self, _pseudo: Option<&PseudoElement>) {
+        panic!("this should be only called on gecko");
+    }
+
+    fn has_css_animations(&self, _pseudo: Option<&PseudoElement>) -> bool {
+        panic!("this should be only called on gecko");
+    }
 }
 
 impl<'le> PartialEq for ServoLayoutElement<'le> {
     fn eq(&self, other: &Self) -> bool {
         self.as_node() == other.as_node()
     }
 }
 
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -534,16 +534,17 @@ mod bindings {
             "RawGeckoKeyframeList",
             "RawGeckoComputedKeyframeValuesList",
             "RawGeckoNode",
             "RawGeckoAnimationValueList",
             "RawServoAnimationValue",
             "RawServoDeclarationBlock",
             "RawGeckoPresContext",
             "RawGeckoPresContextOwned",
+            "RawGeckoStyleAnimationList",
             "GeckoParserExtraData",
             "RefPtr",
             "ThreadSafeURIHolder",
             "ThreadSafePrincipalHolder",
             "CSSPseudoClassType",
             "TraversalRootBehavior",
             "FontFamilyList",
             "FontFamilyType",
@@ -631,16 +632,17 @@ mod bindings {
             ServoOwnedType { name: "ServoElementSnapshot", opaque: false },
         ];
         let servo_immutable_borrow_types = [
             "RawGeckoNode",
             "RawGeckoElement",
             "RawGeckoDocument",
             "RawServoDeclarationBlockStrong",
             "RawGeckoPresContext",
+            "RawGeckoStyleAnimationList",
         ];
         let servo_borrow_types = [
             "nsCSSValue",
             "RawGeckoAnimationValueList",
             "RawGeckoKeyframeList",
             "RawGeckoComputedKeyframeValuesList",
         ];
         for &ty in structs_types.iter() {
--- a/servo/components/style/context.rs
+++ b/servo/components/style/context.rs
@@ -10,16 +10,17 @@ use app_units::Au;
 use bloom::StyleBloom;
 use data::ElementData;
 use dom::{OpaqueNode, TNode, TElement, SendElement};
 use error_reporting::ParseErrorReporter;
 use euclid::Size2D;
 use matching::StyleSharingCandidateCache;
 use parking_lot::RwLock;
 use properties::ComputedValues;
+use selector_parser::PseudoElement;
 use selectors::matching::ElementSelectorFlags;
 use servo_config::opts;
 use std::collections::HashMap;
 use std::env;
 use std::fmt;
 use std::ops::Add;
 use std::sync::{Arc, Mutex};
 use std::sync::mpsc::Sender;
@@ -176,35 +177,48 @@ impl TraversalStatistics {
 
 /// A task to be run in sequential mode on the parent (non-worker) thread. This
 /// is used by the style system to queue up work which is not safe to do during
 /// the parallel traversal.
 pub enum SequentialTask<E: TElement> {
     /// Sets selector flags. This is used when we need to set flags on an
     /// element that we don't have exclusive access to (i.e. the parent).
     SetSelectorFlags(SendElement<E>, ElementSelectorFlags),
+
+    /// Marks that we need to create/remove/update CSS animations after the
+    /// first traversal.
+    UpdateAnimations(SendElement<E>, Option<PseudoElement>),
 }
 
 impl<E: TElement> SequentialTask<E> {
     /// Executes this task.
     pub fn execute(self) {
         use self::SequentialTask::*;
         debug_assert!(thread_state::get() == thread_state::LAYOUT);
         match self {
             SetSelectorFlags(el, flags) => {
                 unsafe { el.set_selector_flags(flags) };
             }
+            UpdateAnimations(el, pseudo) => {
+                unsafe { el.update_animations(pseudo.as_ref()) };
+            }
         }
     }
 
     /// Creates a task to set the selector flags on an element.
     pub fn set_selector_flags(el: E, flags: ElementSelectorFlags) -> Self {
         use self::SequentialTask::*;
         SetSelectorFlags(unsafe { SendElement::new(el) }, flags)
     }
+
+    /// Creates a task to update CSS Animations on a given (pseudo-)element.
+    pub fn update_animations(el: E, pseudo: Option<PseudoElement>) -> Self {
+        use self::SequentialTask::*;
+        UpdateAnimations(unsafe { SendElement::new(el) }, pseudo)
+    }
 }
 
 /// A thread-local style context.
 ///
 /// This context contains data that needs to be used during restyling, but is
 /// not required to be unique among worker threads, so we create one per worker
 /// thread in order to be able to mutate it without locking.
 pub struct ThreadLocalStyleContext<E: TElement> {
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -330,16 +330,23 @@ pub trait TElement : PartialEq + Debug +
     /// This is unsafe, like all the flag-setting methods, because it's only safe
     /// to call with exclusive access to the element. When setting flags on the
     /// parent during parallel traversal, we use SequentialTask to queue up the
     /// set to run after the threads join.
     unsafe fn set_selector_flags(&self, flags: ElementSelectorFlags);
 
     /// Returns true if the element has all the specified selector flags.
     fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool;
+
+    /// Creates a task to update CSS Animations on a given (pseudo-)element.
+    /// Note: Gecko only.
+    fn update_animations(&self, _pseudo: Option<&PseudoElement>);
+
+    /// Returns true if the element has a CSS animation.
+    fn has_css_animations(&self, _pseudo: Option<&PseudoElement>) -> bool;
 }
 
 /// TNode and TElement aren't Send because we want to be careful and explicit
 /// about our parallel traversal. However, there are certain situations
 /// (including but not limited to the traversal) where we need to send DOM
 /// objects to other threads.
 ///
 /// That's the reason why `SendNode` exists.
--- a/servo/components/style/gecko/selector_parser.rs
+++ b/servo/components/style/gecko/selector_parser.rs
@@ -2,21 +2,23 @@
  * 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/. */
 
 //! Gecko-specific bits for selector-parsing.
 
 use cssparser::ToCss;
 use element_state::ElementState;
 use gecko_bindings::structs::CSSPseudoClassType;
+use gecko_bindings::structs::nsIAtom;
 use selector_parser::{SelectorParser, PseudoElementCascadeType};
 use selector_parser::{attr_equals_selector_is_shareable, attr_exists_selector_is_shareable};
 use selectors::parser::AttrSelector;
 use std::borrow::Cow;
 use std::fmt;
+use std::ptr;
 use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
 
 /// A representation of a CSS pseudo-element.
 ///
 /// In Gecko, we represent pseudo-elements as plain `Atom`s.
 ///
 /// The boolean field represents whether this element is an anonymous box. This
 /// is just for convenience, instead of recomputing it.
@@ -106,16 +108,22 @@ impl PseudoElement {
                 }
             }}
         }
 
         include!("generated/gecko_pseudo_element_helper.rs");
 
         None
     }
+
+    /// Returns null or nsIAtom pointer corresponding to a given PseudoElement.
+    #[inline]
+    pub fn ns_atom_or_null_from_opt(pseudo: Option<&PseudoElement>) -> *mut nsIAtom {
+        pseudo.map(|p| p.as_atom().as_ptr()).unwrap_or(ptr::null_mut())
+    }
 }
 
 impl ToCss for PseudoElement {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         // FIXME: why does the atom contain one colon? Pseudo-element has two
         debug_assert!(self.0.as_slice().starts_with(&[b':' as u16]) &&
                       !self.0.as_slice().starts_with(&[b':' as u16, b':' as u16]));
         try!(dest.write_char(':'));
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -24,26 +24,29 @@ use gecko::selector_parser::{SelectorImp
 use gecko::snapshot_helpers;
 use gecko_bindings::bindings;
 use gecko_bindings::bindings::{Gecko_DropStyleChildrenIterator, Gecko_MaybeCreateStyleChildrenIterator};
 use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetLastChild, Gecko_GetNextStyleChild};
 use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement, Gecko_MatchesElement};
 use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink, Gecko_Namespace};
 use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
 use gecko_bindings::bindings::Gecko_ClassOrClassList;
+use gecko_bindings::bindings::Gecko_ElementHasCSSAnimations;
 use gecko_bindings::bindings::Gecko_GetAnimationRule;
 use gecko_bindings::bindings::Gecko_GetHTMLPresentationAttrDeclarationBlock;
 use gecko_bindings::bindings::Gecko_GetStyleAttrDeclarationBlock;
 use gecko_bindings::bindings::Gecko_GetStyleContext;
+use gecko_bindings::bindings::Gecko_UpdateAnimations;
 use gecko_bindings::structs;
 use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode};
 use gecko_bindings::structs::{nsIAtom, nsIContent, nsStyleContext};
 use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
 use gecko_bindings::structs::NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
 use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
+use gecko_bindings::sugar::ownership::HasArcFFI;
 use parking_lot::RwLock;
 use parser::ParserContextExtraData;
 use properties::{ComputedValues, parse_style_attribute};
 use properties::PropertyDeclarationBlock;
 use rule_tree::CascadeLevel as ServoCascadeLevel;
 use selector_parser::{ElementExt, Snapshot};
 use selectors::Element;
 use selectors::matching::ElementSelectorFlags;
@@ -411,17 +414,17 @@ impl<'le> TElement for GeckoElement<'le>
     }
 
     fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>> {
         let declarations = unsafe { Gecko_GetStyleAttrDeclarationBlock(self.0) };
         declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
     }
 
     fn get_animation_rules(&self, pseudo: Option<&PseudoElement>) -> AnimationRules {
-        let atom_ptr = pseudo.map(|p| p.as_atom().as_ptr()).unwrap_or(ptr::null_mut());
+        let atom_ptr = PseudoElement::ns_atom_or_null_from_opt(pseudo);
         unsafe {
             AnimationRules(
                 Gecko_GetAnimationRule(self.0, atom_ptr, CascadeLevel::Animations).into_arc_opt(),
                 Gecko_GetAnimationRule(self.0, atom_ptr, CascadeLevel::Transitions).into_arc_opt())
         }
     }
 
     fn get_state(&self) -> ElementState {
@@ -449,19 +452,18 @@ impl<'le> TElement for GeckoElement<'le>
                                        /* ignoreCase = */ false)
         }
     }
 
     fn existing_style_for_restyle_damage<'a>(&'a self,
                                              _existing_values: &'a Arc<ComputedValues>,
                                              pseudo: Option<&PseudoElement>)
                                              -> Option<&'a nsStyleContext> {
+        let atom_ptr = PseudoElement::ns_atom_or_null_from_opt(pseudo);
         unsafe {
-            let atom_ptr = pseudo.map(|p| p.as_atom().as_ptr())
-                                 .unwrap_or(ptr::null_mut());
             let context_ptr = Gecko_GetStyleContext(self.as_node().0, atom_ptr);
             context_ptr.as_ref()
         }
     }
 
     fn has_dirty_descendants(&self) -> bool {
         self.flags() & (NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0
     }
@@ -500,16 +502,47 @@ impl<'le> TElement for GeckoElement<'le>
         debug_assert!(!flags.is_empty());
         self.set_flags(selector_flags_to_node_flags(flags));
     }
 
     fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool {
         let node_flags = selector_flags_to_node_flags(flags);
         (self.flags() & node_flags) == node_flags
     }
+
+    fn update_animations(&self, pseudo: Option<&PseudoElement>) {
+        let atom_ptr = PseudoElement::ns_atom_or_null_from_opt(pseudo);
+
+        // We have to update animations even if the element has no computed style
+        // since it means the element is in a display:none subtree, we should destroy
+        // all CSS animations in display:none subtree.
+        let computed_data = self.borrow_data();
+        let computed_values = computed_data.as_ref().map(|d| d.styles().primary.values());
+        let computed_values_opt = computed_values.map(|v|
+            *HasArcFFI::arc_as_borrowed(v)
+        );
+
+        let parent_element = self.parent_element();
+        let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
+        let parent_values = parent_data.as_ref().map(|d| d.styles().primary.values());
+        let parent_values_opt = parent_values.map(|v|
+            *HasArcFFI::arc_as_borrowed(v)
+        );
+
+        unsafe {
+            Gecko_UpdateAnimations(self.0, atom_ptr,
+                                   computed_values_opt,
+                                   parent_values_opt);
+        }
+    }
+
+    fn has_css_animations(&self, pseudo: Option<&PseudoElement>) -> bool {
+        let atom_ptr = PseudoElement::ns_atom_or_null_from_opt(pseudo);
+        unsafe { Gecko_ElementHasCSSAnimations(self.0, atom_ptr) }
+    }
 }
 
 impl<'le> PartialEq for GeckoElement<'le> {
     fn eq(&self, other: &Self) -> bool {
         self.0 as *const _ == other.0 as *const _
     }
 }
 
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -9,16 +9,17 @@ use gecko_bindings::structs::RawGeckoEle
 use gecko_bindings::structs::RawGeckoKeyframeList;
 use gecko_bindings::structs::RawGeckoComputedKeyframeValuesList;
 use gecko_bindings::structs::RawGeckoNode;
 use gecko_bindings::structs::RawGeckoAnimationValueList;
 use gecko_bindings::structs::RawServoAnimationValue;
 use gecko_bindings::structs::RawServoDeclarationBlock;
 use gecko_bindings::structs::RawGeckoPresContext;
 use gecko_bindings::structs::RawGeckoPresContextOwned;
+use gecko_bindings::structs::RawGeckoStyleAnimationList;
 use gecko_bindings::structs::GeckoParserExtraData;
 use gecko_bindings::structs::RefPtr;
 use gecko_bindings::structs::ThreadSafeURIHolder;
 use gecko_bindings::structs::ThreadSafePrincipalHolder;
 use gecko_bindings::structs::CSSPseudoClassType;
 use gecko_bindings::structs::TraversalRootBehavior;
 use gecko_bindings::structs::FontFamilyList;
 use gecko_bindings::structs::FontFamilyType;
@@ -227,16 +228,18 @@ pub type RawGeckoNodeBorrowedOrNull<'a> 
 pub type RawGeckoElementBorrowed<'a> = &'a RawGeckoElement;
 pub type RawGeckoElementBorrowedOrNull<'a> = Option<&'a RawGeckoElement>;
 pub type RawGeckoDocumentBorrowed<'a> = &'a RawGeckoDocument;
 pub type RawGeckoDocumentBorrowedOrNull<'a> = Option<&'a RawGeckoDocument>;
 pub type RawServoDeclarationBlockStrongBorrowed<'a> = &'a RawServoDeclarationBlockStrong;
 pub type RawServoDeclarationBlockStrongBorrowedOrNull<'a> = Option<&'a RawServoDeclarationBlockStrong>;
 pub type RawGeckoPresContextBorrowed<'a> = &'a RawGeckoPresContext;
 pub type RawGeckoPresContextBorrowedOrNull<'a> = Option<&'a RawGeckoPresContext>;
+pub type RawGeckoStyleAnimationListBorrowed<'a> = &'a RawGeckoStyleAnimationList;
+pub type RawGeckoStyleAnimationListBorrowedOrNull<'a> = Option<&'a RawGeckoStyleAnimationList>;
 pub type nsCSSValueBorrowed<'a> = &'a nsCSSValue;
 pub type nsCSSValueBorrowedOrNull<'a> = Option<&'a nsCSSValue>;
 pub type nsCSSValueBorrowedMut<'a> = &'a mut nsCSSValue;
 pub type nsCSSValueBorrowedMutOrNull<'a> = Option<&'a mut nsCSSValue>;
 pub type RawGeckoAnimationValueListBorrowed<'a> = &'a RawGeckoAnimationValueList;
 pub type RawGeckoAnimationValueListBorrowedOrNull<'a> = Option<&'a RawGeckoAnimationValueList>;
 pub type RawGeckoAnimationValueListBorrowedMut<'a> = &'a mut RawGeckoAnimationValueList;
 pub type RawGeckoAnimationValueListBorrowedMutOrNull<'a> = Option<&'a mut RawGeckoAnimationValueList>;
@@ -527,16 +530,36 @@ extern "C" {
 extern "C" {
     pub fn Gecko_GetAnimationRule(aElement: RawGeckoElementBorrowed,
                                   aPseudoTag: *mut nsIAtom,
                                   aCascadeLevel:
                                       EffectCompositor_CascadeLevel)
      -> RawServoDeclarationBlockStrong;
 }
 extern "C" {
+    pub fn Gecko_StyleAnimationsEquals(arg1:
+                                           RawGeckoStyleAnimationListBorrowed,
+                                       arg2:
+                                           RawGeckoStyleAnimationListBorrowed)
+     -> bool;
+}
+extern "C" {
+    pub fn Gecko_UpdateAnimations(aElement: RawGeckoElementBorrowed,
+                                  aPseudoTagOrNull: *mut nsIAtom,
+                                  aComputedValues:
+                                      ServoComputedValuesBorrowedOrNull,
+                                  aParentComputedValues:
+                                      ServoComputedValuesBorrowedOrNull);
+}
+extern "C" {
+    pub fn Gecko_ElementHasCSSAnimations(aElement: RawGeckoElementBorrowed,
+                                         aPseudoTagOrNull: *mut nsIAtom)
+     -> bool;
+}
+extern "C" {
     pub fn Gecko_Atomize(aString: *const ::std::os::raw::c_char, aLength: u32)
      -> *mut nsIAtom;
 }
 extern "C" {
     pub fn Gecko_AddRefAtom(aAtom: *mut nsIAtom);
 }
 extern "C" {
     pub fn Gecko_ReleaseAtom(aAtom: *mut nsIAtom);
--- a/servo/components/style/gecko_bindings/structs_debug.rs
+++ b/servo/components/style/gecko_bindings/structs_debug.rs
@@ -6039,17 +6039,17 @@ pub mod root {
         }
         #[repr(i32)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum TraversalRootBehavior {
             Normal = 0,
             UnstyledChildrenOnly = 1,
         }
         pub type CSSPseudoElementTypeBase = u8;
-        pub const CSSPseudoElementType_AnonBox:
+        pub const CSSPseudoElementType_InheritingAnonBox:
                   root::mozilla::CSSPseudoElementType =
             CSSPseudoElementType::Count;
         #[repr(u8)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum CSSPseudoElementType {
             after = 0,
             before = 1,
             backdrop = 2,
@@ -6070,19 +6070,20 @@ pub mod root {
             mozRangeTrack = 17,
             mozRangeProgress = 18,
             mozRangeThumb = 19,
             mozMeterBar = 20,
             mozPlaceholder = 21,
             placeholder = 22,
             mozColorSwatch = 23,
             Count = 24,
-            XULTree = 25,
-            NotPseudo = 26,
-            MAX = 27,
+            NonInheritingAnonBox = 25,
+            XULTree = 26,
+            NotPseudo = 27,
+            MAX = 28,
         }
         pub mod widget {
             #[allow(unused_imports)]
             use self::super::super::super::root;
             #[repr(C)]
             #[derive(Debug, Copy, Clone)]
             pub struct IMEState([u8; 0]);
         }
@@ -7831,22 +7832,16 @@ pub mod root {
         #[derive(Debug, Copy, Clone)]
         pub struct pair<_T1, _T2> {
             pub first: _T1,
             pub second: _T2,
         }
         pub type pair_first_type<_T1> = _T1;
         pub type pair_second_type<_T2> = _T2;
         #[repr(C)]
-        pub struct atomic<_Tp> {
-            pub _base: (),
-            pub _phantom_0: ::std::marker::PhantomData<_Tp>,
-        }
-        pub type atomic___base = [u8; 0usize];
-        #[repr(C)]
         #[derive(Debug, Copy)]
         pub struct input_iterator_tag {
             pub _address: u8,
         }
         #[test]
         fn bindgen_test_layout_input_iterator_tag() {
             assert_eq!(::std::mem::size_of::<input_iterator_tag>() , 1usize ,
                        concat ! (
@@ -7855,284 +7850,269 @@ pub mod root {
                         , concat ! (
                         "Alignment of " , stringify ! ( input_iterator_tag )
                         ));
         }
         impl Clone for input_iterator_tag {
             fn clone(&self) -> Self { *self }
         }
         #[repr(C)]
-        #[derive(Debug, Copy)]
-        pub struct forward_iterator_tag {
-            pub _address: u8,
-        }
-        #[test]
-        fn bindgen_test_layout_forward_iterator_tag() {
-            assert_eq!(::std::mem::size_of::<forward_iterator_tag>() , 1usize
-                       , concat ! (
-                       "Size of: " , stringify ! ( forward_iterator_tag ) ));
-            assert_eq! (::std::mem::align_of::<forward_iterator_tag>() ,
-                        1usize , concat ! (
-                        "Alignment of " , stringify ! ( forward_iterator_tag )
-                        ));
-        }
-        impl Clone for forward_iterator_tag {
-            fn clone(&self) -> Self { *self }
-        }
-        #[repr(C)]
-        #[derive(Debug, Copy)]
-        pub struct bidirectional_iterator_tag {
-            pub _address: u8,
-        }
-        #[test]
-        fn bindgen_test_layout_bidirectional_iterator_tag() {
-            assert_eq!(::std::mem::size_of::<bidirectional_iterator_tag>() ,
-                       1usize , concat ! (
-                       "Size of: " , stringify ! ( bidirectional_iterator_tag
-                       ) ));
-            assert_eq! (::std::mem::align_of::<bidirectional_iterator_tag>() ,
-                        1usize , concat ! (
-                        "Alignment of " , stringify ! (
-                        bidirectional_iterator_tag ) ));
-        }
-        impl Clone for bidirectional_iterator_tag {
-            fn clone(&self) -> Self { *self }
-        }
-        #[repr(C)]
-        #[derive(Debug, Copy)]
-        pub struct random_access_iterator_tag {
-            pub _address: u8,
-        }
-        #[test]
-        fn bindgen_test_layout_random_access_iterator_tag() {
-            assert_eq!(::std::mem::size_of::<random_access_iterator_tag>() ,
-                       1usize , concat ! (
-                       "Size of: " , stringify ! ( random_access_iterator_tag
-                       ) ));
-            assert_eq! (::std::mem::align_of::<random_access_iterator_tag>() ,
-                        1usize , concat ! (
-                        "Alignment of " , stringify ! (
-                        random_access_iterator_tag ) ));
-        }
-        impl Clone for random_access_iterator_tag {
-            fn clone(&self) -> Self { *self }
-        }
-        #[repr(C)]
         #[derive(Debug, Copy, Clone)]
         pub struct iterator<_Category, _Tp, _Distance, _Pointer, _Reference> {
             pub _address: u8,
             pub _phantom_0: ::std::marker::PhantomData<_Category>,
             pub _phantom_1: ::std::marker::PhantomData<_Tp>,
             pub _phantom_2: ::std::marker::PhantomData<_Distance>,
             pub _phantom_3: ::std::marker::PhantomData<_Pointer>,
             pub _phantom_4: ::std::marker::PhantomData<_Reference>,
         }
+        pub type iterator_iterator_category<_Category> = _Category;
         pub type iterator_value_type<_Tp> = _Tp;
         pub type iterator_difference_type<_Distance> = _Distance;
         pub type iterator_pointer<_Pointer> = _Pointer;
         pub type iterator_reference<_Reference> = _Reference;
-        pub type iterator_iterator_category<_Category> = _Category;
-        #[repr(C)]
-        #[derive(Debug, Copy, Clone)]
-        pub struct __bit_const_reference<_Cp> {
-            pub __seg_: root::std::__bit_const_reference___storage_pointer<_Cp>,
-            pub __mask_: root::std::__bit_const_reference___storage_type<_Cp>,
-        }
-        pub type __bit_const_reference___storage_type<_Cp> = _Cp;
-        pub type __bit_const_reference___storage_pointer<_Cp> = _Cp;
-    }
-    pub type __int64_t = ::std::os::raw::c_longlong;
-    pub type __darwin_va_list = root::__builtin_va_list;
-    pub type __darwin_off_t = root::__int64_t;
-    pub type va_list = root::__darwin_va_list;
-    pub type fpos_t = root::__darwin_off_t;
-    #[repr(C)]
-    #[derive(Debug, Copy)]
-    pub struct __sbuf {
-        pub _base: *mut ::std::os::raw::c_uchar,
-        pub _size: ::std::os::raw::c_int,
-    }
-    #[test]
-    fn bindgen_test_layout___sbuf() {
-        assert_eq!(::std::mem::size_of::<__sbuf>() , 16usize , concat ! (
-                   "Size of: " , stringify ! ( __sbuf ) ));
-        assert_eq! (::std::mem::align_of::<__sbuf>() , 8usize , concat ! (
-                    "Alignment of " , stringify ! ( __sbuf ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sbuf ) ) . _base as * const _ as
-                    usize } , 0usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sbuf ) , "::" ,
-                    stringify ! ( _base ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sbuf ) ) . _size as * const _ as
-                    usize } , 8usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sbuf ) , "::" ,
-                    stringify ! ( _size ) ));
-    }
-    impl Clone for __sbuf {
-        fn clone(&self) -> Self { *self }
-    }
-    #[repr(C)]
-    #[derive(Debug, Copy, Clone)]
-    pub struct __sFILEX([u8; 0]);
-    #[repr(C)]
-    #[derive(Debug, Copy)]
-    pub struct __sFILE {
-        pub _p: *mut ::std::os::raw::c_uchar,
-        pub _r: ::std::os::raw::c_int,
-        pub _w: ::std::os::raw::c_int,
-        pub _flags: ::std::os::raw::c_short,
-        pub _file: ::std::os::raw::c_short,
-        pub _bf: root::__sbuf,
-        pub _lbfsize: ::std::os::raw::c_int,
-        pub _cookie: *mut ::std::os::raw::c_void,
-        pub _close: ::std::option::Option<unsafe extern "C" fn(arg1:
-                                                                   *mut ::std::os::raw::c_void)
-                                              -> ::std::os::raw::c_int>,
-        pub _read: ::std::option::Option<unsafe extern "C" fn(arg1:
-                                                                  *mut ::std::os::raw::c_void,
-                                                              arg2:
-                                                                  *mut ::std::os::raw::c_char,
-                                                              arg3:
-                                                                  ::std::os::raw::c_int)
-                                             -> ::std::os::raw::c_int>,
-        pub _seek: ::std::option::Option<unsafe extern "C" fn(arg1:
-                                                                  *mut ::std::os::raw::c_void,
-                                                              arg2:
-                                                                  root::fpos_t,
-                                                              arg3:
-                                                                  ::std::os::raw::c_int)
-                                             -> ::std::os::raw::c_longlong>,
-        pub _write: ::std::option::Option<unsafe extern "C" fn(arg1:
-                                                                   *mut ::std::os::raw::c_void,
-                                                               arg2:
-                                                                   *const ::std::os::raw::c_char,
-                                                               arg3:
-                                                                   ::std::os::raw::c_int)
-                                              -> ::std::os::raw::c_int>,
-        pub _ub: root::__sbuf,
-        pub _extra: *mut root::__sFILEX,
-        pub _ur: ::std::os::raw::c_int,
-        pub _ubuf: [::std::os::raw::c_uchar; 3usize],
-        pub _nbuf: [::std::os::raw::c_uchar; 1usize],
-        pub _lb: root::__sbuf,
-        pub _blksize: ::std::os::raw::c_int,
-        pub _offset: root::fpos_t,
-    }
-    #[test]
-    fn bindgen_test_layout___sFILE() {
-        assert_eq!(::std::mem::size_of::<__sFILE>() , 152usize , concat ! (
-                   "Size of: " , stringify ! ( __sFILE ) ));
-        assert_eq! (::std::mem::align_of::<__sFILE>() , 8usize , concat ! (
-                    "Alignment of " , stringify ! ( __sFILE ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _p as * const _ as
+        #[repr(C)]
+        #[derive(Debug)]
+        pub struct atomic<_Tp> {
+            pub _M_i: _Tp,
+        }
+        pub mod chrono {
+            #[allow(unused_imports)]
+            use self::super::super::super::root;
+        }
+    }
+    pub mod __gnu_cxx {
+        #[allow(unused_imports)]
+        use self::super::super::root;
+    }
+    pub type __off_t = ::std::os::raw::c_long;
+    pub type __off64_t = ::std::os::raw::c_long;
+    #[repr(C)]
+    #[derive(Debug, Copy)]
+    pub struct _IO_FILE {
+        pub _flags: ::std::os::raw::c_int,
+        pub _IO_read_ptr: *mut ::std::os::raw::c_char,
+        pub _IO_read_end: *mut ::std::os::raw::c_char,
+        pub _IO_read_base: *mut ::std::os::raw::c_char,
+        pub _IO_write_base: *mut ::std::os::raw::c_char,
+        pub _IO_write_ptr: *mut ::std::os::raw::c_char,
+        pub _IO_write_end: *mut ::std::os::raw::c_char,
+        pub _IO_buf_base: *mut ::std::os::raw::c_char,
+        pub _IO_buf_end: *mut ::std::os::raw::c_char,
+        pub _IO_save_base: *mut ::std::os::raw::c_char,
+        pub _IO_backup_base: *mut ::std::os::raw::c_char,
+        pub _IO_save_end: *mut ::std::os::raw::c_char,
+        pub _markers: *mut root::_IO_marker,
+        pub _chain: *mut root::_IO_FILE,
+        pub _fileno: ::std::os::raw::c_int,
+        pub _flags2: ::std::os::raw::c_int,
+        pub _old_offset: root::__off_t,
+        pub _cur_column: ::std::os::raw::c_ushort,
+        pub _vtable_offset: ::std::os::raw::c_char,
+        pub _shortbuf: [::std::os::raw::c_char; 1usize],
+        pub _lock: *mut root::_IO_lock_t,
+        pub _offset: root::__off64_t,
+        pub __pad1: *mut ::std::os::raw::c_void,
+        pub __pad2: *mut ::std::os::raw::c_void,
+        pub __pad3: *mut ::std::os::raw::c_void,
+        pub __pad4: *mut ::std::os::raw::c_void,
+        pub __pad5: usize,
+        pub _mode: ::std::os::raw::c_int,
+        pub _unused2: [::std::os::raw::c_char; 20usize],
+    }
+    #[test]
+    fn bindgen_test_layout__IO_FILE() {
+        assert_eq!(::std::mem::size_of::<_IO_FILE>() , 216usize , concat ! (
+                   "Size of: " , stringify ! ( _IO_FILE ) ));
+        assert_eq! (::std::mem::align_of::<_IO_FILE>() , 8usize , concat ! (
+                    "Alignment of " , stringify ! ( _IO_FILE ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _flags as * const _ as
                     usize } , 0usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _p ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _r as * const _ as
-                    usize } , 8usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _r ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _w as * const _ as
-                    usize } , 12usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _w ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _flags as * const _ as
-                    usize } , 16usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
                     stringify ! ( _flags ) ));
         assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _file as * const _ as
-                    usize } , 18usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _file ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _bf as * const _ as
-                    usize } , 24usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _bf ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _lbfsize as * const _
-                    as usize } , 40usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _lbfsize ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _cookie as * const _ as
-                    usize } , 48usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _cookie ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _close as * const _ as
-                    usize } , 56usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _close ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _read as * const _ as
-                    usize } , 64usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _read ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _seek as * const _ as
-                    usize } , 72usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _seek ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _write as * const _ as
-                    usize } , 80usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _write ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _ub as * const _ as
-                    usize } , 88usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _ub ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _extra as * const _ as
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_read_ptr as *
+                    const _ as usize } , 8usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_read_ptr ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_read_end as *
+                    const _ as usize } , 16usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_read_end ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_read_base as *
+                    const _ as usize } , 24usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_read_base ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_write_base as *
+                    const _ as usize } , 32usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_write_base ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_write_ptr as *
+                    const _ as usize } , 40usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_write_ptr ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_write_end as *
+                    const _ as usize } , 48usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_write_end ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_buf_base as *
+                    const _ as usize } , 56usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_buf_base ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_buf_end as * const
+                    _ as usize } , 64usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_buf_end ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_save_base as *
+                    const _ as usize } , 72usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_save_base ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_backup_base as *
+                    const _ as usize } , 80usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_backup_base ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _IO_save_end as *
+                    const _ as usize } , 88usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _IO_save_end ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _markers as * const _
+                    as usize } , 96usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _markers ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _chain as * const _ as
                     usize } , 104usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _extra ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _ur as * const _ as
-                    usize } , 112usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _ur ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _ubuf as * const _ as
-                    usize } , 116usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _ubuf ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _nbuf as * const _ as
-                    usize } , 119usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _nbuf ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _lb as * const _ as
-                    usize } , 120usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _lb ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _blksize as * const _
-                    as usize } , 136usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
-                    stringify ! ( _blksize ) ));
-        assert_eq! (unsafe {
-                    & ( * ( 0 as * const __sFILE ) ) . _offset as * const _ as
-                    usize } , 144usize , concat ! (
-                    "Alignment of field: " , stringify ! ( __sFILE ) , "::" ,
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _chain ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _fileno as * const _
+                    as usize } , 112usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _fileno ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _flags2 as * const _
+                    as usize } , 116usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _flags2 ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _old_offset as * const
+                    _ as usize } , 120usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _old_offset ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _cur_column as * const
+                    _ as usize } , 128usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _cur_column ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _vtable_offset as *
+                    const _ as usize } , 130usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _vtable_offset ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _shortbuf as * const _
+                    as usize } , 131usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _shortbuf ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _lock as * const _ as
+                    usize } , 136usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _lock ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _offset as * const _
+                    as usize } , 144usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
                     stringify ! ( _offset ) ));
-    }
-    impl Clone for __sFILE {
-        fn clone(&self) -> Self { *self }
-    }
-    pub type FILE = root::__sFILE;
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . __pad1 as * const _ as
+                    usize } , 152usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( __pad1 ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . __pad2 as * const _ as
+                    usize } , 160usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( __pad2 ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . __pad3 as * const _ as
+                    usize } , 168usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( __pad3 ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . __pad4 as * const _ as
+                    usize } , 176usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( __pad4 ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . __pad5 as * const _ as
+                    usize } , 184usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( __pad5 ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _mode as * const _ as
+                    usize } , 192usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _mode ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_FILE ) ) . _unused2 as * const _
+                    as usize } , 196usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_FILE ) , "::" ,
+                    stringify ! ( _unused2 ) ));
+    }
+    impl Clone for _IO_FILE {
+        fn clone(&self) -> Self { *self }
+    }
+    pub type FILE = root::_IO_FILE;
+    pub type va_list = root::__builtin_va_list;
+    pub type _IO_lock_t = ::std::os::raw::c_void;
+    #[repr(C)]
+    #[derive(Debug, Copy)]
+    pub struct _IO_marker {
+        pub _next: *mut root::_IO_marker,
+        pub _sbuf: *mut root::_IO_FILE,
+        pub _pos: ::std::os::raw::c_int,
+    }
+    #[test]
+    fn bindgen_test_layout__IO_marker() {
+        assert_eq!(::std::mem::size_of::<_IO_marker>() , 24usize , concat ! (
+                   "Size of: " , stringify ! ( _IO_marker ) ));
+        assert_eq! (::std::mem::align_of::<_IO_marker>() , 8usize , concat ! (
+                    "Alignment of " , stringify ! ( _IO_marker ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_marker ) ) . _next as * const _
+                    as usize } , 0usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_marker ) , "::"
+                    , stringify ! ( _next ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_marker ) ) . _sbuf as * const _
+                    as usize } , 8usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_marker ) , "::"
+                    , stringify ! ( _sbuf ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const _IO_marker ) ) . _pos as * const _ as
+                    usize } , 16usize , concat ! (
+                    "Alignment of field: " , stringify ! ( _IO_marker ) , "::"
+                    , stringify ! ( _pos ) ));
+    }
+    impl Clone for _IO_marker {
+        fn clone(&self) -> Self { *self }
+    }
     /**
  * MozRefCountType is Mozilla's reference count type.
  *
  * We use the same type to represent the refcount of RefCounted objects
  * as well, in order to be able to use the leak detection facilities
  * that are implemented by XPCOM.
  *
  * Note that this type is not in the mozilla namespace so that it is
@@ -15329,73 +15309,73 @@ pub mod root {
                     & ( * ( 0 as * const nsNodeWeakReference ) ) . mNode as *
                     const _ as usize } , 24usize , concat ! (
                     "Alignment of field: " , stringify ! ( nsNodeWeakReference
                     ) , "::" , stringify ! ( mNode ) ));
     }
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsDOMMutationObserver([u8; 0]);
-    pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_LISTENERMANAGER;
-    pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_PROPERTIES;
-    pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_ANONYMOUS_ROOT;
-    pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
-    pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS_ROOT;
-    pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_FORCE_XBL_BINDINGS;
-    pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_MAY_BE_IN_BINDING_MNGR;
-    pub const NODE_IS_EDITABLE: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_EDITABLE;
-    pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS;
-    pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_IN_SHADOW_TREE;
-    pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_EMPTY_SELECTOR;
-    pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_SLOW_SELECTOR;
-    pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_EDGE_CHILD_SELECTOR;
-    pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS;
-    pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_ALL_SELECTOR_FLAGS;
-    pub const NODE_NEEDS_FRAME: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_NEEDS_FRAME;
-    pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_DESCENDANTS_NEED_FRAMES;
-    pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_ACCESSKEY;
-    pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_DIRECTION_RTL;
-    pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_DIRECTION_LTR;
-    pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_ALL_DIRECTION_FLAGS;
-    pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_CHROME_ONLY_ACCESS;
-    pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS;
-    pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1;
-    pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_2;
-    pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1;
-    pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_TYPE_SPECIFIC_BITS_OFFSET;
-    #[repr(u32)]
-    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-    pub enum _bindgen_ty_28 {
+    pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_LISTENERMANAGER;
+    pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_PROPERTIES;
+    pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_IS_ANONYMOUS_ROOT;
+    pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
+    pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_IS_NATIVE_ANONYMOUS_ROOT;
+    pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_FORCE_XBL_BINDINGS;
+    pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_MAY_BE_IN_BINDING_MNGR;
+    pub const NODE_IS_EDITABLE: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_IS_EDITABLE;
+    pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_IS_NATIVE_ANONYMOUS;
+    pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_IS_IN_SHADOW_TREE;
+    pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_EMPTY_SELECTOR;
+    pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_SLOW_SELECTOR;
+    pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_EDGE_CHILD_SELECTOR;
+    pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS;
+    pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_ALL_SELECTOR_FLAGS;
+    pub const NODE_NEEDS_FRAME: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_NEEDS_FRAME;
+    pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_DESCENDANTS_NEED_FRAMES;
+    pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_ACCESSKEY;
+    pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_DIRECTION_RTL;
+    pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_HAS_DIRECTION_LTR;
+    pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_ALL_DIRECTION_FLAGS;
+    pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_CHROME_ONLY_ACCESS;
+    pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS;
+    pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_SHARED_RESTYLE_BIT_1;
+    pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_SHARED_RESTYLE_BIT_2;
+    pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_SHARED_RESTYLE_BIT_1;
+    pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_118 =
+        _bindgen_ty_118::NODE_TYPE_SPECIFIC_BITS_OFFSET;
+    #[repr(u32)]
+    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+    pub enum _bindgen_ty_118 {
         NODE_HAS_LISTENERMANAGER = 4,
         NODE_HAS_PROPERTIES = 8,
         NODE_IS_ANONYMOUS_ROOT = 16,
         NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE = 32,
         NODE_IS_NATIVE_ANONYMOUS_ROOT = 64,
         NODE_FORCE_XBL_BINDINGS = 128,
         NODE_MAY_BE_IN_BINDING_MNGR = 256,
         NODE_IS_EDITABLE = 512,
@@ -20164,16 +20144,31 @@ pub mod root {
         eCSSTokenSerialization_Symbol_Question = 18,
         eCSSTokenSerialization_Symbol_Assorted = 19,
         eCSSTokenSerialization_Symbol_Equals = 20,
         eCSSTokenSerialization_Symbol_Bar = 21,
         eCSSTokenSerialization_Symbol_Slash = 22,
         eCSSTokenSerialization_Symbol_Asterisk = 23,
         eCSSTokenSerialization_Other = 24,
     }
+    /**
+ * An array of objects, similar to AutoTArray<T,1> but which is memmovable. It
+ * always has length >= 1.
+ */
+    #[repr(C)]
+    #[derive(Debug)]
+    pub struct nsStyleAutoArray<T> {
+        pub mFirstElement: T,
+        pub mOtherElements: root::nsTArray<T>,
+    }
+    #[repr(i32)]
+    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+    pub enum nsStyleAutoArray_WithSingleInitialElement {
+        WITH_SINGLE_INITIAL_ELEMENT = 0,
+    }
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsCSSSelector([u8; 0]);
     pub const nsChangeHint_nsChangeHint_Empty: root::nsChangeHint =
         nsChangeHint(0);
     pub const nsChangeHint_nsChangeHint_RepaintFrame: root::nsChangeHint =
         nsChangeHint(1);
     pub const nsChangeHint_nsChangeHint_NeedReflow: root::nsChangeHint =
@@ -22572,31 +22567,16 @@ pub mod root {
         assert_eq! (::std::mem::align_of::<nsStyleColor>() , 4usize , concat !
                     ( "Alignment of " , stringify ! ( nsStyleColor ) ));
         assert_eq! (unsafe {
                     & ( * ( 0 as * const nsStyleColor ) ) . mColor as * const
                     _ as usize } , 0usize , concat ! (
                     "Alignment of field: " , stringify ! ( nsStyleColor ) ,
                     "::" , stringify ! ( mColor ) ));
     }
-    /**
- * An array of objects, similar to AutoTArray<T,1> but which is memmovable. It
- * always has length >= 1.
- */
-    #[repr(C)]
-    #[derive(Debug)]
-    pub struct nsStyleAutoArray<T> {
-        pub mFirstElement: T,
-        pub mOtherElements: root::nsTArray<T>,
-    }
-    #[repr(i32)]
-    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-    pub enum nsStyleAutoArray_WithSingleInitialElement {
-        WITH_SINGLE_INITIAL_ELEMENT = 0,
-    }
     #[repr(C)]
     #[derive(Debug)]
     pub struct nsStyleImageLayers {
         pub mAttachmentCount: u32,
         pub mClipCount: u32,
         pub mOriginCount: u32,
         pub mRepeatCount: u32,
         pub mPositionXCount: u32,
@@ -25505,16 +25485,18 @@ pub mod root {
     pub type RawGeckoPresContext = root::nsPresContext;
     pub type RawGeckoKeyframeList = root::nsTArray<root::mozilla::Keyframe>;
     pub type RawGeckoComputedKeyframeValuesList =
         root::nsTArray<root::nsTArray<root::mozilla::PropertyStyleAnimationValuePair>>;
     pub type RawGeckoAnimationValueList =
         root::nsTArray<root::mozilla::PropertyStyleAnimationValuePair>;
     pub type RawServoAnimationValueBorrowedList =
         root::nsTArray<*const root::RawServoAnimationValue>;
+    pub type RawGeckoStyleAnimationList =
+        root::nsStyleAutoArray<root::mozilla::StyleAnimation>;
     pub type RawGeckoNodeBorrowed = *const root::RawGeckoNode;
     pub type RawGeckoNodeBorrowedOrNull = *const root::RawGeckoNode;
     pub type RawGeckoElementBorrowed = *const root::RawGeckoElement;
     pub type RawGeckoElementBorrowedOrNull = *const root::RawGeckoElement;
     pub type RawGeckoDocumentBorrowed = *const root::RawGeckoDocument;
     pub type RawGeckoDocumentBorrowedOrNull = *const root::RawGeckoDocument;
     pub type RawGeckoPresContextOwned = *mut root::RawGeckoPresContext;
     pub type RawGeckoPresContextBorrowed = *const root::RawGeckoPresContext;
@@ -25523,16 +25505,18 @@ pub mod root {
         *mut root::RawGeckoAnimationValueList;
     pub type RawServoAnimationValueBorrowedListBorrowed =
         *const root::RawServoAnimationValueBorrowedList;
     pub type RawGeckoKeyframeListBorrowedMut =
         *mut root::RawGeckoKeyframeList;
     pub type RawGeckoKeyframeListBorrowed = *const root::RawGeckoKeyframeList;
     pub type RawGeckoComputedKeyframeValuesListBorrowedMut =
         *mut root::RawGeckoComputedKeyframeValuesList;
+    pub type RawGeckoStyleAnimationListBorrowed =
+        *const root::RawGeckoStyleAnimationList;
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct ElementRuleProcessorData([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct PseudoElementRuleProcessorData([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
--- a/servo/components/style/gecko_bindings/structs_release.rs
+++ b/servo/components/style/gecko_bindings/structs_release.rs
@@ -5879,17 +5879,17 @@ pub mod root {
         }
         #[repr(i32)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum TraversalRootBehavior {
             Normal = 0,
             UnstyledChildrenOnly = 1,
         }
         pub type CSSPseudoElementTypeBase = u8;
-        pub const CSSPseudoElementType_AnonBox:
+        pub const CSSPseudoElementType_InheritingAnonBox:
                   root::mozilla::CSSPseudoElementType =
             CSSPseudoElementType::Count;
         #[repr(u8)]
         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
         pub enum CSSPseudoElementType {
             after = 0,
             before = 1,
             backdrop = 2,
@@ -5910,19 +5910,20 @@ pub mod root {
             mozRangeTrack = 17,
             mozRangeProgress = 18,
             mozRangeThumb = 19,
             mozMeterBar = 20,
             mozPlaceholder = 21,
             placeholder = 22,
             mozColorSwatch = 23,
             Count = 24,
-            XULTree = 25,
-            NotPseudo = 26,
-            MAX = 27,
+            NonInheritingAnonBox = 25,
+            XULTree = 26,
+            NotPseudo = 27,
+            MAX = 28,
         }
         pub mod widget {
             #[allow(unused_imports)]
             use self::super::super::super::root;
             #[repr(C)]
             #[derive(Debug, Copy, Clone)]
             pub struct IMEState([u8; 0]);
         }
@@ -7644,22 +7645,16 @@ pub mod root {
         #[derive(Debug, Copy, Clone)]
         pub struct pair<_T1, _T2> {
             pub first: _T1,
             pub second: _T2,
         }
         pub type pair_first_type<_T1> = _T1;
         pub type pair_second_type<_T2> = _T2;
         #[repr(C)]
-        pub struct atomic<_Tp> {
-            pub _base: (),
-            pub _phantom_0: ::std::marker::PhantomData<_Tp>,
-        }
-        pub type atomic___base = [u8; 0usize];
-        #[repr(C)]
         #[derive(Debug, Copy)]
         pub struct input_iterator_tag {
             pub _address: u8,
         }
         #[test]
         fn bindgen_test_layout_input_iterator_tag() {
             assert_eq!(::std::mem::size_of::<input_iterator_tag>() , 1usize ,
                        concat ! (
@@ -7668,97 +7663,41 @@ pub mod root {
                         , concat ! (
                         "Alignment of " , stringify ! ( input_iterator_tag )
                         ));
         }
         impl Clone for input_iterator_tag {
             fn clone(&self) -> Self { *self }
         }
         #[repr(C)]
-        #[derive(Debug, Copy)]
-        pub struct forward_iterator_tag {
-            pub _address: u8,
-        }
-        #[test]
-        fn bindgen_test_layout_forward_iterator_tag() {
-            assert_eq!(::std::mem::size_of::<forward_iterator_tag>() , 1usize
-                       , concat ! (
-                       "Size of: " , stringify ! ( forward_iterator_tag ) ));
-            assert_eq! (::std::mem::align_of::<forward_iterator_tag>() ,
-                        1usize , concat ! (
-                        "Alignment of " , stringify ! ( forward_iterator_tag )
-                        ));
-        }
-        impl Clone for forward_iterator_tag {
-            fn clone(&self) -> Self { *self }
-        }
-        #[repr(C)]
-        #[derive(Debug, Copy)]
-        pub struct bidirectional_iterator_tag {
-            pub _address: u8,
-        }
-        #[test]
-        fn bindgen_test_layout_bidirectional_iterator_tag() {
-            assert_eq!(::std::mem::size_of::<bidirectional_iterator_tag>() ,
-                       1usize , concat ! (
-                       "Size of: " , stringify ! ( bidirectional_iterator_tag
-                       ) ));
-            assert_eq! (::std::mem::align_of::<bidirectional_iterator_tag>() ,
-                        1usize , concat ! (
-                        "Alignment of " , stringify ! (
-                        bidirectional_iterator_tag ) ));
-        }
-        impl Clone for bidirectional_iterator_tag {
-            fn clone(&self) -> Self { *self }
-        }
-        #[repr(C)]
-        #[derive(Debug, Copy)]
-        pub struct random_access_iterator_tag {
-            pub _address: u8,
-        }
-        #[test]
-        fn bindgen_test_layout_random_access_iterator_tag() {
-            assert_eq!(::std::mem::size_of::<random_access_iterator_tag>() ,
-                       1usize , concat ! (
-                       "Size of: " , stringify ! ( random_access_iterator_tag
-                       ) ));
-            assert_eq! (::std::mem::align_of::<random_access_iterator_tag>() ,
-                        1usize , concat ! (
-                        "Alignment of " , stringify ! (
-                        random_access_iterator_tag ) ));
-        }
-        impl Clone for random_access_iterator_tag {
-            fn clone(&self) -> Self { *self }
-        }
-        #[repr(C)]
         #[derive(Debug, Copy, Clone)]
         pub struct iterator<_Category, _Tp, _Distance, _Pointer, _Reference> {
             pub _address: u8,
             pub _phantom_0: ::std::marker::PhantomData<_Category>,
             pub _phantom_1: ::std::marker::PhantomData<_Tp>,
             pub _phantom_2: ::std::marker::PhantomData<_Distance>,
             pub _phantom_3: ::std::marker::PhantomData<_Pointer>,
             pub _phantom_4: ::std::marker::PhantomData<_Reference>,
         }
+        pub type iterator_iterator_category<_Category> = _Category;
         pub type iterator_value_type<_Tp> = _Tp;
         pub type iterator_difference_type<_Distance> = _Distance;
         pub type iterator_pointer<_Pointer> = _Pointer;
         pub type iterator_reference<_Reference> = _Reference;
-        pub type iterator_iterator_category<_Category> = _Category;
-        #[repr(C)]
-        #[derive(Debug, Copy, Clone)]
-        pub struct __bit_const_reference<_Cp> {
-            pub __seg_: root::std::__bit_const_reference___storage_pointer<_Cp>,
-            pub __mask_: root::std::__bit_const_reference___storage_type<_Cp>,
-        }
-        pub type __bit_const_reference___storage_type<_Cp> = _Cp;
-        pub type __bit_const_reference___storage_pointer<_Cp> = _Cp;
-    }
-    pub type __darwin_va_list = root::__builtin_va_list;
-    pub type va_list = root::__darwin_va_list;
+        #[repr(C)]
+        #[derive(Debug)]
+        pub struct atomic<_Tp> {
+            pub _M_i: _Tp,
+        }
+    }
+    pub mod __gnu_cxx {
+        #[allow(unused_imports)]
+        use self::super::super::root;
+    }
+    pub type va_list = root::__builtin_va_list;
     /**
  * MozRefCountType is Mozilla's reference count type.
  *
  * We use the same type to represent the refcount of RefCounted objects
  * as well, in order to be able to use the leak detection facilities
  * that are implemented by XPCOM.
  *
  * Note that this type is not in the mozilla namespace so that it is
@@ -14797,73 +14736,73 @@ pub mod root {
                     & ( * ( 0 as * const nsNodeWeakReference ) ) . mNode as *
                     const _ as usize } , 16usize , concat ! (
                     "Alignment of field: " , stringify ! ( nsNodeWeakReference
                     ) , "::" , stringify ! ( mNode ) ));
     }
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsDOMMutationObserver([u8; 0]);
-    pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_LISTENERMANAGER;
-    pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_PROPERTIES;
-    pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_ANONYMOUS_ROOT;
-    pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
-    pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS_ROOT;
-    pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_FORCE_XBL_BINDINGS;
-    pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_MAY_BE_IN_BINDING_MNGR;
-    pub const NODE_IS_EDITABLE: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_EDITABLE;
-    pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS;
-    pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_IN_SHADOW_TREE;
-    pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_EMPTY_SELECTOR;
-    pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_SLOW_SELECTOR;
-    pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_EDGE_CHILD_SELECTOR;
-    pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS;
-    pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_ALL_SELECTOR_FLAGS;
-    pub const NODE_NEEDS_FRAME: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_NEEDS_FRAME;
-    pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_DESCENDANTS_NEED_FRAMES;
-    pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_ACCESSKEY;
-    pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_DIRECTION_RTL;
-    pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_HAS_DIRECTION_LTR;
-    pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_ALL_DIRECTION_FLAGS;
-    pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_CHROME_ONLY_ACCESS;
-    pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS;
-    pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1;
-    pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_2;
-    pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1;
-    pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_28 =
-        _bindgen_ty_28::NODE_TYPE_SPECIFIC_BITS_OFFSET;
-    #[repr(u32)]
-    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-    pub enum _bindgen_ty_28 {
+    pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_LISTENERMANAGER;
+    pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_PROPERTIES;
+    pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_IS_ANONYMOUS_ROOT;
+    pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
+    pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_IS_NATIVE_ANONYMOUS_ROOT;
+    pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_FORCE_XBL_BINDINGS;
+    pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_MAY_BE_IN_BINDING_MNGR;
+    pub const NODE_IS_EDITABLE: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_IS_EDITABLE;
+    pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_IS_NATIVE_ANONYMOUS;
+    pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_IS_IN_SHADOW_TREE;
+    pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_EMPTY_SELECTOR;
+    pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_SLOW_SELECTOR;
+    pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_EDGE_CHILD_SELECTOR;
+    pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS;
+    pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_ALL_SELECTOR_FLAGS;
+    pub const NODE_NEEDS_FRAME: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_NEEDS_FRAME;
+    pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_DESCENDANTS_NEED_FRAMES;
+    pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_ACCESSKEY;
+    pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_DIRECTION_RTL;
+    pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_HAS_DIRECTION_LTR;
+    pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_ALL_DIRECTION_FLAGS;
+    pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_CHROME_ONLY_ACCESS;
+    pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS;
+    pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_1;
+    pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_2;
+    pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_1;
+    pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_105 =
+        _bindgen_ty_105::NODE_TYPE_SPECIFIC_BITS_OFFSET;
+    #[repr(u32)]
+    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+    pub enum _bindgen_ty_105 {
         NODE_HAS_LISTENERMANAGER = 4,
         NODE_HAS_PROPERTIES = 8,
         NODE_IS_ANONYMOUS_ROOT = 16,
         NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE = 32,
         NODE_IS_NATIVE_ANONYMOUS_ROOT = 64,
         NODE_FORCE_XBL_BINDINGS = 128,
         NODE_MAY_BE_IN_BINDING_MNGR = 256,
         NODE_IS_EDITABLE = 512,
@@ -19564,16 +19503,31 @@ pub mod root {
         eCSSTokenSerialization_Symbol_Question = 18,
         eCSSTokenSerialization_Symbol_Assorted = 19,
         eCSSTokenSerialization_Symbol_Equals = 20,
         eCSSTokenSerialization_Symbol_Bar = 21,
         eCSSTokenSerialization_Symbol_Slash = 22,
         eCSSTokenSerialization_Symbol_Asterisk = 23,
         eCSSTokenSerialization_Other = 24,
     }
+    /**
+ * An array of objects, similar to AutoTArray<T,1> but which is memmovable. It
+ * always has length >= 1.
+ */
+    #[repr(C)]
+    #[derive(Debug)]
+    pub struct nsStyleAutoArray<T> {
+        pub mFirstElement: T,
+        pub mOtherElements: root::nsTArray<T>,
+    }
+    #[repr(i32)]
+    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+    pub enum nsStyleAutoArray_WithSingleInitialElement {
+        WITH_SINGLE_INITIAL_ELEMENT = 0,
+    }
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsCSSSelector([u8; 0]);
     pub const nsChangeHint_nsChangeHint_Empty: root::nsChangeHint =
         nsChangeHint(0);
     pub const nsChangeHint_nsChangeHint_RepaintFrame: root::nsChangeHint =
         nsChangeHint(1);
     pub const nsChangeHint_nsChangeHint_NeedReflow: root::nsChangeHint =
@@ -21971,31 +21925,16 @@ pub mod root {
         assert_eq! (::std::mem::align_of::<nsStyleColor>() , 4usize , concat !
                     ( "Alignment of " , stringify ! ( nsStyleColor ) ));
         assert_eq! (unsafe {
                     & ( * ( 0 as * const nsStyleColor ) ) . mColor as * const
                     _ as usize } , 0usize , concat ! (
                     "Alignment of field: " , stringify ! ( nsStyleColor ) ,
                     "::" , stringify ! ( mColor ) ));
     }
-    /**
- * An array of objects, similar to AutoTArray<T,1> but which is memmovable. It
- * always has length >= 1.
- */
-    #[repr(C)]
-    #[derive(Debug)]
-    pub struct nsStyleAutoArray<T> {
-        pub mFirstElement: T,
-        pub mOtherElements: root::nsTArray<T>,
-    }
-    #[repr(i32)]
-    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-    pub enum nsStyleAutoArray_WithSingleInitialElement {
-        WITH_SINGLE_INITIAL_ELEMENT = 0,
-    }
     #[repr(C)]
     #[derive(Debug)]
     pub struct nsStyleImageLayers {
         pub mAttachmentCount: u32,
         pub mClipCount: u32,
         pub mOriginCount: u32,
         pub mRepeatCount: u32,
         pub mPositionXCount: u32,
@@ -24904,16 +24843,18 @@ pub mod root {
     pub type RawGeckoPresContext = root::nsPresContext;
     pub type RawGeckoKeyframeList = root::nsTArray<root::mozilla::Keyframe>;
     pub type RawGeckoComputedKeyframeValuesList =
         root::nsTArray<root::nsTArray<root::mozilla::PropertyStyleAnimationValuePair>>;
     pub type RawGeckoAnimationValueList =
         root::nsTArray<root::mozilla::PropertyStyleAnimationValuePair>;
     pub type RawServoAnimationValueBorrowedList =
         root::nsTArray<*const root::RawServoAnimationValue>;
+    pub type RawGeckoStyleAnimationList =
+        root::nsStyleAutoArray<root::mozilla::StyleAnimation>;
     pub type RawGeckoNodeBorrowed = *const root::RawGeckoNode;
     pub type RawGeckoNodeBorrowedOrNull = *const root::RawGeckoNode;
     pub type RawGeckoElementBorrowed = *const root::RawGeckoElement;
     pub type RawGeckoElementBorrowedOrNull = *const root::RawGeckoElement;
     pub type RawGeckoDocumentBorrowed = *const root::RawGeckoDocument;
     pub type RawGeckoDocumentBorrowedOrNull = *const root::RawGeckoDocument;
     pub type RawGeckoPresContextOwned = *mut root::RawGeckoPresContext;
     pub type RawGeckoPresContextBorrowed = *const root::RawGeckoPresContext;
@@ -24922,16 +24863,18 @@ pub mod root {
         *mut root::RawGeckoAnimationValueList;
     pub type RawServoAnimationValueBorrowedListBorrowed =
         *const root::RawServoAnimationValueBorrowedList;
     pub type RawGeckoKeyframeListBorrowedMut =
         *mut root::RawGeckoKeyframeList;
     pub type RawGeckoKeyframeListBorrowed = *const root::RawGeckoKeyframeList;
     pub type RawGeckoComputedKeyframeValuesListBorrowedMut =
         *mut root::RawGeckoComputedKeyframeValuesList;
+    pub type RawGeckoStyleAnimationListBorrowed =
+        *const root::RawGeckoStyleAnimationList;
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct ElementRuleProcessorData([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct PseudoElementRuleProcessorData([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy, Clone)]
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -551,75 +551,122 @@ trait PrivateMatchMethods: TElement {
 
         cascade_info.finish(&self.as_node());
         values
     }
 
     /// Computes values and damage for the primary or pseudo style of an element,
     /// setting them on the ElementData.
     fn cascade_primary_or_pseudo<'a>(&self,
-                                     context: &StyleContext<Self>,
+                                     context: &mut StyleContext<Self>,
                                      data: &mut ElementData,
                                      pseudo: Option<&PseudoElement>,
                                      possibly_expired_animations: &mut Vec<PropertyAnimation>,
                                      booleans: CascadeBooleans) {
         // Collect some values.
-        let shared_context = context.shared;
         let (mut styles, restyle) = data.styles_and_restyle_mut();
         let mut primary_style = &mut styles.primary;
         let pseudos = &mut styles.pseudos;
         let mut pseudo_style = pseudo.map(|p| (p, pseudos.get_mut(p).unwrap()));
         let mut old_values =
             pseudo_style.as_mut().map_or_else(|| primary_style.values.take(), |p| p.1.values.take());
 
         // Compute the new values.
         let mut new_values = self.cascade_internal(context, primary_style,
                                                    &mut pseudo_style, &booleans);
 
         // Handle animations.
-        if booleans.animate && cfg!(feature = "servo") {
-            if let Some(ref mut old) = old_values {
-                self.update_animations_for_cascade(shared_context, old,
-                                                   possibly_expired_animations);
-            }
-
-            let new_animations_sender = &context.thread_local.new_animations_sender;
-            let this_opaque = self.as_node().opaque();
-            // Trigger any present animations if necessary.
-            animation::maybe_start_animations(&shared_context,
-                                              new_animations_sender,
-                                              this_opaque, &new_values);
-
-            // Trigger transitions if necessary. This will reset `new_values` back
-            // to its old value if it did trigger a transition.
-            if let Some(ref values) = old_values {
-                animation::start_transitions_if_applicable(
-                    new_animations_sender,
-                    this_opaque,
-                    self.as_node().to_unsafe(),
-                    &**values,
-                    &mut new_values,
-                    &shared_context.timer,
-                    &possibly_expired_animations);
-            }
+        if booleans.animate {
+            self.process_animations(context,
+                                    &mut old_values,
+                                    &mut new_values,
+                                    pseudo,
+                                    possibly_expired_animations);
         }
 
         // Accumulate restyle damage.
         if let Some(old) = old_values {
             self.accumulate_damage(restyle.unwrap(), &old, &new_values, pseudo);
         }
 
         // Set the new computed values.
         if let Some((_, ref mut style)) = pseudo_style {
             style.values = Some(new_values);
         } else {
             primary_style.values = Some(new_values);
         }
     }
 
+    #[cfg(feature = "gecko")]
+    fn process_animations(&self,
+                          context: &mut StyleContext<Self>,
+                          old_values: &mut Option<Arc<ComputedValues>>,
+                          new_values: &mut Arc<ComputedValues>,
+                          pseudo: Option<&PseudoElement>,
+                          _possibly_expired_animations: &mut Vec<PropertyAnimation>) {
+        let ref new_box_style = new_values.get_box();
+        let has_new_animation_style = new_box_style.animation_name_count() >= 1 &&
+                                      new_box_style.animation_name_at(0).0.len() != 0;
+        let has_animations = self.has_css_animations(pseudo);
+
+        let needs_update_animations =
+            old_values.as_ref().map_or(has_new_animation_style, |ref old| {
+                let ref old_box_style = old.get_box();
+                let old_display_style = old_box_style.clone_display();
+                let new_display_style = new_box_style.clone_display();
+                // FIXME: Bug 1344581: We still need to compare keyframe rules.
+                !old_box_style.animations_equals(&new_box_style) ||
+                 (old_display_style == display::T::none &&
+                  new_display_style != display::T::none &&
+                  has_new_animation_style) ||
+                 (old_display_style != display::T::none &&
+                  new_display_style == display::T::none &&
+                  has_animations)
+            });
+        if needs_update_animations {
+            let task = SequentialTask::update_animations(self.as_node().as_element().unwrap(),
+                                                         pseudo.cloned());
+            context.thread_local.tasks.push(task);
+        }
+    }
+
+    #[cfg(feature = "servo")]
+    fn process_animations(&self,
+                          context: &mut StyleContext<Self>,
+                          old_values: &mut Option<Arc<ComputedValues>>,
+                          new_values: &mut Arc<ComputedValues>,
+                          _pseudo: Option<&PseudoElement>,
+                          possibly_expired_animations: &mut Vec<PropertyAnimation>) {
+        let shared_context = context.shared;
+        if let Some(ref mut old) = *old_values {
+            self.update_animations_for_cascade(shared_context, old,
+                                               possibly_expired_animations);
+        }
+
+        let new_animations_sender = &context.thread_local.new_animations_sender;
+        let this_opaque = self.as_node().opaque();
+        // Trigger any present animations if necessary.
+        animation::maybe_start_animations(&shared_context,
+                                          new_animations_sender,
+                                          this_opaque, &new_values);
+
+        // Trigger transitions if necessary. This will reset `new_values` back
+        // to its old value if it did trigger a transition.
+        if let Some(ref values) = *old_values {
+            animation::start_transitions_if_applicable(
+                new_animations_sender,
+                this_opaque,
+                self.as_node().to_unsafe(),
+                &**values,
+                new_values,
+                &shared_context.timer,
+                &possibly_expired_animations);
+        }
+    }
+
     /// Computes and applies non-redundant damage.
     #[cfg(feature = "gecko")]
     fn accumulate_damage(&self,
                          restyle: &mut RestyleData,
                          old_values: &Arc<ComputedValues>,
                          new_values: &Arc<ComputedValues>,
                          pseudo: Option<&PseudoElement>) {
         // If an ancestor is already getting reconstructed by Gecko's top-down
@@ -1005,17 +1052,17 @@ pub trait MatchMethods : TElement {
                 }
             }
         }
     }
 
     /// Run the CSS cascade and compute values for the element, potentially
     /// starting any new transitions or animations.
     fn cascade_element(&self,
-                       context: &StyleContext<Self>,
+                       context: &mut StyleContext<Self>,
                        mut data: &mut AtomicRefMut<ElementData>,
                        primary_is_shareable: bool)
     {
         let mut possibly_expired_animations = vec![];
 
         // Cascade the primary style.
         self.cascade_primary_or_pseudo(context, data, None,
                                        &mut possibly_expired_animations,
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1790,16 +1790,20 @@ fn static_assert() {
         self.gecko.mTransitionPropertyCount = count;
 
         for (index, transition) in self.gecko.mTransitions.iter_mut().enumerate().take(count as usize) {
             transition.mProperty = other.gecko.mTransitions[index].mProperty;
         }
     }
     ${impl_transition_count('property', 'Property')}
 
+    pub fn animations_equals(&self, other: &Self) -> bool {
+        unsafe { bindings::Gecko_StyleAnimationsEquals(&self.gecko.mAnimations, &other.gecko.mAnimations) }
+    }
+
     pub fn set_animation_name(&mut self, v: longhands::animation_name::computed_value::T) {
         use nsstring::nsCString;
 
         debug_assert!(!v.0.is_empty());
         unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
 
         self.gecko.mAnimationNameCount = v.0.len() as u32;
         for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1426,17 +1426,17 @@ pub extern "C" fn Servo_AssertTreeIsClea
 pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSetBorrowed,
                                                       name: *const nsACString,
                                                       timing_function: *const nsTimingFunction,
                                                       style: ServoComputedValuesBorrowed,
                                                       keyframes: RawGeckoKeyframeListBorrowedMut) -> bool {
     use style::gecko_bindings::structs::Keyframe;
     use style::properties::LonghandIdSet;
 
-    let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
+    let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     let name = unsafe { Atom::from(name.as_ref().unwrap().as_str_unchecked()) };
     let style_timing_function = unsafe { timing_function.as_ref().unwrap() };
     let style = ComputedValues::as_arc(&style);
 
     if let Some(ref animation) = data.stylist.animations().get(&name) {
        for step in &animation.steps {
           // Override timing_function if the keyframe has animation-timing-function.
           let timing_function = if let Some(val) = step.get_animation_timing_function() {