diff --git a/dom/animation/AnimationEffectTimingReadOnly.cpp b/dom/animation/AnimationEffectTimingReadOnly.cpp index 8ff6fa5c3f6c..ff574b3bdd4d 100644 --- a/dom/animation/AnimationEffectTimingReadOnly.cpp +++ b/dom/animation/AnimationEffectTimingReadOnly.cpp @@ -6,6 +6,7 @@ #include "mozilla/dom/AnimationEffectTimingReadOnly.h" +#include "mozilla/dom/AnimatableBinding.h" #include "mozilla/dom/AnimationEffectTimingReadOnlyBinding.h" #include "mozilla/dom/KeyframeEffectBinding.h" @@ -37,6 +38,18 @@ TimingParams::FromOptionsUnion( } } +/* static */ TimingParams +TimingParams::FromOptionsUnion( + const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions) +{ + if (aOptions.IsUnrestrictedDouble()) { + return TimingParams(aOptions.GetAsUnrestrictedDouble()); + } else { + MOZ_ASSERT(aOptions.IsKeyframeAnimationOptions()); + return TimingParams(aOptions.GetAsKeyframeAnimationOptions()); + } +} + bool TimingParams::operator==(const TimingParams& aOther) const { diff --git a/dom/animation/AnimationEffectTimingReadOnly.h b/dom/animation/AnimationEffectTimingReadOnly.h index 9497091ac485..03873d53002c 100644 --- a/dom/animation/AnimationEffectTimingReadOnly.h +++ b/dom/animation/AnimationEffectTimingReadOnly.h @@ -27,6 +27,7 @@ namespace mozilla { namespace dom { struct AnimationEffectTimingProperties; class UnrestrictedDoubleOrKeyframeEffectOptions; +class UnrestrictedDoubleOrKeyframeAnimationOptions; } struct TimingParams @@ -38,6 +39,8 @@ struct TimingParams static TimingParams FromOptionsUnion( const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions); + static TimingParams FromOptionsUnion( + const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions); // The unitialized state of mDuration represents "auto". // Bug 1237173: We will replace this with Maybe. diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 9e35159b1497..79ae0048c371 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -21,6 +21,7 @@ #include "nsIContentInlines.h" #include "mozilla/dom/NodeInfo.h" #include "nsIDocumentInlines.h" +#include "mozilla/dom/DocumentTimeline.h" #include "nsIDOMNodeList.h" #include "nsIDOMDocument.h" #include "nsIContentIterator.h" @@ -51,6 +52,7 @@ #include "nsDOMString.h" #include "nsIScriptSecurityManager.h" #include "nsIDOMMutationEvent.h" +#include "mozilla/dom/AnimatableBinding.h" #include "mozilla/AnimationComparator.h" #include "mozilla/AsyncEventDispatcher.h" #include "mozilla/ContentEvents.h" @@ -3309,6 +3311,58 @@ Element::MozRequestPointerLock() OwnerDoc()->RequestPointerLock(this); } +already_AddRefed +Element::Animate(JSContext* aContext, + JS::Handle aFrames, + const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions, + ErrorResult& aError) +{ + nsCOMPtr ownerGlobal = GetOwnerGlobal(); + if (!ownerGlobal) { + aError.Throw(NS_ERROR_FAILURE); + return nullptr; + } + GlobalObject global(aContext, ownerGlobal->GetGlobalJSObject()); + MOZ_ASSERT(!global.Failed()); + + // Wrap the aFrames object for the cross-compartment case. + JS::Rooted frames(aContext); + frames = aFrames; + Maybe ac; + if (js::GetContextCompartment(aContext) != + js::GetObjectCompartment(ownerGlobal->GetGlobalJSObject())) { + ac.emplace(aContext, ownerGlobal->GetGlobalJSObject()); + if (!JS_WrapObject(aContext, &frames)) { + return nullptr; + } + } + + // Bug 1211783: Use KeyframeEffect here (instead of KeyframeEffectReadOnly) + RefPtr effect = + KeyframeEffectReadOnly::Constructor(global, this, frames, + TimingParams::FromOptionsUnion(aOptions), aError); + if (aError.Failed()) { + return nullptr; + } + + RefPtr animation = + Animation::Constructor(global, effect, OwnerDoc()->Timeline(), aError); + if (aError.Failed()) { + return nullptr; + } + + if (aOptions.IsKeyframeAnimationOptions()) { + animation->SetId(aOptions.GetAsKeyframeAnimationOptions().mId); + } + + animation->Play(aError, Animation::LimitBehavior::AutoRewind); + if (aError.Failed()) { + return nullptr; + } + + return animation.forget(); +} + void Element::GetAnimations(nsTArray>& aAnimations) { diff --git a/dom/base/Element.h b/dom/base/Element.h index 304a1b59721b..1c69786997de 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -57,6 +57,7 @@ namespace mozilla { namespace dom { struct ScrollIntoViewOptions; struct ScrollToOptions; + class UnrestrictedDoubleOrKeyframeAnimationOptions; } // namespace dom } // namespace mozilla @@ -825,6 +826,12 @@ public: { } + already_AddRefed Animate( + JSContext* aContext, + JS::Handle aFrames, + const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions, + ErrorResult& aError); + // Note: GetAnimations will flush style while GetAnimationsUnsorted won't. void GetAnimations(nsTArray>& aAnimations); void GetAnimationsUnsorted(nsTArray>& aAnimations); diff --git a/dom/webidl/Animatable.webidl b/dom/webidl/Animatable.webidl index 03985f797b1f..f1e0a5564f25 100644 --- a/dom/webidl/Animatable.webidl +++ b/dom/webidl/Animatable.webidl @@ -10,8 +10,16 @@ * liability, trademark and document use rules apply. */ +dictionary KeyframeAnimationOptions : KeyframeEffectOptions { + DOMString id = ""; +}; + [NoInterfaceObject] interface Animatable { + [Func="nsDocument::IsWebAnimationsEnabled", Throws] + Animation animate(object? frames, + optional (unrestricted double or KeyframeAnimationOptions) + options); [Func="nsDocument::IsWebAnimationsEnabled"] sequence getAnimations(); };