Bug 1277456 part 5 - Pass the document associated with an AnimationEffectTiming/KeyframeEffect object to KeyframeUtils as the context to use when parsing CSS properties; r?hiro draft
authorBrian Birtles <birtles@gmail.com>
Wed, 13 Jul 2016 13:22:25 +0900
changeset 386962 80b698a27db3a93cd2777f61ceb486144a2d1116
parent 386961 4b1c00bf83491daba1713ecc1f54a6e6a62e75df
child 386963 548b28645091d97093663cbb6d6af6f692e33f95
push id22865
push userbbirtles@mozilla.com
push dateWed, 13 Jul 2016 04:26:23 +0000
reviewershiro
bugs1277456
milestone50.0a1
Bug 1277456 part 5 - Pass the document associated with an AnimationEffectTiming/KeyframeEffect object to KeyframeUtils as the context to use when parsing CSS properties; r?hiro Note that when we actually compute values, we will use the composed document of the target element (see the next patch in this series). MozReview-Commit-ID: 8Pp3y19pltP
dom/animation/KeyframeEffect.cpp
dom/animation/KeyframeUtils.cpp
dom/animation/KeyframeUtils.h
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -458,17 +458,17 @@ KeyframeEffectReadOnly::SetKeyframes(JSC
 {
   nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aContext);
   if (!doc) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   nsTArray<Keyframe> keyframes =
-    KeyframeUtils::GetKeyframesFromObject(aContext, aKeyframes, aRv);
+    KeyframeUtils::GetKeyframesFromObject(aContext, mDocument, aKeyframes, aRv);
   if (aRv.Failed()) {
     return;
   }
 
   RefPtr<nsStyleContext> styleContext = GetTargetStyleContext(doc);
   SetKeyframes(Move(keyframes), styleContext);
 }
 
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -336,22 +336,24 @@ IsInvalidValuePair(const PropertyValuePa
 // ------------------------------------------------------------------
 //
 // Internal helper method declarations
 //
 // ------------------------------------------------------------------
 
 static void
 GetKeyframeListFromKeyframeSequence(JSContext* aCx,
+                                    nsIDocument* aDocument,
                                     JS::ForOfIterator& aIterator,
                                     nsTArray<Keyframe>& aResult,
                                     ErrorResult& aRv);
 
 static bool
 ConvertKeyframeSequence(JSContext* aCx,
+                        nsIDocument* aDocument,
                         JS::ForOfIterator& aIterator,
                         nsTArray<Keyframe>& aResult);
 
 static bool
 GetPropertyValuesPairs(JSContext* aCx,
                        JS::Handle<JSObject*> aObject,
                        ListAllowance aAllowLists,
                        nsTArray<PropertyValuesPair>& aResult);
@@ -382,16 +384,17 @@ IsComputeValuesFailureKey(const Property
 
 static void
 BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext,
                               nsTArray<KeyframeValueEntry>& aEntries,
                               nsTArray<AnimationProperty>& aResult);
 
 static void
 GetKeyframeListFromPropertyIndexedKeyframe(JSContext* aCx,
+                                           nsIDocument* aDocument,
                                            JS::Handle<JS::Value> aValue,
                                            nsTArray<Keyframe>& aResult,
                                            ErrorResult& aRv);
 
 static bool
 RequiresAdditiveAnimation(const nsTArray<Keyframe>& aKeyframes,
                           nsIDocument* aDocument);
 
@@ -413,16 +416,17 @@ GetCumulativeDistances(const nsTArray<Co
 // ------------------------------------------------------------------
 //
 // Public API
 //
 // ------------------------------------------------------------------
 
 /* static */ nsTArray<Keyframe>
 KeyframeUtils::GetKeyframesFromObject(JSContext* aCx,
+                                      nsIDocument* aDocument,
                                       JS::Handle<JSObject*> aFrames,
                                       ErrorResult& aRv)
 {
   MOZ_ASSERT(!aRv.Failed());
 
   nsTArray<Keyframe> keyframes;
 
   if (!aFrames) {
@@ -436,42 +440,35 @@ KeyframeUtils::GetKeyframesFromObject(JS
   JS::Rooted<JS::Value> objectValue(aCx, JS::ObjectValue(*aFrames));
   JS::ForOfIterator iter(aCx);
   if (!iter.init(objectValue, JS::ForOfIterator::AllowNonIterable)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return keyframes;
   }
 
   if (iter.valueIsIterable()) {
-    GetKeyframeListFromKeyframeSequence(aCx, iter, keyframes, aRv);
+    GetKeyframeListFromKeyframeSequence(aCx, aDocument, iter, keyframes, aRv);
   } else {
-    GetKeyframeListFromPropertyIndexedKeyframe(aCx, objectValue, keyframes,
-                                               aRv);
+    GetKeyframeListFromPropertyIndexedKeyframe(aCx, aDocument, objectValue,
+                                               keyframes, aRv);
   }
 
   if (aRv.Failed()) {
     MOZ_ASSERT(keyframes.IsEmpty(),
                "Should not set any keyframes when there is an error");
     return keyframes;
   }
 
   // We currently don't support additive animation. However, Web Animations
   // says that if you don't have a keyframe at offset 0 or 1, then you should
   // synthesize one using an additive zero value when you go to compose style.
   // Until we implement additive animations we just throw if we encounter any
   // set of keyframes that would put us in that situation.
 
-  nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aCx);
-  if (!doc) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    keyframes.Clear();
-    return keyframes;
-  }
-
-  if (RequiresAdditiveAnimation(keyframes, doc)) {
+  if (RequiresAdditiveAnimation(keyframes, aDocument)) {
     aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR);
     keyframes.Clear();
   }
 
   return keyframes;
 }
 
 /* static */ void
@@ -707,34 +704,36 @@ KeyframeUtils::IsAnimatableProperty(nsCS
 // Internal helpers
 //
 // ------------------------------------------------------------------
 
 /**
  * Converts a JS object to an IDL sequence<Keyframe>.
  *
  * @param aCx The JSContext corresponding to |aIterator|.
+ * @param aDocument The document to use when parsing CSS properties.
  * @param aIterator An already-initialized ForOfIterator for the JS
  *   object to iterate over as a sequence.
  * @param aResult The array into which the resulting Keyframe objects will be
  *   appended.
  * @param aRv Out param to store any errors thrown by this function.
  */
 static void
 GetKeyframeListFromKeyframeSequence(JSContext* aCx,
+                                    nsIDocument* aDocument,
                                     JS::ForOfIterator& aIterator,
                                     nsTArray<Keyframe>& aResult,
                                     ErrorResult& aRv)
 {
   MOZ_ASSERT(!aRv.Failed());
   MOZ_ASSERT(aResult.IsEmpty());
 
   // Convert the object in aIterator to a sequence of keyframes producing
   // an array of Keyframe objects.
-  if (!ConvertKeyframeSequence(aCx, aIterator, aResult)) {
+  if (!ConvertKeyframeSequence(aCx, aDocument, aIterator, aResult)) {
     aRv.Throw(NS_ERROR_FAILURE);
     aResult.Clear();
     return;
   }
 
   // If the sequence<> had zero elements, we won't generate any
   // keyframes.
   if (aResult.IsEmpty()) {
@@ -752,26 +751,22 @@ GetKeyframeListFromKeyframeSequence(JSCo
 
 /**
  * Converts a JS object wrapped by the given JS::ForIfIterator to an
  * IDL sequence<Keyframe> and stores the resulting Keyframe objects in
  * aResult.
  */
 static bool
 ConvertKeyframeSequence(JSContext* aCx,
+                        nsIDocument* aDocument,
                         JS::ForOfIterator& aIterator,
                         nsTArray<Keyframe>& aResult)
 {
-  nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aCx);
-  if (!doc) {
-    return false;
-  }
-
   JS::Rooted<JS::Value> value(aCx);
-  nsCSSParser parser(doc->CSSLoader());
+  nsCSSParser parser(aDocument->CSSLoader());
 
   for (;;) {
     bool done;
     if (!aIterator.next(&value, &done)) {
       return false;
     }
     if (done) {
       break;
@@ -797,17 +792,17 @@ ConvertKeyframeSequence(JSContext* aCx,
       return false;
     }
     if (!keyframeDict.mOffset.IsNull()) {
       keyframe->mOffset.emplace(keyframeDict.mOffset.Value());
     }
 
     ErrorResult rv;
     keyframe->mTimingFunction =
-      TimingParams::ParseEasing(keyframeDict.mEasing, doc, rv);
+      TimingParams::ParseEasing(keyframeDict.mEasing, aDocument, rv);
     if (rv.MaybeSetPendingException(aCx)) {
       return false;
     }
 
     // Look for additional property-values pairs on the object.
     nsTArray<PropertyValuesPair> propertyValuePairs;
     if (value.isObject()) {
       JS::Rooted<JSObject*> object(aCx, &value.toObject());
@@ -816,17 +811,18 @@ ConvertKeyframeSequence(JSContext* aCx,
                                   propertyValuePairs)) {
         return false;
       }
     }
 
     for (PropertyValuesPair& pair : propertyValuePairs) {
       MOZ_ASSERT(pair.mValues.Length() == 1);
       keyframe->mPropertyValues.AppendElement(
-        MakePropertyValuePair(pair.mProperty, pair.mValues[0], parser, doc));
+        MakePropertyValuePair(pair.mProperty, pair.mValues[0], parser,
+                              aDocument));
 
       // When we go to convert keyframes into arrays of property values we
       // call StyleAnimation::ComputeValues. This should normally return true
       // but in order to test the case where it does not, BaseKeyframeDict
       // includes a chrome-only member that can be set to indicate that
       // ComputeValues should fail for shorthand property values on that
       // keyframe.
       if (nsCSSProps::IsShorthand(pair.mProperty) &&
@@ -1274,23 +1270,25 @@ BuildSegmentsFromValueEntries(nsStyleCon
   }
 }
 
 /**
  * Converts a JS object representing a property-indexed keyframe into
  * an array of Keyframe objects.
  *
  * @param aCx The JSContext for |aValue|.
+ * @param aDocument The document to use when parsing CSS properties.
  * @param aValue The JS object.
  * @param aResult The array into which the resulting AnimationProperty
  *   objects will be appended.
  * @param aRv Out param to store any errors thrown by this function.
  */
 static void
 GetKeyframeListFromPropertyIndexedKeyframe(JSContext* aCx,
+                                           nsIDocument* aDocument,
                                            JS::Handle<JS::Value> aValue,
                                            nsTArray<Keyframe>& aResult,
                                            ErrorResult& aRv)
 {
   MOZ_ASSERT(aValue.isObject());
   MOZ_ASSERT(aResult.IsEmpty());
   MOZ_ASSERT(!aRv.Failed());
 
@@ -1298,40 +1296,33 @@ GetKeyframeListFromPropertyIndexedKeyfra
   // get its explicit dictionary members.
   dom::binding_detail::FastBasePropertyIndexedKeyframe keyframeDict;
   if (!keyframeDict.Init(aCx, aValue, "BasePropertyIndexedKeyframe argument",
                          false)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  // Get the document to use for parsing CSS properties.
-  nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aCx);
-  if (!doc) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
   Maybe<ComputedTimingFunction> easing =
-    TimingParams::ParseEasing(keyframeDict.mEasing, doc, aRv);
+    TimingParams::ParseEasing(keyframeDict.mEasing, aDocument, aRv);
   if (aRv.Failed()) {
     return;
   }
 
   // Get all the property--value-list pairs off the object.
   JS::Rooted<JSObject*> object(aCx, &aValue.toObject());
   nsTArray<PropertyValuesPair> propertyValuesPairs;
   if (!GetPropertyValuesPairs(aCx, object, ListAllowance::eAllow,
                               propertyValuesPairs)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   // Create a set of keyframes for each property.
-  nsCSSParser parser(doc->CSSLoader());
+  nsCSSParser parser(aDocument->CSSLoader());
   nsClassHashtable<nsFloatHashKey, Keyframe> processedKeyframes;
   for (const PropertyValuesPair& pair : propertyValuesPairs) {
     size_t count = pair.mValues.Length();
     if (count == 0) {
       // No animation values for this property.
       continue;
     }
     if (count == 1) {
@@ -1348,17 +1339,17 @@ GetKeyframeListFromPropertyIndexedKeyfra
     for (const nsString& stringValue : pair.mValues) {
       double offset = i++ / double(n);
       Keyframe* keyframe = processedKeyframes.LookupOrAdd(offset);
       if (keyframe->mPropertyValues.IsEmpty()) {
         keyframe->mTimingFunction = easing;
         keyframe->mComputedOffset = offset;
       }
       keyframe->mPropertyValues.AppendElement(
-        MakePropertyValuePair(pair.mProperty, stringValue, parser, doc));
+        MakePropertyValuePair(pair.mProperty, stringValue, parser, aDocument));
     }
   }
 
   aResult.SetCapacity(processedKeyframes.Count());
   for (auto iter = processedKeyframes.Iter(); !iter.Done(); iter.Next()) {
     aResult.AppendElement(Move(*iter.UserData()));
   }
 
--- a/dom/animation/KeyframeUtils.h
+++ b/dom/animation/KeyframeUtils.h
@@ -38,26 +38,28 @@ using ComputedKeyframeValues = nsTArray<
 class KeyframeUtils
 {
 public:
   /**
    * Converts a JS value representing a property-indexed keyframe or a sequence
    * of keyframes to an array of Keyframe objects.
    *
    * @param aCx The JSContext that corresponds to |aFrames|.
+   * @param aDocument The document to use when parsing CSS properties.
    * @param aFrames The JS value, provided as an optional IDL |object?| value,
    *   that is the keyframe list specification.
    * @param aRv (out) Out-param to hold any error returned by this function.
    *   Must be initially empty.
    * @return The set of processed keyframes. If an error occurs, aRv will be
    *   filled-in with the appropriate error code and an empty array will be
    *   returned.
    */
   static nsTArray<Keyframe>
   GetKeyframesFromObject(JSContext* aCx,
+                         nsIDocument* aDocument,
                          JS::Handle<JSObject*> aFrames,
                          ErrorResult& aRv);
 
   /**
    * Calculate the StyleAnimationValues of properties of each keyframe.
    * This involves expanding shorthand properties into longhand properties,
    * removing the duplicated properties for each keyframe, and creating an
    * array of |property:computed value| pairs for each keyframe.