Bug 1402219 - Compute css variables with custom properties in keyframes for getKeyframes(). r?birtles
MozReview-Commit-ID: 7CMnWbzzemY
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -1250,28 +1250,49 @@ KeyframeEffectReadOnly::GetKeyframes(JSC
}
JS::Rooted<JS::Value> keyframeJSValue(aCx);
if (!ToJSValue(aCx, keyframeDict, &keyframeJSValue)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
+ RefPtr<RawServoDeclarationBlock> customProperties;
+ // A workaround for CSS Animations in servo backend, custom properties in
+ // keyframe are stored in a servo's declaration block. Find the declaration
+ // block to resolve CSS variables in the keyframe.
+ // This workaround will be solved by bug 1391537.
+ if (isServo && isCSSAnimation) {
+ for (const PropertyValuePair& propertyValue : keyframe.mPropertyValues) {
+ if (propertyValue.mProperty ==
+ nsCSSPropertyID::eCSSPropertyExtra_variable) {
+ customProperties = propertyValue.mServoDeclarationBlock;
+ break;
+ }
+ }
+ }
+
JS::Rooted<JSObject*> keyframeObject(aCx, &keyframeJSValue.toObject());
for (const PropertyValuePair& propertyValue : keyframe.mPropertyValues) {
nsAutoString stringValue;
if (isServo) {
+ // Don't serialize the custom properties for this keyframe.
+ if (propertyValue.mProperty ==
+ nsCSSPropertyID::eCSSPropertyExtra_variable) {
+ continue;
+ }
if (propertyValue.mServoDeclarationBlock) {
const ServoStyleContext* servoStyleContext =
styleContext ? styleContext->AsServo() : nullptr;
Servo_DeclarationBlock_SerializeOneValue(
propertyValue.mServoDeclarationBlock,
propertyValue.mProperty,
&stringValue,
- servoStyleContext);
+ servoStyleContext,
+ customProperties);
} else {
RawServoAnimationValue* value =
mBaseStyleValuesForServo.GetWeak(propertyValue.mProperty);
if (value) {
Servo_AnimationValue_Serialize(value,
propertyValue.mProperty,
&stringValue);
--- a/dom/animation/test/css-animations/file_keyframeeffect-getkeyframes.html
+++ b/dom/animation/test/css-animations/file_keyframeeffect-getkeyframes.html
@@ -131,23 +131,31 @@
}
@keyframes anim-background-size {
to { background-size: 50%, 6px, contain }
}
:root {
--var-100px: 100px;
+ --end-color: rgb(255, 0, 0);
}
@keyframes anim-variables {
to { transform: translate(var(--var-100px), 0) }
}
@keyframes anim-variables-shorthand {
to { margin: var(--var-100px) }
}
+@keyframes anim-custom-property-in-keyframe {
+ to { --end-color: rgb(0, 255, 0); color: var(--end-color) }
+}
+@keyframes anim-only-custom-property-in-keyframe {
+ from { transform: translate(100px, 0) }
+ to { --not-used: 200px }
+}
</style>
<body>
<script>
"use strict";
function getKeyframes(e) {
return e.getAnimations()[0].effect.getKeyframes();
}
@@ -694,11 +702,52 @@ test(function(t) {
marginRight: "100px",
marginTop: "100px" },
];
for (var i = 0; i < frames.length; i++) {
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
}
}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
'animations with CSS variables as keyframe values in a shorthand property');
+
+test(function(t) {
+ var div = addDiv(t);
+ div.style.animation = 'anim-custom-property-in-keyframe 100s';
+
+ var frames = getKeyframes(div);
+
+ assert_equals(frames.length, 2, "number of frames");
+
+ var expected = [
+ { offset: 0, computedOffset: 0, easing: "ease",
+ color: "rgb(0, 0, 0)" },
+ { offset: 1, computedOffset: 1, easing: "ease",
+ color: "rgb(0, 255, 0)" },
+ ];
+ for (var i = 0; i < frames.length; i++) {
+ assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
+ }
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
+ 'animations with a CSS variable which is overriden by the value in keyframe');
+
+test(function(t) {
+ var div = addDiv(t);
+ div.style.animation = 'anim-only-custom-property-in-keyframe 100s';
+
+ var frames = getKeyframes(div);
+
+ assert_equals(frames.length, 2, "number of frames");
+
+ var expected = [
+ { offset: 0, computedOffset: 0, easing: "ease",
+ transform: "translate(100px, 0px)" },
+ { offset: 1, computedOffset: 1, easing: "ease",
+ transform: "none" },
+ ];
+ for (var i = 0; i < frames.length; i++) {
+ assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
+ }
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
+ 'animations with only custom property in a keyframe');
+
done();
</script>
</body>
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -386,17 +386,18 @@ SERVO_BINDING_FUNC(Servo_DeclarationBloc
RawServoDeclarationBlockBorrowed a,
RawServoDeclarationBlockBorrowed b)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetCssText, void,
RawServoDeclarationBlockBorrowed declarations,
nsAString* result)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_SerializeOneValue, void,
RawServoDeclarationBlockBorrowed declarations,
nsCSSPropertyID property, nsAString* buffer,
- ServoStyleContextBorrowedOrNull computed_values)
+ ServoStyleContextBorrowedOrNull computed_values,
+ RawServoDeclarationBlockBorrowedOrNull custom_properties)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_Count, uint32_t,
RawServoDeclarationBlockBorrowed declarations)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetNthProperty, bool,
RawServoDeclarationBlockBorrowed declarations,
uint32_t index, nsAString* result)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetPropertyValue, void,
RawServoDeclarationBlockBorrowed declarations,
const nsACString* property, nsAString* value)