mirror of
https://github.com/servo/servo.git
synced 2025-08-15 10:25:32 +01:00
Update web-platform-tests to revision de9a09ab7f605aed6a4b53ed96427412bab76463
This commit is contained in:
parent
f3f9303fc9
commit
73a776843f
225 changed files with 5750 additions and 2858 deletions
|
@ -61,7 +61,7 @@ tasks:
|
|||
owner: ${event.pusher.email}
|
||||
source: ${event.repository.url}
|
||||
payload:
|
||||
image: harjgam/web-platform-tests:0.22
|
||||
image: hexcles/web-platform-tests:0.23
|
||||
maxRunTime: 7200
|
||||
artifacts:
|
||||
public/results:
|
||||
|
@ -125,7 +125,7 @@ tasks:
|
|||
owner: ${event.pull_request.user.login}@users.noreply.github.com
|
||||
source: ${event.repository.url}
|
||||
payload:
|
||||
image: harjgam/web-platform-tests:0.22
|
||||
image: hexcles/web-platform-tests:0.23
|
||||
maxRunTime: 7200
|
||||
artifacts:
|
||||
public/results:
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// META: script=support-promises.js
|
||||
|
||||
/**
|
||||
* This file contains a test that was separated out from the rest of the idb
|
||||
* explict commit tests because it requires the flag 'allow_uncaught_exception',
|
||||
* which prevents unintentionally thrown errors from failing tests.
|
||||
*
|
||||
* @author andreasbutler@google.com
|
||||
*/
|
||||
|
||||
setup({allow_uncaught_exception:true});
|
||||
|
||||
promise_test(async testCase => {
|
||||
// Register an event listener that will prevent the intentionally thrown
|
||||
// error from bubbling up to the window and failing the testharness. This
|
||||
// is necessary because currently allow_uncaught_exception does not behave
|
||||
// as expected for promise_test.
|
||||
//
|
||||
// Git issue: https://github.com/web-platform-tests/wpt/issues/14041
|
||||
self.addEventListener('error', (event) => { event.preventDefault(); });
|
||||
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const putRequest = objectStore.put({isbn:'one', title:'title'});
|
||||
txn.commit();
|
||||
putRequest.onsuccess = () => {
|
||||
throw new Error('This error thrown after an explicit commit should not ' +
|
||||
'prevent the transaction from committing.');
|
||||
}
|
||||
await promiseForTransaction(testCase, txn);
|
||||
|
||||
// Ensure that despite the uncaught error after the put request, the explicit
|
||||
// commit still causes the request to be committed.
|
||||
const txn2 = db.transaction(['books'], 'readwrite');
|
||||
const objectStore2 = txn2.objectStore('books');
|
||||
const getRequest = objectStore2.get('one');
|
||||
await promiseForTransaction(testCase, txn2);
|
||||
|
||||
assert_equals(getRequest.result.title, 'title');
|
||||
}, 'Any errors in callbacks that run after an explicit commit will not stop '
|
||||
+ 'the commit from being processed.');
|
|
@ -0,0 +1,181 @@
|
|||
// META: script=support-promises.js
|
||||
|
||||
/**
|
||||
* This file contains the webplatform tests for the explicit commit() method
|
||||
* of the IndexedDB transaction API.
|
||||
*
|
||||
* @author andreasbutler@google.com
|
||||
*/
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
objectStore.put({isbn: 'one', title: 'title1'});
|
||||
objectStore.put({isbn: 'two', title: 'title2'});
|
||||
objectStore.put({isbn: 'three', title: 'title3'});
|
||||
txn.commit();
|
||||
await promiseForTransaction(testCase, txn);
|
||||
|
||||
const txn2 = db.transaction(['books'], 'readonly');
|
||||
const objectStore2 = txn2.objectStore('books');
|
||||
const getRequestitle1 = objectStore2.get('one');
|
||||
const getRequestitle2 = objectStore2.get('two');
|
||||
const getRequestitle3 = objectStore2.get('three');
|
||||
txn2.commit();
|
||||
await promiseForTransaction(testCase, txn2);
|
||||
assert_array_equals(
|
||||
[getRequestitle1.result.title,
|
||||
getRequestitle2.result.title,
|
||||
getRequestitle3.result.title],
|
||||
['title1', 'title2', 'title3'],
|
||||
'All three retrieved titles should match those that were put.');
|
||||
db.close();
|
||||
}, 'Explicitly committed data can be read back out.');
|
||||
|
||||
|
||||
promise_test(async testCase => {
|
||||
let db = await createDatabase(testCase, () => {});
|
||||
assert_equals(1, db.version, 'A database should be created as version 1');
|
||||
db.close();
|
||||
|
||||
// Upgrade the versionDB database and explicitly commit its versionchange
|
||||
// transaction.
|
||||
db = await migrateDatabase(testCase, 2, async (db, txn) => {
|
||||
txn.commit();
|
||||
});
|
||||
assert_equals(2, db.version,
|
||||
'The database version should have been incremented regardless of '
|
||||
+ 'whether the versionchange transaction was explicitly or implicitly '
|
||||
+ 'committed.');
|
||||
db.close();
|
||||
}, 'commit() on a version change transaction does not cause errors.');
|
||||
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
txn.commit();
|
||||
assert_throws('TransactionInactiveError',
|
||||
() => { objectStore.put({isbn: 'one', title: 'title1'}); },
|
||||
'After commit is called, the transaction should be inactive.');
|
||||
db.close();
|
||||
}, 'A committed transaction becomes inactive immediately.');
|
||||
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const putRequest = objectStore.put({isbn: 'one', title: 'title1'});
|
||||
putRequest.onsuccess = testCase.step_func(() => {
|
||||
assert_throws('TransactionInactiveError',
|
||||
() => { objectStore.put({isbn:'two', title:'title2'}); },
|
||||
'The transaction should not be active in the callback of a request after '
|
||||
+ 'commit() is called.');
|
||||
});
|
||||
txn.commit();
|
||||
await promiseForTransaction(testCase, txn);
|
||||
db.close();
|
||||
}, 'A committed transaction is inactive in future request callbacks.');
|
||||
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
txn.commit();
|
||||
|
||||
assert_throws('TransactionInactiveError',
|
||||
() => { objectStore.put({isbn:'one', title:'title1'}); },
|
||||
'After commit is called, the transaction should be inactive.');
|
||||
|
||||
const txn2 = db.transaction(['books'], 'readonly');
|
||||
const objectStore2 = txn2.objectStore('books');
|
||||
const getRequest = objectStore2.get('one');
|
||||
await promiseForTransaction(testCase, txn2);
|
||||
assert_equals(getRequest.result, undefined);
|
||||
|
||||
db.close();
|
||||
}, 'Puts issued after commit are not fulfilled.');
|
||||
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
txn.abort();
|
||||
assert_throws('InvalidStateError',
|
||||
() => { txn.commit(); },
|
||||
'The transaction should have been aborted.');
|
||||
db.close();
|
||||
}, 'Calling commit on an aborted transaction throws.');
|
||||
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
txn.commit();
|
||||
assert_throws('InvalidStateError',
|
||||
() => { txn.commit(); },
|
||||
'The transaction should have already committed.');
|
||||
db.close();
|
||||
}, 'Calling commit on a committed transaction throws.');
|
||||
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const putRequest = objectStore.put({isbn:'one', title:'title1'});
|
||||
txn.commit();
|
||||
assert_throws('InvalidStateError',
|
||||
() => { txn.abort(); },
|
||||
'The transaction should already have committed.');
|
||||
const txn2 = db.transaction(['books'], 'readwrite');
|
||||
const objectStore2 = txn2.objectStore('books');
|
||||
const getRequest = objectStore2.get('one');
|
||||
await promiseForTransaction(testCase, txn2);
|
||||
assert_equals(
|
||||
getRequest.result.title,
|
||||
'title1',
|
||||
'Explicitly committed data should be gettable.');
|
||||
db.close();
|
||||
}, 'Calling abort on a committed transaction throws and does not prevent '
|
||||
+ 'persisting the data.');
|
||||
|
||||
|
||||
promise_test(async testCase => {
|
||||
const db = await createDatabase(testCase, async db => {
|
||||
await createBooksStore(testCase, db);
|
||||
});
|
||||
const txn = db.transaction(['books'], 'readwrite');
|
||||
const objectStore = txn.objectStore('books');
|
||||
const releaseTxnFunction = keepAlive(testCase, txn, 'books');
|
||||
|
||||
// Break up the scope of execution to force the transaction into an inactive
|
||||
// state.
|
||||
await timeoutPromise(0);
|
||||
|
||||
assert_throws('InvalidStateError',
|
||||
() => { txn.commit(); },
|
||||
'The transaction should be inactive so calling commit should throw.');
|
||||
releaseTxnFunction();
|
||||
db.close();
|
||||
}, 'Calling txn.commit() when txn is inactive should throw.');
|
|
@ -312,3 +312,32 @@ async function deleteAllDatabases(testCase) {
|
|||
await eventWatcher.wait_for('success');
|
||||
}
|
||||
}
|
||||
|
||||
// Keeps the passed transaction alive indefinitely (by making requests
|
||||
// against the named store). Returns a function that asserts that the
|
||||
// transaction has not already completed and then ends the request loop so that
|
||||
// the transaction may autocommit and complete.
|
||||
function keepAlive(testCase, transaction, storeName) {
|
||||
let completed = false;
|
||||
transaction.addEventListener('complete', () => { completed = true; });
|
||||
|
||||
let keepSpinning = true;
|
||||
|
||||
function spin() {
|
||||
if (!keepSpinning)
|
||||
return;
|
||||
transaction.objectStore(storeName).get(0).onsuccess = spin;
|
||||
}
|
||||
spin();
|
||||
|
||||
return testCase.step_func(() => {
|
||||
assert_false(completed, 'Transaction completed while kept alive');
|
||||
keepSpinning = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Return a promise that resolves after a setTimeout finishes to break up the
|
||||
// scope of a function's execution.
|
||||
function timeoutPromise(ms) {
|
||||
return new Promise(resolve => { setTimeout(resolve, ms); });
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
var databaseName = "database";
|
||||
var databaseVersion = 1;
|
||||
|
||||
/* Delete created databases
|
||||
*
|
||||
* Go through each finished test, see if it has an associated database. Close
|
||||
|
@ -170,18 +167,18 @@ function is_transaction_active(tx, store_name) {
|
|||
}
|
||||
}
|
||||
|
||||
// Keep the passed transaction alive indefinitely (by making requests
|
||||
// against the named store). Returns a function to to let the
|
||||
// transaction finish, and asserts that the transaction is not yet
|
||||
// finished.
|
||||
// Keeps the passed transaction alive indefinitely (by making requests
|
||||
// against the named store). Returns a function that asserts that the
|
||||
// transaction has not already completed and then ends the request loop so that
|
||||
// the transaction may autocommit and complete.
|
||||
function keep_alive(tx, store_name) {
|
||||
let completed = false;
|
||||
tx.addEventListener('complete', () => { completed = true; });
|
||||
|
||||
let pin = true;
|
||||
let keepSpinning = true;
|
||||
|
||||
function spin() {
|
||||
if (!pin)
|
||||
if (!keepSpinning)
|
||||
return;
|
||||
tx.objectStore(store_name).get(0).onsuccess = spin;
|
||||
}
|
||||
|
@ -189,6 +186,6 @@ function keep_alive(tx, store_name) {
|
|||
|
||||
return () => {
|
||||
assert_false(completed, 'Transaction completed while kept alive');
|
||||
pin = false;
|
||||
keepSpinning = false;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="img-src 'self'">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var t1 = async_test("First image should be blocked");
|
||||
var t2 = async_test("Second image should be blocked");
|
||||
window.onmessage = t1.step_func_done(function(e) {
|
||||
if (e.data == "img blocked") {
|
||||
frames[0].frames[0].frameElement.srcdoc =
|
||||
`<script>
|
||||
window.addEventListener('securitypolicyviolation', function(e) {
|
||||
if (e.violatedDirective == 'img-src') {
|
||||
top.postMessage('img blocked', '*');
|
||||
}
|
||||
})
|
||||
</scr` + `ipt>
|
||||
<img src='/content-security-policy/support/fail.png'
|
||||
onload='top.postMessage("img loaded", "*")'/>`;
|
||||
window.onmessage = t2.step_func_done(function(e) {
|
||||
if (e.data != "img blocked")
|
||||
assert_true(false, "The second image should have been blocked");
|
||||
});
|
||||
} else {
|
||||
assert_true(false, "The first image should have been blocked");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<iframe src="support/srcdoc-child-frame.html"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,19 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="img-src 'none'">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var i = document.createElement('iframe');
|
||||
i.srcdoc=`<script>
|
||||
window.addEventListener('securitypolicyviolation', function(e) {
|
||||
if (e.violatedDirective == 'img-src') {
|
||||
top.postMessage('img blocked', '*');
|
||||
}
|
||||
})
|
||||
</scr` + `ipt>
|
||||
<img src='/content-security-policy/support/fail.png'
|
||||
onload='top.postMessage("img loaded", "*")'/>`;
|
||||
i.id = "srcdoc-frame";
|
||||
document.body.appendChild(i);
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,2 @@
|
|||
<meta http-equiv="Content-Security-Policy" content="{{GET[csp]}}">
|
||||
CHILD FRAME
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<head>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="support/frame-with-csp.sub.html?csp=script-src%20%27self%27"></iframe>
|
||||
<div onclick="frames[0].location.href = 'javascript:parent.postMessage(\'executed\', \'*\')'" id="special_div"></div>
|
||||
<script>
|
||||
var t = async_test("Should have executed the javascript url");
|
||||
window.onmessage = t.step_func(function(e) {
|
||||
if (e.data == "executed")
|
||||
t.done();
|
||||
});
|
||||
window.addEventListener('securitypolicyviolation', t.unreached_func("Should not have raised a violation event"));
|
||||
document.getElementById('special_div').click();
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta http-equiv="content-security-policy" content="script-src 'self' 'nonce-abc'">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="support/frame-with-csp.sub.html"></iframe>
|
||||
<div onclick="frames[0].location.href = 'javascript:parent.postMessage(\'executed\', \'*\')'" id="special_div"></div>
|
||||
<script nonce='abc'>
|
||||
var t = async_test("Should not have executed the javascript url");
|
||||
window.onmessage = t.step_func(function(e) {
|
||||
if (e.data == "executed")
|
||||
assert_true(false, "Javascript url executed");
|
||||
});
|
||||
window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
|
||||
assert_equals(e.blockedURI, 'inline');
|
||||
assert_equals(e.violatedDirective, 'script-src-attr');
|
||||
}));
|
||||
document.getElementById('special_div').click();
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,75 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for the page-break-* legacy shorthands.</title>
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-cascade-4/#legacy-shorthand">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-break/#page-break-properties">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div></div>
|
||||
<script>
|
||||
const NEW_VALUES = ["page", "column"].filter(v => CSS.supports("break-before", v));
|
||||
const LEGACY_VALUES = ["always", "auto", "left", "right", "avoid"];
|
||||
const LEGACY_MAPPING = { "always": "page" };
|
||||
const REVERSE_LEGACY_MAPPING = { "page": "always" };
|
||||
const div = document.querySelector("div");
|
||||
const cs = getComputedStyle(div);
|
||||
|
||||
test(function() {
|
||||
for (const property of ["break-before", "break-after"]) {
|
||||
for (const val of LEGACY_VALUES) {
|
||||
const mapped_value = LEGACY_MAPPING[val] || val;
|
||||
|
||||
div.style["page-" + property] = val;
|
||||
|
||||
assert_equals(div.style["page-" + property], val);
|
||||
assert_equals(div.style[property], mapped_value);
|
||||
assert_equals(cs.getPropertyValue("page-" + property), val);
|
||||
assert_equals(cs.getPropertyValue(property), mapped_value);
|
||||
assert_not_equals(div.style.cssText.indexOf(property + ": " + mapped_value + ";"), -1);
|
||||
assert_equals(div.style.cssText.indexOf("page-" + property), -1,
|
||||
"Legacy shorthands don't appear in cssText");
|
||||
}
|
||||
}
|
||||
}, "Legacy values of the shorthands work as expected")
|
||||
|
||||
test(function() {
|
||||
for (const property of ["break-before", "break-after"]) {
|
||||
for (const val of NEW_VALUES) {
|
||||
const mapped_value = REVERSE_LEGACY_MAPPING[val] || "";
|
||||
|
||||
div.style[property] = val;
|
||||
|
||||
assert_equals(div.style[property], val);
|
||||
assert_equals(div.style["page-" + property], mapped_value);
|
||||
assert_equals(cs.getPropertyValue("page-" + property), mapped_value);
|
||||
assert_equals(cs.getPropertyValue(property), val);
|
||||
}
|
||||
}
|
||||
}, "New values work on the new longhands, but serialize to the empty string in the legacy shorthands");
|
||||
|
||||
test(function() {
|
||||
for (const property of ["break-before", "break-after"]) {
|
||||
for (const val of NEW_VALUES) {
|
||||
div.style["page-" + property] = "";
|
||||
div.style["page-" + property] = val;
|
||||
assert_equals(div.style["page-" + property], "");
|
||||
assert_equals(div.style[property], "");
|
||||
assert_equals(cs.getPropertyValue("page-" + property), "auto");
|
||||
assert_equals(cs.getPropertyValue(property), "auto");
|
||||
}
|
||||
}
|
||||
}, "New values of the break longhands don't work on legacy shorthands");
|
||||
|
||||
// See https://github.com/w3c/csswg-drafts/issues/3332
|
||||
test(function() {
|
||||
for (const property of ["break-before", "break-after"]) {
|
||||
div.style["page-" + property] = "var(--a)";
|
||||
|
||||
assert_equals(div.style["page-" + property], "var(--a)");
|
||||
assert_equals(div.style[property], "");
|
||||
assert_equals(div.style.cssText.indexOf("page-" + property), -1);
|
||||
}
|
||||
}, "Legacy shorthands really never appear on cssText, even when there are variable references");
|
||||
</script>
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Multi-column Layout Test Reference: column-span:all should act like column-span:none in different block formatting context</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
|
||||
<style>
|
||||
#column {
|
||||
column-count: 3;
|
||||
column-rule: 6px solid;
|
||||
width: 600px;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
h3 {
|
||||
column-span: none;
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body onload="runTest();">
|
||||
<article id="column">
|
||||
<div>block1</div>
|
||||
<div style="display: inline-block;">
|
||||
<h3>non-spanner</h3>
|
||||
</div>
|
||||
<div style="overflow: hidden;">
|
||||
<h3>non-spanner</h3>
|
||||
</div>
|
||||
<div style="column-span: all; outline: 1px solid green;">
|
||||
Spanner
|
||||
<h3>non-spanner in a spanner</h3>
|
||||
</div>
|
||||
<div>block2</div>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Multi-column Layout Test: column-span:all should act like column-span:none in different block formatting context</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span">
|
||||
<link rel="match" href="multicol-span-all-004-ref.html">
|
||||
<meta name="assert" content="This test checks a column-span:all element should act like column-span: none if it's under different block formatting context.">
|
||||
|
||||
<style>
|
||||
#column {
|
||||
column-count: 3;
|
||||
column-rule: 6px solid;
|
||||
width: 600px;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
h3 {
|
||||
column-span: all;
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body onload="runTest();">
|
||||
<article id="column">
|
||||
<div>block1</div>
|
||||
<div style="display: inline-block;">
|
||||
<h3>non-spanner</h3>
|
||||
</div>
|
||||
<div style="overflow: hidden;">
|
||||
<h3>non-spanner</h3>
|
||||
</div>
|
||||
<div style="column-span: all; outline: 1px solid green;">
|
||||
Spanner
|
||||
<h3>non-spanner in a spanner</h3>
|
||||
</div>
|
||||
<div>block2</div>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
|
@ -42,7 +42,7 @@
|
|||
<script type="text/javascript">
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield outside region");
|
||||
test1.step( function() {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeypress event fired in textfield inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeypress event fired in textfield inside region");
|
||||
test1.step( function() {
|
||||
var testTarget = document.getElementById("textfield-inside");
|
||||
testTarget.onkeypress = test1.step_func(function (evt) {
|
||||
|
@ -59,7 +59,7 @@
|
|||
keyDown("textfield-inside");
|
||||
});
|
||||
|
||||
var test2 = async_test("onkeypress event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onkeypress event fired in textfield outside region");
|
||||
test2.step( function() {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onkeypress = test2.step_func(function (evt) {
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
@ -59,7 +59,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test2 = async_test("onkeyup event fired in textfield inside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onkeyup event fired in textfield inside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside");
|
||||
testTarget.onkeyup = test2.step_func(function (evt) {
|
||||
|
@ -74,7 +74,7 @@
|
|||
keyDown("textfield-inside");
|
||||
});
|
||||
|
||||
var test3 = async_test("onkeydown event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test3 = async_test("onkeydown event fired in textfield outside region");
|
||||
test3.step( function() {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onkeydown = test3.step_func(function (evt) {
|
||||
|
@ -88,7 +88,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test4 = async_test("onkeyup event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test4 = async_test("onkeyup event fired in textfield outside region");
|
||||
test4.step( function() {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onkeyup = test4.step_func(function (evt) {
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield outside region");
|
||||
test1.step( function() {
|
||||
var testTarget = document.getElementById("textfield-outside");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
@ -66,7 +66,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test2 = async_test("onkeyup event fired in textarea outside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onkeyup event fired in textarea outside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("textarea-outside");
|
||||
testTarget.onkeyup = test2.step_func(function (evt) {
|
||||
|
@ -80,7 +80,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test3 = async_test("onkeydown event fired in textarea outside region", {timeout: testTimeout});
|
||||
var test3 = async_test("onkeydown event fired in textarea outside region");
|
||||
test3.step( function() {
|
||||
var testTarget = document.getElementById("textarea-outside");
|
||||
testTarget.onkeydown = test3.step_func( function(evt) {
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
@ -63,7 +63,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test2 = async_test("onkeyup event fired in textfield inside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onkeyup event fired in textfield inside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside");
|
||||
testTarget.onkeyup = test2.step_func(function (evt) {
|
||||
|
@ -78,7 +78,7 @@
|
|||
pressDeleteKey("textfield-inside");
|
||||
});
|
||||
|
||||
var test3 = async_test("onkeydown event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test3 = async_test("onkeydown event fired in textfield outside region");
|
||||
test3.step(function () {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onkeydown = test3.step_func(function (evt) {
|
||||
|
@ -92,7 +92,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test4 = async_test("onkeyup event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test4 = async_test("onkeyup event fired in textfield outside region");
|
||||
test4.step( function() {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onkeyup = test4.step_func(function (evt) {
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield1 inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield1 inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside1");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
@ -66,7 +66,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test2 = async_test("onkeyup event fired in textfield2 inside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onkeyup event fired in textfield2 inside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside2");
|
||||
testTarget.onkeyup = test2.step_func(function (evt) {
|
||||
|
@ -77,7 +77,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test3 = async_test("onkeydown event fired in textfield2 inside region", {timeout: testTimeout});
|
||||
var test3 = async_test("onkeydown event fired in textfield2 inside region");
|
||||
test3.step( function() {
|
||||
var testTarget = document.getElementById("textfield-inside2");
|
||||
testTarget.onkeydown = test3.step_func(function (evt) {
|
||||
|
@ -96,7 +96,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test4 = async_test("onkeyup event fired in textarea inside region", {timeout: testTimeout});
|
||||
var test4 = async_test("onkeyup event fired in textarea inside region");
|
||||
test4.step( function() {
|
||||
var testTarget = document.getElementById("textarea-inside");
|
||||
testTarget.onkeyup = test4.step_func(function (evt) {
|
||||
|
@ -110,7 +110,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test5 = async_test("onkeydown event fired in textarea inside region", {timeout: testTimeout});
|
||||
var test5 = async_test("onkeydown event fired in textarea inside region");
|
||||
test5.step( function() {
|
||||
var testTarget = document.getElementById("textarea-inside");
|
||||
testTarget.onkeydown = test5.step_func(function (evt) {
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
@ -63,7 +63,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test2 = async_test("onkeydown event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onkeydown event fired in textfield outside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("textfield-outside");
|
||||
testTarget.onkeydown = test2.step_func(function (evt) {
|
||||
|
@ -77,7 +77,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test3 = async_test("onkeyup event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test3 = async_test("onkeyup event fired in textfield outside region");
|
||||
test3.step(function () {
|
||||
var testTarget = document.getElementById("textfield-outside");
|
||||
testTarget.onkeyup = test3.step_func(function (evt) {
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield outside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("textfield-outside");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
@ -63,7 +63,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test2 = async_test("onkeyup event fired in textfield outside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onkeyup event fired in textfield outside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("textfield-outside");
|
||||
testTarget.onkeyup = test2.step_func(function (evt) {
|
||||
|
@ -75,7 +75,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test3 = async_test("onkeydown event fired in textarea outside region", {timeout: testTimeout});
|
||||
var test3 = async_test("onkeydown event fired in textarea outside region");
|
||||
test3.step(function () {
|
||||
var testTarget = document.getElementById("textarea-outside");
|
||||
testTarget.onkeydown = test3.step_func(function (evt) {
|
||||
|
@ -89,7 +89,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test4 = async_test("onkeyup event fired in textarea outside region", {timeout: testTimeout});
|
||||
var test4 = async_test("onkeyup event fired in textarea outside region");
|
||||
test4.step( function() {
|
||||
var testTarget = document.getElementById("textarea-outside");
|
||||
testTarget.onkeyup = test4.step_func(function (evt) {
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onkeydown event fired in textfield inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("textfield-inside");
|
||||
testTarget.onkeydown = test1.step_func(function (evt) {
|
||||
|
@ -63,7 +63,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test2 = async_test("onkeyup event fired in textarea inside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onkeyup event fired in textarea inside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("textarea-inside");
|
||||
testTarget.onkeyup = test2.step_func(function (evt) {
|
||||
|
@ -77,7 +77,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
var test3 = async_test("onkeydown event fired in textarea inside region", {timeout: testTimeout});
|
||||
var test3 = async_test("onkeydown event fired in textarea inside region");
|
||||
test3.step( function() {
|
||||
var testTarget = document.getElementById("textarea-inside");
|
||||
testTarget.onkeydown = test3.step_func(function (evt) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("onclick event fired inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onclick event fired inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("target-block");
|
||||
testTarget.onclick = test1.step_func(function (evt) {
|
||||
|
@ -46,7 +46,7 @@
|
|||
mouseClick("target-block");
|
||||
});
|
||||
|
||||
var test2 = async_test("onclick event fired outside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onclick event fired outside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onclick = test2.step_func(function (evt) {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("onmousedown event fired inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onmousedown event fired inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("target-block");
|
||||
testTarget.onmousedown = test1.step_func(function (evt) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("onmousedown event fired outside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onmousedown event fired outside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onmousedown = test1.step_func(function (evt) {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("onmouseup event fired inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onmouseup event fired inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("target-block");
|
||||
testTarget.onmouseup = test1.step_func(function (evt) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("onmouseup event fired outside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onmouseup event fired outside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onmouseup = test1.step_func(function (evt) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("ondblclick event fired inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("ondblclick event fired inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("target-block");
|
||||
testTarget.ondblclick = test1.step_func(function (evt) {
|
||||
|
@ -46,7 +46,7 @@
|
|||
mouseDblClick("target-block");
|
||||
});
|
||||
|
||||
var test2 = async_test("ondblclick event fired outside region", {timeout: testTimeout});
|
||||
var test2 = async_test("ondblclick event fired outside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.ondblclick = test2.step_func( function(evt) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("onmousemove event fired inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onmousemove event fired inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("target-block");
|
||||
testTarget.onmousemove = test1.step_func(function (evt) {
|
||||
|
@ -46,7 +46,7 @@
|
|||
mouseMove("target-block");
|
||||
});
|
||||
|
||||
var test2 = async_test("onmousemove event fired outside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onmousemove event fired outside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onmousemove = test2.step_func(function (evt) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("onmouseover event fired inside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onmouseover event fired inside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("target-block");
|
||||
testTarget.onmouseover = test1.step_func(function (evt) {
|
||||
|
@ -46,7 +46,7 @@
|
|||
mouseOver("target-block");
|
||||
});
|
||||
|
||||
var test2 = async_test("onmouseout event fired inside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onmouseout event fired inside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("target-block");
|
||||
testTarget.onmouseout = test2.step_func(function (evt) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
if(getLeftPosition("target-block") !== 0) {
|
||||
var test1 = async_test("onmouseover event fired outside region", {timeout: testTimeout});
|
||||
var test1 = async_test("onmouseover event fired outside region");
|
||||
test1.step(function () {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onmouseover = test1.step_func(function (evt) {
|
||||
|
@ -46,7 +46,7 @@
|
|||
mouseOver("outside-region");
|
||||
});
|
||||
|
||||
var test2 = async_test("onmouseout event fired outside region", {timeout: testTimeout});
|
||||
var test2 = async_test("onmouseout event fired outside region");
|
||||
test2.step(function () {
|
||||
var testTarget = document.getElementById("outside-region");
|
||||
testTarget.onmouseout = test2.step_func(function (evt) {
|
||||
|
|
|
@ -21,7 +21,7 @@ function runSelectionTest(inSelectionTests, useMouse)
|
|||
|
||||
if( isRegionsEnabled() )
|
||||
{
|
||||
var selectionTest = async_test("Text was selected", {timeout: testTimeout});
|
||||
var selectionTest = async_test("Text was selected");
|
||||
selectionTest.step( function()
|
||||
{
|
||||
var endSelect = document.getElementById("end-select");
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Ruby Reference: ruby content w. layout-internal 'display' values</title>
|
||||
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
|
||||
<style>
|
||||
html,body {
|
||||
color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 20px;
|
||||
-webkit-appearance: none;
|
||||
border: 1px solid black;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.thg { display: table-header-group; }
|
||||
.trg { display: table-row-group; }
|
||||
.tfg { display: table-footer-group; }
|
||||
.tr { display: table-row; }
|
||||
.tc { display: table-cell; }
|
||||
.tcg { display: table-column-group; }
|
||||
.tco { display: table-column; }
|
||||
.tca { display: table-caption; }
|
||||
.t { display: table; }
|
||||
|
||||
.rb { display: ruby-base; }
|
||||
.rt { display: ruby-text; }
|
||||
.rbc { display: ruby-base-container; }
|
||||
.rtc { display: ruby-text-container; }
|
||||
|
||||
.x { background: red}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<ruby><rb><span>a<span><input class="thg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="thg"><input class="thg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="thg">b</div><input class="thg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="thg">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="trg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="trg"><input class="trg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="trg">b</div><input class="trg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="trg">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="tfg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="tfg"><input class="tfg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tfg">b</div><input class="tfg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tfg">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="tr"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="tr"><input class="tr"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tr">b</div><input class="tr"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tr">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="tc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="tc"><input class="tc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tc">b</div><input class="tc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tc">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="tcg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="tcg"><input class="tcg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tcg">b</div><input class="tcg"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tcg">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="tco"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="tco"><input class="tco"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tco">b</div><input class="tco"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tco">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="tca"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="tca"><input class="tca"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tca">b</div><input class="tca"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="tca">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="t"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="t"><input class="t"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="t">b</div><input class="t"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="t">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="rb"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="rb"><input class="rb"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="rb">b</div><input class="rb"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="rb">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="rt"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="rt"><input class="rt"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="rt">b</div><input class="rt"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="rt">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="rbc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="rbc"><input class="rbc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="rbc">b</div><input class="rbc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="rbc">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<span><input class="rtc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><input class="rtc"><input class="rtc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="rtc">b</div><input class="rtc"></span>b</span></rb></ruby>
|
||||
<ruby><rb><span>a<span><div class="rtc">b</div></span>c</span></rb></ruby>
|
||||
|
||||
<br><hr>
|
||||
|
||||
<!-- -->
|
||||
|
||||
<ruby><rb><span><input class="thg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="thg"><input class="thg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="thg">b</div><input class="thg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="thg">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="trg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="trg"><input class="trg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="trg">b</div><input class="trg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="trg">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="tfg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="tfg"><input class="tfg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tfg">b</div><input class="tfg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tfg">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="tr"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="tr"><input class="tr"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tr">b</div><input class="tr"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tr">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="tc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="tc"><input class="tc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tc">b</div><input class="tc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tc">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="tcg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="tcg"><input class="tcg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tcg">b</div><input class="tcg"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tcg">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="tco"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="tco"><input class="tco"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tco">b</div><input class="tco"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tco">b</div></span>c</rb></ruby>
|
||||
|
||||
<!-- bug NNNNNN
|
||||
<ruby><rb><span><input class="tca"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="tca"><input class="tca"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tca">b</div><input class="tca"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="tca">b</div></span>c</rb></ruby>
|
||||
-->
|
||||
|
||||
<ruby><rb><span><input class="t"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="t"><input class="t"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="t">b</div><input class="t"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="t">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="rb"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="rb"><input class="rb"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="rb">b</div><input class="rb"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="rb">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="rt"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="rt"><input class="rt"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="rt">b</div><input class="rt"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="rt">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="rbc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="rbc"><input class="rbc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="rbc">b</div><input class="rbc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="rbc">b</div></span>c</rb></ruby>
|
||||
|
||||
<ruby><rb><span><input class="rtc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><input class="rtc"><input class="rtc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="rtc">b</div><input class="rtc"></span>b</rb></ruby>
|
||||
<ruby><rb><span><div class="rtc">b</div></span>c</rb></ruby>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,181 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Ruby Test: ruby content w. layout-internal 'display' values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#box-fixup">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-display-3/#inlinify">
|
||||
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
|
||||
<link rel="match" href="ruby-layout-internal-boxes-ref.html">
|
||||
<style>
|
||||
html,body {
|
||||
color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 20px;
|
||||
-webkit-appearance: none;
|
||||
border: 1px solid black;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.thg { display: table-header-group; }
|
||||
.trg { display: table-row-group; }
|
||||
.tfg { display: table-footer-group; }
|
||||
.tr { display: table-row; }
|
||||
.tc { display: table-cell; }
|
||||
.tcg { display: table-column-group; }
|
||||
.tco { display: table-column; }
|
||||
.tca { display: table-caption; }
|
||||
.t { display: table; }
|
||||
|
||||
.rb { display: ruby-base; }
|
||||
.rt { display: ruby-text; }
|
||||
.rbc { display: ruby-base-container; }
|
||||
.rtc { display: ruby-text-container; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<ruby><rb><span>a<input class="thg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="thg"><input class="thg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="thg">b</div><input class="thg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="thg">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="trg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="trg"><input class="trg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="trg">b</div><input class="trg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="trg">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="tfg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="tfg"><input class="tfg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tfg">b</div><input class="tfg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tfg">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="tr">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="tr"><input class="tr">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tr">b</div><input class="tr">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tr">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="tc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="tc"><input class="tc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tc">b</div><input class="tc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tc">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="tcg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="tcg"><input class="tcg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tcg">b</div><input class="tcg">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tcg">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="tco">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="tco"><input class="tco">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tco">b</div><input class="tco">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tco">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="tca">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="tca"><input class="tca">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tca">b</div><input class="tca">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="tca">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="t">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="t"><input class="t">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="t">b</div><input class="t">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="t">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="rb">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="rb"><input class="rb">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="rb">b</div><input class="rb">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="rb">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="rt">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="rt"><input class="rt">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="rt">b</div><input class="rt">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="rt">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="rbc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="rbc"><input class="rbc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="rbc">b</div><input class="rbc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="rbc">b</div>c</span></rb></ruby>
|
||||
|
||||
<ruby><rb><span>a<input class="rtc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<input class="rtc"><input class="rtc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="rtc">b</div><input class="rtc">b</span></rb></ruby>
|
||||
<ruby><rb><span>a<div class="rtc">b</div>c</span></rb></ruby>
|
||||
|
||||
<br><hr>
|
||||
|
||||
<!-- same as above but without the SPAN wrapper -->
|
||||
|
||||
<ruby><rb><input class="thg">b</rb></ruby>
|
||||
<ruby><rb><input class="thg"><input class="thg">b</rb></ruby>
|
||||
<ruby><rb><div class="thg">b</div><input class="thg">b</rb></ruby>
|
||||
<ruby><rb><div class="thg">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="trg">b</rb></ruby>
|
||||
<ruby><rb><input class="trg"><input class="trg">b</rb></ruby>
|
||||
<ruby><rb><div class="trg">b</div><input class="trg">b</rb></ruby>
|
||||
<ruby><rb><div class="trg">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="tfg">b</rb></ruby>
|
||||
<ruby><rb><input class="tfg"><input class="tfg">b</rb></ruby>
|
||||
<ruby><rb><div class="tfg">b</div><input class="tfg">b</rb></ruby>
|
||||
<ruby><rb><div class="tfg">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="tr">b</rb></ruby>
|
||||
<ruby><rb><input class="tr"><input class="tr">b</rb></ruby>
|
||||
<ruby><rb><div class="tr">b</div><input class="tr">b</rb></ruby>
|
||||
<ruby><rb><div class="tr">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="tc">b</rb></ruby>
|
||||
<ruby><rb><input class="tc"><input class="tc">b</rb></ruby>
|
||||
<ruby><rb><div class="tc">b</div><input class="tc">b</rb></ruby>
|
||||
<ruby><rb><div class="tc">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="tcg">b</rb></ruby>
|
||||
<ruby><rb><input class="tcg"><input class="tcg">b</rb></ruby>
|
||||
<ruby><rb><div class="tcg">b</div><input class="tcg">b</rb></ruby>
|
||||
<ruby><rb><div class="tcg">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="tco">b</rb></ruby>
|
||||
<ruby><rb><input class="tco"><input class="tco">b</rb></ruby>
|
||||
<ruby><rb><div class="tco">b</div><input class="tco">b</rb></ruby>
|
||||
<ruby><rb><div class="tco">b</div>c</rb></ruby>
|
||||
|
||||
<!-- FIXME after https://bugzilla.mozilla.org/show_bug.cgi?id=1510299
|
||||
<ruby><rb><input class="tca">b</rb></ruby>
|
||||
<ruby><rb><input class="tca"><input class="tca">b</rb></ruby>
|
||||
<ruby><rb><div class="tca">b</div><input class="tca">b</rb></ruby>
|
||||
<ruby><rb><div class="tca">b</div>c</rb></ruby>
|
||||
-->
|
||||
|
||||
<ruby><rb><input class="t">b</rb></ruby>
|
||||
<ruby><rb><input class="t"><input class="t">b</rb></ruby>
|
||||
<ruby><rb><div class="t">b</div><input class="t">b</rb></ruby>
|
||||
<ruby><rb><div class="t">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="rb">b</rb></ruby>
|
||||
<ruby><rb><input class="rb"><input class="rb">b</rb></ruby>
|
||||
<ruby><rb><div class="rb">b</div><input class="rb">b</rb></ruby>
|
||||
<ruby><rb><div class="rb">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="rt">b</rb></ruby>
|
||||
<ruby><rb><input class="rt"><input class="rt">b</rb></ruby>
|
||||
<ruby><rb><div class="rt">b</div><input class="rt">b</rb></ruby>
|
||||
<ruby><rb><div class="rt">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="rbc">b</rb></ruby>
|
||||
<ruby><rb><input class="rbc"><input class="rbc">b</rb></ruby>
|
||||
<ruby><rb><div class="rbc">b</div><input class="rbc">b</rb></ruby>
|
||||
<ruby><rb><div class="rbc">b</div>c</rb></ruby>
|
||||
|
||||
<ruby><rb><input class="rtc">b</rb></ruby>
|
||||
<ruby><rb><input class="rtc"><input class="rtc">b</rb></ruby>
|
||||
<ruby><rb><div class="rtc">b</div><input class="rtc">b</rb></ruby>
|
||||
<ruby><rb><div class="rtc">b</div>c</rb></ruby>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -20,15 +20,15 @@
|
|||
<custom-element id="c-e-1"></custom-element>
|
||||
The following text should be green:
|
||||
<custom-element id="c-e-2"></custom-element>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e-1", "part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e-1", "part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "::part with host selector styles in first host");
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e-2", "part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e-2", "part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "::part with host selector styles in second host");
|
||||
</script>
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
<custom-element-inner id="c-e-inner" part="c-e-part"></custom-element-inner>
|
||||
</template>
|
||||
<custom-element-outer id="c-e-outer"></custom-element-outer>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "::part cannot be chained to reach elements in the inner host");
|
||||
test(function() {
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
</template>
|
||||
The following text should be green:
|
||||
<div><custom-element id="c-e"></custom-element></div>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "Complex selector for host works");
|
||||
</script>
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
</template>
|
||||
The following text should be green:
|
||||
<pre><custom-element id="c-e"></custom-element></pre>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "Non-matching complex selector for host does not style");
|
||||
</script>
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
</template>
|
||||
The following text should be green:
|
||||
<custom-element id="c-e"></custom-element>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "Part is not styled when host is not selected");
|
||||
</script>
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
</template>
|
||||
The following text should be green:
|
||||
<custom-element id="c-e"></custom-element>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "Part in selected host is not styled by ::part in a stylesheet inside the host");
|
||||
</script>
|
||||
|
|
|
@ -25,16 +25,16 @@
|
|||
</template>
|
||||
The following text should be green:
|
||||
<custom-element-outer id="c-e-outer"></custom-element-outer>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
const colorBlue = "rgb(0, 0, 255)";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e-outer", "green_part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e-outer", "green_part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "Part in outer host is styled by document style sheet");
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "blue_part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "blue_part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorBlue);
|
||||
}, "Part in inner host is not styled by document style sheet");
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Shadow Parts - Invalidation Change Part Name IDL DOMTokenList</title>
|
||||
<meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly">
|
||||
<link href="http://www.google.com/" rel="author" title="Google">
|
||||
<link href="https://drafts.csswg.org/css-shadow-parts/" rel="help">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="support/shadow-helper.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<style>#c-e::part(partp) { color: red; }</style>
|
||||
<style>#c-e::part(new-partp) { color: green; }</style>
|
||||
<script>installCustomElement("custom-element", "custom-element-template");</script>
|
||||
<template id="custom-element-template">
|
||||
<style>span { color: blue; }</style>
|
||||
<span id="part" part="partp">This text</span>
|
||||
</template>
|
||||
The following text should be green:
|
||||
<div><custom-element id="c-e"></custom-element></div>
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
const el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
el.part.remove("partp");
|
||||
el.part.add("new-partp");
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "Part in selected host changed color via part IDL DOMTokenList attribute.");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Shadow Parts - Invalidation Change Part Name IDL Setter</title>
|
||||
<meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly">
|
||||
<link href="http://www.google.com/" rel="author" title="Google">
|
||||
<link href="https://drafts.csswg.org/css-shadow-parts/" rel="help">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="support/shadow-helper.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<style>#c-e::part(partp) { color: red; }</style>
|
||||
<script>installCustomElement("custom-element", "custom-element-template");</script>
|
||||
<template id="custom-element-template">
|
||||
<style>span { color: green; }</style>
|
||||
<span id="part" part="partp">This text</span>
|
||||
</template>
|
||||
The following text should be green:
|
||||
<div><custom-element id="c-e"></custom-element></div>
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
const el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
el.part = "new-partp"
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "Part in selected host changed color via part IDL attribute setter.");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -18,13 +18,13 @@
|
|||
</template>
|
||||
The following text should be green:
|
||||
<div><custom-element id="c-e"></custom-element></div>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
test(function() {
|
||||
var part = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
var before = window.getComputedStyle(part).color;
|
||||
const part = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
const before = window.getComputedStyle(part).color;
|
||||
part.setAttribute("part", "new-partp");
|
||||
var after = window.getComputedStyle(part).color;
|
||||
const after = window.getComputedStyle(part).color;
|
||||
assert_not_equals(before, after);
|
||||
}, "Part in selected host changed color");
|
||||
</script>
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
</template>
|
||||
The following text should be green:
|
||||
<div id="elem"><custom-element id="c-e"></custom-element></div>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
test(function() {
|
||||
var part = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
var before = window.getComputedStyle(part).color;
|
||||
const part = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
const before = window.getComputedStyle(part).color;
|
||||
document.getElementById("elem").setAttribute("id", "new-elem");
|
||||
var after = window.getComputedStyle(part).color;
|
||||
const after = window.getComputedStyle(part).color;
|
||||
assert_not_equals(before, after);
|
||||
}, "Part in selected host changed color");
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Shadow Parts - Part Name IDL</title>
|
||||
<meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly">
|
||||
<link href="http://www.google.com/" rel="author" title="Google">
|
||||
<link href="https://drafts.csswg.org/css-shadow-parts/" rel="help">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="support/shadow-helper.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<span id="s_no_part"></span>
|
||||
<span id="s_part" part="part1"></span>
|
||||
<span id="s_2_parts" part="part1 part2"></span>
|
||||
<script>
|
||||
"use strict";
|
||||
test(function() {
|
||||
const parts = s_no_part.part;
|
||||
assert_equals(parts.length, 0);
|
||||
assert_equals(parts.value, "");
|
||||
}, "Access to .part returns an empty DOMTokenList.");
|
||||
test(function() {
|
||||
const parts = s_2_parts.part;
|
||||
assert_equals(parts.length, 2);
|
||||
assert_equals(parts[0], "part1");
|
||||
assert_equals(parts[1], "part2");
|
||||
assert_equals(parts.value, "part1 part2");
|
||||
}, "Multiple names give a DOMTokenList with multiple entries.");
|
||||
test(function() {
|
||||
const parts = s_no_part.part;
|
||||
assert_equals(parts.length, 0);
|
||||
assert_equals(parts.value, "");
|
||||
parts.add("part1");
|
||||
assert_equals(parts.length, 1);
|
||||
assert_equals(parts.value, "part1");
|
||||
}, "DOMTokenList created by access is persisted.");
|
||||
test(function() {
|
||||
const parts = s_part.part;
|
||||
assert_equals(parts.length, 1);
|
||||
assert_equals(parts.value, "part1");
|
||||
parts.add("part2");
|
||||
assert_equals(parts.length, 2);
|
||||
assert_equals(parts.value, "part1 part2");
|
||||
assert_equals(s_part.getAttribute("part"), parts.value);
|
||||
parts.remove("part1");
|
||||
assert_equals(parts.length, 1);
|
||||
assert_equals(parts.value, "part2");
|
||||
assert_equals(s_part.getAttribute("part"), parts.value);
|
||||
}, "Changes in DOMTokenList are refected in attribute.");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -18,11 +18,11 @@
|
|||
</template>
|
||||
The following text should be green:
|
||||
<custom-element id="c-e"></custom-element>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
const colorGreen = "rgb(0, 128, 0)";
|
||||
test(function() {
|
||||
var el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
const el = getElementByShadowIds(document, ["c-e", "part"]);
|
||||
assert_equals(window.getComputedStyle(el).color, colorGreen);
|
||||
}, "Part in selected host is styled");
|
||||
</script>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: white-space-collapsing - discard - basic cases Reftest Reference</title>
|
||||
<title>CSS Test: text-space-collapse - discard - basic cases Reftest Reference</title>
|
||||
<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: white-space-collapsing - preserve-breaks - basic cases Reftest Reference</title>
|
||||
<title>CSS Test: text-space-collapse - preserve-breaks - basic cases Reftest Reference</title>
|
||||
<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: white-space-collapsing - trim-inner - basic cases Reftest Reference</title>
|
||||
<title>CSS Test: text-space-trim - trim-inner - basic cases Reftest Reference</title>
|
||||
<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
|
@ -17,20 +17,20 @@
|
|||
Test passes if each text positions in the first line match the corresponding positions in the second line.
|
||||
</p>
|
||||
<div>
|
||||
<span>1 2</span>
|
||||
<span> 3 4 </span>
|
||||
<span>5 6</span>
|
||||
<span>7
|
||||
[<span>1 2</span>]
|
||||
[<span> 3 4 </span>]
|
||||
[<span>5 6</span>]
|
||||
[<span>7
|
||||
|
||||
8</span>
|
||||
8</span>]
|
||||
</div>
|
||||
<div>
|
||||
<span>1 2</span>
|
||||
<span> 3 4 </span>
|
||||
<span>5 6</span>
|
||||
<span>7
|
||||
[<span>1 2</span>]
|
||||
[<span> 3 4 </span>]
|
||||
[<span>5 6</span>]
|
||||
[<span>7
|
||||
|
||||
8</span>
|
||||
8</span>]
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -2,16 +2,16 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: white-space-collapsing - discard - basic cases</title>
|
||||
<title>CSS Test: text-space-collapse - discard - basic cases</title>
|
||||
<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
|
||||
<link rel="help" title="CSS Text Level 3: 4.1. White Space Collapsing: the ‘white-space-collapsing’ property" href="http://www.w3.org/TR/css-text-3/#white-space-collapsing" />
|
||||
<link rel="match" href="reference/white-space-collapsing-discard-001-ref.xht"/>
|
||||
<link rel="help" title="CSS Text Level 4: 3.1. White Space Collapsing: the ‘text-space-collapse’ property" href="https://drafts.csswg.org/css-text-4/#white-space-collapsing" />
|
||||
<link rel="match" href="reference/text-space-collapse-discard-001-ref.xht"/>
|
||||
<meta name="flags" content="" />
|
||||
<meta name="assert" content="The UA should discard all white space in the element when white-space-collapsing is set to discard." />
|
||||
<meta name="assert" content="The UA should discard all white space in the element when text-space-collapse is set to discard." />
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.test span {
|
||||
white-space-collapsing: discard;
|
||||
text-space-collapse: discard;
|
||||
}
|
||||
/* the CSS below is not part of the test */
|
||||
span {
|
|
@ -2,16 +2,16 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: white-space-collapsing - preserve-breaks - basic cases</title>
|
||||
<title>CSS Test: text-space-collapse - preserve-breaks - basic cases</title>
|
||||
<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
|
||||
<link rel="help" title="CSS Text Level 3: 4.1. White Space Collapsing: the ‘white-space-collapsing’ property" href="http://www.w3.org/TR/css-text-3/#white-space-collapsing" />
|
||||
<link rel="match" href="reference/white-space-collapsing-preserve-breaks-001-ref.xht"/>
|
||||
<link rel="help" title="CSS Text Level 4: 3.1. White Space Collapsing: the ‘text-space-collapse’ property" href="https://drafts.csswg.org/css-text-4/#white-space-collapsing" />
|
||||
<link rel="match" href="reference/text-space-collapse-preserve-breaks-001-ref.xht"/>
|
||||
<meta name="flags" content="" />
|
||||
<meta name="assert" content="The UA should collapse sequences of white space into a single character when white-space-collapsing is set to preserve." />
|
||||
<meta name="assert" content="The UA should collapse sequences of white space into a single character but preserve segment breaks as forced line breaks when text-space-collapse is set to preserve-breaks." />
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.test span {
|
||||
white-space-collapsing: preserve-breaks;
|
||||
text-space-collapse: preserve-breaks;
|
||||
}
|
||||
/* the CSS below is not part of the test */
|
||||
span {
|
|
@ -2,16 +2,16 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: white-space-collapsing - trim-inner - basic cases</title>
|
||||
<title>CSS Test: text-space-trim - trim-inner - basic cases</title>
|
||||
<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
|
||||
<link rel="help" title="CSS Text Level 3: 4.1. White Space Collapsing: the ‘white-space-collapsing’ property" href="http://www.w3.org/TR/css-text-3/#white-space-collapsing" />
|
||||
<link rel="match" href="reference/white-space-collapsing-trim-inner-001-ref.xht"/>
|
||||
<link rel="help" title="CSS Text Level 4: 3.2. White Space Trimming: the ‘text-space-trim’ property" href="https://drafts.csswg.org/css-text-4/#white-space-trim" />
|
||||
<link rel="match" href="reference/text-space-trim-trim-inner-001-ref.xht"/>
|
||||
<meta name="flags" content="" />
|
||||
<meta name="assert" content="The UA should discard all white space at the beginning of a block and all white space at the end of a block when white-space-collapsing is set to trim-inner." />
|
||||
<meta name="assert" content="The UA should discard all white space at the beginning of a block and all white space at the end of a block when text-space-trim is set to trim-inner." />
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.test span {
|
||||
white-space-collapsing: trim-inner;
|
||||
text-space-trim: trim-inner;
|
||||
}
|
||||
/* the CSS below is not part of the test */
|
||||
div {
|
||||
|
@ -26,24 +26,24 @@
|
|||
</p>
|
||||
<div>
|
||||
<div class="test">
|
||||
<span> 1 2 </span>
|
||||
<span> 3 4 </span>
|
||||
<span> 5 6 </span>
|
||||
<span>
|
||||
[<span> 1 2 </span>]
|
||||
[<span> 3 4 </span>]
|
||||
[<span> 5 6 </span>]
|
||||
[<span>
|
||||
|
||||
7
|
||||
|
||||
8
|
||||
|
||||
</span>
|
||||
</span>]
|
||||
</div>
|
||||
<div>
|
||||
<span>1 2</span>
|
||||
<span> 3 4 </span>
|
||||
<span>5 6</span>
|
||||
<span>7
|
||||
[<span>1 2</span>]
|
||||
[<span> 3 4 </span>]
|
||||
[<span>5 6</span>]
|
||||
[<span>7
|
||||
|
||||
8</span>
|
||||
8</span>]
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
|
@ -75,8 +75,6 @@
|
|||
testsPerSlice: 1,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -76,8 +76,6 @@
|
|||
testsPerSlice: 1,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -86,8 +86,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -69,8 +69,6 @@
|
|||
testsPerSlice: 1,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -65,8 +65,6 @@
|
|||
testsPerSlice: 1,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -67,8 +67,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -70,8 +70,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -71,8 +71,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -70,8 +70,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
var styles = {
|
||||
|
|
|
@ -70,8 +70,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
// as we're dealing with em-based lengths, we need to define a font-size
|
||||
|
|
|
@ -70,8 +70,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
// clone and overwrite initial styles to be
|
||||
|
|
|
@ -71,8 +71,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
// clone and overwrite initial styles to be
|
||||
|
|
|
@ -71,8 +71,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
// have parent transition the font-size only
|
||||
|
|
|
@ -93,8 +93,6 @@
|
|||
testsPerSlice: 50,
|
||||
// milliseconds to wait before calling teardown and ending test
|
||||
duration: parseFloat(duration) * 1000,
|
||||
// the global suite timeout
|
||||
timeout: timeout,
|
||||
// prepare individual test
|
||||
setup: function(data, options) {
|
||||
generalParallelTest.setup(data, options);
|
||||
|
|
|
@ -81,7 +81,7 @@ root.runParallelAsyncHarness = function(options) {
|
|||
options.tests.forEach(function(data, index) {
|
||||
data.cases = {};
|
||||
cases.forEach(function(name) {
|
||||
data.cases[name] = async_test(data.name + " / " + name, {timeout: options.timeout || 60000});
|
||||
data.cases[name] = async_test(data.name + " / " + name);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>Reference: text-overflow:ellipsis and ruby</title>
|
||||
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
|
||||
<style>
|
||||
html,body {
|
||||
color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
|
||||
}
|
||||
|
||||
.clip {
|
||||
overflow: hidden;
|
||||
width: 40px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
input { width: 40px; -webkit-appearance: none; border: 1px solid black; }
|
||||
span { white-space: pre; }
|
||||
.thg { display: inline-table; }
|
||||
.tc { display: inline-table; }
|
||||
.t { display: inline-table; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div style="float:left; width:300px">
|
||||
<div class="clip">
|
||||
<span><span><span>aa<input class="thg">bb</span></span></span>
|
||||
<br>
|
||||
<span><span><span>aa<div class="thg">bbbbbb</div>cc</span></span></span>
|
||||
<br>
|
||||
<span><span><span>aa<span>bbbbbb</span>cc</span></span></span>
|
||||
<br>
|
||||
<span><span><span>aa<input class="tc">bb</span></span></span>
|
||||
<br>
|
||||
<span><span><span>aa<div class="tc">bbbbbb</div>cc</span></span></span>
|
||||
<br>
|
||||
<span><span><span>aa<input class="t">bb</span></span></span>
|
||||
<br>
|
||||
<span><span><span>aa<div class="t">bbbbbb</div>cc</span></span></span>
|
||||
|
||||
<br>
|
||||
<span><span><span><input class="thg">bb</span></span></span>
|
||||
<br>
|
||||
<span><span><span><div class="thg">bbbbbb</div>cc</span></span></span>
|
||||
<br>
|
||||
<span><span><span><span>bbbbbb</span>cc</span></span></span>
|
||||
<br>
|
||||
<span><span><span><input class="tc">bb</span></span></span>
|
||||
<br>
|
||||
<span><span><span><div class="tc">bbbbbb</div>cc</span></span></span>
|
||||
<br>
|
||||
<span><span><span><input class="t">bb</span></span></span>
|
||||
<br>
|
||||
<span><span><span><div class="t">bbbbbb</div>cc</span></span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="float:left; width:300px">
|
||||
<div class="clip">
|
||||
<span><span><input class="thg">bb</span></span>
|
||||
<br>
|
||||
<span><span><div class="thg">bbbbbb</div>cc</span></span>
|
||||
<br>
|
||||
<span><span>bbbbbbcc</span></span>
|
||||
<br>
|
||||
<span><span><input class="tc">bb</span></span>
|
||||
<br>
|
||||
<span><span><div class="tc">bbbbbb</div>cc</span></span>
|
||||
<br>
|
||||
<span><span><input class="t">bb</span></span>
|
||||
<br>
|
||||
<span><span><div class="t">bbbbbb</div>cc</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,85 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Basic User Interface Test: text-overflow:ellipsis and ruby</title>
|
||||
<link rel="help" href="http://www.w3.org/TR/css3-ui/#text-overflow">
|
||||
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
|
||||
<link rel="match" href="text-overflow-ruby-ref.html">
|
||||
<style>
|
||||
html,body {
|
||||
color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
|
||||
}
|
||||
|
||||
.clip {
|
||||
overflow: hidden;
|
||||
width: 40px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
input { width: 40px; -webkit-appearance: none; border: 1px solid black; }
|
||||
|
||||
.thg { display: table-header-group; }
|
||||
.tc { display: table-cell; }
|
||||
.t { display: table; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div style="float:left; width:300px">
|
||||
<div class="clip">
|
||||
<ruby><rb><span>aa<input class="thg">bb</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span>aa<div class="thg">bbbbbb</div>cc</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span>aa<span>bbbbbb</span>cc</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span>aa<input class="tc">bb</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span>aa<div class="tc">bbbbbb</div>cc</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span>aa<input class="t">bb</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span>aa<div class="t">bbbbbb</div>cc</span></rb></ruby>
|
||||
|
||||
<br>
|
||||
<ruby><rb><span><input class="thg">bb</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span><div class="thg">bbbbbb</div>cc</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span><span>bbbbbb</span>cc</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span><input class="tc">bb</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span><div class="tc">bbbbbb</div>cc</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span><input class="t">bb</span></rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><span><div class="t">bbbbbb</div>cc</span></rb></ruby>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="float:left; width:300px">
|
||||
<div class="clip">
|
||||
<ruby><rb><input class="thg">bb</rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><div class="thg">bbbbbb</div>cc</rb></ruby>
|
||||
<br>
|
||||
<ruby><rb>bbbbbbcc</rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><input class="tc">bb</rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><div class="tc">bbbbbb</div>cc</rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><input class="t">bb</rb></ruby>
|
||||
<br>
|
||||
<ruby><rb><div class="t">bbbbbb</div>cc</rb></ruby>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!doctype html>
|
||||
<title>CSS Variables Test: Exponential blowup doesn't crash</title>
|
||||
<meta charset="UTF-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="author" href="https://mozilla.org" title="Mozilla">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-variables/">
|
||||
<script>
|
||||
let css = `
|
||||
--v0: "Something really really really long";
|
||||
`;
|
||||
for (let i = 0; i < 30; ++i)
|
||||
css += `--v${i + 1}: var(--v${i}), var(--v${i});`;
|
||||
let s = document.createElement("style");
|
||||
s.innerHTML = `
|
||||
:root { ${css}; }
|
||||
:root::before { content: var(--v31); }
|
||||
`;
|
||||
document.head.appendChild(s);
|
||||
</script>
|
||||
PASS if doesn't crash
|
||||
<script>
|
||||
test(function() {
|
||||
getComputedStyle(document.documentElement, "::before").content;
|
||||
assert_true(true, "Didn't crash");
|
||||
});
|
||||
</script>
|
|
@ -6,12 +6,11 @@
|
|||
|
||||
|
||||
<div>
|
||||
<p>Expected: A green box and an overlapping black box, with a magenta<br>
|
||||
overlapping region.</p>
|
||||
<p>Expected: Just a single green box.</p>
|
||||
</div>
|
||||
<div class="colorbox"></div>
|
||||
<div class="box2outside"></div>
|
||||
<div class="box2inside"></div>
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.colorbox {
|
||||
|
@ -22,21 +21,5 @@
|
|||
left: 10px;
|
||||
top: 100px;
|
||||
}
|
||||
.box2outside {
|
||||
background: black;
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
left: 60px;
|
||||
top: 150px;
|
||||
}
|
||||
.box2inside {
|
||||
background: #ff7fff;
|
||||
position: absolute;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
left: 60px;
|
||||
top: 150px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
<link rel="match" href="backdrop-filter-basic-opacity-ref.html">
|
||||
|
||||
<div>
|
||||
<p>Expected: A green box and an overlapping black box, with a magenta<br>
|
||||
overlapping region.</p>
|
||||
<p>Expected: Just a single green box.</p>
|
||||
</div>
|
||||
<div class="colorbox">
|
||||
<div class="filterbox"></div>
|
||||
|
@ -29,7 +28,7 @@
|
|||
left: 50px;
|
||||
top: 50px;
|
||||
backdrop-filter: invert(1);
|
||||
opacity: 0.5;
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>backdrop-filter: Should not filter outside of clip/scroll.</title>
|
||||
<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
|
||||
|
||||
|
||||
|
||||
<div style="width:600px;">
|
||||
<p>Expected: A green box, overlapping red box, and a small, inset cyan box. The<br>
|
||||
cyan should not extend to the bottom/right edges of the red box.</p>
|
||||
</div>
|
||||
|
||||
<div id="A">
|
||||
<div id="B">
|
||||
<div id="F"></div>
|
||||
<div id="T"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
position:absolute;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
#A {
|
||||
overflow:hidden;
|
||||
top: 110px;
|
||||
left: 10px;
|
||||
}
|
||||
#B {
|
||||
|
||||
background:green;
|
||||
}
|
||||
#F {
|
||||
position:fixed;
|
||||
background:#f008;
|
||||
top:150px;
|
||||
left:50px;
|
||||
}
|
||||
#T {
|
||||
background:#c0e3ff;
|
||||
top:90px;
|
||||
left:90px;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>backdrop-filter: Should not filter outside of clip/scroll.</title>
|
||||
<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
|
||||
<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty">
|
||||
<link rel="match" href="backdrop-filter-fixed-clip-ref.html">
|
||||
|
||||
<div style="width:600px;">
|
||||
<p>Expected: A green box, overlapping red box, and a small, inset cyan box. The<br>
|
||||
cyan should not extend to the bottom/right edges of the red box.</p>
|
||||
</div>
|
||||
|
||||
<div id="A">
|
||||
<div id="B">
|
||||
<div id="F"></div>
|
||||
<div id="T"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
position:absolute;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
#A {
|
||||
overflow:hidden;
|
||||
top: 110px;
|
||||
left: 10px;
|
||||
}
|
||||
#B {
|
||||
opacity: 0.99999;
|
||||
background:green;
|
||||
}
|
||||
#F {
|
||||
position:fixed;
|
||||
background:#f008;
|
||||
top:150px;
|
||||
left:50px;
|
||||
}
|
||||
#T {
|
||||
background:#fff8;
|
||||
top:90px;
|
||||
left:90px;
|
||||
backdrop-filter:invert(1);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>backdrop-filter: Should not filter outside parent stacking context.</title>
|
||||
<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
|
||||
<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty">
|
||||
<link rel="match" href="backdrop-filter-isolation-ref.html">
|
||||
|
||||
<div class="outside">
|
||||
<div class="stacking-context">
|
||||
<div class="filter">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
div {
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
.outside {
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
.stacking-context {
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 130px;
|
||||
}
|
||||
.filter {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
top: 30px;
|
||||
left: -90px;
|
||||
opacity: 0.3;
|
||||
backdrop-filter: invert(1);
|
||||
background: yellow;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -37,6 +37,12 @@
|
|||
checkDOMMatrix(matrix, initialMatrix());
|
||||
},"test scale() doesn't mutate");
|
||||
|
||||
test(function() {
|
||||
var matrix = initialMatrix();
|
||||
matrix.scaleNonUniform(1,5);
|
||||
checkDOMMatrix(matrix, initialMatrix());
|
||||
},"test scaleNonUniform() doesn't mutate");
|
||||
|
||||
test(function() {
|
||||
var matrix = initialMatrix();
|
||||
matrix.scale3d(3,2,1,1);
|
||||
|
|
|
@ -139,6 +139,27 @@
|
|||
checkDOMMatrix(result, expected);
|
||||
},"test scale() with offsets");
|
||||
|
||||
test(function() {
|
||||
var result = initialDOMMatrix().scaleNonUniform();
|
||||
var expected = initialDOMMatrix()
|
||||
.scale(1, 1, 1, 0, 0, 0);
|
||||
checkDOMMatrix(result, expected);
|
||||
},"test scaleNonUniform()");
|
||||
|
||||
test(function() {
|
||||
var result = initialDOMMatrix().scaleNonUniform(6);
|
||||
var expected = initialDOMMatrix()
|
||||
.scale(6, 1, 1, 0, 0, 0);
|
||||
checkDOMMatrix(result, expected);
|
||||
},"test scaleNonUniform() with sx");
|
||||
|
||||
test(function() {
|
||||
var result = initialDOMMatrix().scaleNonUniform(5, 7);
|
||||
var expected = initialDOMMatrix()
|
||||
.scale(5, 7, 1, 0, 0, 0);
|
||||
checkDOMMatrix(result, expected);
|
||||
},"test scaleNonUniform() with sx, sy");
|
||||
|
||||
test(function() {
|
||||
var result = initialDOMMatrix().scale3d(7, 5, 2, 3);
|
||||
var expected = initialDOMMatrix()
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
// Removed members
|
||||
[
|
||||
// https://github.com/w3c/fxtf-drafts/commit/99e3212469026b2f2f50926a41912d110a1741b7
|
||||
['DOMMatrixReadOnly', 'scaleNonUniform'],
|
||||
['DOMMatrix', 'scaleNonUniformSelf'],
|
||||
// https://github.com/w3c/fxtf-drafts/commit/86da3dc961d442f9d8dc7ab59065a9804e109286
|
||||
['DOMMatrix', 'multiplyBy'],
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Custom Elements: create an element for a token must perform a microtask checkpoint</title>
|
||||
<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
|
||||
<meta name="assert" content="When the HTML parser creates an element for a token, it must perform a microtask checkpoint before invoking the constructor">
|
||||
<meta name="help" content="https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token">
|
||||
<meta name="help" content="https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint">
|
||||
<meta name="help" content="https://html.spec.whatwg.org/multipage/parsing.html#adoption-agency-algorithm">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/custom-elements-helpers.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
||||
async function construct_custom_element_in_parser(test, markup)
|
||||
{
|
||||
const window = await create_window_in_test(test, `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body><script>
|
||||
class SomeElement extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
window.recordsListInConstructor = recordsList.map((records) => records.slice(0));
|
||||
}
|
||||
}
|
||||
customElements.define('some-element', SomeElement);
|
||||
|
||||
const recordsList = [];
|
||||
const observer = new MutationObserver((records) => {
|
||||
recordsList.push(records);
|
||||
});
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
|
||||
window.onload = () => {
|
||||
window.recordsListInDOMContentLoaded = recordsList.map((records) => records.slice(0));
|
||||
}
|
||||
|
||||
</scr` + `ipt>${markup}</body></html>`);
|
||||
return window;
|
||||
}
|
||||
|
||||
promise_test(async function () {
|
||||
const contentWindow = await construct_custom_element_in_parser(this, '<b><some-element></b>');
|
||||
const contentDocument = contentWindow.document;
|
||||
|
||||
let recordsList = contentWindow.recordsListInConstructor;
|
||||
assert_true(Array.isArray(recordsList));
|
||||
assert_equals(recordsList.length, 1);
|
||||
assert_true(Array.isArray(recordsList[0]));
|
||||
assert_equals(recordsList[0].length, 1);
|
||||
let record = recordsList[0][0];
|
||||
assert_equals(record.type, 'childList');
|
||||
assert_equals(record.target, contentDocument.body);
|
||||
assert_equals(record.previousSibling, contentDocument.querySelector('script'));
|
||||
assert_equals(record.nextSibling, null);
|
||||
assert_equals(record.removedNodes.length, 0);
|
||||
assert_equals(record.addedNodes.length, 1);
|
||||
assert_equals(record.addedNodes[0], contentDocument.querySelector('b'));
|
||||
|
||||
recordsList = contentWindow.recordsListInDOMContentLoaded;
|
||||
assert_true(Array.isArray(recordsList));
|
||||
assert_equals(recordsList.length, 2);
|
||||
assert_true(Array.isArray(recordsList[1]));
|
||||
assert_equals(recordsList[1].length, 1);
|
||||
record = recordsList[1][0];
|
||||
assert_equals(record.type, 'childList');
|
||||
assert_equals(record.target, contentDocument.querySelector('b'));
|
||||
assert_equals(record.previousSibling, null);
|
||||
assert_equals(record.nextSibling, null);
|
||||
assert_equals(record.removedNodes.length, 0);
|
||||
assert_equals(record.addedNodes.length, 1);
|
||||
assert_equals(record.addedNodes[0], contentDocument.querySelector('some-element'));
|
||||
}, 'HTML parser must perform a microtask checkpoint before constructing a custom element');
|
||||
|
||||
promise_test(async function () {
|
||||
const contentWindow = await construct_custom_element_in_parser(this, '<b><i>hello</b><some-element>');
|
||||
const contentDocument = contentWindow.document;
|
||||
let recordsList = contentWindow.recordsListInConstructor;
|
||||
assert_true(Array.isArray(recordsList));
|
||||
assert_equals(recordsList.length, 1);
|
||||
assert_true(Array.isArray(recordsList[0]));
|
||||
assert_equals(recordsList[0].length, 4);
|
||||
|
||||
let record = recordsList[0][0];
|
||||
assert_equals(record.type, 'childList');
|
||||
assert_equals(record.target, contentDocument.body);
|
||||
assert_equals(record.previousSibling, contentDocument.querySelector('script'));
|
||||
assert_equals(record.nextSibling, null);
|
||||
assert_equals(record.removedNodes.length, 0);
|
||||
assert_equals(record.addedNodes.length, 1);
|
||||
assert_equals(record.addedNodes[0], contentDocument.querySelector('b'));
|
||||
|
||||
record = recordsList[0][1];
|
||||
assert_equals(record.type, 'childList');
|
||||
assert_equals(record.target, contentDocument.querySelector('b'));
|
||||
assert_equals(record.previousSibling, null);
|
||||
assert_equals(record.nextSibling, null);
|
||||
assert_equals(record.removedNodes.length, 0);
|
||||
assert_equals(record.addedNodes.length, 1);
|
||||
assert_equals(record.addedNodes[0], contentDocument.querySelector('i'));
|
||||
|
||||
record = recordsList[0][2];
|
||||
assert_equals(record.type, 'childList');
|
||||
assert_equals(record.target, contentDocument.querySelector('i'));
|
||||
assert_equals(record.previousSibling, null);
|
||||
assert_equals(record.nextSibling, null);
|
||||
assert_equals(record.removedNodes.length, 0);
|
||||
assert_equals(record.addedNodes.length, 1);
|
||||
assert_equals(record.addedNodes[0].nodeType, Node.TEXT_NODE);
|
||||
assert_equals(record.addedNodes[0].data, "hello");
|
||||
|
||||
record = recordsList[0][3];
|
||||
assert_equals(record.type, 'childList');
|
||||
assert_equals(record.target, contentDocument.body);
|
||||
assert_equals(record.previousSibling, contentDocument.querySelector('b'));
|
||||
assert_equals(record.nextSibling, null);
|
||||
assert_equals(record.removedNodes.length, 0);
|
||||
assert_equals(record.addedNodes.length, 1);
|
||||
assert_equals(record.addedNodes[0], contentDocument.querySelectorAll('i')[1]);
|
||||
|
||||
recordsList = contentWindow.recordsListInDOMContentLoaded;
|
||||
assert_true(Array.isArray(recordsList));
|
||||
assert_equals(recordsList.length, 2);
|
||||
assert_true(Array.isArray(recordsList[1]));
|
||||
assert_equals(recordsList[1].length, 1);
|
||||
|
||||
record = recordsList[1][0];
|
||||
assert_equals(record.type, 'childList');
|
||||
assert_equals(record.target, contentDocument.querySelectorAll('i')[1]);
|
||||
assert_equals(record.previousSibling, null);
|
||||
assert_equals(record.nextSibling, null);
|
||||
assert_equals(record.removedNodes.length, 0);
|
||||
assert_equals(record.addedNodes.length, 1);
|
||||
assert_equals(record.addedNodes[0], contentDocument.querySelector('some-element'));
|
||||
}, 'HTML parser must perform a microtask checkpoint before constructing a custom element during the adoption agency algorithm');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -8,7 +8,7 @@
|
|||
<meta name="help" content="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/custom-elements-helpers.js"></script>
|
||||
<script src="./resources/custom-elements-helpers.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<meta name="help" content="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/custom-elements-helpers.js"></script>
|
||||
<script src="./resources/custom-elements-helpers.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
|
|
|
@ -26,6 +26,41 @@ This function causes a sequence of actions to be sent to the browser. It is base
|
|||
The action can be a keyboard action, a pointer action or a pause. It returns a `Promise` that
|
||||
resolves after the actions have been sent or rejects if an error was thrown.
|
||||
|
||||
Test authors are encouraged to use the builder API to generate the sequence of actions. The builder
|
||||
API can be accessed via the `new test_driver.Actions()` object.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
let text_box = document.getElementById("text");
|
||||
|
||||
let actions = new test_driver.Actions()
|
||||
.pointerMove(0, 0, {origin: text_box})
|
||||
.pointerDown()
|
||||
.pointerUp()
|
||||
.addTick()
|
||||
.keyDown("p")
|
||||
.keyUp("p");
|
||||
|
||||
actions.send();
|
||||
```
|
||||
|
||||
Calling into `send()` is going to dispatch the action sequence (via `test_driver.action_sequence`) and also returns a `Promise` which should be handled however is appropriate in the test. The other functions in the `Actions()` object are going to modify the state of the object by adding a new action in the sequence and return the same object. So the functions can be easily chained as shown in the example above. Here is a list of helper functions in the `Actions` class:
|
||||
|
||||
```
|
||||
pointerDown: Create a pointerDown event for the current default pointer source
|
||||
pointerUp: Create a pointerUp event for the current default pointer source
|
||||
pointerMove: Create a move event for the current default pointer source
|
||||
keyDown: Create a keyDown event for the current default key source
|
||||
keyUp: Create a keyUp event for the current default key source
|
||||
pause: Add a pause to the current tick
|
||||
addTick: Insert a new actions tick
|
||||
setPointer: Set the current default pointer source (By detault the pointerType is mouse)
|
||||
addPointer: Add a new pointer input source with the given name
|
||||
setKeyboard: Set the current default key source
|
||||
addKeyboard: Add a new key input source with the given name
|
||||
```
|
||||
|
||||
### bless
|
||||
|
||||
Usage: `test_driver.bless(intent, action)`
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8 />
|
||||
<title>Event Timing: buffer long-latency events before onload</title>
|
||||
<button id='button' onclick='clickDelay()'>Generate a 'click' event</button>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/testdriver.js></script>
|
||||
<script src=/resources/testdriver-vendor.js></script>
|
||||
|
||||
<script src=resources/event-timing-support.js></script>
|
||||
<img src=resources/slow-image.py>
|
||||
|
||||
<script>
|
||||
let clickTimeMin;
|
||||
let processingStartMin;
|
||||
let onloadStart;
|
||||
let firstClickStart = 0;
|
||||
let firstClickEnd = 0;
|
||||
function clickDelay() {
|
||||
const onclickStart = performance.now();
|
||||
if (firstClickStart === 0)
|
||||
firstClickStart = onclickStart;
|
||||
while(performance.now() < onclickStart + 60) {}
|
||||
if (firstClickEnd === 0)
|
||||
firstClickEnd = performance.now();
|
||||
}
|
||||
|
||||
function validateEntries() {
|
||||
const entries = performance.getEntriesByName('click', 'event');
|
||||
|
||||
const entriesBeforeOnload = entries.filter(
|
||||
e => e.startTime < onloadStart);
|
||||
assert_equals(entriesBeforeOnload.length, 1,
|
||||
"Long latency events before onload should be buffered.");
|
||||
const entry = entriesBeforeOnload[0];
|
||||
verifyClickEvent(entry, true);
|
||||
|
||||
assert_greater_than_equal(entry.startTime, clickTimeMin,
|
||||
"The entry's start time should be later than clickTimeMin.");
|
||||
assert_greater_than_equal(entry.processingStart, processingStartMin,
|
||||
"The entry should be processed later than processingStartMin.");
|
||||
assert_less_than_equal(entry.processingStart, firstClickStart,
|
||||
"The processingStart must be before firstClickStart.")
|
||||
assert_greater_than_equal(entry.processingEnd, firstClickEnd,
|
||||
"The processingEnd must be after firstClickEnd.");
|
||||
|
||||
const entriesAfterOnload = entries.filter(
|
||||
e => e.startTime >= onloadStart);
|
||||
assert_equals(entriesAfterOnload.length, 0,
|
||||
"Events after onload shouldn't be buffered.");
|
||||
}
|
||||
|
||||
/* Timeline:
|
||||
Begin Busy Loop
|
||||
Click 1 arrives
|
||||
End Busy Loop
|
||||
(Dispatch and Process Click 1 - buffered)
|
||||
Onload Event Fires
|
||||
Begin Busy Loop
|
||||
Click 2 arrives
|
||||
End Busy Loop
|
||||
(Dispatch and Process Click 2 - not buffered)
|
||||
*/
|
||||
async_test(function(t) {
|
||||
clickTimeMin = performance.now();
|
||||
clickAndBlockMain('button');
|
||||
// Event handlers will be dispatched asynchronously, so this will be called
|
||||
// before processing begins.
|
||||
processingStartMin = performance.now();
|
||||
on_event(window, 'load', e => {
|
||||
onloadStart = performance.now();
|
||||
clickAndBlockMain('button').then(wait).then(
|
||||
t.step_func_done(validateEntries));
|
||||
});
|
||||
}, "Event Timing: click, onload.");
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset=utf-8 />
|
||||
<title>Event Timing: entries should be observable by its own frame.</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<button id='button' onclick='1'>Generate a 'click' event</button>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/testdriver.js></script>
|
||||
<script src=/resources/testdriver-vendor.js></script>
|
||||
|
||||
<script src=resources/event-timing-support.js></script>
|
||||
<img src=./resources/slow-image.py>
|
||||
<iframe src=resources/event-timing-crossiframe-childframe.html></iframe>
|
||||
<script>
|
||||
let clickTimeMin;
|
||||
let processingStartMin;
|
||||
let onloadStart;
|
||||
|
||||
function validateEntries() {
|
||||
const entries = performance.getEntriesByName('click', 'event');
|
||||
|
||||
assert_equals(entries.length, 1,
|
||||
"Observer of main frames should only capture main-frame event-timing entries."
|
||||
);
|
||||
const entry = entries[0];
|
||||
verifyClickEvent(entry, true);
|
||||
|
||||
assert_greater_than(entry.processingStart, processingStartMin,
|
||||
"The entry's processing start should be later than processingStartMin.");
|
||||
assert_greater_than(onloadStart, entry.processingStart,
|
||||
"onload should occur later than the entry's procesisng start.");
|
||||
assert_greater_than(entry.startTime, clickTimeMin,
|
||||
"The entry's start time should be later than clickTimeMin.");
|
||||
assert_greater_than(onloadStart, entry.startTime,
|
||||
"onload should occur later than the entry's start time.");
|
||||
}
|
||||
|
||||
function validateChildFrameEntries(childFrameData) {
|
||||
assert_equals(childFrameData.bufferedEntries.length, 1,
|
||||
"Event Timing of child frames should only capture child-frame event-timing entries."
|
||||
);
|
||||
const entry = entries[0];
|
||||
verifyClickEvent(entry);
|
||||
|
||||
assert_greater_than(entry.processingStart, childFrameData.processingStartMin,
|
||||
"The entry's processing start should be later than the child frame's processingStartMin.");
|
||||
assert_greater_than(childFrameData.onloadStart, entry.processingStart,
|
||||
"Child frame's onload should occur later than the entry's processing \
|
||||
start.");
|
||||
assert_greater_than(entry.startTime, childFrameData.clickTimeMin,
|
||||
"The entry's start time should be later than the child frame's \
|
||||
clickTimeMin.");
|
||||
assert_greater_than(childFrameData.onloadStart, entry.startTime,
|
||||
"Child frame's onload should be later than the entry's start time.");
|
||||
|
||||
assert_array_equals(childFrameData.observedEntries,
|
||||
childFrameData.bufferedEntries,
|
||||
"The child frame's observed entries should be buffered as well.");
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
clickTimeMin = performance.now();
|
||||
clickAndBlockMain('button');
|
||||
processingStartMin = performance.now();
|
||||
const childFrameEntriesPromise = new Promise((resolve, reject) => {
|
||||
window.addEventListener("message", (event) => {
|
||||
resolve(event.data);
|
||||
}, false);
|
||||
});
|
||||
on_event(window, 'load', e => {
|
||||
onloadStart = performance.now();
|
||||
childFrameEntriesPromise.then((entries) => {
|
||||
t.step(() => {
|
||||
validateChildFrameEntries(entries);
|
||||
validateEntries();
|
||||
});
|
||||
t.done();
|
||||
});
|
||||
});
|
||||
}, "Event Timing: entries should only be observable by its own frame.");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8 />
|
||||
<title>Event Timing: entries should be observable by its own frame.
|
||||
</title>
|
||||
<script src=./resources/event-timing-support.js></script>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Description:</h2>
|
||||
<p>
|
||||
<div>
|
||||
The goal of this manual test is to verify that observers that have
|
||||
registered "event" entry type can observe the long-latency input events,
|
||||
and verify the same behavior within iframe and in cross-frame scenario.
|
||||
</div>
|
||||
</p>
|
||||
<h2>Manual test steps:</h2>
|
||||
<p>
|
||||
<div>
|
||||
Step 1: Click the "make busy" button to make main-thread busy for 2 seconds.</span>
|
||||
</div>
|
||||
<div>
|
||||
Step 2: do several clicks on "click while busy" while busy to generate long-latency inputs.
|
||||
</div>
|
||||
<div>
|
||||
Step 3: observe in the "timeline" section that the long-latency clicks are captured by the observer.
|
||||
</div>
|
||||
<div>
|
||||
Step 4: do step 1 to step 3 for the iframe. Observe that the observers only observe input events within its frame.
|
||||
</div>
|
||||
</p>
|
||||
<div>
|
||||
<h2>Actions:</h2>
|
||||
<button id='busy_button' onclick='onMakeBusy()'>make busy</button>
|
||||
<button id='click_input_button' onclick='1'> click while busy </button>
|
||||
</div>
|
||||
<h2>iframe:</h2>
|
||||
<div>
|
||||
<iframe name='childframe' width="100%" height="30%" src=./resources/event-timing-observer-manual-childframe.html></iframe>
|
||||
</div>
|
||||
<h2>Timeline:</h2>
|
||||
<p id='timeline'></p>
|
||||
</body>
|
||||
<script>
|
||||
function log(message) {
|
||||
const timestamp = performance.now();
|
||||
const elem = document.createElement('div');
|
||||
elem.innerHTML = `${timestamp.toFixed(1)}: ${message}`;
|
||||
const timeline = document.getElementById('timeline');
|
||||
timeline.appendChild(elem);
|
||||
}
|
||||
|
||||
function onMakeBusy() {
|
||||
log("busy start");
|
||||
step_timeout(()=>{
|
||||
mainThreadBusy(2000);
|
||||
log("busy end");
|
||||
}, 0);
|
||||
}
|
||||
|
||||
document.body.onload = () => {
|
||||
new PerformanceObserver((entryList) => {
|
||||
entryList.getEntries().forEach(e => {
|
||||
log(`entry observed: ${JSON.stringify(e)}`);
|
||||
});
|
||||
}).observe({ entryTypes: ['event'] });
|
||||
log("observer registered");
|
||||
};
|
||||
|
||||
window.onmessage = (msg) => {
|
||||
log("received msg: " + msg.data);
|
||||
if (msg.data === 'CHILD_FRAME_IS_READY') {
|
||||
// TODO(crbug/831729): automate clicks on iframe when testdriver support
|
||||
// clicking in iframe.
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,103 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8 />
|
||||
<title>Event Timing: Performance observers can observe long-latency events
|
||||
</title>
|
||||
<button id='button' onclick='1'>Generate a 'click' event</button>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/testdriver.js></script>
|
||||
<script src=/resources/testdriver-vendor.js></script>
|
||||
|
||||
<script src=resources/event-timing-support.js></script>
|
||||
<img src=resources/slow-image.py>
|
||||
|
||||
<script>
|
||||
let timeBeforeFirstClick;
|
||||
let timeAfterFirstClick;
|
||||
let timeAfterSecondClick;
|
||||
let onloadStart;
|
||||
let observedEntries = [];
|
||||
|
||||
function verifyBuffer(bufferedEntries) {
|
||||
assert_equals(bufferedEntries.length, 1,
|
||||
"Only events before onload should be buffered.");
|
||||
const entry = bufferedEntries[0];
|
||||
assert_greater_than(onloadStart, entry.startTime,
|
||||
"Onload should be later than entry's start time.");
|
||||
assert_greater_than(entry.processingStart, timeBeforeFirstClick,
|
||||
"The entry's processing start should be after timeBeforeFirstClick");
|
||||
assert_less_than(entry.processingStart, timeAfterFirstClick,
|
||||
"The entry's processing start should be before timeAfterFirstClick.");
|
||||
verifyClickEvent(entry, true);
|
||||
}
|
||||
|
||||
function verifyObserverEntries(observedEntries) {
|
||||
const entriesAfterFirstClick = observedEntries.filter(
|
||||
e => e.startTime > timeAfterFirstClick);
|
||||
assert_equals(entriesAfterFirstClick.length, 1,
|
||||
'There should be one event after timeAfterFirstClick.');
|
||||
const entry1 = entriesAfterFirstClick[0];
|
||||
verifyClickEvent(entry1);
|
||||
assert_greater_than(entry1.processingStart, timeAfterFirstClick,
|
||||
"entry1's processing start should be after timeAfterFirstClick");
|
||||
assert_less_than(entry1.processingStart, timeAfterSecondClick,
|
||||
"entry1's processing start should be before timeAfterSecondClick.");
|
||||
assert_greater_than(entry1.startTime, onloadStart,
|
||||
"entry1's start time should be later than onloadStart.");
|
||||
|
||||
const entriesBeforeFirstClick =
|
||||
observedEntries.filter(e => e.startTime < timeAfterFirstClick);
|
||||
assert_equals(entriesBeforeFirstClick.length, 1,
|
||||
'There should be one event before timeAfterFirstClick.'
|
||||
);
|
||||
const entry2 = entriesBeforeFirstClick[0];
|
||||
verifyClickEvent(entry2);
|
||||
assert_greater_than(entry2.processingStart, timeBeforeFirstClick,
|
||||
"entry2's processing start should be after timeBeforeFirstClick");
|
||||
assert_less_than(entry2.processingStart, timeAfterFirstClick,
|
||||
"entry2's processing start should be berfore timeAfterFirstClick.");
|
||||
assert_greater_than(timeAfterFirstClick, entry2.startTime,
|
||||
"timeAfterFirstClick should be later than entry2's start time.");
|
||||
}
|
||||
|
||||
/* Timeline:
|
||||
Observer starts
|
||||
Begin Busy Loop
|
||||
Click 1 arrives
|
||||
End Busy Loop
|
||||
(Dispatch and Process Click 1 (buffered, observed))
|
||||
Onload Event Fires
|
||||
Begin Busy Loop
|
||||
Click 2 arrives
|
||||
End Busy Loop
|
||||
(Dispatch and Process Click 2 (buffered, observed))
|
||||
observer callback start
|
||||
*/
|
||||
async_test(function(t) {
|
||||
const observerPromise = new Promise((resolve, reject) => {
|
||||
new PerformanceObserver(function(entryList) {
|
||||
observedEntries = observedEntries.concat(entryList.getEntries());
|
||||
if (observedEntries.length < 2) return;
|
||||
resolve(observedEntries);
|
||||
}).observe({ entryTypes: ['event'] });
|
||||
});
|
||||
timeBeforeFirstClick = performance.now();
|
||||
clickAndBlockMain('button').then( () => {
|
||||
timeAfterFirstClick = performance.now();
|
||||
});
|
||||
on_event(window, 'load', function(e) {
|
||||
onloadStart = performance.now();
|
||||
// After onload start and before registering observer.
|
||||
const bufferPromise = clickAndBlockMain('button').then(wait);
|
||||
Promise.all([observerPromise, bufferPromise]).then((results) => {
|
||||
timeAfterSecondClick = performance.now();
|
||||
t.step(verifyObserverEntries.bind(null, results[0]));
|
||||
t.step(verifyBuffer.bind(null, performance.getEntriesByName('click', 'event')));
|
||||
t.done();
|
||||
});
|
||||
});
|
||||
}, "Event Timing: click, observer, onload, click.");
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8 />
|
||||
<title>Event Timing: buffer long-latency events before onload</title>
|
||||
<button id='button' onclick='1'>Generate a 'click' event</button>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/testdriver.js></script>
|
||||
<script src=/resources/testdriver-vendor.js></script>
|
||||
|
||||
<script src=resources/event-timing-support.js></script>
|
||||
|
||||
<script>
|
||||
/* Timeline:
|
||||
Onload
|
||||
PerformanceObserver is registered
|
||||
Click 1
|
||||
Click 2
|
||||
PerformanceObserver should observe only one firstInput entry.
|
||||
(Dispatch and Process Click 2 - not buffered)
|
||||
*/
|
||||
async_test(function(t) {
|
||||
let numFirstInputObserved = 0;
|
||||
let numEventsObserved = 0;
|
||||
new PerformanceObserver(t.step_func((entryList, obs) => {
|
||||
const observedEntries = entryList.getEntries();
|
||||
numEventsObserved += observedEntries.filter(entry =>
|
||||
entry.entryType == 'event').length;
|
||||
numFirstInputObserved += observedEntries.filter(entry =>
|
||||
entry.entryType == 'firstInput').length;
|
||||
if (numEventsObserved >= 2) {
|
||||
assert_equals(performance.getEntriesByType('event').length, 0,
|
||||
"There should be no buffered event entries.");
|
||||
assert_equals(performance.getEntriesByType('firstInput').length, 0,
|
||||
"There should be no buffered firstInput entries.");
|
||||
// There should be 2 event entries and one firstInput entry.
|
||||
assert_equals(numEventsObserved, 2,
|
||||
"There should be 2 observed event entries.");
|
||||
assert_equals(numFirstInputObserved, 1,
|
||||
"There should be only 1 observed firstInput entry.");
|
||||
t.done();
|
||||
}
|
||||
})).observe({ entryTypes: ['event', 'firstInput'] });
|
||||
on_event(window, 'load', () => {
|
||||
clickAndBlockMain('button').then(wait).then(() => {
|
||||
clickAndBlockMain('button').then(wait);
|
||||
});
|
||||
});
|
||||
},
|
||||
"Event Timing: check firstInput after onload, observer, click, click."
|
||||
);
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,76 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8 />
|
||||
<title>Event Timing: long-latency events after onload and before observer
|
||||
registration are lost
|
||||
</title>
|
||||
<button id='button' onclick='1'>Generate a 'click' event</button>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/testdriver.js></script>
|
||||
<script src=/resources/testdriver-vendor.js></script>
|
||||
|
||||
<script src=resources/event-timing-support.js></script>
|
||||
<script>
|
||||
let callbackTime;
|
||||
let observerStart;
|
||||
let processingStartMin;
|
||||
|
||||
function verifyBufferAndObserverEntries(observedEntries) {
|
||||
// Verify buffer entries
|
||||
const bufferedEntries = performance.getEntriesByName('click', 'event');
|
||||
const bufferedEntriesBeforeObserver = bufferedEntries.filter(e => e.startTime <
|
||||
observerStart);
|
||||
assert_equals(bufferedEntries.length, 0,
|
||||
"Long latency events after onload should not be buffered."
|
||||
);
|
||||
|
||||
// Verify observer entries
|
||||
assert_equals(observedEntries.length, 1, "Long latency task after observer start should be observed.");
|
||||
const entry = observedEntries[0];
|
||||
verifyClickEvent(entry);
|
||||
assert_greater_than(entry.processingStart, processingStartMin,
|
||||
"The entry's processing start should be later than processingStartMin.");
|
||||
assert_greater_than(callbackTime, entry.processingStart,
|
||||
"The callback time should be later than the entry's processing start.");
|
||||
assert_greater_than(entry.startTime, observerStart,
|
||||
"The entry's start time should be later than observer start.");
|
||||
assert_greater_than(callbackTime, entry.startTime,
|
||||
"The callback time should be later than entry's start time.");
|
||||
}
|
||||
|
||||
function startObserver(t) {
|
||||
new PerformanceObserver(t.step_func_done((entryList, obs) => {
|
||||
callbackTime = performance.now();
|
||||
const observedEntries = entryList.getEntries();
|
||||
verifyBufferAndObserverEntries(observedEntries);
|
||||
})).observe({ entryTypes: ['event'] });
|
||||
observerStart = performance.now();
|
||||
}
|
||||
|
||||
/* Timeline:
|
||||
Onload Event fires
|
||||
Begin Busy Loop
|
||||
Click 1 arrives
|
||||
End Busy Loop
|
||||
(Dispatch and Process Click 1 (not buffered, not observed))
|
||||
Observer start
|
||||
Begin Busy Loop
|
||||
Click 2 arrives
|
||||
End Busy Loop
|
||||
(Dispatch and Process Click 2 (not buffered, observed))
|
||||
*/
|
||||
async_test(function(t) {
|
||||
on_event(window, 'load', () => {
|
||||
clickAndBlockMain('button').then(() => {
|
||||
startObserver(t);
|
||||
clickAndBlockMain('button').then(wait);
|
||||
processingStartMin = performance.now();
|
||||
});
|
||||
});
|
||||
},
|
||||
"Event Timing: onload, click, observer, click."
|
||||
);
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8 />
|
||||
<title>Event Timing: only observe the first input</title>
|
||||
<button id='button' onclick='1'>Generate a 'click' event</button>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/testdriver.js></script>
|
||||
<script src=/resources/testdriver-vendor.js></script>
|
||||
|
||||
<script src=resources/event-timing-support.js></script>
|
||||
|
||||
<script>
|
||||
/* Test:
|
||||
PerformanceObserver for firstInput is registered
|
||||
Click 1
|
||||
Click 2
|
||||
Wait
|
||||
Expected result:
|
||||
PerformanceObserver should observe one and only one entry.
|
||||
*/
|
||||
async_test(function(t) {
|
||||
let hasObservedFirstInput = false;
|
||||
new PerformanceObserver(t.step_func((entryList) => {
|
||||
assert_false(hasObservedFirstInput);
|
||||
hasObservedFirstInput = true;
|
||||
const observedEntries = entryList.getEntries();
|
||||
assert_equals(observedEntries.length, 1);
|
||||
assert_equals(observedEntries[0].entryType, 'firstInput');
|
||||
assert_equals(observedEntries[0].name, 'click');
|
||||
})).observe({ entryTypes: ['firstInput'] });
|
||||
on_event(window, 'load', () => {
|
||||
clickAndBlockMain('button').then(() => {
|
||||
clickAndBlockMain('button').then(wait).then( () => {
|
||||
// After some wait, the PerformanceObserver should have processed both clicks.
|
||||
// One and only one firstInput entry should have been dispatched, so
|
||||
// |hasObservedFirstInput| should be true.
|
||||
t.step_timeout( () => {
|
||||
assert_true(hasObservedFirstInput);
|
||||
t.done();
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
"Event Timing: check firstInput for a PerformanceObserver observing only firstInput."
|
||||
);
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8>
|
||||
<title>Event Timing: make sure event-timing entries are retrievable by existing perf APIs.</title>
|
||||
<button id='button' onclick='1'>Generate a 'click' event</button>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/testdriver.js></script>
|
||||
<script src=/resources/testdriver-vendor.js></script>
|
||||
|
||||
<script src=resources/event-timing-support.js></script>
|
||||
<img src=resources/slow-image.py>
|
||||
|
||||
<script>
|
||||
function validateEntries() {
|
||||
const entriesByName = performance.getEntriesByName('click', 'event');
|
||||
const entriesByType = performance.getEntriesByType('event');
|
||||
const allEntries = performance.getEntries();
|
||||
assert_equals(entriesByName.length, 1, 'event-timing entry should be retrievable by getEntriesByName');
|
||||
const e = entriesByName[0];
|
||||
assert_true(entriesByType.includes(e), 'event-timing entry should be retrievable by getEntries');
|
||||
assert_true(allEntries.includes(e), 'event-timing entry should be retrievable by getEntriesByType');
|
||||
}
|
||||
|
||||
/* Timeline:
|
||||
Begin Busy Loop
|
||||
Click 1 arrives
|
||||
End Busy Loop
|
||||
(Dispatch and Process Click 1 - buffered)
|
||||
Onload Event Fires
|
||||
Validate entries
|
||||
*/
|
||||
async_test(function(t) {
|
||||
clickAndBlockMain('button');
|
||||
on_event(window, 'load', e => {
|
||||
validateEntries();
|
||||
t.done();
|
||||
});
|
||||
}, "Event Timing: make sure event-timing entries are retrievable by existing perf APIs.");
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,58 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8 />
|
||||
<title>Event Timing only times certain types of trusted event.
|
||||
</title>
|
||||
<button id='button' onclick='mainThreadBusy(60)'
|
||||
onfocus='mainThreadBusy(60)'>Generate a 'click' event</button>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/testdriver.js></script>
|
||||
<script src=/resources/testdriver-vendor.js></script>
|
||||
|
||||
<script src=resources/event-timing-support.js></script>
|
||||
<script>
|
||||
let trustedClickStart;
|
||||
function trustedClickAndBlockMain(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
trustedClickStart = performance.now();
|
||||
clickOnElement(id, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function untrustedClickAndBlockMain(id) {
|
||||
const target = document.getElementById(id);
|
||||
// Block mainthread in the callback, as dispatchEvent() is a sync call.
|
||||
target.dispatchEvent(new MouseEvent('click'));
|
||||
}
|
||||
|
||||
function trustedFocusAndBlockMain(id) {
|
||||
const target = document.getElementById(id);
|
||||
trustedFocusStart = performance.now();
|
||||
// Block mainthread in the callback, as focus() is a sync call.
|
||||
target.focus();
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
new PerformanceObserver(t.step_func_done(entryList => {
|
||||
const observerCallbackTime = performance.now();
|
||||
const entries = entryList.getEntries();
|
||||
assert_equals(entries.length, 1,
|
||||
"Should only observe one entry: " +
|
||||
JSON.stringify(entries) + ".");
|
||||
assert_equals(entries[0].name, 'click',
|
||||
"The observed entry should be a click");
|
||||
assert_less_than(entries[0].startTime, observerCallbackTime,
|
||||
"The startTime should be before observerCallbackTime");
|
||||
assert_greater_than(entries[0].startTime, trustedClickStart,
|
||||
"The startTime should be after trustedClickStart");
|
||||
})).observe({ entryTypes: ['event'] });
|
||||
// Untrusted event of a type event timing cares about.
|
||||
untrustedClickAndBlockMain('button');
|
||||
// Trusted event of a type event timing doesn't cares about.
|
||||
trustedFocusAndBlockMain('button');
|
||||
// Trusted event of a type event timing cares about.
|
||||
trustedClickAndBlockMain('button').then(wait);
|
||||
}, "Event Timing only times certain types of trusted event.");
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCType html>
|
||||
<html>
|
||||
<script src=event-timing-support.js></script>
|
||||
<button id='button_child_frame' onclick='2'>Generate a 'click' event</button>
|
||||
<img src=slow-image.py>
|
||||
<script>
|
||||
const clickTimeMin = performance.now();
|
||||
clickAndBlockMain('button_child_frame');
|
||||
const processingStartMin = performance.now();
|
||||
const observerPromise = new Promise((resolve, reject) => {
|
||||
new PerformanceObserver((entryList) => {
|
||||
resolve(entryList.getEntries());
|
||||
}).observe({ entryTypes: ['event'] });
|
||||
});
|
||||
window.addEventListener('load', e => {
|
||||
observerPromise.then((observedEntries) => {
|
||||
const onloadStart = performance.now();
|
||||
const bufferedEntries = performance.getEntriesByType('event');
|
||||
top.postMessage({
|
||||
"bufferedEntries" : bufferedEntries,
|
||||
"observedEntries": observedEntries,
|
||||
"clickTimeMin": clickTimeMin,
|
||||
"processingStartMin" : processingStartMin,
|
||||
"onloadStart" : onloadStart,
|
||||
}, '*');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8 />
|
||||
</head>
|
||||
<script src=./event-timing-support.js></script>
|
||||
<script>
|
||||
function log(message) {
|
||||
const timestamp = performance.now();
|
||||
const elem = document.createElement('div');
|
||||
elem.innerHTML = `${timestamp.toFixed(1)}: ${message}`;
|
||||
const timeline = document.getElementById('timeline');
|
||||
timeline.appendChild(elem);
|
||||
}
|
||||
|
||||
function run() {
|
||||
new PerformanceObserver((entryList) => {
|
||||
entryList.getEntries().forEach(e => {
|
||||
log(`entry observed: ${JSON.stringify(e)}`);
|
||||
});
|
||||
}).observe({ entryTypes: ['event'] });
|
||||
log("observer registered");
|
||||
top.postMessage('CHILD_FRAME_IS_READY', "*");
|
||||
}
|
||||
|
||||
function onMakeBusy() {
|
||||
log("busy start");
|
||||
step_timeout(()=>{
|
||||
mainThreadBusy(2000);
|
||||
log("busy end");
|
||||
}, 0);
|
||||
}
|
||||
</script>
|
||||
<body onload='run()'>
|
||||
<h3>Actions:</h3>
|
||||
<p>
|
||||
<button id='busy_button' onclick='onMakeBusy()'>Make busy</button>
|
||||
<button id='click_input_button' onclick='1'> click while busy </button>
|
||||
</p>
|
||||
<h3>Timeline:</h3>
|
||||
<p id='timeline'></p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,66 @@
|
|||
// Clicks on the element with the given ID. It adds an event handler to the element
|
||||
// which ensures that the events have a long duration and reported by EventTiming
|
||||
// where appropriate. Calls |callback| during event handler.
|
||||
function clickOnElement(id, callback) {
|
||||
const element = document.getElementById(id);
|
||||
const rect = element.getBoundingClientRect();
|
||||
const xCenter = rect.x + rect.width / 2;
|
||||
const yCenter = rect.y + rect.height / 2;
|
||||
const leftButton = 0;
|
||||
const clickHandler = () => {
|
||||
mainThreadBusy(60);
|
||||
if (callback)
|
||||
callback();
|
||||
element.removeEventListener("click", clickHandler);
|
||||
};
|
||||
element.addEventListener("click", clickHandler);
|
||||
test_driver.click(element);
|
||||
}
|
||||
|
||||
function mainThreadBusy(duration) {
|
||||
const now = performance.now();
|
||||
while (performance.now() < now + duration);
|
||||
}
|
||||
|
||||
// This method should receive an entry of type 'event'. |is_first| is true only
|
||||
// when the event also happens to correspond to the first event. In this case,
|
||||
// the timings of the 'firstInput' entry should be equal to those of this entry.
|
||||
function verifyClickEvent(entry, is_first=false) {
|
||||
assert_true(entry.cancelable);
|
||||
assert_equals(entry.name, 'click');
|
||||
assert_equals(entry.entryType, 'event');
|
||||
assert_greater_than(entry.duration, 50,
|
||||
"The entry's duration should be greater than 50ms.");
|
||||
assert_greater_than(entry.processingStart, entry.startTime,
|
||||
"The entry's processingStart should be greater than startTime.");
|
||||
assert_greater_than_equal(entry.processingEnd, entry.processingStart,
|
||||
"The entry's processingEnd must be at least as large as processingStart.");
|
||||
assert_greater_than_equal(entry.duration, entry.processingEnd - entry.startTime,
|
||||
"The entry's duration must be at least as large as processingEnd - startTime.");
|
||||
if (is_first) {
|
||||
let firstInputs = performance.getEntriesByType('firstInput');
|
||||
assert_equals(firstInputs.length, 1, 'There should be a single firstInput entry');
|
||||
let firstInput = firstInputs[0];
|
||||
assert_equals(firstInput.name, entry.name);
|
||||
assert_equals(firstInput.entryType, 'firstInput');
|
||||
assert_equals(firstInput.startTime, entry.startTime);
|
||||
assert_equals(firstInput.duration, entry.duration);
|
||||
assert_equals(firstInput.processingStart, entry.processingStart);
|
||||
assert_equals(firstInput.processingEnd, entry.processingEnd);
|
||||
assert_equals(firstInput.cancelable, entry.cancelable);
|
||||
}
|
||||
}
|
||||
|
||||
function wait() {
|
||||
return new Promise((resolve, reject) => {
|
||||
step_timeout(() => {
|
||||
resolve();
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
function clickAndBlockMain(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
clickOnElement(id, resolve);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import time
|
||||
|
||||
def main(request, response):
|
||||
# Sleep for 500ms to delay onload.
|
||||
time.sleep(0.5)
|
||||
response.headers.set("Cache-Control", "no-cache, must-revalidate");
|
||||
response.headers.set("Location", "data:image/gif;base64,R0lGODlhAQABAJAAAMjIyAAAACwAAAAAAQABAAACAgQBADs%3D");
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Fetch destination test for prefetching</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/get-host-info.sub.js"></script>
|
||||
<script src="/common/media.js"></script>
|
||||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
let frame;
|
||||
|
||||
// Set up the service worker and the frame.
|
||||
promise_test(t => {
|
||||
const kScope = 'resources/empty.https.html';
|
||||
const kScript = 'resources/fetch-destination-worker.js';
|
||||
return service_worker_unregister_and_register(t, kScript, kScope)
|
||||
.then(registration => {
|
||||
add_completion_callback(() => {
|
||||
registration.unregister();
|
||||
});
|
||||
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(() => {
|
||||
return with_iframe(kScope);
|
||||
})
|
||||
.then(f => {
|
||||
frame = f;
|
||||
add_completion_callback(() => { f.remove(); });
|
||||
});
|
||||
}, 'Initialize global state');
|
||||
|
||||
// HTMLLinkElement with rel=prefetch - empty string destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
let node = frame.contentWindow.document.createElement("link");
|
||||
node.rel = "prefetch";
|
||||
node.onload = resolve;
|
||||
node.onerror = reject;
|
||||
node.href = "dummy?dest=";
|
||||
frame.contentWindow.document.body.appendChild(node);
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLLinkElement with rel=prefetch fetches with an empty string Request.destination');
|
||||
|
||||
</script>
|
|
@ -425,18 +425,4 @@ promise_test(async t => {
|
|||
});
|
||||
}, 'HTMLLinkElement with rel=preload and as=manifest fetches with a "manifest" Request.destination');
|
||||
|
||||
// HTMLLinkElement with rel=prefetch - empty string destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
let node = frame.contentWindow.document.createElement("link");
|
||||
node.rel = "prefetch";
|
||||
node.onload = resolve;
|
||||
node.onerror = reject;
|
||||
node.href = "dummy?dest=";
|
||||
frame.contentWindow.document.body.appendChild(node);
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLLinkElement with rel=prefetch fetches with an empty string Request.destination');
|
||||
|
||||
</script>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue