Commit d30aa507 authored by Anders Hartvoll Ruud's avatar Anders Hartvoll Ruud Committed by Commit Bot

Ship @supports selector()

Unfortunately, some animation tests are now failing, because the tests
use CSS.supports to query for ::marker support, and change their
behavior to include ::marker animations. Animating ::marker is currently
not allowed by the spec, and therefore not supported by Blink.

I2S: https://groups.google.com/a/chromium.org/d/topic/blink-dev/MVXTnyC_4bQ/discussion
Bug: 979041, 1054509
Change-Id: Ib97bec4b4ef9e83598543b6d77bc48e434c6180a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2064930
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Reviewed-by: default avatarXiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745427}
parent 7f26909f
......@@ -521,6 +521,7 @@
},
{
name: "CSSSupportsSelector",
status: "stable",
},
{
name: "CSSVariables2",
......
......@@ -1801,6 +1801,8 @@ crbug.com/1012289 external/wpt/css/css-lists/list-style-type-string-005b.html [
crbug.com/995106 external/wpt/css/css-pseudo/first-letter-exclude-inline-marker.html [ Failure ]
crbug.com/995106 external/wpt/css/css-pseudo/first-letter-exclude-inline-child-marker.html [ Failure ]
crbug.com/1054509 external/wpt/css/css-transitions/non-rendered-element-004.tentative.html [ Skip ]
# ====== Style team owned tests to here ======
# ====== OOPIF-mode failures from here ======
......@@ -3408,7 +3410,6 @@ crbug.com/626703 external/wpt/css/css-text/white-space/trailing-ideographic-spac
crbug.com/626703 external/wpt/css/css-fonts/variations/font-descriptor-range-reversed.html [ Failure ]
crbug.com/626703 external/wpt/css/css-will-change/will-change-abspos-cb-dynamic-001.html [ Failure ]
crbug.com/626703 external/wpt/css/css-will-change/will-change-abspos-cb-001.html [ Failure ]
crbug.com/626703 external/wpt/css/css-conditional/at-supports-040.html [ Failure ]
### See crbug.com/891427 comment near the top of this file:
crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-block-margins-2.html [ Failure ]
crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_center.html [ Failure ]
......
......@@ -14,5 +14,6 @@ PASS Yet-to-start CSS Animations are returned
PASS CSS Animations canceled via the API are not returned
PASS CSS Animations canceled and restarted via the API are returned
PASS CSS Animations targetting (pseudo-)elements should have correct order after sorting
FAIL CSS Animations targetting (pseudo-)elements should have correct order after sorting (::marker) assert_equals: CSS animations on both pseudo-elements and elements are returned expected 5 but got 4
Harness: the test ran to completion.
......@@ -262,83 +262,88 @@ test(t => {
'returned');
}, 'CSS Animations canceled and restarted via the API are returned');
test(t => {
// Create two divs with the following arrangement:
//
// parent
// (::marker,)
// ::before,
// ::after
// |
// child
addStyle(t, {
'#parent::after': "content: ''; animation: animLeft 100s;",
'#parent::before': "content: ''; animation: animRight 100s;",
});
function pseudoTest(description, testMarkerPseudos) {
test(t => {
// Create two divs with the following arrangement:
//
// parent
// (::marker,) // Optionally
// ::before,
// ::after
// |
// child
const supportsMarkerPseudos = CSS.supports('selector(::marker)');
if (supportsMarkerPseudos) {
addStyle(t, {
'#parent': 'display: list-item;',
'#parent::marker': "content: ''; animation: animLeft 100s;",
'#parent::after': "content: ''; animation: animLeft 100s;",
'#parent::before': "content: ''; animation: animRight 100s;",
});
}
const parent = addDiv(t, { id: 'parent' });
const child = addDiv(t);
parent.appendChild(child);
for (const div of [parent, child]) {
div.setAttribute('style', 'animation: animBottom 100s');
}
const expectedAnimations = [
[parent, undefined],
[parent, '::marker'],
[parent, '::before'],
[parent, '::after'],
[child, undefined],
];
if (!supportsMarkerPseudos) {
expectedAnimations.splice(1, 1);
}
const animations = document.getAnimations();
assert_equals(
animations.length,
expectedAnimations.length,
'CSS animations on both pseudo-elements and elements are returned'
);
for (const [index, expected] of expectedAnimations.entries()) {
const [element, pseudo] = expected;
const actual = animations[index];
if (pseudo) {
assert_equals(
actual.effect.target,
element,
`Animation #${index + 1} has expected target`
);
assert_equals(
actual.effect.pseudoElement,
pseudo,
`Animation #${index + 1} has expected pseudo type`
);
} else {
assert_equals(
actual.effect.target,
element,
`Animation #${index + 1} has expected target`
);
assert_equals(
actual.effect.pseudoElement,
null,
`Animation #${index + 1} has null pseudo type`
);
if (testMarkerPseudos) {
addStyle(t, {
'#parent': 'display: list-item;',
'#parent::marker': "content: ''; animation: animLeft 100s;",
});
}
const parent = addDiv(t, { id: 'parent' });
const child = addDiv(t);
parent.appendChild(child);
for (const div of [parent, child]) {
div.setAttribute('style', 'animation: animBottom 100s');
}
}
}, 'CSS Animations targetting (pseudo-)elements should have correct order '
+ 'after sorting');
const expectedAnimations = [
[parent, undefined],
[parent, '::marker'],
[parent, '::before'],
[parent, '::after'],
[child, undefined],
];
if (!testMarkerPseudos) {
expectedAnimations.splice(1, 1);
}
const animations = document.getAnimations();
assert_equals(
animations.length,
expectedAnimations.length,
'CSS animations on both pseudo-elements and elements are returned'
);
for (const [index, expected] of expectedAnimations.entries()) {
const [element, pseudo] = expected;
const actual = animations[index];
if (pseudo) {
assert_equals(
actual.effect.target,
element,
`Animation #${index + 1} has expected target`
);
assert_equals(
actual.effect.pseudoElement,
pseudo,
`Animation #${index + 1} has expected pseudo type`
);
} else {
assert_equals(
actual.effect.target,
element,
`Animation #${index + 1} has expected target`
);
assert_equals(
actual.effect.pseudoElement,
null,
`Animation #${index + 1} has null pseudo type`
);
}
}
}, description);
}
pseudoTest('CSS Animations targetting (pseudo-)elements should have correct '
+ 'order after sorting', false);
pseudoTest('CSS Animations targetting (pseudo-)elements should have correct '
+ 'order after sorting (::marker)', true);
</script>
This is a testharness.js-based test.
PASS Same events are ordered by elements
PASS Same events on pseudo-elements follow the prescribed order
FAIL Same events on pseudo-elements follow the prescribed order (::marker) assert_equals: Number of events received (4) should match expected number (5) (expected: animationstart, animationstart, animationstart, animationstart, animationstart, actual: animationstart, animationstart, animationstart, animationstart) expected 5 but got 4
FAIL Start and iteration events are ordered by time assert_equals: Event #1 types should match (expected: animationiteration, animationstart, actual: animationstart, animationiteration) expected "animationiteration" but got "animationstart"
FAIL Iteration and end events are ordered by time assert_equals: Event #1 types should match (expected: animationiteration, animationend, actual: animationend, animationiteration) expected "animationiteration" but got "animationend"
FAIL Start and end events are sorted correctly when fired simultaneously assert_equals: Event #1 targets should match expected Element node <div style="animation: anim 100s 2"></div> but got Element node <div style="animation: anim 100s 100s"></div>
......
......@@ -129,62 +129,68 @@ promise_test(async t => {
['animationend', div2, 200]);
}, 'Same events are ordered by elements');
promise_test(async t => {
// Setup a hierarchy as follows:
//
// parent
// |
// (::marker, ::before, ::after)
// |
// child
const parentDiv = addDiv(t, { style: 'animation: anim 100s' });
parentDiv.id = 'parent-div';
addStyle(t, {
'#parent-div::after': "content: ''; animation: anim 100s",
'#parent-div::before': "content: ''; animation: anim 100s",
});
if (CSS.supports('selector(::marker)')) {
parentDiv.style.display = 'list-item';
function pseudoTest(description, testMarkerPseudos) {
promise_test(async t => {
// Setup a hierarchy as follows:
//
// parent
// |
// (::marker, ::before, ::after) // ::marker optional
// |
// child
const parentDiv = addDiv(t, { style: 'animation: anim 100s' });
parentDiv.id = 'parent-div';
addStyle(t, {
'#parent-div::marker': "content: ''; animation: color-anim 100s",
'#parent-div::after': "content: ''; animation: anim 100s",
'#parent-div::before': "content: ''; animation: anim 100s",
});
}
const childDiv = addDiv(t, { style: 'animation: anim 100s' });
parentDiv.append(childDiv);
// Setup event handlers
let events = [];
for (const name of ['start', 'iteration', 'end', 'cancel']) {
parentDiv['onanimation' + name] = evt => {
events.push({
type: evt.type,
target: evt.target,
pseudoElement: evt.pseudoElement,
elapsedTime: evt.elapsedTime,
if (testMarkerPseudos) {
parentDiv.style.display = 'list-item';
addStyle(t, {
'#parent-div::marker': "content: ''; animation: color-anim 100s",
});
};
}
// Wait a couple of frames for the events to be dispatched
await waitForFrame();
await waitForFrame();
const expectedEvents = [
['animationstart', parentDiv, 0],
['animationstart', parentDiv, '::marker', 0],
['animationstart', parentDiv, '::before', 0],
['animationstart', parentDiv, '::after', 0],
['animationstart', childDiv, 0],
];
if (!CSS.supports('selector(::marker)')) {
expectedEvents.splice(1, 1);
}
}
const childDiv = addDiv(t, { style: 'animation: anim 100s' });
parentDiv.append(childDiv);
// Setup event handlers
let events = [];
for (const name of ['start', 'iteration', 'end', 'cancel']) {
parentDiv['onanimation' + name] = evt => {
events.push({
type: evt.type,
target: evt.target,
pseudoElement: evt.pseudoElement,
elapsedTime: evt.elapsedTime,
});
};
}
// Wait a couple of frames for the events to be dispatched
await waitForFrame();
await waitForFrame();
const expectedEvents = [
['animationstart', parentDiv, 0],
['animationstart', parentDiv, '::marker', 0],
['animationstart', parentDiv, '::before', 0],
['animationstart', parentDiv, '::after', 0],
['animationstart', childDiv, 0],
];
if (!testMarkerPseudos) {
expectedEvents.splice(1, 1);
}
checkEvents(events, ...expectedEvents);
}, description);
}
checkEvents(events, ...expectedEvents);
}, 'Same events on pseudo-elements follow the prescribed order');
pseudoTest('Same events on pseudo-elements follow the prescribed order', false);
pseudoTest('Same events on pseudo-elements follow the prescribed order ' +
'(::marker)', true);
promise_test(async t => {
let events = [];
......
This is a testharness.js-based test.
PASS getAnimations for non-animated content
PASS getAnimations for CSS Transitions
PASS CSS Transitions targetting (pseudo-)elements should have correct order after sorting
FAIL CSS Transitions targetting (pseudo-)elements should have correct order after sorting (::marker) assert_equals: CSS transition on both pseudo-elements and elements are returned expected 5 but got 4
PASS Transitions are not returned after they have finished
Harness: the test ran to completion.
......@@ -35,94 +35,99 @@ test(t => {
'getAnimations returns no running CSS Transitions');
}, 'getAnimations for CSS Transitions');
test(t => {
// Create two divs with the following arrangement:
//
// parent
// (::marker,)
// ::before,
// ::after
// |
// child
addStyle(t, {
'.init::after': 'content: ""; width: 0px; transition: all 100s;',
'.init::before': 'content: ""; width: 0px; transition: all 100s;',
'.change::after': 'width: 100px;',
'.change::before': 'width: 100px;',
});
const supportsMarkerPseudos = CSS.supports('selector(::marker)');
if (supportsMarkerPseudos) {
function pseudoTest(description, testMarkerPseudos) {
test(t => {
// Create two divs with the following arrangement:
//
// parent
// (::marker,) // Optionally
// ::before,
// ::after
// |
// child
addStyle(t, {
'.init::marker': 'content: ""; color: red; transition: all 100s;',
'.change::marker': 'color: green;',
'.init::after': 'content: ""; width: 0px; transition: all 100s;',
'.init::before': 'content: ""; width: 0px; transition: all 100s;',
'.change::after': 'width: 100px;',
'.change::before': 'width: 100px;',
});
}
const parent = addDiv(t, { 'style': 'display: list-item' });
const child = addDiv(t);
parent.appendChild(child);
parent.style.left = '0px';
parent.style.transition = 'left 100s';
parent.classList.add('init');
child.style.left = '0px';
child.style.transition = 'left 100s';
getComputedStyle(parent).left;
parent.style.left = '100px';
parent.classList.add('change');
child.style.left = '100px';
const expectedTransitions = [
[parent, undefined],
[parent, '::marker'],
[parent, '::before'],
[parent, '::after'],
[child, undefined],
];
if (!supportsMarkerPseudos) {
expectedTransitions.splice(1, 1);
}
const transitions = document.getAnimations();
assert_equals(
transitions.length,
expectedTransitions.length,
'CSS transition on both pseudo-elements and elements are returned'
);
for (const [index, expected] of expectedTransitions.entries()) {
const [element, pseudo] = expected;
const actual = transitions[index];
if (pseudo) {
assert_equals(
actual.effect.target,
element,
`Transition #${index + 1} has expected target`
);
assert_equals(
actual.effect.pseudoElement,
pseudo,
`Transition #${index + 1} has expected pseudo type`
);
} else {
assert_equals(
actual.effect.target,
element,
`Transition #${index + 1} has expected target`
);
assert_equals(
actual.effect.pseudoElement,
null,
`Transition #${index + 1} has null pseudo type`
);
if (testMarkerPseudos) {
addStyle(t, {
'.init::marker': 'content: ""; color: red; transition: all 100s;',
'.change::marker': 'color: green;',
});
}
const parent = addDiv(t, { 'style': 'display: list-item' });
const child = addDiv(t);
parent.appendChild(child);
parent.style.left = '0px';
parent.style.transition = 'left 100s';
parent.classList.add('init');
child.style.left = '0px';
child.style.transition = 'left 100s';
getComputedStyle(parent).left;
parent.style.left = '100px';
parent.classList.add('change');
child.style.left = '100px';
const expectedTransitions = [
[parent, undefined],
[parent, '::marker'],
[parent, '::before'],
[parent, '::after'],
[child, undefined],
];
if (!testMarkerPseudos) {
expectedTransitions.splice(1, 1);
}
const transitions = document.getAnimations();
assert_equals(
transitions.length,
expectedTransitions.length,
'CSS transition on both pseudo-elements and elements are returned'
);
for (const [index, expected] of expectedTransitions.entries()) {
const [element, pseudo] = expected;
const actual = transitions[index];
if (pseudo) {
assert_equals(
actual.effect.target,
element,
`Transition #${index + 1} has expected target`
);
assert_equals(
actual.effect.pseudoElement,
pseudo,
`Transition #${index + 1} has expected pseudo type`
);
} else {
assert_equals(
actual.effect.target,
element,
`Transition #${index + 1} has expected target`
);
assert_equals(
actual.effect.pseudoElement,
null,
`Transition #${index + 1} has null pseudo type`
);
}
}
}
}, 'CSS Transitions targetting (pseudo-)elements should have correct order '
+ 'after sorting');
}, description);
}
pseudoTest('CSS Transitions targetting (pseudo-)elements should have correct '
+ 'order after sorting', false)
pseudoTest('CSS Transitions targetting (pseudo-)elements should have correct '
+ 'order after sorting (::marker)', true)
promise_test(async t => {
const div = addDiv(t, { style: 'left: 0px; transition: all 50ms' });
......
......@@ -51,39 +51,6 @@ promise_test(async t => {
}, 'Transitions on ::before/::after pseudo-elements are canceled when the'
+ ' content property is cleared');
promise_test(async t => {
if (!CSS.supports('selector(::marker)')) {
return;
}
addStyle(t, {
'.init::marker': 'content: ""; color: red; transition: color 100s;',
'.change::marker': 'color: green',
});
// Create element (and pseudo-element) and attach event listeners
const div = addDiv(t, { 'style': 'display: list-item' });
div.classList.add('init');
const eventWatcher = new EventWatcher(t, div, [
'transitionrun',
'transitioncancel',
]);
// Trigger transition
getComputedStyle(div).color;
div.classList.add('change');
getComputedStyle(div).color;
await eventWatcher.wait_for('transitionrun');
// Make the parent element no longer display: list-item so that the pseudo
// element no longer renders
div.style.display = 'block';
await eventWatcher.wait_for('transitioncancel');
}, 'Transitions on ::marker pseudo-elements are canceled when the'
+ ' parent display type is no longer list-item');
</script>
</body>
......
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>CSS Transitions Test: Transitions do not run for a ::marker-element that is not being rendered</title>
<link rel="help" title="Starting transitions"
href="https://drafts.csswg.org/css-transitions/#starting">
<script src="/resources/testharness.js" type="text/javascript"></script>
<script src="/resources/testharnessreport.js" type="text/javascript"></script>
<script src="./support/helper.js" type="text/javascript"></script>
</head>
<body>
<div id="log"></div>
<script>
promise_test(async t => {
addStyle(t, {
'.init::marker': 'content: ""; color: red; transition: color 100s;',
'.change::marker': 'color: green',
});
// Create element (and pseudo-element) and attach event listeners
const div = addDiv(t, { 'style': 'display: list-item' });
div.classList.add('init');
const eventWatcher = new EventWatcher(t, div, [
'transitionrun',
'transitioncancel',
]);
// Trigger transition
getComputedStyle(div).color;
div.classList.add('change');
getComputedStyle(div).color;
await eventWatcher.wait_for('transitionrun');
// Make the parent element no longer display: list-item so that the pseudo
// element no longer renders
div.style.display = 'block';
await eventWatcher.wait_for('transitioncancel');
}, 'Transitions on ::marker pseudo-elements are canceled when the'
+ ' parent display type is no longer list-item');
</script>
</body>
</html>
This is a testharness.js-based test.
PASS CSS.escape
PASS CSS.supports, one argument form
PASS CSS.supports, two argument form
FAIL CSS.supports, selector function assert_equals: CSS.supports: selector() function accepts a selector expected true but got false
Harness: the test ran to completion.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment