Bug 1244586 part 1 - Add KeyframeEffect constructor in dom/webidl/KeyframeEffect.webidl. r=smaug,birtles

This commit is contained in:
Ryo Motozawa 2016-02-15 09:34:47 +09:00
parent e54a74b405
commit cc127029f8
5 changed files with 159 additions and 72 deletions

View File

@ -76,14 +76,24 @@ KeyframeEffectReadOnly::KeyframeEffectReadOnly(
Element* aTarget,
nsCSSPseudoElements::Type aPseudoType,
const TimingParams& aTiming)
: KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType,
new AnimationEffectTimingReadOnly(aTiming))
{
}
KeyframeEffectReadOnly::KeyframeEffectReadOnly(
nsIDocument* aDocument,
Element* aTarget,
nsCSSPseudoElements::Type aPseudoType,
AnimationEffectTimingReadOnly* aTiming)
: AnimationEffectReadOnly(aDocument)
, mTarget(aTarget)
, mTiming(*aTiming)
, mPseudoType(aPseudoType)
, mInEffectOnLastAnimationTimingUpdate(false)
{
MOZ_ASSERT(aTiming);
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
mTiming = new AnimationEffectTimingReadOnly(aTiming);
}
JSObject*
@ -595,6 +605,72 @@ KeyframeEffectReadOnly::~KeyframeEffectReadOnly()
{
}
template <class KeyframeEffectType>
/* static */ already_AddRefed<KeyframeEffectType>
KeyframeEffectReadOnly::ConstructKeyframeEffect(const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const TimingParams& aTiming,
ErrorResult& aRv)
{
if (aTarget.IsNull()) {
// We don't support null targets yet.
aRv.Throw(NS_ERROR_DOM_ANIM_NO_TARGET_ERR);
return nullptr;
}
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->GetComposedDoc()) {
aRv.Throw(NS_ERROR_DOM_ANIM_TARGET_NOT_IN_DOC_ERR);
return nullptr;
}
InfallibleTArray<AnimationProperty> animationProperties;
BuildAnimationPropertyList(aGlobal.Context(), targetElement, pseudoType,
aFrames, animationProperties, aRv);
if (aRv.Failed()) {
return nullptr;
}
RefPtr<KeyframeEffectType> effect =
new KeyframeEffectType(targetElement->OwnerDoc(), targetElement,
pseudoType, aTiming);
effect->mProperties = Move(animationProperties);
return effect.forget();
}
// Explicit instantiations to avoid linker errors.
template
already_AddRefed<KeyframeEffectReadOnly>
KeyframeEffectReadOnly::ConstructKeyframeEffect<>(const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const TimingParams& aTiming,
ErrorResult& aRv);
template
already_AddRefed<KeyframeEffect>
KeyframeEffectReadOnly::ConstructKeyframeEffect<>(const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const TimingParams& aTiming,
ErrorResult& aRv);
void
KeyframeEffectReadOnly::ResetIsRunningOnCompositor()
{
@ -1635,55 +1711,6 @@ KeyframeEffectReadOnly::BuildAnimationPropertyList(
}
}
/* static */ already_AddRefed<KeyframeEffectReadOnly>
KeyframeEffectReadOnly::Constructor(
const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const TimingParams& aTiming,
ErrorResult& aRv)
{
if (aTarget.IsNull()) {
// We don't support null targets yet.
aRv.Throw(NS_ERROR_DOM_ANIM_NO_TARGET_ERR);
return nullptr;
}
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, pseudoType,
aFrames, animationProperties, aRv);
if (aRv.Failed()) {
return nullptr;
}
RefPtr<KeyframeEffectReadOnly> effect =
new KeyframeEffectReadOnly(targetElement->OwnerDoc(), targetElement,
pseudoType, aTiming);
effect->mProperties = Move(animationProperties);
return effect.forget();
}
void
KeyframeEffectReadOnly::GetTarget(
Nullable<OwningElementOrCSSPseudoElement>& aRv) const
@ -2091,6 +2118,21 @@ KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(const nsIFrame*
return false;
}
//---------------------------------------------------------------------
//
// KeyframeEffect
//
//---------------------------------------------------------------------
KeyframeEffect::KeyframeEffect(nsIDocument* aDocument,
Element* aTarget,
nsCSSPseudoElements::Type aPseudoType,
const TimingParams& aTiming)
: KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType,
new AnimationEffectTiming(aTiming))
{
}
JSObject*
KeyframeEffect::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)

View File

@ -20,6 +20,7 @@
#include "mozilla/StyleAnimationValue.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/AnimationEffectReadOnly.h"
#include "mozilla/dom/AnimationEffectTiming.h"
#include "mozilla/dom/AnimationEffectTimingReadOnly.h" // TimingParams
#include "mozilla/dom/Element.h"
#include "mozilla/dom/KeyframeBinding.h"
@ -195,20 +196,11 @@ public:
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
ErrorResult& aRv)
{
return Constructor(aGlobal, aTarget, aFrames,
TimingParams::FromOptionsUnion(aOptions, aTarget),
aRv);
return ConstructKeyframeEffect<KeyframeEffectReadOnly>(
aGlobal, aTarget, aFrames,
TimingParams::FromOptionsUnion(aOptions, aTarget), aRv);
}
// More generalized version for Animatable.animate.
// Not exposed to content.
static already_AddRefed<KeyframeEffectReadOnly>
Constructor(const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const TimingParams& aTiming,
ErrorResult& aRv);
void GetTarget(Nullable<OwningElementOrCSSPseudoElement>& aRv) const;
void GetFrames(JSContext*& aCx,
nsTArray<JSObject*>& aResult,
@ -328,7 +320,21 @@ public:
inline AnimationCollection* GetCollection() const;
protected:
KeyframeEffectReadOnly(nsIDocument* aDocument,
Element* aTarget,
nsCSSPseudoElements::Type aPseudoType,
AnimationEffectTimingReadOnly* aTiming);
virtual ~KeyframeEffectReadOnly();
template<typename KeyframeEffectType>
static already_AddRefed<KeyframeEffectType>
ConstructKeyframeEffect(const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const TimingParams& aTiming,
ErrorResult& aRv);
void ResetIsRunningOnCompositor();
// This effect is registered with its target element so long as:
@ -390,11 +396,35 @@ public:
KeyframeEffect(nsIDocument* aDocument,
Element* aTarget,
nsCSSPseudoElements::Type aPseudoType,
const TimingParams& aTiming)
: KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType, aTiming) { }
const TimingParams& aTiming);
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
static already_AddRefed<KeyframeEffect>
Constructor(const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
ErrorResult& aRv)
{
return ConstructKeyframeEffect<KeyframeEffect>(
aGlobal, aTarget, aFrames,
TimingParams::FromOptionsUnion(aOptions, aTarget), aRv);
}
// More generalized version for Animatable.animate.
// Not exposed to content.
static already_AddRefed<KeyframeEffect>
inline Constructor(const GlobalObject& aGlobal,
const Nullable<ElementOrCSSPseudoElement>& aTarget,
JS::Handle<JSObject*> aFrames,
const TimingParams& aTiming,
ErrorResult& aRv)
{
return ConstructKeyframeEffect<KeyframeEffect>(aGlobal, aTarget, aFrames,
aTiming, aRv);
}
};
} // namespace dom

View File

@ -3337,9 +3337,8 @@ Element::Animate(JSContext* aContext,
Nullable<ElementOrCSSPseudoElement> target;
target.SetValue().SetAsElement() = this;
// Bug 1211783: Use KeyframeEffect here (instead of KeyframeEffectReadOnly)
RefPtr<KeyframeEffectReadOnly> effect =
KeyframeEffectReadOnly::Constructor(global, target, frames,
RefPtr<KeyframeEffect> effect =
KeyframeEffect::Constructor(global, target, frames,
TimingParams::FromOptionsUnion(aOptions, target), aError);
if (aError.Failed()) {
return nullptr;

View File

@ -46,10 +46,9 @@ interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
};
// Bug 1211783 Implement KeyframeEffect constructor
// [Constructor (Animatable? target,
// object? frames,
// optional (unrestricted double or KeyframeEffectOptions) options)]
[Constructor ((Element or CSSPseudoElement)? target,
object? frames,
optional (unrestricted double or KeyframeEffectOptions) options)]
interface KeyframeEffect : KeyframeEffectReadOnly {
// Bug 1067769 - Allow setting KeyframeEffect.target
// inherit attribute Animatable? target;

View File

@ -629,6 +629,23 @@ gKeyframeEffectOptionTests.forEach(function(stest) {
}, "a KeyframeEffectReadOnly constructed by " + stest.desc);
});
test(function(t) {
var effect = new KeyframeEffect(target,
{left: ["10px", "20px"]});
assert_class_string(effect, "KeyframeEffect");
assert_class_string(effect.timing, "AnimationEffectTiming");
}, "KeyframeEffect constructor creates an AnimationEffectTiming timing object");
test(function(t) {
var test_error = { name: "test" };
assert_throws(test_error, function() {
new KeyframeEffect(target, { get left() { throw test_error }})
});
}, "KeyframeEffect constructor propagates exceptions generated by accessing"
+ " the options object");
done();
</script>
</body>