Bug 1631989 [wpt PR 23159] - [@property] Add PropertyRegistry::Version, a=testonly

Automatic update from web-platform-tests
[@property] Add PropertyRegistry::Version

The version is simply a number that increases monotonically for each
change to the registry. This is needed by the animations machinery to
handle cases where the type of a registered custom property changes
on the fly during an ongoing animation. (See InvalidatableInterpolation
::EnsureValidInterpolationTypes). When the version changes, we can
clear the conversion cache, which causes the keyframes to be
reinterpreted according to the new registration.

Also move some utils from at-property.html to utils.js, for reuse
in other test files.

Bug: 973830
Change-Id: I97d0a37f016ccde649fe1482084707edd123903b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2159212
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#761323}

--

wpt-commits: 0a970f919e3a8f134f6b8b4cd03e63ef865bd38f
wpt-pr: 23159
This commit is contained in:
Anders Hartvoll Ruud 2020-04-28 11:36:19 +00:00 committed by moz-wptsync-bot
parent ddccae8e0f
commit 3fe27d14e9
3 changed files with 230 additions and 46 deletions

View File

@ -0,0 +1,190 @@
<!DOCTYPE html>
<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./resources/utils.js"></script>
<div id=outer>
<div id=div></div>
</div>
<script>
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, (name) => {
with_style_node(`
@keyframes test {
from { ${name}: 100px; }
to { ${name}: 200px; }
}
#div { animation: test 100s -50s linear; }
`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), '150px');
});
}, '@keyframes works with @property');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, (name) => {
with_style_node(`
@property ${name} {
syntax: "<color>";
inherits: false;
initial-value: black;
}
@keyframes test {
from { ${name}: rgb(100, 100, 100); }
to { ${name}: rgb(200, 200, 200); }
}
#div { animation: test 100s -50s linear; }
`, () => {
assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(150, 150, 150)');
});
}, '@keyframes picks up the latest @property in the document');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, (name) => {
// These keyframes are initially invalid for the declared custom property.
let animation = div.animate([
{ [name]: 'rgb(100, 100, 100)'},
{ [name]: 'rgb(200, 200, 200)'},
], { duration: 10000, delay: -5000, easing: 'linear' });
let cs = getComputedStyle(div);
assert_equals(cs.getPropertyValue(name), '0px');
// Redeclare the property as a <color>, effectively making the existing
// keyframes valid.
with_at_property({
name: name,
syntax: '"<color>"',
inherits: false,
initalValue: 'black'
}, (name) => {
assert_equals(cs.getPropertyValue(name), 'rgb(150, 150, 150)');
});
animation.finish();
}, 'Ongoing animation picks up redeclared custom property');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, (name) => {
// These keyframes are initially invalid for the declared custom property.
let animation = div.animate([
{ [name]: 'rgb(100, 100, 100)'},
{ [name]: 'rgb(200, 200, 200)'},
], { duration: 10000, delay: -5000, easing: 'linear' });
let cs = getComputedStyle(div);
assert_equals(cs.getPropertyValue(name), '0px');
// Setting the keyframes to something that matches <length> makes the
// interpolation valid.
animation.effect.setKeyframes([
{[name]: '100px'},
{[name]: '200px'}
]);
assert_equals(cs.getPropertyValue(name), '150px');
animation.finish();
}, 'Ongoing animation matches new keyframes against the current registration');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, (name) => {
let animation = div.animate([
{ [name]: 'initial'},
{ [name]: '400px'},
], { duration: 10000, delay: -5000, easing: 'linear' });
let cs = getComputedStyle(div);
assert_equals(cs.getPropertyValue(name), '200px');
// Change initial value.
with_at_property({
name: name,
syntax: '"<length>"',
inherits: false,
initialValue: '100px'
}, (name) => {
assert_equals(cs.getPropertyValue(name), '250px');
});
animation.finish();
}, 'Ongoing animation picks up redeclared intial value');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, (name) => {
try {
document.body.style = `${name}: 100px`;
// Note that 'inherit' here refers to #outer, which has the initial
// value. (#outer did not inherit from body, since the property is not
// yet declared as inherited).
let animation = div.animate([
{ [name]: 'inherit'},
{ [name]: '400px'},
], { duration: 10000, delay: -5000, easing: 'linear' });
let cs = getComputedStyle(div);
assert_equals(cs.getPropertyValue(name), '200px');
// Change inherits to 'true'. The value should now propagate from body
// to #outer.
with_at_property({
name: name,
syntax: '"<length>"',
inherits: true,
initialValue: '0px'
}, (name) => {
assert_equals(cs.getPropertyValue(name), '250px');
});
animation.finish();
} finally {
document.body.style = '';
}
}, 'Ongoing animation picks up redeclared inherits flag');
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
}, (name) => {
try {
outer.style = `${name}: 100px`;
// 'unset' should take the initial value (not the value from #outer), since
// the property is not declared as inherited.
let animation = div.animate([
{ [name]: 'unset'},
{ [name]: '400px'},
], { duration: 10000, delay: -5000, easing: 'linear' });
let cs = getComputedStyle(div);
assert_equals(cs.getPropertyValue(name), '200px');
// Change inherits to 'true'. 'unset' now refers to #outer's value.
with_at_property({
name: name,
syntax: '"<length>"',
inherits: true,
initialValue: '0px'
}, (name) => {
assert_equals(cs.getPropertyValue(name), '250px');
});
animation.finish();
} finally {
outer.style = '';
}
}, 'Ongoing animation picks up redeclared meaning of \'unset\'');
</script>

View File

@ -2,50 +2,12 @@
<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1/#at-property-rule">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./resources/utils.js"></script>
<div id="outer">
<div id="target"></div>
</div>
<script>
let g_id = 0;
function generate_name() {
g_id++;
return `--property-${g_id}`;
}
function with_style_node(text, fn) {
let node = document.createElement('style');
node.textContent = text;
try {
document.body.append(node);
fn(node);
} finally {
node.remove();
}
}
function with_at_rule(desc, fn) {
let name = typeof(desc.name) === 'undefined' ? generate_name() : desc.name;
let text = `@property ${name} {`;
if (typeof(desc.syntax) !== 'undefined')
text += `syntax:${desc.syntax};`;
if (typeof(desc.initialValue) !== 'undefined')
text += `initial-value:${desc.initialValue};`;
if (typeof(desc.inherits) !== 'undefined')
text += `inherits:${desc.inherits};`;
text += '}';
with_style_node(text, (node) => fn(name, node.sheet.rules[0]));
}
function test_with_at_rule(desc, fn, description) {
test(() => with_at_rule(desc, fn), description);
}
function test_with_style_node(text, fn, description) {
test(() => with_style_node(text, fn), description);
}
// Parsing:
let uppercase_first = (x) => x.charAt(0).toUpperCase() + x.slice(1);
@ -72,7 +34,7 @@ function test_descriptor(descriptor, specified_value, expected_value) {
let camel = to_camel_case(descriptor);
if (typeof(expected_value) === 'undefined')
expected_value = specified_value;
test_with_at_rule({ [camel]: specified_value }, (name, rule) => {
test_with_at_property({ [camel]: specified_value }, (name, rule) => {
assert_equals(get_cssom_descriptor_value(rule, descriptor), expected_value);
}, `Attribute '${descriptor}' returns expected value for [${specified_value}]`);
}
@ -120,7 +82,7 @@ test_with_style_node('@property -foo { }', (node) => {
// Applying @property rules
function test_applied(syntax, initial, inherits, expected) {
test_with_at_rule({
test_with_at_property({
syntax: `"${syntax}"`,
initialValue: initial,
inherits: inherits
@ -131,7 +93,7 @@ function test_applied(syntax, initial, inherits, expected) {
}
function test_not_applied(syntax, initial, inherits) {
test_with_at_rule({
test_with_at_property({
syntax: `"${syntax}"`,
initialValue: initial,
inherits: inherits
@ -168,7 +130,7 @@ test_applied('<url>', 'url("http://a/")', false, 'url("http://a/")');
test_applied('<color>', 'tomato', false, 'rgb(255, 99, 71)');
test_applied('<color>', 'tomato', true, 'rgb(255, 99, 71)');
test_with_at_rule({ syntax: '"*"', inherits: true }, (name, rule) => {
test_with_at_property({ syntax: '"*"', inherits: true }, (name, rule) => {
try {
outer.style.setProperty(name, 'foo');
let actual = getComputedStyle(target).getPropertyValue(name);
@ -188,7 +150,7 @@ test_not_applied('<length>', '10em', false);
// Inheritance
test_with_at_rule({
test_with_at_property({
syntax: '"<length>"',
inherits: false,
initialValue: '0px'
@ -202,7 +164,7 @@ test_with_at_rule({
}
}, 'Non-inherited properties do not inherit');
test_with_at_rule({
test_with_at_property({
syntax: '"<length>"',
inherits: true,
initialValue: '0px'
@ -216,7 +178,7 @@ test_with_at_rule({
}
}, 'Inherited properties inherit');
test_with_at_rule({
test_with_at_property({
syntax: '"<color>"',
inherits: true,
initialValue: 'green'

View File

@ -92,3 +92,35 @@ function all_syntaxes() {
'<url>'
]
}
function with_style_node(text, fn) {
let node = document.createElement('style');
node.textContent = text;
try {
document.body.append(node);
fn(node);
} finally {
node.remove();
}
}
function with_at_property(desc, fn) {
let name = typeof(desc.name) === 'undefined' ? generate_name() : desc.name;
let text = `@property ${name} {`;
if (typeof(desc.syntax) !== 'undefined')
text += `syntax:${desc.syntax};`;
if (typeof(desc.initialValue) !== 'undefined')
text += `initial-value:${desc.initialValue};`;
if (typeof(desc.inherits) !== 'undefined')
text += `inherits:${desc.inherits};`;
text += '}';
with_style_node(text, (node) => fn(name, node.sheet.rules[0]));
}
function test_with_at_property(desc, fn, description) {
test(() => with_at_property(desc, fn), description);
}
function test_with_style_node(text, fn, description) {
test(() => with_style_node(text, fn), description);
}