Bug 1317209 - Part 1: Introduce ServoAnimationRule and implement uncompute FFI. r=heycam draft
authorBoris Chiou <boris.chiou@gmail.com>
Tue, 24 Jan 2017 15:19:18 +0800
changeset 466067 6a3d7fc2521f80dc0c35592226d4574dbfa28901
parent 465014 1f671f8dfcc624408b29ec3ad9b9cc9bee8203e8
child 466068 1e2415841e68b85fac380a87640f847572ed35d2
push id42776
push userbmo:boris.chiou@gmail.com
push dateWed, 25 Jan 2017 06:34:29 +0000
reviewersheycam
bugs1317209
milestone53.0a1
Bug 1317209 - Part 1: Introduce ServoAnimationRule and implement uncompute FFI. r=heycam 1. Introduce ServoAnimationRule, which is an equivalent of AnimValuesStyleRule. 2. Wrap ServoAnimationRule and AnimValuesStyleRule into a struct, and use it as the parameter of Animation::ComposeStyle and KeyframeEffectReadOnly::ComposeStyle. 3. Uncompute the RawServoAnimationValues in ServoAnimationRule when we need it. MozReview-Commit-ID: HahXDYBCAhH
dom/animation/Animation.cpp
dom/animation/Animation.h
dom/animation/AnimationRule.h
dom/animation/EffectCompositor.cpp
dom/animation/EffectSet.h
dom/animation/KeyframeEffectReadOnly.cpp
dom/animation/KeyframeEffectReadOnly.h
dom/animation/ServoAnimationRule.cpp
dom/animation/ServoAnimationRule.h
dom/animation/moz.build
layout/style/ServoBindingList.h
layout/style/ServoBindingTypes.h
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -8,16 +8,17 @@
 #include "AnimationUtils.h"
 #include "mozilla/dom/AnimationBinding.h"
 #include "mozilla/dom/AnimationPlaybackEvent.h"
 #include "mozilla/dom/DocumentTimeline.h"
 #include "mozilla/AnimationTarget.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/AsyncEventDispatcher.h" // For AsyncEventDispatcher
 #include "mozilla/Maybe.h" // For Maybe
+#include "mozilla/AnimationRule.h" // For AnimationRule
 #include "nsAnimationManager.h" // For CSSAnimation
 #include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch
 #include "nsIDocument.h" // For nsIDocument
 #include "nsIPresShell.h" // For nsIPresShell
 #include "nsThreadUtils.h" // For nsRunnableMethod and nsRevocableEventPtr
 #include "nsTransitionManager.h" // For CSSTransition
 #include "PendingAnimationTracker.h" // For PendingAnimationTracker
 
@@ -911,17 +912,17 @@ Animation::HasLowerCompositeOrderThan(co
              "Animation indices should be unique");
 
   // 3. Finally, generic animations sort by their position in the global
   // animation array.
   return mAnimationIndex < aOther.mAnimationIndex;
 }
 
 void
-Animation::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
+Animation::ComposeStyle(AnimationRule& aStyleRule,
                         const nsCSSPropertyIDSet& aPropertiesToSkip)
 {
   if (!mEffect) {
     return;
   }
 
   // In order to prevent flicker, there are a few cases where we want to use
   // a different time for rendering that would otherwise be returned by
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -35,17 +35,17 @@
 
 struct JSContext;
 class nsCSSPropertyIDSet;
 class nsIDocument;
 class nsIFrame;
 
 namespace mozilla {
 
-class AnimValuesStyleRule;
+struct AnimationRule;
 
 namespace dom {
 
 class CSSAnimation;
 class CSSTransition;
 
 class Animation
   : public DOMEventTargetHelper
@@ -312,17 +312,17 @@ public:
    */
   bool CanThrottle() const;
   /**
    * Updates |aStyleRule| with the animation values of this animation's effect,
    * if any.
    * Any properties contained in |aPropertiesToSkip| will not be added or
    * updated in |aStyleRule|.
    */
-  void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
+  void ComposeStyle(AnimationRule& aStyleRule,
                     const nsCSSPropertyIDSet& aPropertiesToSkip);
 
   void NotifyEffectTimingUpdated();
   void NotifyGeometricAnimationsStartingThisFrame();
 
   /**
    * Used by subclasses to synchronously queue a cancel event in situations
    * where the Animation may have been cancelled.
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationRule.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_AnimationRule_h
+#define mozilla_AnimationRule_h
+
+#include "AnimValuesStyleRule.h"
+#include "ServoAnimationRule.h"
+
+namespace mozilla {
+
+// A wrapper for animation rules.
+struct AnimationRule
+{
+  RefPtr<AnimValuesStyleRule> mGecko;
+  RefPtr<ServoAnimationRule> mServo;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_AnimationRule_h
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -415,17 +415,17 @@ EffectCompositor::GetAnimationRule(dom::
   }
 #endif
 
   EffectSet* effectSet = EffectSet::GetEffectSet(aElement, aPseudoType);
   if (!effectSet) {
     return nullptr;
   }
 
-  return effectSet->AnimationRule(aCascadeLevel);
+  return effectSet->AnimationRule(aCascadeLevel).mGecko;
 }
 
 /* static */ dom::Element*
 EffectCompositor::GetElementToRestyle(dom::Element* aElement,
                                       CSSPseudoElementType aPseudoType)
 {
   if (aPseudoType == CSSPseudoElementType::NotPseudo) {
     return aElement;
@@ -680,29 +680,28 @@ EffectCompositor::ComposeAnimationRule(d
 
   // Get a list of effects sorted by composite order.
   nsTArray<KeyframeEffectReadOnly*> sortedEffectList(effects->Count());
   for (KeyframeEffectReadOnly* effect : *effects) {
     sortedEffectList.AppendElement(effect);
   }
   sortedEffectList.Sort(EffectCompositeOrderComparator());
 
-  RefPtr<AnimValuesStyleRule>& animationRule =
-    effects->AnimationRule(aCascadeLevel);
-  animationRule = nullptr;
+  AnimationRule& animRule = effects->AnimationRule(aCascadeLevel);
+  animRule.mGecko = nullptr;
 
   // If multiple animations affect the same property, animations with higher
   // composite order (priority) override or add or animations with lower
   // priority except properties in propertiesToSkip.
   const nsCSSPropertyIDSet& propertiesToSkip =
     aCascadeLevel == CascadeLevel::Animations
     ? effects->PropertiesForAnimationsLevel().Invert()
     : effects->PropertiesForAnimationsLevel();
   for (KeyframeEffectReadOnly* effect : sortedEffectList) {
-    effect->GetAnimation()->ComposeStyle(animationRule, propertiesToSkip);
+    effect->GetAnimation()->ComposeStyle(animRule, propertiesToSkip);
   }
 
   MOZ_ASSERT(effects == EffectSet::GetEffectSet(aElement, aPseudoType),
              "EffectSet should not change while composing style");
 
   effects->UpdateAnimationRuleRefreshTime(aCascadeLevel, aRefreshTime);
 }
 
--- a/dom/animation/EffectSet.h
+++ b/dom/animation/EffectSet.h
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #ifndef mozilla_EffectSet_h
 #define mozilla_EffectSet_h
 
-#include "mozilla/AnimValuesStyleRule.h"
+#include "mozilla/AnimationRule.h" // For AnimationRule
 #include "mozilla/DebugOnly.h"
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/KeyframeEffectReadOnly.h"
 #include "nsHashKeys.h" // For nsPtrHashKey
 #include "nsTHashtable.h" // For nsTHashtable
 
@@ -158,18 +158,18 @@ public:
 #ifdef DEBUG
   bool IsBeingEnumerated() const { return mActiveIterators != 0; }
 #endif
 
   bool IsEmpty() const { return mEffects.IsEmpty(); }
 
   size_t Count() const { return mEffects.Count(); }
 
-  RefPtr<AnimValuesStyleRule>& AnimationRule(EffectCompositor::CascadeLevel
-                                             aCascadeLevel)
+  struct AnimationRule&
+  AnimationRule(EffectCompositor::CascadeLevel aCascadeLevel)
   {
     return mAnimationRule[aCascadeLevel];
   }
 
   const TimeStamp& AnimationRuleRefreshTime(EffectCompositor::CascadeLevel
                                               aCascadeLevel) const
   {
     return mAnimationRuleRefreshTime[aCascadeLevel];
@@ -227,17 +227,17 @@ private:
   // These style rules contain the style data for currently animating
   // values.  They only match when styling with animation.  When we
   // style without animation, we need to not use them so that we can
   // detect any new changes; if necessary we restyle immediately
   // afterwards with animation.
   EnumeratedArray<EffectCompositor::CascadeLevel,
                   EffectCompositor::CascadeLevel(
                     EffectCompositor::kCascadeLevelCount),
-                  RefPtr<AnimValuesStyleRule>> mAnimationRule;
+                  mozilla::AnimationRule> mAnimationRule;
 
   // A parallel array to mAnimationRule that records the refresh driver
   // timestamp when the rule was last updated. This is used for certain
   // animations which are updated only periodically (e.g. transform animations
   // running on the compositor that affect the scrollable overflow region).
   EnumeratedArray<EffectCompositor::CascadeLevel,
                   EffectCompositor::CascadeLevel(
                     EffectCompositor::kCascadeLevelCount),
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/KeyframeEffectReadOnly.h"
 
 #include "mozilla/dom/KeyframeAnimationOptionsBinding.h"
   // For UnrestrictedDoubleOrKeyframeAnimationOptions;
 #include "mozilla/dom/CSSPseudoElement.h"
 #include "mozilla/dom/KeyframeEffectBinding.h"
+#include "mozilla/AnimationRule.h"
 #include "mozilla/AnimationUtils.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/FloatingPoint.h" // For IsFinite
 #include "mozilla/LookAndFeel.h" // For LookAndFeel::GetInt
 #include "mozilla/KeyframeUtils.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/StyleAnimationValue.h"
@@ -459,17 +460,17 @@ KeyframeEffectReadOnly::EnsureBaseStyles
       SetNeedsBaseStyle(property.mProperty);
       break;
     }
   }
 }
 
 void
 KeyframeEffectReadOnly::ComposeStyle(
-  RefPtr<AnimValuesStyleRule>& aStyleRule,
+  AnimationRule& aStyleRule,
   const nsCSSPropertyIDSet& aPropertiesToSkip)
 {
   MOZ_DIAGNOSTIC_ASSERT(!mIsComposingStyle,
                         "Should not be called recursively");
   if (mIsComposingStyle) {
     return;
   }
 
@@ -526,59 +527,59 @@ KeyframeEffectReadOnly::ComposeStyle(
       MOZ_ASSERT(segment->mFromKey == (segment-1)->mToKey, "incorrect keys");
     }
     MOZ_ASSERT(segment->mFromKey <= segment->mToKey, "incorrect keys");
     MOZ_ASSERT(segment >= prop.mSegments.Elements() &&
                size_t(segment - prop.mSegments.Elements()) <
                  prop.mSegments.Length(),
                "out of array bounds");
 
-    if (!aStyleRule) {
+    if (!aStyleRule.mGecko) {
       // Allocate the style rule now that we know we have animation data.
-      aStyleRule = new AnimValuesStyleRule();
+      aStyleRule.mGecko = new AnimValuesStyleRule();
     }
 
     StyleAnimationValue fromValue =
-      CompositeValue(prop.mProperty, aStyleRule,
+      CompositeValue(prop.mProperty, aStyleRule.mGecko,
                      segment->mFromValue,
                      segment->mFromComposite);
     StyleAnimationValue toValue =
-      CompositeValue(prop.mProperty, aStyleRule,
+      CompositeValue(prop.mProperty, aStyleRule.mGecko,
                      segment->mToValue,
                      segment->mToComposite);
 
     // Iteration composition for accumulate
     if (mEffectOptions.mIterationComposite ==
           IterationCompositeOperation::Accumulate &&
         computedTiming.mCurrentIteration > 0) {
       const AnimationPropertySegment& lastSegment =
         prop.mSegments.LastElement();
       // FIXME: Bug 1293492: Add a utility function to calculate both of
       // below StyleAnimationValues.
       StyleAnimationValue lastValue = lastSegment.mToValue.IsNull()
-        ? GetUnderlyingStyle(prop.mProperty, aStyleRule)
+        ? GetUnderlyingStyle(prop.mProperty, aStyleRule.mGecko)
         : lastSegment.mToValue;
       fromValue =
         StyleAnimationValue::Accumulate(prop.mProperty,
                                         lastValue,
                                         Move(fromValue),
                                         computedTiming.mCurrentIteration);
       toValue =
         StyleAnimationValue::Accumulate(prop.mProperty,
                                         lastValue,
                                         Move(toValue),
                                         computedTiming.mCurrentIteration);
     }
 
     // Special handling for zero-length segments
     if (segment->mToKey == segment->mFromKey) {
       if (computedTiming.mProgress.Value() < 0) {
-        aStyleRule->AddValue(prop.mProperty, Move(fromValue));
+        aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
       } else {
-        aStyleRule->AddValue(prop.mProperty, Move(toValue));
+        aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
       }
       continue;
     }
 
     double positionInSegment =
       (computedTiming.mProgress.Value() - segment->mFromKey) /
       (segment->mToKey - segment->mFromKey);
     double valuePosition =
@@ -587,21 +588,21 @@ KeyframeEffectReadOnly::ComposeStyle(
                                          computedTiming.mBeforeFlag);
 
     MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
     StyleAnimationValue val;
     if (StyleAnimationValue::Interpolate(prop.mProperty,
                                          fromValue,
                                          toValue,
                                          valuePosition, val)) {
-      aStyleRule->AddValue(prop.mProperty, Move(val));
+      aStyleRule.mGecko->AddValue(prop.mProperty, Move(val));
     } else if (valuePosition < 0.5) {
-      aStyleRule->AddValue(prop.mProperty, Move(fromValue));
+      aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
     } else {
-      aStyleRule->AddValue(prop.mProperty, Move(toValue));
+      aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
     }
   }
 
   // For properties that can be run on the compositor, we may need to prepare
   // base styles to send to the compositor even if the current processing
   // segment for properties does not have either an additive or accumulative
   // composite mode, and even if the animation is not in-effect. That's because
   // the animation may later progress to a segment which has an additive or
--- a/dom/animation/KeyframeEffectReadOnly.h
+++ b/dom/animation/KeyframeEffectReadOnly.h
@@ -35,16 +35,17 @@ class nsIFrame;
 class nsIPresShell;
 class nsPresContext;
 
 namespace mozilla {
 
 class AnimValuesStyleRule;
 enum class CSSPseudoElementType : uint8_t;
 class ErrorResult;
+struct AnimationRule;
 struct TimingParams;
 
 namespace dom {
 class ElementOrCSSPseudoElement;
 class GlobalObject;
 class OwningElementOrCSSPseudoElement;
 class UnrestrictedDoubleOrKeyframeAnimationOptions;
 class UnrestrictedDoubleOrKeyframeEffectOptions;
@@ -286,17 +287,17 @@ public:
 
   // Update |mProperties| by recalculating from |mKeyframes| using
   // |aStyleContext| to resolve specified values.
   void UpdateProperties(nsStyleContext* aStyleContext);
 
   // Updates |aStyleRule| with the animation values produced by this
   // AnimationEffect for the current time except any properties contained
   // in |aPropertiesToSkip|.
-  void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
+  void ComposeStyle(AnimationRule& aStyleRule,
                     const nsCSSPropertyIDSet& aPropertiesToSkip);
 
   // Composite |aValueToComposite| on |aUnderlyingValue| with
   // |aCompositeOperation|.
   // Returns |aValueToComposite| if |aCompositeOperation| is Replace.
   static StyleAnimationValue CompositeValue(
     nsCSSPropertyID aProperty,
     const StyleAnimationValue& aValueToComposite,
new file mode 100644
--- /dev/null
+++ b/dom/animation/ServoAnimationRule.cpp
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "ServoAnimationRule.h"
+
+namespace mozilla {
+
+void
+ServoAnimationRule::AddValue(nsCSSPropertyID aProperty,
+                             RawServoAnimationValue* aValue)
+{
+  MOZ_ASSERT(aProperty != eCSSProperty_UNKNOWN,
+             "Unexpected css property");
+  mAnimationValues.Put(aProperty, aValue);
+}
+
+RawServoDeclarationBlockStrong
+ServoAnimationRule::GetValues() const
+{
+  // FIXME: Pass the hash table into the FFI directly.
+  nsTArray<const RawServoAnimationValue*> values(mAnimationValues.Count());
+  auto iter = mAnimationValues.ConstIter();
+  for (; !iter.Done(); iter.Next()) {
+    values.AppendElement(iter.Data());
+  }
+  return Servo_AnimationValues_Uncompute(&values);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/animation/ServoAnimationRule.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_ServoAnimationRule_h
+#define mozilla_ServoAnimationRule_h
+
+#include "nsCSSPropertyID.h"
+#include "nsHashKeys.h" // For nsUint32HashKey
+#include "nsRefPtrHashtable.h"
+#include "ServoBindings.h"
+
+namespace mozilla {
+
+/**
+ * A rule for Stylo Animation Rule.
+ */
+class ServoAnimationRule
+{
+public:
+  ServoAnimationRule() = default;
+
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ServoAnimationRule)
+
+  void AddValue(nsCSSPropertyID aProperty,
+                RawServoAnimationValue* aValue);
+  MOZ_MUST_USE RawServoDeclarationBlockStrong GetValues() const;
+
+private:
+  ~ServoAnimationRule() = default;
+
+  nsRefPtrHashtable<nsUint32HashKey, RawServoAnimationValue> mAnimationValues;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoAnimationRule_h
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -17,27 +17,29 @@ EXPORTS.mozilla.dom += [
     'DocumentTimeline.h',
     'KeyframeEffect.h',
     'KeyframeEffectReadOnly.h',
 ]
 
 EXPORTS.mozilla += [
     'AnimationComparator.h',
     'AnimationPerformanceWarning.h',
+    'AnimationRule.h',
     'AnimationTarget.h',
     'AnimationUtils.h',
     'AnimValuesStyleRule.h',
     'ComputedTiming.h',
     'ComputedTimingFunction.h',
     'EffectCompositor.h',
     'EffectSet.h',
     'KeyframeEffectParams.h',
     'KeyframeUtils.h',
     'PendingAnimationTracker.h',
     'PseudoElementHashEntry.h',
+    'ServoAnimationRule.h',
     'TimingParams.h',
 ]
 
 UNIFIED_SOURCES += [
     'Animation.cpp',
     'AnimationEffectReadOnly.cpp',
     'AnimationEffectTiming.cpp',
     'AnimationEffectTimingReadOnly.cpp',
@@ -50,16 +52,17 @@ UNIFIED_SOURCES += [
     'DocumentTimeline.cpp',
     'EffectCompositor.cpp',
     'EffectSet.cpp',
     'KeyframeEffect.cpp',
     'KeyframeEffectParams.cpp',
     'KeyframeEffectReadOnly.cpp',
     'KeyframeUtils.cpp',
     'PendingAnimationTracker.cpp',
+    'ServoAnimationRule.cpp',
     'TimingParams.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/layout/base',
     '/layout/style',
 ]
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -108,16 +108,19 @@ SERVO_BINDING_FUNC(Servo_RestyleWithAdde
 
 // AnimationValues handling
 SERVO_BINDING_FUNC(Servo_AnimationValues_Populate, void,
                    RawGeckoAnimationValueListBorrowedMut,
                    RawServoDeclarationBlockBorrowed,
                    ServoComputedValuesBorrowed,
                    ServoComputedValuesBorrowedOrNull,
                    RawGeckoPresContextBorrowed)
+SERVO_BINDING_FUNC(Servo_AnimationValues_Uncompute,
+                   RawServoDeclarationBlockStrong,
+                   RawServoAnimationValueBorrowedListBorrowed value)
 
 // Style attribute
 SERVO_BINDING_FUNC(Servo_ParseStyleAttribute, RawServoDeclarationBlockStrong,
                    const nsACString* data)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_CreateEmpty,
                    RawServoDeclarationBlockStrong)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_Clone, RawServoDeclarationBlockStrong,
                    RawServoDeclarationBlockBorrowed declarations)
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -36,16 +36,17 @@ class nsPresContext;
 using mozilla::dom::StyleChildrenIterator;
 using mozilla::ServoElementSnapshot;
 
 typedef nsINode RawGeckoNode;
 typedef mozilla::dom::Element RawGeckoElement;
 typedef nsIDocument RawGeckoDocument;
 typedef nsPresContext RawGeckoPresContext;
 typedef nsTArray<mozilla::PropertyStyleAnimationValuePair> RawGeckoAnimationValueList;
+typedef nsTArray<const RawServoAnimationValue*> RawServoAnimationValueBorrowedList;
 
 // We have these helper types so that we can directly generate
 // things like &T or Borrowed<T> on the Rust side in the function, providing
 // additional safety benefits.
 //
 // FFI has a problem with templated types, so we just use raw pointers here.
 //
 // The "Borrowed" types generate &T or Borrowed<T> in the nullable case.
@@ -105,16 +106,17 @@ DECL_BORROWED_REF_TYPE_FOR(RawGeckoDocum
 DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawGeckoDocument)
 DECL_BORROWED_MUT_REF_TYPE_FOR(StyleChildrenIterator)
 DECL_BORROWED_MUT_REF_TYPE_FOR(ServoElementSnapshot)
 DECL_BORROWED_REF_TYPE_FOR(nsCSSValue)
 DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSValue)
 DECL_OWNED_REF_TYPE_FOR(RawGeckoPresContext)
 DECL_BORROWED_REF_TYPE_FOR(RawGeckoPresContext)
 DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoAnimationValueList)
+DECL_BORROWED_REF_TYPE_FOR(RawServoAnimationValueBorrowedList)
 
 #undef DECL_ARC_REF_TYPE_FOR
 #undef DECL_OWNED_REF_TYPE_FOR
 #undef DECL_NULLABLE_OWNED_REF_TYPE_FOR
 #undef DECL_BORROWED_REF_TYPE_FOR
 #undef DECL_NULLABLE_BORROWED_REF_TYPE_FOR
 #undef DECL_BORROWED_MUT_REF_TYPE_FOR
 #undef DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR