Bug 1174575 - Part 6: Implement KeyframeEffectReadOnly Constructor for CSSPseudoElement. r=birtles

Let KeyframeEffectReadOnly::Constructor support both Element and
CSSPseudoElement as the target.
This commit is contained in:
Boris Chiou 2016-02-09 05:05:00 +01:00
parent b33754c9da
commit 5b3edc8d6b
3 changed files with 57 additions and 36 deletions

View File

@ -40,6 +40,7 @@ public:
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
nsCSSPseudoElements::Type GetType() const { return mPseudoType; }
void GetType(nsString& aRetVal) const
{
MOZ_ASSERT(nsCSSPseudoElements::GetPseudoAtom(mPseudoType),

View File

@ -1147,12 +1147,14 @@ ApplyDistributeSpacing(nsTArray<OffsetIndexedKeyframe>& 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<OffsetIndexedKeyframe>& aKeyframes,
nsTArray<KeyframeValueEntry>& 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<ComputedTimingFunction> 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<PropertyStyleAnimationValuePair> 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<AnimationProperty>& aResult,
ErrorResult& aRv)
@ -1388,7 +1392,7 @@ BuildAnimationPropertyListFromKeyframeSequence(
// Convert the OffsetIndexedKeyframes into a list of KeyframeValueEntry
// objects.
nsTArray<KeyframeValueEntry> 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<JS::Value> aValue,
InfallibleTArray<AnimationProperty>& 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<ComputedTimingFunction> easing =
AnimationUtils::ParseEasing(aTarget, keyframes.mEasing);
@ -1479,14 +1486,13 @@ BuildAnimationPropertyListFromPropertyIndexedKeyframes(
// value instead.
nsTArray<PropertyStyleAnimationValuePair> 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<PropertyStyleAnimationValuePair> 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<JSObject*> aFrames,
InfallibleTArray<AnimationProperty>& 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<Element> 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<AnimationProperty> animationProperties;
BuildAnimationPropertyList(aGlobal.Context(), &targetElement, aFrames,
animationProperties, aRv);
BuildAnimationPropertyList(aGlobal.Context(), targetElement, pseudoType,
aFrames, animationProperties, aRv);
if (aRv.Failed()) {
return nullptr;
}
RefPtr<KeyframeEffectReadOnly> effect =
new KeyframeEffectReadOnly(targetElement.OwnerDoc(), &targetElement,
nsCSSPseudoElements::ePseudo_NotPseudoElement,
aTiming);
new KeyframeEffectReadOnly(targetElement->OwnerDoc(), targetElement,
pseudoType, aTiming);
effect->mProperties = Move(animationProperties);
return effect.forget();
}

View File

@ -345,6 +345,7 @@ protected:
static void BuildAnimationPropertyList(
JSContext* aCx,
Element* aTarget,
nsCSSPseudoElements::Type aPseudoType,
JS::Handle<JSObject*> aFrames,
InfallibleTArray<AnimationProperty>& aResult,
ErrorResult& aRv);