From bce920d78f829e5999e01a33d725da581d557109 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Tue, 9 Feb 2016 05:05:00 +0100 Subject: [PATCH] Bug 1174575 - Part 6: Implement KeyframeEffectReadOnly Constructor for CSSPseudoElement. r=birtles Let KeyframeEffectReadOnly::Constructor support both Element and CSSPseudoElement as the target. --- dom/animation/CSSPseudoElement.h | 1 + dom/animation/KeyframeEffect.cpp | 91 +++++++++++++++++++------------- dom/animation/KeyframeEffect.h | 1 + 3 files changed, 57 insertions(+), 36 deletions(-) diff --git a/dom/animation/CSSPseudoElement.h b/dom/animation/CSSPseudoElement.h index 6be3b844e6bd..be8b2d993a72 100644 --- a/dom/animation/CSSPseudoElement.h +++ b/dom/animation/CSSPseudoElement.h @@ -40,6 +40,7 @@ public: virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + nsCSSPseudoElements::Type GetType() const { return mPseudoType; } void GetType(nsString& aRetVal) const { MOZ_ASSERT(nsCSSPseudoElements::GetPseudoAtom(mPseudoType), diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index 89ee3b07970a..79b0c2ecefa8 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -1147,12 +1147,14 @@ ApplyDistributeSpacing(nsTArray& aKeyframes) * objects. * * @param aTarget The target of the animation. + * @param aPseudoType The pseudo type of the target if it is a pseudo element. * @param aKeyframes The keyframes to read. * @param aResult The array to append the resulting KeyframeValueEntry * objects to. */ static void GenerateValueEntries(Element* aTarget, + nsCSSPseudoElements::Type aPseudoType, nsTArray& aKeyframes, nsTArray& aResult, ErrorResult& aRv) @@ -1163,6 +1165,8 @@ GenerateValueEntries(Element* aTarget, for (OffsetIndexedKeyframe& keyframe : aKeyframes) { float offset = float(keyframe.mKeyframeDict.mOffset.Value()); + // ParseEasing uses element's owner doc, so if it is a pseudo element, + // we use its parent element's owner doc. Maybe easing = AnimationUtils::ParseEasing(aTarget, keyframe.mKeyframeDict.mEasing); // We ignore keyframe.mKeyframeDict.mComposite since we don't support @@ -1197,14 +1201,13 @@ GenerateValueEntries(Element* aTarget, // Parse the property's string value and produce a KeyframeValueEntry (or // more than one, for shorthands) for it. nsTArray values; - if (StyleAnimationValue::ComputeValues( - pair.mProperty, - nsCSSProps::eEnabledForAllContent, - aTarget, - nsCSSPseudoElements::ePseudo_NotPseudoElement, - pair.mValues[0], - /* aUseSVGMode */ false, - values)) { + if (StyleAnimationValue::ComputeValues(pair.mProperty, + nsCSSProps::eEnabledForAllContent, + aTarget, + aPseudoType, + pair.mValues[0], + /* aUseSVGMode */ false, + values)) { for (auto& value : values) { // If we already got a value for this property on the keyframe, // skip this one. @@ -1355,6 +1358,7 @@ static void BuildAnimationPropertyListFromKeyframeSequence( JSContext* aCx, Element* aTarget, + nsCSSPseudoElements::Type aPseudoType, JS::ForOfIterator& aIterator, nsTArray& aResult, ErrorResult& aRv) @@ -1388,7 +1392,7 @@ BuildAnimationPropertyListFromKeyframeSequence( // Convert the OffsetIndexedKeyframes into a list of KeyframeValueEntry // objects. nsTArray entries; - GenerateValueEntries(aTarget, keyframes, entries, aRv); + GenerateValueEntries(aTarget, aPseudoType, keyframes, entries, aRv); if (aRv.Failed()) { return; } @@ -1412,6 +1416,7 @@ static void BuildAnimationPropertyListFromPropertyIndexedKeyframes( JSContext* aCx, Element* aTarget, + nsCSSPseudoElements::Type aPseudoType, JS::Handle aValue, InfallibleTArray& aResult, ErrorResult& aRv) @@ -1427,6 +1432,8 @@ BuildAnimationPropertyListFromPropertyIndexedKeyframes( return; } + // ParseEasing uses element's owner doc, so if it is a pseudo element, + // we use its parent element's owner doc. Maybe easing = AnimationUtils::ParseEasing(aTarget, keyframes.mEasing); @@ -1479,14 +1486,13 @@ BuildAnimationPropertyListFromPropertyIndexedKeyframes( // value instead. nsTArray fromValues; float fromKey = 0.0f; - if (!StyleAnimationValue::ComputeValues( - pair.mProperty, - nsCSSProps::eEnabledForAllContent, - aTarget, - nsCSSPseudoElements::ePseudo_NotPseudoElement, - pair.mValues[0], - /* aUseSVGMode */ false, - fromValues)) { + if (!StyleAnimationValue::ComputeValues(pair.mProperty, + nsCSSProps::eEnabledForAllContent, + aTarget, + aPseudoType, + pair.mValues[0], + /* aUseSVGMode */ false, + fromValues)) { // We need to throw for an invalid first value, since that would imply an // additive animation, which we don't support yet. aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR); @@ -1533,14 +1539,13 @@ BuildAnimationPropertyListFromPropertyIndexedKeyframes( for (size_t i = 0; i < count - 1; ++i) { nsTArray toValues; float toKey = (i + 1) * portion; - if (!StyleAnimationValue::ComputeValues( - pair.mProperty, - nsCSSProps::eEnabledForAllContent, - aTarget, - nsCSSPseudoElements::ePseudo_NotPseudoElement, - pair.mValues[i + 1], - /* aUseSVGMode */ false, - toValues)) { + if (!StyleAnimationValue::ComputeValues(pair.mProperty, + nsCSSProps::eEnabledForAllContent, + aTarget, + aPseudoType, + pair.mValues[i + 1], + /* aUseSVGMode */ false, + toValues)) { if (i + 1 == count - 1) { // We need to throw for an invalid last value, since that would // imply an additive animation, which we don't support yet. @@ -1586,6 +1591,7 @@ BuildAnimationPropertyListFromPropertyIndexedKeyframes( KeyframeEffectReadOnly::BuildAnimationPropertyList( JSContext* aCx, Element* aTarget, + nsCSSPseudoElements::Type aPseudoType, JS::Handle aFrames, InfallibleTArray& aResult, ErrorResult& aRv) @@ -1619,10 +1625,11 @@ KeyframeEffectReadOnly::BuildAnimationPropertyList( } if (iter.valueIsIterable()) { - BuildAnimationPropertyListFromKeyframeSequence(aCx, aTarget, iter, - aResult, aRv); + BuildAnimationPropertyListFromKeyframeSequence(aCx, aTarget, aPseudoType, + iter, aResult, aRv); } else { BuildAnimationPropertyListFromPropertyIndexedKeyframes(aCx, aTarget, + aPseudoType, objectValue, aResult, aRv); } @@ -1636,31 +1643,43 @@ KeyframeEffectReadOnly::Constructor( const TimingParams& aTiming, ErrorResult& aRv) { - if (aTarget.IsNull() || aTarget.Value().IsCSSPseudoElement()) { - // We don't support null or CSSPseudoElement targets yet. + if (aTarget.IsNull()) { + // We don't support null targets yet. aRv.Throw(NS_ERROR_DOM_ANIM_NO_TARGET_ERR); return nullptr; } - Element& targetElement = aTarget.Value().GetAsElement(); - if (!targetElement.GetCurrentDoc()) { + const ElementOrCSSPseudoElement& target = aTarget.Value(); + MOZ_ASSERT(target.IsElement() || target.IsCSSPseudoElement(), + "Uninitialized target"); + + RefPtr targetElement; + nsCSSPseudoElements::Type pseudoType = + nsCSSPseudoElements::ePseudo_NotPseudoElement; + if (target.IsElement()) { + targetElement = &target.GetAsElement(); + } else { + targetElement = target.GetAsCSSPseudoElement().ParentElement(); + pseudoType = target.GetAsCSSPseudoElement().GetType(); + } + + if (!targetElement->GetCurrentDoc()) { // Bug 1245748: We don't support targets that are not in a document yet. aRv.Throw(NS_ERROR_DOM_ANIM_TARGET_NOT_IN_DOC_ERR); return nullptr; } InfallibleTArray animationProperties; - BuildAnimationPropertyList(aGlobal.Context(), &targetElement, aFrames, - animationProperties, aRv); + BuildAnimationPropertyList(aGlobal.Context(), targetElement, pseudoType, + aFrames, animationProperties, aRv); if (aRv.Failed()) { return nullptr; } RefPtr effect = - new KeyframeEffectReadOnly(targetElement.OwnerDoc(), &targetElement, - nsCSSPseudoElements::ePseudo_NotPseudoElement, - aTiming); + new KeyframeEffectReadOnly(targetElement->OwnerDoc(), targetElement, + pseudoType, aTiming); effect->mProperties = Move(animationProperties); return effect.forget(); } diff --git a/dom/animation/KeyframeEffect.h b/dom/animation/KeyframeEffect.h index 4a834c0757d4..5a4a52b5f292 100644 --- a/dom/animation/KeyframeEffect.h +++ b/dom/animation/KeyframeEffect.h @@ -345,6 +345,7 @@ protected: static void BuildAnimationPropertyList( JSContext* aCx, Element* aTarget, + nsCSSPseudoElements::Type aPseudoType, JS::Handle aFrames, InfallibleTArray& aResult, ErrorResult& aRv);