Chrome · Animation
CVE-2026-110166
OOB in Animation
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc |
modified | |
ifthird_party/blink/renderer/core/animation/css_transform_interpolation_type.cc |
modified | |
forthird_party/blink/renderer/core/animation/invalidatable_interpolation.cc |
modified | |
ifthird_party/blink/renderer/core/animation/invalidatable_interpolation.cc |
modified |
Files Changed
third_party/blink/renderer/core/animation/css_transform_interpolation_type.ccthird_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.htmlthird_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.htmlthird_party/blink/renderer/core/animation/invalidatable_interpolation.ccthird_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.htmlthird_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
Patch
From 544a340956293550ca5eeb89d7a046879527df18 Mon Sep 17 00:00:00 2001 From: Robert Flack <[email protected]> Date: Wed, 07 Oct 2026 06:30:41 -0700 Subject: [PATCH] Fix pre-interpolation composition with mismatched underlying values When converting non-neutral additive or accumulative keyframes, InvalidatableInterpolation::MaybeConvertPairwise and ConvertSingleKeyframe should only pass underlying_value_owner.Value() to with a matching InterpolationType. This fixes issues when animating a registered custom property whose underlying value may be absent, or not convertible by any InterpolationType, or produced by a different InterpolationType. Bug: 566496747 Change-Id: Ide25c19ff4a63c8e000f90c26fcd4dc1a5b7bc65 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8521821 Commit-Queue: Robert Flack <[email protected]> Reviewed-by: Kevin Ellis <[email protected]> Cr-Commit-Position: refs/heads/main@{#1713374} --- diff --git a/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc index b3fda63..cdf44e25 100644 --- a/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc @@ -73,6 +73,12 @@ const InterpolationValue& underlying, EffectModel::CompositeOperation composite, ConversionCheckers& conversion_checkers) const { + conversion_checkers.push_back(MakeGarbageCollected<UnderlyingLengthChecker>( + UnderlyingLengthChecker::GetUnderlyingLength(underlying))); + if (!underlying) { + return value; + } + // This adapts a ListInterpolationFunctions::CompositeItemCallback function // such that we can use the InterpolationType::Composite function of the // inner interpolation type to get the answer. @@ -82,12 +88,10 @@ UnderlyingValueOwner owner; owner.Set(this, underlying); - ConversionCheckers null_checkers; - const CSSInterpolationType* interpolation_type = inner_interpolation_type_.Get(); auto composite_callback = - [interpolation_type, composite, &null_checkers]( + [interpolation_type, composite, &conversion_checkers]( UnderlyingValue& underlying_value, double underlying_fraction, const InterpolableValue& interpolable_value, const NonInterpolableValue* non_interpolable_value) { @@ -99,7 +103,7 @@ underlying_value.GetNonInterpolableValue()); InterpolationValue composite_result = interpolation_type->PreInterpolationCompositeIfNeeded( - std::move(value), underlying, composite, null_checkers); + std::move(value), underlying, composite, conversion_checkers); composite_result = composite_result.Clone(); underlying_value.SetInterpolableValue( composite_result.interpolable_value); diff --git a/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc index 860bf75..3fc0f43c 100644 --- a/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc @@ -156,6 +156,10 @@ conversion_checkers.push_back( MakeGarbageCollected<AlwaysInvalidateChecker>()); + if (!underlying) { + return value; + } + InterpolableTransformList& transform_list = To<InterpolableTransformList>(*value.interpolable_value); const InterpolableTransformList& underlying_transform_list = diff --git a/third_party/blink/renderer/core/animation/invalidatable_interpolation.cc b/third_party/blink/renderer/core/animation/invalidatable_interpolation.cc index 7f46d93..b757be9 100644 --- a/third_party/blink/renderer/core/animation/invalidatable_interpolation.cc +++ b/third_party/blink/renderer/core/animation/invalidatable_interpolation.cc @@ -42,17 +42,23 @@ InvalidatableInterpolation::MaybeConvertPairwise( const CSSInterpolationEnvironment& environment, const UnderlyingValueOwner& underlying_value_owner) const { + const InterpolationValue null_underlying(nullptr); for (const InterpolationType* interpolation_type : *interpolation_types_) { if ((start_keyframe_->IsNeutral() || end_keyframe_->IsNeutral()) && (!underlying_value_owner || underlying_value_owner.GetType() != interpolation_type)) { continue; } + const InterpolationValue& underlying = + (underlying_value_owner && + underlying_value_owner.GetType() == interpolation_type) + ? underlying_value_owner.Value() + : null_underlying; ConversionCheckers conversion_checkers; PairwiseInterpolationValue result = interpolation_type->MaybeConvertPairwise( - *start_keyframe_, *end_keyframe_, environment, - underlying_value_owner.Value(), conversion_checkers); + *start_keyframe_, *end_keyframe_, environment, underlying, + conversion_checkers); AddConversionCheckers(interpolation_type, conversion_checkers); if (result) { return MakeGarbageCollected<PairwisePrimitiveInterpolation>( @@ -71,15 +77,20 @@ if (keyframe.IsNeutral() && !underlying_value_owner) { return nullptr; } + const InterpolationValue null_underlying(nullptr); for (const InterpolationType* interpolation_type : *interpolation_types_) { if (keyframe.IsNeutral() && underlying_value_owner.GetType() != interpolation_type) { continue; } + const InterpolationValue& underlying = + (underlying_value_owner && + underlying_value_owner.GetType() == interpolation_type) + ? underlying_value_owner.Value() + : null_underlying; ConversionCheckers conversion_checkers; InterpolationValue result = interpolation_type->MaybeConvertSingle( - keyframe, environment, underlying_value_owner.Value(), - conversion_checkers); + keyframe, environment, underlying, conversion_checkers); AddConversionCheckers(interpolation_type, conversion_checkers); if (result) { return MakeGarbageCollected<TypedInterpolationValue>(interpolation_type, @@ -154,8 +165,14 @@ return false; } } + const InterpolationValue null_underlying(nullptr); for (const auto& checker : conversion_checkers_) { - if (!checker->IsValid(environment, underlying_value_owner.Value())) { + const InterpolationValue& underlying = + (underlying_value_owner && + underlying_value_owner.GetType() == checker->GetType()) + ? underlying_value_owner.Value() + : null_underlying; + if (!checker->IsValid(environment, underlying)) { return false; } } diff --git a/third_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.html b/third_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.html index f8e0a01..0ef9f7c3 100644 --- a/third_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.html +++ b/third_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.html @@ -144,5 +144,70 @@ {at: 1.5, is: '100px'}, ]); +CSS.registerProperty({ + name: '--transform-list-or-none', + syntax: '<transform-list> | none', + initialValue: 'none', + inherits: false +}); + +CSS.registerProperty({ + name: '--number-list-or-transform-list', + syntax: '<number>+ | <transform-list>', + initialValue: '100', + inherits: false +}); + +CSS.registerProperty({ + name: '--length-list-or-transform-function-list', + syntax: '<length># | <transform-function>#', + initialValue: '10px, 20px', + inherits: false +}); + +assertComposition({ + property: '--transform-list-or-none', + underlying: 'none', + addFrom: 'translateX(10px) scale(2)', + addTo: 'translateX(100px) scale(4)', +}, [ + {at: 0, is: 'translateX(10px) scale(2)'}, + {at: 0.5, is: 'translateX(55px) scale(3)'}, + {at: 1, is: 'translateX(100px) scale(4)'}, +]); + +assertComposition({ + property: '--number-list-or-transform-list', + underlying: '100', + addFrom: 'translateX(10px)', + addTo: 'translateX(100px)', +}, [ + {at: 0, is: 'translateX(10px)'}, + {at: 0.5, is: 'translateX(55px)'}, + {at: 1, is: 'translateX(100px)'}, +]); + +assertComposition({ + property: '--number-list-or-transform-list', + underlying: 'translateX(100px)', + addFrom: '10', + addTo: '100', +}, [ + {at: 0, is: '10'}, + {at: 0.5, is: '55'}, + {at: 1, is: '100'}, +]); + +assertComposition({ + property: '--length-list-or-transform-function-list', + underlying: '10px, 20px', + addFrom: 'translateX(10px), scale(2)', + addTo: 'translateX(100px), scale(4)', +}, [ + {at: 0, is: 'translateX(10px), scale(2)'}, + {at: 0.5, is: 'translateX(55px), scale(3)'}, + {at: 1, is: 'translateX(100px), scale(4)'}, +]); + </script> </body> diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.html index 9575744..3f0fc5bf 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.html +++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.html @@ -15,4 +15,88 @@ expected: "200" }, 'Animating a custom property allowing multiple list types with two mismatching types'); +animation_test({ + syntax: "<number>+ | <transform-list>", + inherits: false, + initialValue: "translateX(100px)" +}, { + composite: "add", + keyframes: ["100", "200"], + expected: "150" +}, 'Additive animation of <number>+ when underlying value is <transform-list>'); + +animation_test({ + syntax: "<number>+ | <transform-list>", + inherits: false, + initialValue: "100" +}, { + composite: "add", + keyframes: ["translateX(100px)", "translateX(200px)"], + expected: "translateX(150px)" +}, 'Additive animation of <transform-list> when underlying value is <number>+'); + +animation_test({ + syntax: "<transform-function> | <transform-list>", + inherits: false, + initialValue: "translateX(100px) scale(2)" +}, { + composite: "add", + keyframes: ["translateX(200px)", "translateX(300px)"], + expected: "translateX(250px)" +}, 'Additive animation of <transform-function> when underlying value is a multi-item <transform-list>'); + +animation_test({ + syntax: "<length># | <transform-function>#", + inherits: false, + initialValue: "10px, 20px" +}, { + composite: "add", + keyframes: ["translateX(100px), scale(2)", "translateX(200px), scale(4)"], + expected: "translateX(150px), scale(3)" +}, 'Additive animation of <transform-function># when underlying value is <length>#'); + +animation_test({ + syntax: "<transform-function># | none", + inherits: false, + initialValue: "none" +}, { + composite: "add", + keyframes: ["translateX(100px), scale(2)", "translateX(200px), scale(4)"], + expected: "translateX(150px), scale(3)" +}, 'Additive animation of <transform-function># when underlying value is none'); + +test(() => { + const name = generate_name(); + CSS.registerProperty({ + name, + syntax: "<transform-function>#", + inherits: false, + initialValue: "translateX(10px), scale(2)" + }); + + target.style.setProperty(name, "translateX(10px)"); + const anim = target.animate( + { [name]: ["translateX(20px), scale(3)", "translateX(40px), scale(5)"] }, + { duration: 1000, composite: "add" } + ); + anim.pause(); + anim.currentTime = 500; + + // Underlying list length (1) != keyframe list length (2), falls back to replace. + assert_equals( + getComputedStyle(target).getPropertyValue(name), + "translateX(30px), scale(4)" + ); + + // Dynamically updating underlying list to length 2 invalidates cache and composites. + target.style.setProperty(name, "translateX(10px), scale(2)"); + assert_equals( + getComputedStyle(target).getPropertyValue(name), + "translateX(40px), scale(5)" + ); + + target.style.removeProperty(name); + anim.cancel(); +}, 'Additive <transform-function># animation with dynamic underlying list length and value update'); + </script> diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html index 161703a6..f090251 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html +++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html @@ -65,4 +65,123 @@ assert_function: assert_matrix_equals }, 'Animating a custom property of type <transform-list> containing multiple values and with mismatching list lengths'); +animation_test({ + syntax: "<transform-list> | none", + inherits: false, + initialValue: "none" +}, { + composite: "add", + keyframes: ["translateX(100px) scale(2)", "translateX(200px) scale(4)"], + expected: "translateX(150px) scale(3)" +}, 'Animating a custom property of type <transform-list> | none with additivity when underlying value is none'); + +animation_test({ + syntax: "<transform-list> | none", + inherits: false, + initialValue: "none" +}, { + composite: "accumulate", + keyframes: ["translateX(100px) scale(2)", "translateX(200px) scale(4)"], + expected: "translateX(150px) scale(3)" +}, 'Animating a custom property of type <transform-list> | none with accumulation when underlying value is none'); + +test(() => { + const name = generate_name(); + CSS.registerProperty({ + name, + syntax: "<transform-list> | none", + inherits: false, + initialValue: "translateX(100px) scale(2)" + }); + + target.style.setProperty(name, "none"); + const animation = target.animate( + { [name]: ["translateX(200px) scale(3)", "translateX(300px) scale(4)"] }, + { duration: 1000, composite: "add" } + ); + animation.pause(); + animation.currentTime = 500; + + // When the underlying value is none, composition falls back to replace. + assert_equals( + getComputedStyle(target).getPropertyValue(name), + "translateX(250px) scale(3.5)" + ); + + // Dynamically restoring a valid underlying <transform-list> invalidates the + // conversion cache and composites with the new underlying value. + target.style.setProperty(name, "translateX(100px) scale(2)"); + assert_equals( + getComputedStyle(target).getPropertyValue(name), + "translateX(100px) scale(2) translateX(250px) scale(3.5)" + ); + + target.style.removeProperty(name); + animation.cancel(); +}, 'Additive <transform-list> | none animation with dynamic underlying value update from none'); + +test(() => { + const name = generate_name(); + CSS.registerProperty({ + name, + syntax: "<transform-list>", + inherits: false, + initialValue: "translateX(100px) scale(2)" + }); + + const baseAnim = target.animate( + { [name]: ["var(--invalid, invalid)", "var(--invalid, invalid)"] }, + { duration: 1000 } + ); + baseAnim.pause(); + baseAnim.currentTime = 500; + + const addAnim = target.animate( + { [name]: ["translateX(200px) scale(3)", "translateX(300px) scale(4)"] }, + { duration: 1000, composite: "add" } + ); + addAnim.pause(); + addAnim.currentTime = 500; + + assert_equals( ... (file diff truncated)
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/third_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.html b/third_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.html
index f8e0a01..0ef9f7c3 100644
--- a/third_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.html
+++ b/third_party/blink/web_tests/animations/custom-properties/custom-list-type-interpolation.html
@@ -144,5 +144,70 @@
{at: 1.5, is: '100px'},
]);
+CSS.registerProperty({
+ name: '--transform-list-or-none',
+ syntax: '<transform-list> | none',
+ initialValue: 'none',
+ inherits: false
+});
+
+CSS.registerProperty({
+ name: '--number-list-or-transform-list',
+ syntax: '<number>+ | <transform-list>',
+ initialValue: '100',
+ inherits: false
+});
+
+CSS.registerProperty({
+ name: '--length-list-or-transform-function-list',
+ syntax: '<length># | <transform-function>#',
+ initialValue: '10px, 20px',
+ inherits: false
+});
+
+assertComposition({
+ property: '--transform-list-or-none',
+ underlying: 'none',
+ addFrom: 'translateX(10px) scale(2)',
+ addTo: 'translateX(100px) scale(4)',
+}, [
+ {at: 0, is: 'translateX(10px) scale(2)'},
+ {at: 0.5, is: 'translateX(55px) scale(3)'},
+ {at: 1, is: 'translateX(100px) scale(4)'},
+]);
+
+assertComposition({
+ property: '--number-list-or-transform-list',
+ underlying: '100',
+ addFrom: 'translateX(10px)',
+ addTo: 'translateX(100px)',
+}, [
+ {at: 0, is: 'translateX(10px)'},
+ {at: 0.5, is: 'translateX(55px)'},
+ {at: 1, is: 'translateX(100px)'},
+]);
+
+assertComposition({
+ property: '--number-list-or-transform-list',
+ underlying: 'translateX(100px)',
+ addFrom: '10',
+ addTo: '100',
+}, [
+ {at: 0, is: '10'},
+ {at: 0.5, is: '55'},
+ {at: 1, is: '100'},
+]);
+
+assertComposition({
+ property: '--length-list-or-transform-function-list',
+ underlying: '10px, 20px',
+ addFrom: 'translateX(10px), scale(2)',
+ addTo: 'translateX(100px), scale(4)',
+}, [
+ {at: 0, is: 'translateX(10px), scale(2)'},
+ {at: 0.5, is: 'translateX(55px), scale(3)'},
+ {at: 1, is: 'translateX(100px), scale(4)'},
+]);
+
</script>
</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.html
index 9575744..3f0fc5bf 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-list-type-mismatch.html
@@ -15,4 +15,88 @@
expected: "200"
}, 'Animating a custom property allowing multiple list types with two mismatching types');
+animation_test({
+ syntax: "<number>+ | <transform-list>",
+ inherits: false,
+ initialValue: "translateX(100px)"
+}, {
+ composite: "add",
+ keyframes: ["100", "200"],
+ expected: "150"
+}, 'Additive animation of <number>+ when underlying value is <transform-list>');
+
+animation_test({
+ syntax: "<number>+ | <transform-list>",
+ inherits: false,
+ initialValue: "100"
+}, {
+ composite: "add",
+ keyframes: ["translateX(100px)", "translateX(200px)"],
+ expected: "translateX(150px)"
+}, 'Additive animation of <transform-list> when underlying value is <number>+');
+
+animation_test({
+ syntax: "<transform-function> | <transform-list>",
+ inherits: false,
+ initialValue: "translateX(100px) scale(2)"
+}, {
+ composite: "add",
+ keyframes: ["translateX(200px)", "translateX(300px)"],
+ expected: "translateX(250px)"
+}, 'Additive animation of <transform-function> when underlying value is a multi-item <transform-list>');
+
+animation_test({
+ syntax: "<length># | <transform-function>#",
+ inherits: false,
+ initialValue: "10px, 20px"
+}, {
+ composite: "add",
+ keyframes: ["translateX(100px), scale(2)", "translateX(200px), scale(4)"],
+ expected: "translateX(150px), scale(3)"
+}, 'Additive animation of <transform-function># when underlying value is <length>#');
+
+animation_test({
+ syntax: "<transform-function># | none",
+ inherits: false,
+ initialValue: "none"
+}, {
+ composite: "add",
+ keyframes: ["translateX(100px), scale(2)", "translateX(200px), scale(4)"],
+ expected: "translateX(150px), scale(3)"
+}, 'Additive animation of <transform-function># when underlying value is none');
+
+test(() => {
+ const name = generate_name();
+ CSS.registerProperty({
+ name,
+ syntax: "<transform-function>#",
+ inherits: false,
+ initialValue: "translateX(10px), scale(2)"
+ });
+
+ target.style.setProperty(name, "translateX(10px)");
+ const anim = target.animate(
+ { [name]: ["translateX(20px), scale(3)", "translateX(40px), scale(5)"] },
+ { duration: 1000, composite: "add" }
+ );
+ anim.pause();
+ anim.currentTime = 500;
+
+ // Underlying list length (1) != keyframe list length (2), falls back to replace.
+ assert_equals(
+ getComputedStyle(target).getPropertyValue(name),
+ "translateX(30px), scale(4)"
+ );
+
+ // Dynamically updating underlying list to length 2 invalidates cache and composites.
+ target.style.setProperty(name, "translateX(10px), scale(2)");
+ assert_equals(
+ getComputedStyle(target).getPropertyValue(name),
+ "translateX(40px), scale(5)"
+ );
+
+ target.style.removeProperty(name);
+ anim.cancel();
+}, 'Additive <transform-function># animation with dynamic underlying list length and value update');
+
</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html
index 161703a6..f090251 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html
@@ -65,4 +65,123 @@
assert_function: assert_matrix_equals
}, 'Animating a custom property of type <transform-list> containing multiple values and with mismatching list lengths');
+animation_test({
+ syntax: "<transform-list> | none",
+ inherits: false,
+ initialValue: "none"
+}, {
+ composite: "add",
+ keyframes: ["translateX(100px) scale(2)", "translateX(200px) scale(4)"],
+ expected: "translateX(150px) scale(3)"
+}, 'Animating a custom property of type <transform-list> | none with additivity when underlying value is none');
+
+animation_test({
+ syntax: "<transform-list> | none",
+ inherits: false,
+ initialValue: "none"
+}, {
+ composite: "accumulate",
+ keyframes: ["translateX(100px) scale(2)", "translateX(200px) scale(4)"],
+ expected: "translateX(150px) scale(3)"
+}, 'Animating a custom property of type <transform-list> | none with accumulation when underlying value is none');
+
+test(() => {
+ const name = generate_name();
+ CSS.registerProperty({
+ name,
+ syntax: "<transform-list> | none",
+ inherits: false,
+ initialValue: "translateX(100px) scale(2)"
+ });
+
+ target.style.setProperty(name, "none");
+ const animation = target.animate(
+ { [name]: ["translateX(200px) scale(3)", "translateX(300px) scale(4)"] },
+ { duration: 1000, composite: "add" }
+ );
+ animation.pause();
+ animation.currentTime = 500;
+
+ // When the underlying value is none, composition falls back to replace.
+ assert_equals(
+ getComputedStyle(target).getPropertyValue(name),
+ "translateX(250px) scale(3.5)"
+ );
+
+ // Dynamically restoring a valid underlying <transform-list> invalidates the
+ // conversion cache and composites with the new underlying value.
+ target.style.setProperty(name, "translateX(100px) scale(2)");
+ assert_equals(
+ getComputedStyle(target).getPropertyValue(name),
+ "translateX(100px) scale(2) translateX(250px) scale(3.5)"
+ );
+
+ target.style.removeProperty(name);
+ animation.cancel();
+}, 'Additive <transform-list> | none animation with dynamic underlying value update from none');
+
+test(() => {
+ const name = generate_name();
+ CSS.registerProperty({
+ name,
+ syntax: "<transform-list>",
+ inherits: false,
+ initialValue: "translateX(100px) scale(2)"
+ });
+
+ const baseAnim = target.animate(
+ { [name]: ["var(--invalid, invalid)", "var(--invalid, invalid)"] },
+ { duration: 1000 }
+ );
+ baseAnim.pause();
+ baseAnim.currentTime = 500;
+
+ const addAnim = target.animate(
+ { [name]: ["translateX(200px) scale(3)", "translateX(300px) scale(4)"] },
+ { duration: 1000, composite: "add" }
+ );
+ addAnim.pause();
+ addAnim.currentTime = 500;
+
+ assert_equals(
+ getComputedStyle(target).getPropertyValue(name),
+ "translateX(250px) scale(3.5)"
+ );
+
+ addAnim.cancel();
+ baseAnim.cancel();
+}, 'Additive <transform-list> animation stacked on top of a discrete var(--invalid, invalid) animation');
+
+test(() => {
+ const name = generate_name();
+ CSS.registerProperty({
+ name,
+ syntax: "<transform-list> | none",
+ inherits: false,
+ initialValue: "translateX(100px) scale(2)"
+ });
+
+ const baseAnim = target.animate(
+ { [name]: ["none", "none"] },
+ { duration: 1000 }
+ );
+ baseAnim.pause();
+ baseAnim.currentTime = 500;
+
+ const addAnim = target.animate(
+ { [name]: ["translateX(200px) scale(3)", "translateX(300px) scale(4)"] },
+ { duration: 1000, composite: "add" }
+ );
+ addAnim.pause();
+ addAnim.currentTime = 500;
+
+ assert_equals(
+ getComputedStyle(target).getPropertyValue(name),
+ "translateX(250px) scale(3.5)"
+ );
+
+ addAnim.cancel();
+ baseAnim.cancel();
+}, 'Additive <transform-list> animation stacked on top of a discrete none animation');
+
</script>
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page