Issue #1689 - Part 2: Add a preference for implicit keyframes

This preference controls whether authors are allowed to specify animations
without a 0% or 100% keyframe.

We intend to ship this but it isn't implemented yet (needs a follow-up) but this
preference acts as a safeguard in case we discover we need to disable it once
it's implemented.
This commit is contained in:
Moonchild 2021-01-14 16:05:53 +00:00 • committed by roytam1
commit d9693c298c
5 changed files with 35 additions and 10 deletions

View file

@ -7,6 +7,7 @@
#include "mozilla/AnimationUtils.h" #include "mozilla/AnimationUtils.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/Move.h" #include "mozilla/Move.h"
#include "mozilla/Preferences.h"
#include "mozilla/RangedArray.h" #include "mozilla/RangedArray.h"
#include "mozilla/ServoBindings.h" #include "mozilla/ServoBindings.h"
#include "mozilla/StyleAnimationValue.h" #include "mozilla/StyleAnimationValue.h"
@ -21,6 +22,7 @@
#include "nsCSSPropertyIDSet.h" #include "nsCSSPropertyIDSet.h"
#include "nsCSSProps.h" #include "nsCSSProps.h"
#include "nsCSSPseudoElements.h" // For CSSPseudoElementType #include "nsCSSPseudoElements.h" // For CSSPseudoElementType
#include "nsDocument.h"
#include "nsTArray.h" #include "nsTArray.h"
#include <algorithm> // For std::stable_sort #include <algorithm> // For std::stable_sort
@ -400,7 +402,7 @@ GetKeyframeListFromPropertyIndexedKeyframe(JSContext* aCx,
ErrorResult& aRv); ErrorResult& aRv);
static bool static bool
RequiresAdditiveAnimation(const nsTArray<Keyframe>& aKeyframes, HasImplicitKeyframeValues(const nsTArray<Keyframe>& aKeyframes,
nsIDocument* aDocument); nsIDocument* aDocument);
static void static void
@ -467,11 +469,13 @@ KeyframeUtils::GetKeyframesFromObject(JSContext* aCx,
// says that if you don't have a keyframe at offset 0 or 1, then you should // 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. // 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 // Until we implement additive animations we just throw if we encounter any
// set of keyframes that would put us in that situation. // set of keyframes that would put us in that situation and keyframes aren't
// explicitly force-enabled.
if (RequiresAdditiveAnimation(keyframes, aDocument)) { if (!nsDocument::AreWebAnimationsImplicitKeyframesEnabled(aCx, nullptr) &&
aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR); HasImplicitKeyframeValues(keyframes, aDocument)) {
keyframes.Clear(); keyframes.Clear();
aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR);
} }
return keyframes; return keyframes;
@ -1330,10 +1334,16 @@ GetKeyframeListFromPropertyIndexedKeyframe(JSContext* aCx,
// No animation values for this property. // No animation values for this property.
continue; continue;
} }
if (count == 1) { if (!Preferences::GetBool("dom.animations-api.implicit-keyframes.enabled") &&
// We don't support additive values and so can't support an count == 1) {
// animation that goes from the underlying value to this // We don't support implicit keyframes by preference.
// specified value. Throw an exception until we do support this. aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR);
return;
} else if (count == 1) {
// Implicit keyframes isn't implemented yet and so we can't
// support an animation that goes from the underlying value
// to this specified value.
// Throw an exception until we do support this.
aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR); aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR);
return; return;
} }
@ -1374,7 +1384,7 @@ GetKeyframeListFromPropertyIndexedKeyframe(JSContext* aCx,
* try to detect where we have an invalid value at 0%/100%. * try to detect where we have an invalid value at 0%/100%.
*/ */
static bool static bool
RequiresAdditiveAnimation(const nsTArray<Keyframe>& aKeyframes, HasImplicitKeyframeValues(const nsTArray<Keyframe>& aKeyframes,
nsIDocument* aDocument) nsIDocument* aDocument)
{ {
// We are looking to see if that every property referenced in |aKeyframes| // We are looking to see if that every property referenced in |aKeyframes|
@ -1385,7 +1395,7 @@ RequiresAdditiveAnimation(const nsTArray<Keyframe>& aKeyframes,
// a document which we might not always have at the point where we want to // a document which we might not always have at the point where we want to
// perform this check. // perform this check.
// //
// This is only a temporary measure until we implement additive animation. // This is only a temporary measure until we implement implicit keyframes.
// So as long as this check catches most cases, and we don't do anything // So as long as this check catches most cases, and we don't do anything
// horrible in one of the cases we can't detect, it should be sufficient. // horrible in one of the cases we can't detect, it should be sufficient.

View file

@ -1,4 +1,8 @@
[DEFAULT] [DEFAULT]
prefs =
dom.animations-api.core.enabled=true
dom.animations-api.implicit-keyframes.enabled=true
dom.animations-api.timelines.enabled=true
# Support files for chrome tests that we want to load over HTTP need # Support files for chrome tests that we want to load over HTTP need
# to go in here, not chrome.ini. # to go in here, not chrome.ini.
support-files = support-files =

View file

@ -2932,6 +2932,15 @@ nsDocument::AreWebAnimationsTimelinesEnabled(JSContext* /*unused*/, JSObject* /*
Preferences::GetBool("dom.animations-api.timelines.enabled"); Preferences::GetBool("dom.animations-api.timelines.enabled");
} }
bool
nsDocument::AreWebAnimationsImplicitKeyframesEnabled(JSContext* /*unused*/, JSObject* /*unused*/)
{
MOZ_ASSERT(NS_IsMainThread());
return nsContentUtils::IsCallerChrome() ||
Preferences::GetBool("dom.animations-api.implicit-keyframes.enabled");
}
DocumentTimeline* DocumentTimeline*
nsDocument::Timeline() nsDocument::Timeline()
{ {

View file

@ -433,6 +433,7 @@ public:
static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject); static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject);
static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject); static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
static bool AreWebAnimationsImplicitKeyframesEnabled(JSContext* aCx, JSObject* aObject);
static bool AreWebAnimationsTimelinesEnabled(JSContext* aCx, JSObject* aObject); static bool AreWebAnimationsTimelinesEnabled(JSContext* aCx, JSObject* aObject);
virtual mozilla::dom::DocumentTimeline* Timeline() override; virtual mozilla::dom::DocumentTimeline* Timeline() override;

View file

@ -2719,6 +2719,7 @@ pref("dom.animations-api.core.enabled", false);
pref("dom.animations-api.core.enabled", true); pref("dom.animations-api.core.enabled", true);
#endif #endif
pref("dom.animations-api.timelines.enabled", false); pref("dom.animations-api.timelines.enabled", false);
pref("dom.animations-api.implicit-keyframes.enabled", false);
// Is support for the Element.animate() function (a subset of the Web Animations // Is support for the Element.animate() function (a subset of the Web Animations
// API) enabled? // API) enabled?