diff options
Diffstat (limited to 'tests/wpt/tests')
559 files changed, 16393 insertions, 5624 deletions
diff --git a/tests/wpt/tests/.azure-pipelines.yml b/tests/wpt/tests/.azure-pipelines.yml index 590500e9740..56b67ef6057 100644 --- a/tests/wpt/tests/.azure-pipelines.yml +++ b/tests/wpt/tests/.azure-pipelines.yml @@ -54,7 +54,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/affected_tests.yml parameters: checkoutCommit: 'HEAD^1' @@ -75,7 +75,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/checkout.yml - script: | set -eux -o pipefail @@ -96,7 +96,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/install_fonts.yml - template: tools/ci/azure/install_certs.yml @@ -134,8 +134,8 @@ jobs: directory: tools/ toxenv: py38 -- job: tools_unittest_mac_py311 - displayName: 'tools/ unittests: macOS + Python 3.12' +- job: tools_unittest_mac_py313 + displayName: 'tools/ unittests: macOS + Python 3.13' dependsOn: decision condition: dependencies.decision.outputs['test_jobs.tools_unittest'] pool: @@ -143,12 +143,12 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/tox_pytest.yml parameters: directory: tools/ - toxenv: py311 + toxenv: py313 - job: wptrunner_unittest_mac_py38 displayName: 'tools/wptrunner/ unittests: macOS + Python 3.8' @@ -166,8 +166,8 @@ jobs: directory: tools/wptrunner/ toxenv: py38 -- job: wptrunner_unittest_mac_py311 - displayName: 'tools/wptrunner/ unittests: macOS + Python 3.12' +- job: wptrunner_unittest_mac_py313 + displayName: 'tools/wptrunner/ unittests: macOS + Python 3.13' dependsOn: decision condition: dependencies.decision.outputs['test_jobs.wptrunner_unittest'] pool: @@ -175,12 +175,12 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/tox_pytest.yml parameters: directory: tools/wptrunner/ - toxenv: py311 + toxenv: py313 - job: wpt_integration_mac_py38 displayName: 'tools/wpt/ tests: macOS + Python 3.8' @@ -202,8 +202,8 @@ jobs: directory: tools/wpt/ toxenv: py38 -- job: wpt_integration_mac_py311 - displayName: 'tools/wpt/ tests: macOS + Python 3.12' +- job: wpt_integration_mac_py313 + displayName: 'tools/wpt/ tests: macOS + Python 3.13' dependsOn: decision condition: dependencies.decision.outputs['test_jobs.wpt_integration'] pool: @@ -212,7 +212,7 @@ jobs: # full checkout required - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/install_chrome.yml - template: tools/ci/azure/install_firefox.yml - template: tools/ci/azure/update_hosts.yml @@ -220,7 +220,7 @@ jobs: - template: tools/ci/azure/tox_pytest.yml parameters: directory: tools/wpt/ - toxenv: py311 + toxenv: py313 - job: tools_unittest_win_py38 displayName: 'tools/ unittests: Windows + Python 3.8' @@ -241,8 +241,8 @@ jobs: directory: tools/ toxenv: py38 -- job: tools_unittest_win_py311 - displayName: 'tools/ unittests: Windows + Python 3.12' +- job: tools_unittest_win_py313 + displayName: 'tools/ unittests: Windows + Python 3.13' dependsOn: decision condition: dependencies.decision.outputs['test_jobs.tools_unittest'] pool: @@ -250,13 +250,13 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' addToPath: false - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/tox_pytest.yml parameters: directory: tools/ - toxenv: py311 + toxenv: py313 - job: wptrunner_unittest_win_py38 displayName: 'tools/wptrunner/ unittests: Windows + Python 3.8' @@ -275,8 +275,8 @@ jobs: directory: tools/wptrunner/ toxenv: py38 -- job: wptrunner_unittest_win_py311 - displayName: 'tools/wptrunner/ unittests: Windows + Python 3.12' +- job: wptrunner_unittest_win_py313 + displayName: 'tools/wptrunner/ unittests: Windows + Python 3.13' dependsOn: decision condition: dependencies.decision.outputs['test_jobs.wptrunner_unittest'] pool: @@ -284,13 +284,13 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' addToPath: false - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/tox_pytest.yml parameters: directory: tools/wptrunner/ - toxenv: py311 + toxenv: py313 - job: wpt_integration_win_py38 displayName: 'tools/wpt/ tests: Windows + Python 3.8' @@ -314,8 +314,8 @@ jobs: directory: tools/wpt/ toxenv: py38 -- job: wpt_integration_win_py311 - displayName: 'tools/wpt/ tests: Windows + Python 3.12' +- job: wpt_integration_win_py313 + displayName: 'tools/wpt/ tests: Windows + Python 3.13' dependsOn: decision condition: dependencies.decision.outputs['test_jobs.wpt_integration'] pool: @@ -324,7 +324,7 @@ jobs: # full checkout required - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' # currently just using the outdated Chrome/Firefox on the VM rather than # figuring out how to install Chrome Dev channel on Windows # - template: tools/ci/azure/install_chrome.yml @@ -334,7 +334,7 @@ jobs: - template: tools/ci/azure/tox_pytest.yml parameters: directory: tools/wpt/ - toxenv: py311 + toxenv: py313 - job: results_edge_stable displayName: 'all tests: Edge Stable' @@ -350,7 +350,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/system_info.yml - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/install_certs.yml @@ -386,7 +386,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/system_info.yml - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/install_certs.yml @@ -422,7 +422,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/install_certs.yml - template: tools/ci/azure/install_edge.yml @@ -456,7 +456,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.12' + versionSpec: '3.13' - template: tools/ci/azure/checkout.yml - template: tools/ci/azure/install_certs.yml - template: tools/ci/azure/color_profile.yml diff --git a/tests/wpt/tests/WebCryptoAPI/import_export/okp_importKey.js b/tests/wpt/tests/WebCryptoAPI/import_export/okp_importKey.js index 0e6a016fe20..8627f85e466 100644 --- a/tests/wpt/tests/WebCryptoAPI/import_export/okp_importKey.js +++ b/tests/wpt/tests/WebCryptoAPI/import_export/okp_importKey.js @@ -11,7 +11,7 @@ function runTests(algorithmName) { ['spki', 'jwk', 'raw'].forEach(function(format) { if (format === "jwk") { // Not all fields used for public keys testFormat(format, algorithm, jwkData, algorithmName, usages, extractable); - // Test for https://github.com/WICG/webcrypto-secure-curves/pull/24 + // Test for https://github.com/w3c/webcrypto/pull/401 if (extractable) { testJwkAlgBehaviours(algorithm, jwkData.jwk, algorithmName, usages); } @@ -27,7 +27,7 @@ function runTests(algorithmName) { ['pkcs8', 'jwk'].forEach(function(format) { testFormat(format, algorithm, data, algorithmName, usages, extractable); - // Test for https://github.com/WICG/webcrypto-secure-curves/pull/24 + // Test for https://github.com/w3c/webcrypto/pull/401 if (format === "jwk" && extractable) { testJwkAlgBehaviours(algorithm, data.jwk, algorithmName, usages); } @@ -67,27 +67,34 @@ function testFormat(format, algorithm, keyData, keySize, usages, extractable) { }); } -// Test importKey/exportKey "alg" behaviours, alg is ignored upon import and alg is missing for Ed25519 and Ed448 JWK export -// https://github.com/WICG/webcrypto-secure-curves/pull/24 +// Test importKey/exportKey "alg" behaviours (https://github.com/w3c/webcrypto/pull/401) +// - alg is ignored for ECDH import +// - TODO: alg is checked to be the algorithm.name or EdDSA for Ed25519 and Ed448 import +// - alg is missing for ECDH export +// - alg is the algorithm name for Ed25519 and Ed448 export function testJwkAlgBehaviours(algorithm, keyData, crv, usages) { [algorithm, algorithm.name].forEach((alg) => { - promise_test(function(test) { - return subtle.importKey('jwk', { ...keyData, alg: 'this is ignored' }, alg, true, usages). - then(function(key) { - assert_equals(key.constructor, CryptoKey, "Imported a CryptoKey object"); - - return subtle.exportKey('jwk', key). - then(function(result) { - assert_equals(Object.keys(result).length, keyData.d ? 6 : 5, "Correct number of JWK members"); - assert_equals(result.alg, undefined, 'No JWK "alg" member is present'); - assert_true(equalJwk(keyData, result), "Round trip works"); - }, function(err) { + (crv.startsWith('Ed') ? [algorithm.name, 'EdDSA'] : ['this is ignored']).forEach((jwkAlg) => { + promise_test(function(test) { + return subtle.importKey('jwk', { ...keyData, alg: jwkAlg }, alg, true, usages). + then(function(key) { + assert_equals(key.constructor, CryptoKey, "Imported a CryptoKey object"); + + return subtle.exportKey('jwk', key). + then(function(result) { + let expectedKeys = crv.startsWith('Ed') ? 6 : 5 + if (keyData.d) expectedKeys++ + assert_equals(Object.keys(result).length, expectedKeys, "Correct number of JWK members"); + assert_equals(result.alg, crv.startsWith('Ed') ? algorithm.name : undefined, 'Expected JWK "alg" member'); + assert_true(equalJwk(keyData, result), "Round trip works"); + }, function(err) { + assert_unreached("Threw an unexpected error: " + err.toString()); + }); + }, function(err) { assert_unreached("Threw an unexpected error: " + err.toString()); - }); - }, function(err) { - assert_unreached("Threw an unexpected error: " + err.toString()); - }); - }, "Good parameters with ignored JWK alg: " + crv.toString() + " " + parameterString('jwk', keyData, alg, true, usages)); + }); + }, 'Good parameters with JWK alg' + (crv.startsWith('Ed') ? ` ${jwkAlg}: ` : ': ') + crv.toString() + " " + parameterString('jwk', keyData, alg, true, usages, jwkAlg)); + }); }); } diff --git a/tests/wpt/tests/ai/translator/ai_translator_translate.tentative.https.any.js b/tests/wpt/tests/ai/translator/ai_translator_translate.tentative.https.any.js index 926325b620c..4dfbf874a00 100644 --- a/tests/wpt/tests/ai/translator/ai_translator_translate.tentative.https.any.js +++ b/tests/wpt/tests/ai/translator/ai_translator_translate.tentative.https.any.js @@ -27,8 +27,6 @@ promise_test(async t => { // Creating the translator with user activation succeeds. await createTranslator(languagePair); - // TODO(crbug.com/390459310): Replace with availability. - // // Creating it should have switched it to readily. const capabilities = await ai.translator.capabilities(); const {sourceLanguage, targetLanguage} = languagePair; @@ -36,9 +34,12 @@ promise_test(async t => { capabilities.languagePairAvailable(sourceLanguage, targetLanguage), 'readily'); + const availability = await ai.translator.availability(languagePair); + assert_equals(availability, 'available'); + // Now that it is readily, we should no longer need user activation. await ai.translator.create(languagePair); -}, 'AITranslator.create() requires user activation when availability is "after-download".'); +}, 'AITranslator.create() requires user activation when availability is "downloadable.'); promise_test(async t => { const translator = diff --git a/tests/wpt/tests/compat/webkit-box-horizontal-reverse-variants-ref.html b/tests/wpt/tests/compat/webkit-box-horizontal-reverse-variants-ref.html index 72d0b2c6f68..c7e2b707da6 100644 --- a/tests/wpt/tests/compat/webkit-box-horizontal-reverse-variants-ref.html +++ b/tests/wpt/tests/compat/webkit-box-horizontal-reverse-variants-ref.html @@ -3,14 +3,11 @@ .flexbox { width: 300px; display: flex; + flex-direction: row-reverse; border-style: solid; border-width: 1px 2px 1px 4px; } -.reverse { - flex-direction: row-reverse; -} - .redbox { background: red; width: 100px; @@ -27,47 +24,44 @@ <p>Exercises -webkit-box with various box-pack settings when direction is reverse. In all cases the order of letters in the boxes should be alphabetized left to right. -<p>Start. Boxes should be aligned to left side. -<div class="flexbox reverse" style="justify-content: flex-end;"> +<p>Start. Boxes should be aligned to right side. +<div class="flexbox" style="justify-content: flex-end;"> <div class="redbox">B</div> <div class="greenbox">A</div> </div> <p>Centered. Boxes should be centered. -<div class="flexbox reverse" style="justify-content: center;"> +<div class="flexbox" style="justify-content: center;"> <div class="redbox">B</div> <div class="greenbox">A</div> </div> -<p>End. Boxes should be aligned to right side. -<div class="flexbox reverse"> +<p>End. Boxes should be aligned to left side. +<div class="flexbox"> <div class="redbox">B</div> <div class="greenbox">A</div> </div> -<p>Start, content too big. Boxes should start at left edge and extend - outside border. +<p>Start, content too big. <div class="flexbox"> - <div class="greenbox">A</div> - <div class="redbox">B</div> - <div class="greenbox">C</div> <div class="redbox">D</div> + <div class="greenbox">C</div> + <div class="redbox">B</div> + <div class="greenbox">A</div> </div> -<p>Center, content too big. Boxes should start at left edge and extend - outside border. -<div class="flexbox"> - <div class="greenbox">A</div> - <div class="redbox">B</div> - <div class="greenbox">C</div> +<p>Center, content too big. +<div class="flexbox" style="justify-content: center;"> <div class="redbox">D</div> + <div class="greenbox">C</div> + <div class="redbox">B</div> + <div class="greenbox">A</div> </div> -<p>End, content too big. Boxes should start at left edge and extend - outside border. -<div class="flexbox"> - <div class="greenbox">A</div> - <div class="redbox">B</div> - <div class="greenbox">C</div> +<p>End, content too big. +<div class="flexbox" style="justify-content: flex-end;"> <div class="redbox">D</div> + <div class="greenbox">C</div> + <div class="redbox">B</div> + <div class="greenbox">A</div> </div> diff --git a/tests/wpt/tests/compat/webkit-box-horizontal-reverse-variants.html b/tests/wpt/tests/compat/webkit-box-horizontal-reverse-variants.html index 09dba694f26..4c4de5ffe87 100644 --- a/tests/wpt/tests/compat/webkit-box-horizontal-reverse-variants.html +++ b/tests/wpt/tests/compat/webkit-box-horizontal-reverse-variants.html @@ -24,8 +24,8 @@ <p>Exercises -webkit-box with various box-pack settings when direction is reverse. In all cases the order of letters in the boxes should be alphabetized left to right. -<p>Start. Boxes should be aligned to left side. -<div class="webkitbox"> +<p>Start. Boxes should be aligned to right side. +<div class="webkitbox" style="-webkit-box-pack: end"> <div class="redbox">B</div> <div class="greenbox">A</div> </div> @@ -36,14 +36,13 @@ <div class="greenbox">A</div> </div> -<p>End. Boxes should be aligned to right side. -<div class="webkitbox" style="-webkit-box-pack: end"> +<p>End. Boxes should be aligned to left side. +<div class="webkitbox"> <div class="redbox">B</div> <div class="greenbox">A</div> </div> -<p>Start, content too big. Boxes should start at left edge and extend - outside border. +<p>Start, content too big. <div class="webkitbox"> <div class="redbox">D</div> <div class="greenbox">C</div> @@ -51,8 +50,7 @@ <div class="greenbox">A</div> </div> -<p>Center, content too big. Boxes should start at left edge and extend - outside border. +<p>Center, content too big. <div class="webkitbox" style="-webkit-box-pack: center"> <div class="redbox">D</div> <div class="greenbox">C</div> @@ -60,8 +58,7 @@ <div class="greenbox">A</div> </div> -<p>End, content too big. Boxes should start at left edge and extend - outside border. +<p>End, content too big. <div class="webkitbox" style="-webkit-box-pack: end"> <div class="redbox">D</div> <div class="greenbox">C</div> diff --git a/tests/wpt/tests/compat/webkit-box-horizontal-rtl-variants-ref.html b/tests/wpt/tests/compat/webkit-box-horizontal-rtl-variants-ref.html index 42321c50697..fd1fbe433db 100644 --- a/tests/wpt/tests/compat/webkit-box-horizontal-rtl-variants-ref.html +++ b/tests/wpt/tests/compat/webkit-box-horizontal-rtl-variants-ref.html @@ -3,14 +3,11 @@ .flexbox { width: 300px; display: flex; + direction: rtl; border-style: solid; border-width: 1px 2px 1px 4px; } -.rtl { - direction: rtl; -} - .redbox { background: red; width: 100px; @@ -27,46 +24,43 @@ <p>Exercises -webkit-box with various box-pack settings when rtl. In all cases the order of letters in the boxes should be alphabetized left to right. <p>Start. Boxes should be aligned to right side. -<div class="flexbox rtl"> +<div class="flexbox"> <div class="redbox">B</div> <div class="greenbox">A</div> </div> <p>Centered. Boxes should be centered. -<div class="flexbox rtl" style="justify-content: center;"> +<div class="flexbox" style="justify-content: center;"> <div class="redbox">B</div> <div class="greenbox">A</div> </div> <p>End. Boxes should be aligned to left side. -<div class="flexbox rtl" style="justify-content: flex-end;"> +<div class="flexbox" style="justify-content: flex-end;"> <div class="redbox">B</div> <div class="greenbox">A</div> </div> -<p>Start, content too big. Boxes should start at left edge and extend - outside border. +<p>Start, content too big. <div class="flexbox"> - <div class="greenbox rtl">A</div> - <div class="redbox rtl">B</div> - <div class="greenbox rtl">C</div> - <div class="redbox rtl">D</div> + <div class="redbox">D</div> + <div class="greenbox">C</div> + <div class="redbox">B</div> + <div class="greenbox">A</div> </div> -<p>Center, content too big. Boxes should start at left edge and extend - outside border. -<div class="flexbox"> - <div class="greenbox rtl">A</div> - <div class="redbox rtl">B</div> - <div class="greenbox rtl">C</div> - <div class="redbox rtl">D</div> +<p>Center, content too big. +<div class="flexbox" style="justify-content: center;"> + <div class="redbox">D</div> + <div class="greenbox">C</div> + <div class="redbox">B</div> + <div class="greenbox">A</div> </div> -<p>End, content too big. Boxes should start at left edge and extend - outside border. -<div class="flexbox"> - <div class="greenbox rtl">A</div> - <div class="redbox rtl">B</div> - <div class="greenbox rtl">C</div> - <div class="redbox rtl">D</div> +<p>End, content too big. +<div class="flexbox" style="justify-content: flex-end;"> + <div class="redbox">D</div> + <div class="greenbox">C</div> + <div class="redbox">B</div> + <div class="greenbox">A</div> </div> diff --git a/tests/wpt/tests/compat/webkit-box-horizontal-rtl-variants.html b/tests/wpt/tests/compat/webkit-box-horizontal-rtl-variants.html index 085a5899bc8..e173c5d172f 100644 --- a/tests/wpt/tests/compat/webkit-box-horizontal-rtl-variants.html +++ b/tests/wpt/tests/compat/webkit-box-horizontal-rtl-variants.html @@ -41,8 +41,7 @@ <div class="greenbox">A</div> </div> -<p>Start, content too big. Boxes should start at left edge and extend - outside border. +<p>Start, content too big. <div class="webkitbox"> <div class="redbox">D</div> <div class="greenbox">C</div> @@ -50,8 +49,7 @@ <div class="greenbox">A</div> </div> -<p>Center, content too big. Boxes should start at left edge and extend - outside border. +<p>Center, content too big. <div class="webkitbox" style="-webkit-box-pack: center"> <div class="redbox">D</div> <div class="greenbox">C</div> @@ -59,8 +57,7 @@ <div class="greenbox">A</div> </div> -<p>End, content too big. Boxes should start at left edge and extend - outside border. +<p>End, content too big. <div class="webkitbox" style="-webkit-box-pack: end"> <div class="redbox">D</div> <div class="greenbox">C</div> diff --git a/tests/wpt/tests/compat/webkit-box-ignore-box-pack.html b/tests/wpt/tests/compat/webkit-box-ignore-box-pack.html deleted file mode 100644 index 80b52fbf1fe..00000000000 --- a/tests/wpt/tests/compat/webkit-box-ignore-box-pack.html +++ /dev/null @@ -1,25 +0,0 @@ -<!DOCTYPE html> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<style> -#outer { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-box-pack: center; - width: 100px; - height: 100px; -} -#inner { - width: 100px; - height: 200px; -} -</style> -<div id="outer"> - <div id="inner"></div> -</div> -<script> - test(function() { - var child = document.getElementById("inner"); - assert_greater_than(child.offsetTop, 0); - }, "Child should be positioned at y-offset greater than 0 if children exceed bounds of parent"); -</script> diff --git a/tests/wpt/tests/content-security-policy/support/testharness-helper.js b/tests/wpt/tests/content-security-policy/support/testharness-helper.js index 5c36e286da2..70d5c161f55 100644 --- a/tests/wpt/tests/content-security-policy/support/testharness-helper.js +++ b/tests/wpt/tests/content-security-policy/support/testharness-helper.js @@ -84,43 +84,41 @@ function assert_service_worker_is_loaded(url, description) { } // Given the URL of a worker that pings its opener upon load, this -// function builds a test that asserts that the constructor throws -// a SecurityError, and that a CSP event fires. +// function builds a test that asserts that the an error event is +// fired on the worker, and that a CSP event fires. function assert_worker_is_blocked(url, description) { async_test(t => { + var w = new Worker(url); + w.onmessage = t.unreached_func("Ping should not be sent."); // If |url| is a blob, it will be stripped down to "blob" for reporting. var reportedURL = new URL(url).protocol == "blob:" ? "blob" : url; - waitUntilCSPEventForURL(t, reportedURL) - .then(t.step_func_done(e => { - assert_equals(e.blockedURI, reportedURL); - assert_equals(e.violatedDirective, "worker-src"); - assert_equals(e.effectiveDirective, "worker-src"); - })); - - // TODO(mkwst): We shouldn't be throwing here. We should be firing an - // `error` event on the Worker. https://crbug.com/663298 - assert_throws_dom("SecurityError", function () { - var w = new Worker(url); - }); + Promise.all([ + waitUntilCSPEventForURL(t, reportedURL) + .then(t.step_func(e => { + assert_equals(e.blockedURI, reportedURL); + assert_equals(e.violatedDirective, "worker-src"); + assert_equals(e.effectiveDirective, "worker-src"); + })), + waitUntilEvent(w, "error") + ]).then(t.step_func_done()); }, description); } function assert_shared_worker_is_blocked(url, description) { async_test(t => { + var w = new SharedWorker(url); + w.onmessage = t.unreached_func("Ping should not be sent."); // If |url| is a blob, it will be stripped down to "blob" for reporting. var reportedURL = new URL(url).protocol == "blob:" ? "blob" : url; - waitUntilCSPEventForURL(t, reportedURL) - .then(t.step_func_done(e => { - assert_equals(e.blockedURI, reportedURL); - assert_equals(e.violatedDirective, "worker-src"); - assert_equals(e.effectiveDirective, "worker-src"); - })); - - // TODO(mkwst): We shouldn't be throwing here. We should be firing an - // `error` event on the SharedWorker. https://crbug.com/663298 - assert_throws_dom("SecurityError", function () { - var w = new SharedWorker(url); - }); + Promise.all([ + waitUntilCSPEventForURL(t, reportedURL) + .then(t.step_func(e => { + assert_equals(e.blockedURI, reportedURL); + assert_equals(e.violatedDirective, "worker-src"); + assert_equals(e.effectiveDirective, "worker-src"); + })), + waitUntilEvent(w, "error") + ]).then(t.step_func_done()); }, description); } diff --git a/tests/wpt/tests/core-aam/roles-contextual.html b/tests/wpt/tests/core-aam/roles-contextual.html new file mode 100644 index 00000000000..f1a39c40708 --- /dev/null +++ b/tests/wpt/tests/core-aam/roles-contextual.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> +<head> + <title>Core AAM Contextual-Specific Role Verification Tests</title> + <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/testdriver-actions.js"></script> + <script src="/wai-aria/scripts/aria-utils.js"></script> +</head> +<body> + + +<p>Tests contextual computed role mappings defined in <a href="https://w3c.github.io/core-aam/">HTML AAM</a>, where the returned computed role is expected to change based on the context. Most test names correspond to a unique ID defined in the spec.<p> + +<p>These should remain in alphabetical order.</code></p> + +<!-- role-map-region and role-map-region-nameless --> +<div role="region" data-testname="role-map-region" aria-label="x" data-expectedrole="region" class="ex">x</div> +<div role="region" data-testname="role-map-region-nameless" class="ex-generic">x</div> +<div role="region" data-testname="role-map-region-aria-label-empty" class="ex-generic" aria-label="">x</div> +<div role="region" data-testname="role-map-region-aria-label-whitespace" class="ex-generic" aria-label=" ">x</div> +<div role="region" data-testname="role-map-region-aria-labelledby" data-expectedrole="region" class="ex" aria-labelledby="labelledby">x</div> +<div role="region" data-testname="role-map-region-aria-labelledby-non-existing" class="ex-generic" aria-labelledby="non-existing">x</div> +<div role="region" data-testname="role-map-region-aria-labelledby-empty" class="ex-generic" aria-labelledby="empty">x</div> +<div role="region" data-testname="role-map-region-aria-labelledby-whitespace" class="ex-generic" aria-labelledby="space">x</div> +<div role="region" data-testname="role-map-region-title" data-expectedrole="region" title="x" class="ex">x</div> +<div role="region" data-testname="role-map-region-title-empty" class="ex-generic" title="">x</div> +<div role="region" data-testname="role-map-region-title-whitespace" class="ex-generic" title=" ">x</div> + +<!-- element to reference for aria-labelledby tests --> +<div id="labelledby">labelledby</div> +<div id="empty"></div> +<div id="space"> </div> + +<script> + AriaUtils.verifyRolesBySelector(".ex"); + AriaUtils.verifyGenericRolesBySelector(".ex-generic"); +</script> + +</body> +</html>
\ No newline at end of file diff --git a/tests/wpt/tests/css/compositing/root-element-background-image-transparency-002.html b/tests/wpt/tests/css/compositing/root-element-background-image-transparency-002.html index 0da51986f1c..c1f68c8b62e 100644 --- a/tests/wpt/tests/css/compositing/root-element-background-image-transparency-002.html +++ b/tests/wpt/tests/css/compositing/root-element-background-image-transparency-002.html @@ -7,7 +7,7 @@ <meta name="assert" content="The background image should have opacity applied to it as part of the Root Element Group"> <link rel="match" href="root-element-background-image-transparency-001-ref.html"> - <meta name="fuzzy" content="maxDifference=0-1; totalPixels=0-9600" /> + <meta name="fuzzy" content="maxDifference=0-1; totalPixels=0-250000" /> <style> html { background: url(support/transform-triangle-left.svg) fixed; diff --git a/tests/wpt/tests/css/compositing/root-element-background-image-transparency-004.html b/tests/wpt/tests/css/compositing/root-element-background-image-transparency-004.html index 1bc4b446149..6233246f9bd 100644 --- a/tests/wpt/tests/css/compositing/root-element-background-image-transparency-004.html +++ b/tests/wpt/tests/css/compositing/root-element-background-image-transparency-004.html @@ -7,7 +7,7 @@ <meta name="assert" content="The background image should have opacity applied to it as part of the Root Element Group"> <link rel="match" href="root-element-background-image-transparency-001-ref.html"> - <meta name="fuzzy" content="maxDifference=0-1; totalPixels=0-237600" /> + <meta name="fuzzy" content="maxDifference=0-1; totalPixels=0-250000" /> <style> html { background: url(support/transform-triangle-left.svg) fixed; diff --git a/tests/wpt/tests/css/css-anchor-position/anchor-center-003.html b/tests/wpt/tests/css/css-anchor-position/anchor-center-003.html new file mode 100644 index 00000000000..fd5a85a4f5f --- /dev/null +++ b/tests/wpt/tests/css/css-anchor-position/anchor-center-003.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#anchor-center"> +<link rel="author" href="mailto:plampe@igalia.com"> +<title>Tests the position and available-size of 'anchor-center' alignment with target width: auto.</title> +<style> +.container { + width: 100px; + height: 100px; + border: solid 3px; + position: relative; + margin: 50px; +} + +.anchor { + anchor-name: --anchor; + position: relative; + width: 50px; + height: 50px; + left: 40px; + top: 5px; + background: lime; +} + +.target { + position-anchor: --anchor; + position: fixed; + background: cyan; + justify-self: anchor-center; + top: anchor(bottom); +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> + +<body onload="checkLayout('.target')"> + +<div class="container"> + <div class="anchor"></div> + <div class="target" data-expected-width="30" data-offset-x="111"> + <div style="width:30px;height:20px;"></div> + </div> +</div> diff --git a/tests/wpt/tests/css/css-anchor-position/anchor-size-parse-valid.html b/tests/wpt/tests/css/css-anchor-position/anchor-size-parse-valid.html index b8ecb9b0607..8e69476512b 100644 --- a/tests/wpt/tests/css/css-anchor-position/anchor-size-parse-valid.html +++ b/tests/wpt/tests/css/css-anchor-position/anchor-size-parse-valid.html @@ -99,8 +99,10 @@ test_valid_value('width', 'anchor-size(10px)'); // Tests that anchor-size() can be used in a calc tree // Still follow the simplification process as outlined in https://drafts.csswg.org/css-values-4/#calc-simplification -test_valid_value('width', 'calc((anchor-size(--foo width) + anchor-size(--bar height)) / 2)', 'calc(0.5 * (anchor-size(--foo width) + anchor-size(--bar height)))'); -test_valid_value('width', 'calc(0.5 * (anchor-size(--foo width) + anchor-size(--bar height)))'); -test_valid_value('width', 'anchor-size(--foo width, calc(anchor-size(--bar height) * 0.5))'); -test_valid_value('width', 'min(100px, 10%, anchor-size(--foo width), anchor-size(--bar height))'); +for (const prop of ['width', 'max-width', 'margin-left']) { + test_valid_value(prop, 'calc((anchor-size(--foo width) + anchor-size(--bar height)) / 2)', 'calc(0.5 * (anchor-size(--foo width) + anchor-size(--bar height)))'); + test_valid_value(prop, 'calc(0.5 * (anchor-size(--foo width) + anchor-size(--bar height)))'); + test_valid_value(prop, 'anchor-size(--foo width, calc(anchor-size(--bar height) * 0.5))'); + test_valid_value(prop, 'min(100px, 10%, anchor-size(--foo width), anchor-size(--bar height))'); +} </script> diff --git a/tests/wpt/tests/css/css-anchor-position/parsing/anchor-scope-computed.html b/tests/wpt/tests/css/css-anchor-position/parsing/anchor-scope-computed.html index d595537a720..f8a3200adb3 100644 --- a/tests/wpt/tests/css/css-anchor-position/parsing/anchor-scope-computed.html +++ b/tests/wpt/tests/css/css-anchor-position/parsing/anchor-scope-computed.html @@ -15,6 +15,8 @@ test_computed_value("anchor-scope", "--a"); test_computed_value("anchor-scope", "--a, --b"); test_computed_value("anchor-scope", "--a, --b, --c"); + test_computed_value('anchor-scope', '--foo, --bar'); + test_computed_value('anchor-scope', '--bar, --foo'); assert_not_inherited("anchor-scope", "none", "all"); </script> diff --git a/tests/wpt/tests/css/css-anchor-position/parsing/anchor-scope-parsing.html b/tests/wpt/tests/css/css-anchor-position/parsing/anchor-scope-parsing.html index bc24c78722b..6791417a96a 100644 --- a/tests/wpt/tests/css/css-anchor-position/parsing/anchor-scope-parsing.html +++ b/tests/wpt/tests/css/css-anchor-position/parsing/anchor-scope-parsing.html @@ -15,6 +15,8 @@ test_valid_value("anchor-scope", "--a"); test_valid_value("anchor-scope", "--a, --b"); test_valid_value("anchor-scope", "--a, --b, --c"); + test_valid_value('anchor-scope', '--foo, --bar'); + test_valid_value('anchor-scope', '--bar, --foo'); test_invalid_value("anchor-scope", "--a none"); test_invalid_value("anchor-scope", "none --a"); diff --git a/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-computed.tentative.html b/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-computed.html index 8a8ba88706b..1ba494ca332 100644 --- a/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-computed.tentative.html +++ b/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-computed.html @@ -14,10 +14,20 @@ test_computed_value("position-visibility", "anchors-valid"); test_computed_value("position-visibility", "anchors-visible"); test_computed_value("position-visibility", "no-overflow"); + + test_computed_value("position-visibility", "anchors-valid anchors-visible"); test_computed_value("position-visibility", "anchors-valid no-overflow"); + test_computed_value("position-visibility", "anchors-visible anchors-valid", "anchors-valid anchors-visible"); test_computed_value("position-visibility", "anchors-visible no-overflow"); test_computed_value("position-visibility", "no-overflow anchors-valid", "anchors-valid no-overflow"); test_computed_value("position-visibility", "no-overflow anchors-visible", "anchors-visible no-overflow"); - assert_not_inherited("position-visibility", "always", "no-overflow"); + test_computed_value("position-visibility", "anchors-valid anchors-visible no-overflow"); + test_computed_value("position-visibility", "anchors-valid no-overflow anchors-visible", "anchors-valid anchors-visible no-overflow"); + test_computed_value("position-visibility", "anchors-visible anchors-valid no-overflow", "anchors-valid anchors-visible no-overflow"); + test_computed_value("position-visibility", "anchors-visible no-overflow anchors-valid", "anchors-valid anchors-visible no-overflow"); + test_computed_value("position-visibility", "no-overflow anchors-valid anchors-visible", "anchors-valid anchors-visible no-overflow"); + test_computed_value("position-visibility", "no-overflow anchors-visible anchors-valid", "anchors-valid anchors-visible no-overflow"); + + assert_not_inherited("position-visibility", "anchors-visible", "no-overflow"); </script> diff --git a/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-parsing.html b/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-parsing.html new file mode 100644 index 00000000000..47b08b0ca65 --- /dev/null +++ b/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-parsing.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Anchor Positioning Test: Parsing of position-visibility</title> +<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#position-visibility"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +<div id="target"></div> +<script> + test_valid_value("position-visibility", "initial"); + test_valid_value("position-visibility", "inherit"); + test_valid_value("position-visibility", "unset"); + test_valid_value("position-visibility", "revert"); + + test_valid_value("position-visibility", "always"); + test_valid_value("position-visibility", "anchors-valid"); + test_valid_value("position-visibility", "anchors-visible"); + test_valid_value("position-visibility", "no-overflow"); + + test_valid_value("position-visibility", "anchors-valid anchors-visible"); + test_valid_value("position-visibility", "anchors-valid no-overflow"); + test_valid_value("position-visibility", "anchors-visible anchors-valid", "anchors-valid anchors-visible"); + test_valid_value("position-visibility", "anchors-visible no-overflow"); + test_valid_value("position-visibility", "no-overflow anchors-valid", "anchors-valid no-overflow"); + test_valid_value("position-visibility", "no-overflow anchors-visible", "anchors-visible no-overflow"); + + test_valid_value("position-visibility", "anchors-valid anchors-visible no-overflow"); + test_valid_value("position-visibility", "anchors-valid no-overflow anchors-visible", "anchors-valid anchors-visible no-overflow"); + test_valid_value("position-visibility", "anchors-visible anchors-valid no-overflow", "anchors-valid anchors-visible no-overflow"); + test_valid_value("position-visibility", "anchors-visible no-overflow anchors-valid", "anchors-valid anchors-visible no-overflow"); + test_valid_value("position-visibility", "no-overflow anchors-valid anchors-visible", "anchors-valid anchors-visible no-overflow"); + test_valid_value("position-visibility", "no-overflow anchors-visible anchors-valid", "anchors-valid anchors-visible no-overflow"); + + test_invalid_value("position-visibility", "foobar"); + + test_invalid_value("position-visibility", "always foobar"); + test_invalid_value("position-visibility", "always anchors-valid"); + test_invalid_value("position-visibility", "always anchors-visible"); + test_invalid_value("position-visibility", "always no-overflow"); + test_invalid_value("position-visibility", "always anchors-valid no-overflow"); + test_invalid_value("position-visibility", "always anchors-valid anchors-visible no-overflow"); + + test_invalid_value("position-visibility", "no-overflow foobar"); + test_invalid_value("position-visibility", "anchors-valid no-overflow foobar"); + test_invalid_value("position-visibility", "anchors-valid no-overflow anchors-valid anchors-visible"); +</script> diff --git a/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-parsing.tentative.html b/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-parsing.tentative.html deleted file mode 100644 index 942ec717545..00000000000 --- a/tests/wpt/tests/css/css-anchor-position/parsing/position-visibility-parsing.tentative.html +++ /dev/null @@ -1,28 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Anchor Positioning Test: Parsing of position-visibility</title> -<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#position-visibility"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/css/support/parsing-testcommon.js"></script> -<div id="target"></div> -<script> - test_valid_value("position-visibility", "initial"); - test_valid_value("position-visibility", "inherit"); - test_valid_value("position-visibility", "unset"); - test_valid_value("position-visibility", "revert"); - test_valid_value("position-visibility", "always"); - test_valid_value("position-visibility", "anchors-valid"); - test_valid_value("position-visibility", "anchors-visible"); - test_valid_value("position-visibility", "no-overflow"); - test_valid_value("position-visibility", "anchors-valid no-overflow"); - test_valid_value("position-visibility", "anchors-visible no-overflow"); - test_valid_value("position-visibility", "no-overflow anchors-valid", "anchors-valid no-overflow"); - test_valid_value("position-visibility", "no-overflow anchors-visible", "anchors-visible no-overflow"); - - test_invalid_value("position-visibility", "always anchors-valid"); - test_invalid_value("position-visibility", "always anchors-visible"); - test_invalid_value("position-visibility", "always no-overflow"); - test_invalid_value("position-visibility", "anchors-valid anchors-visible"); - test_invalid_value("position-visibility", "no-overflow no-overflow"); -</script> diff --git a/tests/wpt/tests/css/css-anchor-position/position-area-parsing.html b/tests/wpt/tests/css/css-anchor-position/position-area-parsing.html index 9eefd256f41..e6de6d7e269 100644 --- a/tests/wpt/tests/css/css-anchor-position/position-area-parsing.html +++ b/tests/wpt/tests/css/css-anchor-position/position-area-parsing.html @@ -159,4 +159,20 @@ test_invalid_position_area_value_equal_pairs(block); test_invalid_position_area_value_equal_pairs(self_inline); test_invalid_position_area_value_equal_pairs(self_block); + + // Test one invalid keyword + test_invalid_value("position-area", "foobar"); + test_invalid_value("position-area", "visible"); + test_invalid_value("position-area", "hidden"); + + // Test one valid and one invalid keyword + test_invalid_value("position-area", "start foobar"); + test_invalid_value("position-area", "end visible"); + test_invalid_value("position-area", "block-start hidden"); + test_invalid_value("position-area", "hidden inline-end"); + + // Test two invalid keywords + test_invalid_value("position-area", "foo bar"); + test_invalid_value("position-area", "visible hidden"); + test_invalid_value("position-area", "hidden visible"); </script> diff --git a/tests/wpt/tests/css/css-anchor-position/position-area-scrolling-007.html b/tests/wpt/tests/css/css-anchor-position/position-area-scrolling-007.html new file mode 100644 index 00000000000..8e865f1c491 --- /dev/null +++ b/tests/wpt/tests/css/css-anchor-position/position-area-scrolling-007.html @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<title>position-try-fallbacks with flip-block and flip-inline</title> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-anchor-position/#position-try-fallbacks"> +<link rel="help" href="https://issues.chromium.org/issues/400761086"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-common.js"></script> +<style> + #anchor { + anchor-name: --a; + margin-top: 200px; + margin-left: 100px; + width: 150px; + height: 50px; + background: blue; + } + #anchored { + position: absolute; + position-anchor: --a; + position-area: top left; + position-try-fallbacks: flip-inline, flip-block, flip-block flip-inline; + width: 100%; + height: 100%; + background: hotpink; + } +</style> + +<div id="scroller" style="position:relative; overflow:hidden; width:400px; height:400px;"> + <div id="anchor"></div> + <div style="width:1000px; height:1000px;"></div> + <div id="anchored"></div> +</div> + +<script> + promise_test(async () => { + await waitUntilNextAnimationFrame(); + await waitUntilNextAnimationFrame(); + assert_equals(anchored.offsetLeft, 0); + assert_equals(anchored.offsetTop, 0); + assert_equals(anchored.offsetWidth, 100); + assert_equals(anchored.offsetHeight, 200); + }, 'initial position'); + + promise_test(async () => { + scroller.scrollTo(0, 10); + await waitUntilNextAnimationFrame(); + await waitUntilNextAnimationFrame(); + assert_equals(anchored.offsetLeft, 0); + assert_equals(anchored.offsetTop, 250); + assert_equals(anchored.offsetWidth, 100); + assert_equals(anchored.offsetHeight, 160); + }, 'Scroll down to 0,10'); + + promise_test(async () => { + scroller.scrollTo(10, 10); + await waitUntilNextAnimationFrame(); + await waitUntilNextAnimationFrame(); + assert_equals(anchored.offsetLeft, 250); + assert_equals(anchored.offsetTop, 10); + assert_equals(anchored.offsetWidth, 160); + assert_equals(anchored.offsetHeight, 190); + }, 'Scroll right to 10,10'); + + promise_test(async () => { + scroller.scrollTo(10, 0); + await waitUntilNextAnimationFrame(); + await waitUntilNextAnimationFrame(); + assert_equals(anchored.offsetLeft, 250); + assert_equals(anchored.offsetTop, 10); + assert_equals(anchored.offsetWidth, 160); + assert_equals(anchored.offsetHeight, 190); + }, 'Scroll up to 10,0'); + + promise_test(async () => { + scroller.scrollTo(10, 20); + await waitUntilNextAnimationFrame(); + await waitUntilNextAnimationFrame(); + assert_equals(anchored.offsetLeft, 10); + assert_equals(anchored.offsetTop, 250); + assert_equals(anchored.offsetWidth, 90); + assert_equals(anchored.offsetHeight, 170); + }, 'Scroll down to 10,20'); + + promise_test(async () => { + scroller.scrollTo(101, 20); + await waitUntilNextAnimationFrame(); + await waitUntilNextAnimationFrame(); + assert_equals(anchored.offsetLeft, 250); + assert_equals(anchored.offsetTop, 20); + assert_equals(anchored.offsetWidth, 251); + assert_equals(anchored.offsetHeight, 180); + }, 'Scroll down to 101,20'); + + promise_test(async () => { + scroller.scrollTo(101, 30); + await waitUntilNextAnimationFrame(); + await waitUntilNextAnimationFrame(); + assert_equals(anchored.offsetLeft, 250); + assert_equals(anchored.offsetTop, 250); + assert_equals(anchored.offsetWidth, 251); + assert_equals(anchored.offsetHeight, 180); + }, 'Scroll down to 101,30'); +</script> diff --git a/tests/wpt/tests/css/css-animations/CSSAnimation-effect.tentative.html b/tests/wpt/tests/css/css-animations/CSSAnimation-effect.tentative.html index 04812d24e58..591ffe770b6 100644 --- a/tests/wpt/tests/css/css-animations/CSSAnimation-effect.tentative.html +++ b/tests/wpt/tests/css/css-animations/CSSAnimation-effect.tentative.html @@ -170,6 +170,7 @@ test(t => { div.style.animationFillMode = 'both'; div.style.animationPlayState = 'paused'; div.style.animationComposition = 'add'; + div.style.animationTimeline = 'none'; // Update the keyframes keyframesRule.deleteRule(0); @@ -212,13 +213,18 @@ test(t => { 'composite should be the value set by the API' ); - // Unlike the other properties animation-play-state maps to the Animation - // not the KeyframeEffect so it should be overridden. + // Unlike the other properties animation-play-state and animation-timeline map + // to the Animation, not the KeyframeEffect, so they should be overridden. assert_equals( animation.playState, 'paused', 'play state should be the value set by style' ); + assert_equals( + animation.timeline, + null, + 'timeline should be the value set by style' + ); }, 'Replacing the effect of a CSSAnimation causes subsequent changes to' + ' corresponding animation-* properties to be ignored'); diff --git a/tests/wpt/tests/css/css-animations/animate-with-relative-color.html b/tests/wpt/tests/css/css-animations/animate-with-relative-color.html new file mode 100644 index 00000000000..b70b5e0855c --- /dev/null +++ b/tests/wpt/tests/css/css-animations/animate-with-relative-color.html @@ -0,0 +1,91 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <link rel="help" href="https://www.w3.org/TR/css-color-4/#interpolation"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>CSS animations with relative colors</title> +</head> +<style> + @keyframes oklch { + 0% { background: oklch(0% 0 0deg); } + 100% { background: oklch(from oklch(0% 0 0deg) calc(l + 0.5) c h); } + } + @keyframes rgb { + 0% { background: black; } + 100% { background: rgb(from green r g 255); } + } + #target { + background: oklch(0% 0 0deg); + animation-duration: 1s; + animation-timing-function: linear; + animation-play-state: paused; + animation-fill-mode: forwards; + height: 100px; + width: 100px; + } + .oklch { + animation-name: oklch; + } + .rgb { + animation-name: rgb; + } +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="/css/support/color-testcommon.js"></script> + +<body> + <div id="target"></div> + <div id="test"></div> +</body> +<script> + 'use strict'; + + async function runAnimationTest(t, name, expected_colors) { + const target = document.getElementById('target'); + target.classList.add(name); + t.add_cleanup(() => { + target.classList.remove(name); + }); + const anim = document.getAnimations()[0]; + await anim.ready; + expected_colors.forEach(data => { + anim.currentTime = 1000 * data.at; + const actual = getComputedStyle(target).backgroundColor; + const expected = data.value; + assert_oklab_color( + actual, expected, + `Background color at ${100*data.at}% animation progress`); + }); + } + + const oklch = [ + { at: 0, value: 'oklab(0.0000 0.0000 0.0000)' }, + { at: 0.25, value: 'oklab(0.125 0 0)' }, + { at: 0.5, value: 'oklab(0.25 0 0)' }, + { at: 0.75, value: 'oklab(0.375 0 0)' }, + { at: 1, value: 'oklab(0.5 0 0)' } + ]; + + const rgb = [ + { at: 0, value: 'oklab(0.0000 0.0000 0.0000)' }, + { at: 0.25, value: 'oklab(0.153779 -0.0126551 -0.0511623)' }, + { at: 0.5, value: 'oklab(0.307559 -0.0253101 -0.102325)' }, + { at: 0.75, value: 'oklab(0.461338 -0.0379652 -0.153487)' }, + { at: 1, value: 'oklab(0.615117 -0.0506203 -0.204649)' } + ]; + + window.onload = async () => { + promise_test(t => { + return runAnimationTest(t, 'oklch', oklch); + }, 'Animate from absolute oklch to relative oklch'); + + promise_test(t => { + return runAnimationTest(t, 'rgb', rgb); + }, 'Animate from color keyword to relative rgb'); + }; + +</script> +</html> diff --git a/tests/wpt/tests/css/css-animations/display-via-custom-prop-animation-crash.html b/tests/wpt/tests/css/css-animations/display-via-custom-prop-animation-crash.html new file mode 100644 index 00000000000..8ea697a9868 --- /dev/null +++ b/tests/wpt/tests/css/css-animations/display-via-custom-prop-animation-crash.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html class="test-wait"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1941651"> +<style> + :root { + --disp: block; + } + + @keyframes switch { + 0% { --disp: none; } + 100% { --disp: block; } + } + + #target { + height: 100px; + width: 100px; + background-color: green; + animation: switch 0.5s; + display: var(--disp); + } +</style> +<div id="target"> + <div></div> +</div> +<script> + target.addEventListener("animationend", function() { + document.documentElement.classList = ""; + }) + target.getBoundingClientRect(); +</script> diff --git a/tests/wpt/tests/css/css-animations/parsing/animation-range-end-invalid.html b/tests/wpt/tests/css/css-animations/parsing/animation-range-end-invalid.html index 459cdfd0cd2..2abf4f16cfa 100644 --- a/tests/wpt/tests/css/css-animations/parsing/animation-range-end-invalid.html +++ b/tests/wpt/tests/css/css-animations/parsing/animation-range-end-invalid.html @@ -17,4 +17,6 @@ test_invalid_value("animation-range-end", "50% exit"); test_invalid_value("animation-range-end", "contain contain"); test_invalid_value("animation-range-end", "none"); test_invalid_value("animation-range-end", "cover 50% enter 50%"); +test_invalid_value("animation-range-end", "normal 10px"); +test_invalid_value("animation-range-end", "normal foo"); </script> diff --git a/tests/wpt/tests/css/css-animations/parsing/animation-range-shorthand.html b/tests/wpt/tests/css/css-animations/parsing/animation-range-shorthand.html index 25f5c140d8c..c9ac154c4e1 100644 --- a/tests/wpt/tests/css/css-animations/parsing/animation-range-shorthand.html +++ b/tests/wpt/tests/css/css-animations/parsing/animation-range-shorthand.html @@ -108,6 +108,8 @@ test_invalid_value("animation-range", "thing 42%"); test_invalid_value("animation-range", "thing 100%"); test_invalid_value("animation-range", "thing 100px"); test_invalid_value("animation-range", "100% thing"); +test_invalid_value("animation-range", "normal foo normal 100%"); +test_invalid_value("animation-range", "normal normal 100%"); test_shorthand_value('animation-range', 'normal', { 'animation-range-start': 'normal', diff --git a/tests/wpt/tests/css/css-animations/parsing/animation-range-start-invalid.html b/tests/wpt/tests/css/css-animations/parsing/animation-range-start-invalid.html index 32357d8bd4c..874bde44338 100644 --- a/tests/wpt/tests/css/css-animations/parsing/animation-range-start-invalid.html +++ b/tests/wpt/tests/css/css-animations/parsing/animation-range-start-invalid.html @@ -13,4 +13,6 @@ test_invalid_value("animation-range-start", "50% exit"); test_invalid_value("animation-range-start", "contain contain"); test_invalid_value("animation-range-start", "none"); test_invalid_value("animation-range-start", "cover 50% enter 50%"); +test_invalid_value("animation-range-start", "normal 10px"); +test_invalid_value("animation-range-start", "normal foo"); </script> diff --git a/tests/wpt/tests/css/css-break/rounded-clipped-border.html b/tests/wpt/tests/css/css-break/rounded-clipped-border.html index 60f4dfd8ba6..fe48fd3bcca 100644 --- a/tests/wpt/tests/css/css-break/rounded-clipped-border.html +++ b/tests/wpt/tests/css/css-break/rounded-clipped-border.html @@ -2,7 +2,7 @@ <link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> <link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1433413"> <link rel="match" href="rounded-clipped-border-ref.html"> -<meta name="fuzzy" content="maxDifference=0-15;totalPixels=0-900"> +<meta name="fuzzy" content="maxDifference=0-75;totalPixels=0-1200"> <style> .container { diff --git a/tests/wpt/tests/css/css-display/reading-flow/tentative/reading-flow-computed.html b/tests/wpt/tests/css/css-display/reading-flow/tentative/reading-flow-computed.html index 65ef90f5a50..43972c5825f 100644 --- a/tests/wpt/tests/css/css-display/reading-flow/tentative/reading-flow-computed.html +++ b/tests/wpt/tests/css/css-display/reading-flow/tentative/reading-flow-computed.html @@ -14,5 +14,6 @@ test_computed_value('reading-flow', 'flex-flow'); test_computed_value('reading-flow', 'grid-rows'); test_computed_value('reading-flow', 'grid-columns'); test_computed_value('reading-flow', 'grid-order'); +test_computed_value('reading-flow', 'source-order'); </script> </body> diff --git a/tests/wpt/tests/css/css-display/reading-flow/tentative/reading-flow-valid.html b/tests/wpt/tests/css/css-display/reading-flow/tentative/reading-flow-valid.html index 3d650c53063..f006ca07949 100644 --- a/tests/wpt/tests/css/css-display/reading-flow/tentative/reading-flow-valid.html +++ b/tests/wpt/tests/css/css-display/reading-flow/tentative/reading-flow-valid.html @@ -13,5 +13,6 @@ test_valid_value('reading-flow', 'flex-flow'); test_valid_value('reading-flow', 'grid-rows'); test_valid_value('reading-flow', 'grid-columns'); test_valid_value('reading-flow', 'grid-order'); +test_valid_value('reading-flow', 'source-order'); </script> </body> diff --git a/tests/wpt/tests/css/css-fonts/lang-attribute-affects-rendering-of-second-text-run-ref.html b/tests/wpt/tests/css/css-fonts/lang-attribute-affects-rendering-of-second-text-run-ref.html new file mode 100644 index 00000000000..7d2f4e7129f --- /dev/null +++ b/tests/wpt/tests/css/css-fonts/lang-attribute-affects-rendering-of-second-text-run-ref.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <style> + * { font-size: 50px } + + @font-face { + font-family: test-font-family; + /* <Lato-Medium.ttf> provides different ligatures for English and + Turkish. */ + src: url(support/fonts/Lato-Medium.ttf); + } + + div { font-family: test-font-family; } + </style> +</head> +<body> + `lang="en"` should render ligatures, `lang="tr"` not. + Different scripts should correspond to different text runs. + <div lang="tr">αβ fi</div> +</body> +</html> + diff --git a/tests/wpt/tests/css/css-fonts/lang-attribute-affects-rendering-of-second-text-run.html b/tests/wpt/tests/css/css-fonts/lang-attribute-affects-rendering-of-second-text-run.html new file mode 100644 index 00000000000..296468719c9 --- /dev/null +++ b/tests/wpt/tests/css/css-fonts/lang-attribute-affects-rendering-of-second-text-run.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <link rel="help" href="https://html.spec.whatwg.org/#attr-lang"> + <link rel="mismatch" href="lang-attribute-affects-rendering-of-second-text-run-ref.html"> + <style> + * { font-size: 50px } + + @font-face { + font-family: test-font-family; + /* <Lato-Medium.ttf> provides different ligatures for English and + Turkish. */ + src: url(support/fonts/Lato-Medium.ttf); + } + + div { font-family: test-font-family; } + </style> +</head> +<body> + `lang="en"` should render ligatures, `lang="tr"` not. + Different scripts should correspond to different text runs. + <div lang="en">αβ fi</div> +</body> +</html> diff --git a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-001.html b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-001.html index 2741196e522..5fe13a11bbf 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-001.html +++ b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-001.html @@ -17,6 +17,9 @@ column-rule-color: green; column-rule-style: solid; column-rule-width: 10px; + row-rule-color: green; + row-rule-style: solid; + row-rule-width: 10px; } .grid-item { diff --git a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-002.html b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-002.html index 8cad606c6ac..429798d0fe7 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-002.html +++ b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-002.html @@ -9,7 +9,6 @@ .grid-container { height: 110px; width: 110px; - background-color: green; display: grid; grid-template-columns: repeat(2, 1fr); @@ -20,6 +19,10 @@ column-rule-color: pink; column-rule-style: solid; column-rule-width: 10px; + + row-rule-color: green; + row-rule-style: solid; + row-rule-width: 10px; } .grid-item { diff --git a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-003-ref.html b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-003-ref.html index 86796edba42..15fc305633d 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-003-ref.html +++ b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-003-ref.html @@ -2,19 +2,20 @@ <link rel="help" href="https://drafts.csswg.org/css-gaps-1/"> <link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com"> <style> + body { + margin: 0px; + } + .container { width: 110px; height: 110px; - background-color: green; - column-count: 2; column-gap: 10px; - column-rule-color: pink; column-rule-style: dotted; column-rule-width: 10px; - overflow: hidden; + position: relative; } .item { @@ -29,10 +30,25 @@ .item:nth-child(odd) { margin-bottom: 10px; } + + .row-rule { + margin: 0px; + padding: 0px; + height: 0px; + + width: 110px; + border-bottom: 10px dotted; + border-color: green; + position: absolute; + top: 50px; + } + </style> <div class="container"> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> + <div class="item"></div> + <div class="item"></div> + <div class="item"></div> + <div class="item"></div> </div> +<div class="row-rule"> +</div>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-003.html b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-003.html index 5e618aae79b..f9d07a183ec 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-003.html +++ b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-003.html @@ -6,10 +6,14 @@ <link rel="match" href="grid-gap-decorations-003-ref.html"> <link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com"> <style> + + body { + margin: 0px; + } + .grid-container { height: 110px; width: 110px; - background-color: green; display: grid; grid-template-columns: repeat(2, 1fr); @@ -20,6 +24,10 @@ column-rule-color: pink; column-rule-style: dotted; column-rule-width: 10px; + + row-rule-color: green; + row-rule-style: dotted; + row-rule-width: 10px; } .grid-item { diff --git a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-004-ref.html b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-004-ref.html index 9011957ea4d..e4e6b8b458f 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-004-ref.html +++ b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-004-ref.html @@ -2,24 +2,28 @@ <link rel="help" href="https://drafts.csswg.org/css-gaps-1/"> <link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com"> <style> + body { + margin: 0px; + } + .container { - width: 110px; - height: 110px; + width: 108px; + height: 108px; background: green; column-count: 2; - column-gap: 10px; + column-gap: 12px; column-rule-color: pink; column-rule-style: double; - column-rule-width: 10px; + column-rule-width: 12px; overflow: hidden; } .item { background: skyblue; - height: 50px; + height: 48px; width: 100%; margin: 0; } @@ -27,12 +31,26 @@ /* For 2x2 grid-like layout, add a 10px bottom margin to odd children(#1 & #3) to simulate a horizontal row gap.*/ .item:nth-child(odd) { - margin-bottom: 10px; + margin-bottom: 12px; + } + + .row-gap { + margin: 0px; + padding: 0px; + height: 4px; + background: pink; + width: 108px; + position: absolute; } + </style> <div class="container"> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> + <div class="item"></div> + <div class="item"></div> + <div class="item"></div> + <div class="item"></div> </div> + +<!-- Two horizontal bars to simulate row gaps with style double --> +<div id="horizontal1" class="row-gap" style="top: 48px;"></div> +<div id="horizontal2" class="row-gap" style="top: 56px;"></div>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-004.html b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-004.html index ab7e5d6695c..e28988151a5 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-004.html +++ b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-004.html @@ -6,21 +6,30 @@ <link rel="match" href="grid-gap-decorations-004-ref.html"> <link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com"> <style> + + body { + margin: 0px; + } + .grid-container { - height: 110px; - width: 110px; + height: 108px; + width: 108px; display: grid; grid-template-columns: repeat(2, 1fr); - column-gap: 10px; - row-gap: 10px; + column-gap: 12px; + row-gap: 12px; background-color: green; column-rule-color: pink; column-rule-style: double; - column-rule-width: 10px; + column-rule-width: 12px; + + row-rule-color: pink; + row-rule-style: double; + row-rule-width: 12px; } .grid-item { diff --git a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-005-ref.html b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-005-ref.html index 887c9f18f12..aebfba5a20e 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-005-ref.html +++ b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-005-ref.html @@ -2,6 +2,10 @@ <link rel="help" href="https://drafts.csswg.org/css-gaps-1/"> <link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com"> <style> + body { + margin: 0px; + } + .container { width: 110px; height: 110px; @@ -24,6 +28,23 @@ margin: 0; } + .double { + margin: 0px; + padding: 0px; + height: 0px; + + width: 110px; + border-bottom: 5px double; + border-color: pink; + position: absolute; + /* + The top position of the double border is set to 52.5px + to account for 10px gap and 5px height of the double border, + in order to center it in the gap. + */ + top: 52.5px; + } + /* For 2x2 grid-like layout, add a 10px bottom margin to odd children(#1 & #3) to simulate a horizontal row gap.*/ .item:nth-child(odd) { @@ -36,3 +57,6 @@ <div class="item"></div> <div class="item"></div> </div> + +<div class="double"> +</div>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-005.html b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-005.html index 8a429eea355..741977d2eb4 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-005.html +++ b/tests/wpt/tests/css/css-gaps/tentative/grid/grid-gap-decorations-005.html @@ -6,6 +6,11 @@ <link rel="match" href="grid-gap-decorations-005-ref.html"> <link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com"> <style> + + body { + margin: 0px; + } + .grid-container { height: 110px; width: 110px; @@ -21,6 +26,10 @@ column-rule-color: pink; column-rule-style: double; column-rule-width: 5px; + + row-rule-color: pink; + row-rule-style: double; + row-rule-width: 5px; } .grid-item { diff --git a/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-computed.html b/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-computed.html index 31b311a0ab4..3ef68de7392 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-computed.html +++ b/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-computed.html @@ -5,7 +5,7 @@ <title>CSS Gap Decoration: column-rule-color getComputedStyle()</title> <link rel="help" href="https://tabatkins.github.io/specs/css-masonry/"> <link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com"> -<meta name="assert" content="column-rule-color computed value is as specified."> +<meta name="assert" content="*-rule-color computed value is as specified."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/css/support/computed-testcommon.js"></script> @@ -18,20 +18,23 @@ } </style> <script> -test_computed_value("column-rule-color", "currentcolor", "rgb(0, 255, 0)"); -test_computed_value("column-rule-color", "red", "rgb(255, 0, 0)"); -test_computed_value("column-rule-color", "repeat(4, yellow)", "repeat(4, rgb(255, 255, 0))"); -test_computed_value("column-rule-color", "red green blue", "rgb(255, 0, 0) rgb(0, 128, 0) rgb(0, 0, 255)"); -test_computed_value("column-rule-color", "repeat(7, lime) repeat(3, red)", "repeat(7, rgb(0, 255, 0)) repeat(3, rgb(255, 0, 0))"); -test_computed_value("column-rule-color", "repeat(auto, red)", "repeat(auto, rgb(255, 0, 0))"); +const properties = ["column-rule-color", "row-rule-color"]; +for (let property of properties) { + test_computed_value(property, "currentcolor", "rgb(0, 255, 0)"); + test_computed_value(property, "red", "rgb(255, 0, 0)"); + test_computed_value(property, "repeat(4, yellow)", "repeat(4, rgb(255, 255, 0))"); + test_computed_value(property, "red green blue", "rgb(255, 0, 0) rgb(0, 128, 0) rgb(0, 0, 255)"); + test_computed_value(property, "repeat(7, lime) repeat(3, red)", "repeat(7, rgb(0, 255, 0)) repeat(3, rgb(255, 0, 0))"); + test_computed_value(property, "repeat(auto, red)", "repeat(auto, rgb(255, 0, 0))"); -test_computed_value("column-rule-color", "repeat(calc(5 + 3), salmon)", "repeat(8, rgb(250, 128, 114))"); + test_computed_value(property, "repeat(calc(5 + 3), salmon)", "repeat(8, rgb(250, 128, 114))"); -test_computed_value("column-rule-color", "color-mix(in srgb, red 50%, blue 50%)", "color(srgb 0.5 0 0.5)"); -test_computed_value("column-rule-color", "color-mix(in srgb, lime 25%, yellow 75%)", "color(srgb 0.75 1 0)"); + test_computed_value(property, "color-mix(in srgb, red 50%, blue 50%)", "color(srgb 0.5 0 0.5)"); + test_computed_value(property, "color-mix(in srgb, lime 25%, yellow 75%)", "color(srgb 0.75 1 0)"); -test_computed_value("column-rule-color", "repeat(auto, rgb(from lime r g b))", "repeat(auto, color(srgb 0 1 0))"); -test_computed_value("column-rule-color", "rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b))", "color(srgb 0 0 1)"); + test_computed_value(property, "repeat(auto, rgb(from lime r g b))", "repeat(auto, color(srgb 0 1 0))"); + test_computed_value(property, "rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b))", "color(srgb 0 0 1)"); +} </script> </body> </html> diff --git a/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-invalid.html b/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-invalid.html index 36f26ceb163..e553d24ea7b 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-invalid.html +++ b/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-invalid.html @@ -5,20 +5,23 @@ <title>CSS Gap Decorations: column-rule-color parsing</title> <link rel="help" href="https://drafts.csswg.org/css-gaps-1/#column-row-rule-color"> <link rel="author" title="Sam Davis Omekara Jr." href="mailto:samomekarajr@microsoft.com"> -<meta name="assert" content="column-rule-color supports only the grammar '[ <line-color-list> | <auto-line-color-list> ]'."> +<meta name="assert" content="*-rule-color supports only the grammar '[ <line-color-list> | <auto-line-color-list> ]'."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/css/support/parsing-testcommon.js"></script> </head> <body> <script> -test_invalid_value("column-rule-color", "auto"); +const properties = ["column-rule-color", "row-rule-color"]; +for (let property of properties) { + test_invalid_value(property, "auto"); -test_invalid_value("column-rule-color", "red, blue, green"); -test_invalid_value("column-rule-color", "repeat(auto, red, blue, green)"); -test_invalid_value("column-rule-color", "repeat(0, red, blue, green)"); -test_invalid_value("column-rule-color", "repeat(-1, red, blue, green)"); -test_invalid_value("column-rule-color", "repeat(auto, red) red repeat(auto, blue)"); + test_invalid_value(property, "red, blue, green"); + test_invalid_value(property, "repeat(auto, red, blue, green)"); + test_invalid_value(property, "repeat(0, red, blue, green)"); + test_invalid_value(property, "repeat(-1, red, blue, green)"); + test_invalid_value(property, "repeat(auto, red) red repeat(auto, blue)"); +} </script> </body> </html> diff --git a/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-valid.html b/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-valid.html index d4cb5b1168f..af24afc3c98 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-valid.html +++ b/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-color-valid.html @@ -12,32 +12,35 @@ </head> <body> <script> -// <repeat-line-color> = repeat( [ <integer [1,∞]> ] , [ <color> ]+ ) -test_valid_value("column-rule-color", "repeat(4, blue)"); -test_valid_value("column-rule-color", "repeat(3, red green blue)"); -test_valid_value("column-rule-color", "repeat(1, red green blue yellow)"); +const properties = ["column-rule-color", "row-rule-color"]; +for (let property of properties) { + // <repeat-line-color> = repeat( [ <integer [1,∞]> ] , [ <color> ]+ ) + test_valid_value(property, "repeat(4, blue)"); + test_valid_value(property, "repeat(3, red green blue)"); + test_valid_value(property, "repeat(1, red green blue yellow)"); -// <line-color-or-repeat> = [ <color> | <repeat-line-color> ] -test_valid_value("column-rule-color", "red"); -test_valid_value("column-rule-color", "repeat(4, cyan)"); + // <line-color-or-repeat> = [ <color> | <repeat-line-color> ] + test_valid_value(property, "red"); + test_valid_value(property, "repeat(4, cyan)"); -// <line-color-list> = [ <line-color-or-repeat> ]+ -test_valid_value("column-rule-color", "green blue"); -test_valid_value("column-rule-color", "red blue green yellow pink"); -test_valid_value("column-rule-color", "repeat(3, blue) repeat(4, red)"); -test_valid_value("column-rule-color", "red repeat(3, blue) blue repeat(4, red green cyan)"); -test_valid_value("column-rule-color", "repeat(4, red green cyan) repeat(5, yellow) blue"); + // <line-color-list> = [ <line-color-or-repeat> ]+ + test_valid_value(property, "green blue"); + test_valid_value(property, "red blue green yellow pink"); + test_valid_value(property, "repeat(3, blue) repeat(4, red)"); + test_valid_value(property, "red repeat(3, blue) blue repeat(4, red green cyan)"); + test_valid_value(property, "repeat(4, red green cyan) repeat(5, yellow) blue"); -// <auto-repeat-line-color> = repeat( auto , [ <color> ]+ ) -test_valid_value("column-rule-color", "repeat(auto, red)"); -test_valid_value("column-rule-color", "repeat(auto, red green blue)"); + // <auto-repeat-line-color> = repeat( auto , [ <color> ]+ ) + test_valid_value(property, "repeat(auto, red)"); + test_valid_value(property, "repeat(auto, red green blue)"); -// <auto-line-color-list> = [ <line-color-or-repeat> ]* -// <auto-repeat-line-color> -// [ <line-color-or-repeat> ]* -test_valid_value("column-rule-color", "repeat(auto, red green) red"); -test_valid_value("column-rule-color", "repeat(4, blue red green) repeat(auto, red)"); -test_valid_value("column-rule-color", "blue repeat(auto, red green) repeat(4, blue red green)"); + // <auto-line-color-list> = [ <line-color-or-repeat> ]* + // <auto-repeat-line-color> + // [ <line-color-or-repeat> ]* + test_valid_value(property, "repeat(auto, red green) red"); + test_valid_value(property, "repeat(4, blue red green) repeat(auto, red)"); + test_valid_value(property, "blue repeat(auto, red green) repeat(4, blue red green)"); +} </script> </body> </html> diff --git a/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-width-invalid.html b/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-width-invalid.html index 1b93fb53a98..902c619affb 100644 --- a/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-width-invalid.html +++ b/tests/wpt/tests/css/css-gaps/tentative/parsing/gap-decorations-width-invalid.html @@ -28,4 +28,4 @@ for (let property of properties) { </script> </body> -</html> +</html>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-grid/layout-algorithm/flex-sizing-rows-indefinite-height-002.html b/tests/wpt/tests/css/css-grid/layout-algorithm/flex-sizing-rows-indefinite-height-002.html new file mode 100644 index 00000000000..d0136b3ee2f --- /dev/null +++ b/tests/wpt/tests/css/css-grid/layout-algorithm/flex-sizing-rows-indefinite-height-002.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Expand flexible tracks with a fractional size</title> +<link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org/"> +<link rel="help" href="https://drafts.csswg.org/css-grid-2/#algo-flex-tracks"> +<link rel="help" href="https://drafts.csswg.org/css-grid-2/#algo-find-fr-size"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> + +<style> +.grid { + display: grid; + width: 100px; + background: red; +} +.item { + grid-row: 2 / span 1; + background: green; + width: 100px; + height: 100px; + position: relative; + top: -32px; /* To move this item up to cover the first row */ +} +</style> + +<!-- + Flexible row track sizes are resolved in two passes: + + The first pass: + - The only grid item has a max-content height of 100px, which is also the + hypothetical fr size. + - Initially, each flexible track (0.4fr) is given a hypothetical size of + 100px * 0.4 = 40px. + - This makes the grid container's height 40px * 2 = 80px in this pass. + + The second pass: + - With the grid container's height now became fixed at 80px, the available + grid space is known. + - Per https://drafts.csswg.org/css-grid-2/#algo-find-fr-size + the hypothetical fr size is 80px * max(0.4 * 2 , 1.0) = 80px. + - In this pass, each 0.4fr row track resolves to 80px * 0.4 = 32px in height. +--> + +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div class="grid" style="grid-template-rows: repeat(2, minmax(0,0.4fr))"> + <span class="item"></span> +</div> diff --git a/tests/wpt/tests/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001.html b/tests/wpt/tests/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001.html index 0b380574bc5..1129d369832 100644 --- a/tests/wpt/tests/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001.html +++ b/tests/wpt/tests/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001.html @@ -1,5 +1,6 @@ <!DOCTYPE html> <meta charset="UTF-8"> +<meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-2"> <title>CSS Highlight API Test: Overlapping Highlights</title> <link rel="help" href="https://drafts.csswg.org/css-highlight-api-1/"> <link rel="match" href="custom-highlight-painting-overlapping-highlights-001-ref.html"> @@ -40,4 +41,4 @@ CSS.highlights.set("highlight1", new Highlight(r)); CSS.highlights.set("highlight2", new Highlight(r)); -</script>
\ No newline at end of file +</script> diff --git a/tests/wpt/tests/css/css-images/object-fit-none-png-001c.html b/tests/wpt/tests/css/css-images/object-fit-none-png-001c.html index 8819de80151..fe483baa963 100644 --- a/tests/wpt/tests/css/css-images/object-fit-none-png-001c.html +++ b/tests/wpt/tests/css/css-images/object-fit-none-png-001c.html @@ -12,7 +12,6 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-none-png-001-ref.html"> - <meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-50"> <style type="text/css"> canvas { border: 1px dashed gray; diff --git a/tests/wpt/tests/css/css-images/object-fit-none-png-002c.html b/tests/wpt/tests/css/css-images/object-fit-none-png-002c.html index a240681abec..09bc836d024 100644 --- a/tests/wpt/tests/css/css-images/object-fit-none-png-002c.html +++ b/tests/wpt/tests/css/css-images/object-fit-none-png-002c.html @@ -12,7 +12,6 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-none-png-002-ref.html"> - <meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-50"> <style type="text/css"> canvas { border: 1px dashed gray; diff --git a/tests/wpt/tests/css/css-images/object-fit-scale-down-png-001c.html b/tests/wpt/tests/css/css-images/object-fit-scale-down-png-001c.html index d897dc24f76..5b8116ecbcb 100644 --- a/tests/wpt/tests/css/css-images/object-fit-scale-down-png-001c.html +++ b/tests/wpt/tests/css/css-images/object-fit-scale-down-png-001c.html @@ -12,7 +12,6 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-scale-down-png-001-ref.html"> - <meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-50"> <style type="text/css"> canvas { border: 1px dashed gray; diff --git a/tests/wpt/tests/css/css-images/object-fit-scale-down-png-002c.html b/tests/wpt/tests/css/css-images/object-fit-scale-down-png-002c.html index 9bdafced565..626f379f1c7 100644 --- a/tests/wpt/tests/css/css-images/object-fit-scale-down-png-002c.html +++ b/tests/wpt/tests/css/css-images/object-fit-scale-down-png-002c.html @@ -12,7 +12,6 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-scale-down-png-002-ref.html"> - <meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-50"> <style type="text/css"> canvas { border: 1px dashed gray; diff --git a/tests/wpt/tests/css/css-mixins/at-function-parsing.html b/tests/wpt/tests/css/css-mixins/at-function-parsing.html index 8c011a88023..60a84422af8 100644 --- a/tests/wpt/tests/css/css-mixins/at-function-parsing.html +++ b/tests/wpt/tests/css/css-mixins/at-function-parsing.html @@ -90,6 +90,15 @@ test_invalid_prelude('@function --foo(--x <length> | auto)'); test_invalid_prelude('@function --foo(--x none | auto)'); test_invalid_prelude('@function --foo(--x <dino>)'); + test_invalid_prelude('@function --foo(!)'); + test_invalid_prelude('@function --foo(--x: !)'); + test_invalid_prelude('@function --foo(--x type(!))'); + test_invalid_prelude('@function --foo(,)'); + test_invalid_prelude('@function --foo(,,,)'); + test_invalid_prelude('@function --foo(--x, ;)'); + test_invalid_prelude('@function --foo(;)'); + test_invalid_prelude('@function --foo(])'); + test_invalid_prelude('@function --foo(, --x])'); // Return value types. test_valid_prelude('@function --foo(--x) returns type(*)'); @@ -100,6 +109,8 @@ test_valid_prelude('@function --foo(--x) returns type(foo | bar)'); test_invalid_prelude('@function --foo(--x) !'); + test_invalid_prelude('@function --foo(--x) ! <length>'); + test_invalid_prelude('@function --foo(--x) returns <length>!'); test_invalid_prelude('@function --foo(--x) length'); test_invalid_prelude('@function --foo(--x) returns'); test_invalid_prelude('@function --foo(--x) returns '); diff --git a/tests/wpt/tests/css/css-mixins/dashed-function-cycles.tentative.html b/tests/wpt/tests/css/css-mixins/dashed-function-cycles.tentative.html index 808fe2c23b3..11e653e9b7d 100644 --- a/tests/wpt/tests/css/css-mixins/dashed-function-cycles.tentative.html +++ b/tests/wpt/tests/css/css-mixins/dashed-function-cycles.tentative.html @@ -71,9 +71,9 @@ </style> </template> -<template data-name="Local shadowing cyclic outer local --x "> +<template data-name="Local shadowing cyclic outer local --x"> <style> - /* The locals --x and --y are in a cycle in --f(). */ + /* The locals --x and --y are in a cycle within --f(). */ @function --f() { --x: var(--y); --y: var(--x); @@ -90,6 +90,22 @@ </style> </template> +<template data-name="Argument shadowing cyclic outer local --x"> + <style> + @function --f() { + --x: var(--x); /* Cycle */ + result: --g(10px); + } + @function --g(--x) { + result: var(--x); + } + #target { + --actual: --f(); + --expected: 10px; + } + </style> +</template> + <template data-name="Arguments shadowing cyclic properties"> <style> @function --f(--x, --y) { @@ -287,6 +303,23 @@ </style> </template> +<template data-name="Cycle through local, other function, fallback in function"> + <style> + @function --f() { + --a: --g(); + result: var(--a, PASS); + } + + @function --g() { + result: var(--a); + } + #target { + --actual: --f(); + --expected: PASS; + } + </style> +</template> + <template data-name="Cycle through various variables and other functions"> <style> @function --f() { @@ -332,6 +365,44 @@ </style> </template> +<template data-name="Cyclic outer --b shadows custom property"> + <style> + @function --f() { + --b: var(--b); + --a: --g(); + result: var(--a); + } + + @function --g(--a: var(--b)) { + result: var(--a, PASS); + } + #target { + --b: FAIL; + --actual: --f(); + --expected: PASS; + } + </style> +</template> + +<template data-name="Locals are function specific"> + <style> + @function --f() { + --a: --g(); + result: var(--a); + } + + @function --g() { + --a: 10px; + result: var(--a); + } + #target { + /* Nothing is in a cycle here. */ + --actual: --f(); + --expected: 10px; + } + </style> +</template> + <script> test_all_templates(); </script> diff --git a/tests/wpt/tests/css/css-mixins/dashed-function-eval.html b/tests/wpt/tests/css/css-mixins/dashed-function-eval.html index 604523b8dc8..872180d8997 100644 --- a/tests/wpt/tests/css/css-mixins/dashed-function-eval.html +++ b/tests/wpt/tests/css/css-mixins/dashed-function-eval.html @@ -5,7 +5,9 @@ <script src="/resources/testharnessreport.js"></script> <script src="resources/utils.js"></script> -<div id=target></div> +<div id=parent> + <div id=target></div> +</div> <div id=main></div> <!-- To pass, a test must produce matching computed values for --actual and @@ -964,6 +966,322 @@ </style> </template> +<!-- CSS-wide keywords --> + +<!-- initial --> + +<template data-name="Local variable with initial keyword"> + <style> + @function --f(--x: FAIL1) { + --x: FAIL2; + --x: initial; + result: var(--x); + } + #target { + --actual: --f(PASS); + --expected: PASS; + } + </style> +</template> + +<template data-name="Local variable with initial keyword, defaulted"> + <style> + @function --f(--x: PASS) { + --x: FAIL; + --x: initial; + result: var(--x); + } + #target { + --actual: --f(); + --expected: PASS; + } + </style> +</template> + +<template data-name="Local variable with initial keyword, no value via IACVT-capture"> + <style> + @function --f(--x) { + --x: FAIL; + --x: initial; + result: var(--x, PASS); + } + #target { + --actual: --f(var(--unknown)); + --expected: PASS; + } + </style> +</template> + +<template data-name="Default with initial keyword"> + <style> + @function --f(--x: initial) { + result: var(--x, PASS); + } + #target { + --actual: --f(); + --expected: PASS; + } + </style> +</template> + +<template data-name="initial appearing via fallback"> + <style> + @function --f(--x: PASS) { + --x: var(--unknown, initial); + result: var(--x); + } + #target { + --actual: --f(); + --expected: PASS; + } + </style> +</template> + +<!-- inherit --> + +<template data-name="Local variable with inherit keyword"> + <style> + @function --f(--x: FAIL1) { + --x: FAIL2; + --x: inherit; + result: var(--x); + } + #target { + --x: PASS; + --actual: --f(FAIL3); + --expected: PASS; + } + </style> +</template> + +<template data-name="Local variable with inherit keyword (nested)"> + <style> + @function --f(--x: FAIL1) { + --x: FAIL2; + --x: inherit; + result: var(--x); + } + @function --g(--x) { + --x: PASS; + result: --f(FAIL3); + } + #target { + --actual: --g(FAIL4); + --expected: PASS; + } + </style> +</template> + +<template data-name="Inheriting an invalid value"> + <style> + @function --f(--x) { + --x: FAIL2; + --x: inherit; + result: var(--x, PASS); + } + @function --g() { + --x: var(--unknown); + result: --f(FAIL1); + } + #target { + --actual: --g(); + --expected: PASS; + } + </style> +</template> + +<template data-name="Default with inherit keyword"> + <style> + @function --f(--x: inherit) { + result: var(--x); + } + #target { + --x: PASS1; + --actual: --f() --f(PASS2); + --expected: PASS1 PASS2; + } + </style> +</template> + +<template data-name="Default with inherit keyword (nested)"> + <style> + @function --f(--x: inherit) { + result: var(--x); + } + @function --g() { + --x: PASS1; + result: --f() --f(PASS2); + } + #target { + --x: FAIL; + --actual: --g(); + --expected: PASS1 PASS2; + } + </style> +</template> + +<!-- Other CSS-wide keywords (invalid in locals) --> + +<template data-name="Local with the unset keyword"> + <style> + @function --f() { + --x: unset; + result: var(--x, PASS); + } + #target { + --actual: --f(); + --expected: PASS; + } + </style> +</template> + +<template data-name="Local with the revert keyword"> + <style> + @function --f() { + --x: revert; + result: var(--x, PASS); + } + #target { + --actual: --f(); + --expected: PASS; + } + </style> +</template> + +<template data-name="Local with the revert-layer keyword"> + <style> + @function --f() { + --x: revert-layer; + result: var(--x, PASS); + } + #target { + --actual: --f(); + --expected: PASS; + } + </style> +</template> + +<!-- Keywords in 'result' descriptor --> + +<template data-name="initial keyword left unresolved on result descriptor"> + <style> + @function --f() { + result: initial; + } + #target { + --tmp: --f(); + --actual: var(--tmp, PASS); + --expected: PASS; + } + </style> +</template> + +<template data-name="inherit keyword left unresolved on result descriptor"> + <style> + @function --f() { + result: inherit; + } + #parent { + --tmp: PASS; + } + #target { + --tmp: --f(); + --actual: var(--tmp, FAIL); + --expected: PASS; + } + </style> +</template> + +<template data-name="unset keyword left unresolved on result descriptor"> + <style> + @function --f() { + result: unset; + } + #parent { + --tmp: PASS; + } + #target { + --tmp: --f(); + --actual: var(--tmp, FAIL); + --expected: PASS; + } + </style> +</template> + +<template data-name="revert keyword left unresolved on result descriptor"> + <style> + @function --f() { + result: revert; + } + #parent { + --tmp: PASS; + } + #target { + --tmp: --f(); + --actual: var(--tmp, FAIL); + --expected: PASS; + } + </style> +</template> + +<template data-name="revert-layer keyword left unresolved on result descriptor"> + <style> + @function --f() { + result: revert-layer; + } + @layer one { + #target { + --tmp: PASS; + } + } + @layer two { + #target { + --tmp: --f(); + --actual: var(--tmp, FAIL); + --expected: PASS; + } + } + </style> +</template> + +<template data-name="Keyword can be returned from function into local variable"> + <style> + @function --f() { + result: initial; + } + @function --g(--x: PASS) { + --x: FAIL1; + --x: --f(); + result: var(--x, FAIL2); + } + #target { + --actual: --g(); + --expected: PASS; + } + </style> +</template> + + +<template data-name="Can not return CSS-wide keyword as length"> + <style> + @function --f() returns <length> { + result: revert-layer; + } + @layer one { + #target { + --tmp: FAIL; + } + } + @layer two { + #target { + --tmp: --f(); + --actual: var(--tmp, PASS); + --expected: PASS; + } + } + </style> +</template> + <script> test_all_templates(); </script> diff --git a/tests/wpt/tests/css/css-mixins/function-attr.html b/tests/wpt/tests/css/css-mixins/function-attr.html new file mode 100644 index 00000000000..69cb69723ff --- /dev/null +++ b/tests/wpt/tests/css/css-mixins/function-attr.html @@ -0,0 +1,247 @@ +<!DOCTYPE html> +<title>Custom Functions: attr(), url(), tainting</title> +<link rel="help" href="https://drafts.csswg.org/css-mixins-1/#using-custom-functions"> +<link rel="help" href="https://drafts.csswg.org/css-values-5/#attr-security"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/utils.js"></script> + +<style> + #parent { + list-style-image: url(parent); + } +</style> +<div id=parent> + <div id=actual data-42="42px" data-cat="url(cat.png)"></div> + <div id=expected></div> +</div> +<main id=main></main> + +<!-- + Each <template> represents a test, and is executed by comparing the computed + values of #actual and #expected. +--> +<script> + // Only these properties are actually compared. + let relevant_properties = ['list-style-image', 'width']; +</script> + +<template data-name="Return untyped url() from function"> + <style> + @function --f() { + result: url(img.png); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(img.png); } + </style> +</template> + +<template data-name="Return untyped url() from function, quoted"> + <style> + @function --f() { + result: url("img.png"); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url("img.png"); } + </style> +</template> + +<template data-name="Return typed url() from function"> + <style> + @function --f() returns <url> { + result: url(img.png); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(img.png); } + </style> +</template> + +<template data-name="Return typed url() from function, quoted"> + <style> + @function --f() returns <url> { + result: url("img.png"); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url("img.png"); } + </style> +</template> + +<!-- Permitted uses of attr() --> + +<template data-name="Return attr(type(<length>)) from untyped function"> + <style> + @function --f() { + result: attr(data-42 type(<length>)); + } + #actual { width: --f(); } + #expected { width: 42px; } + </style> +</template> + +<template data-name="Return attr(type(<length>)) from typed function"> + <style> + @function --f() returns <length> { + result: attr(data-42 type(<length>)); + } + #actual { width: --f(); } + #expected { width: 42px; } + </style> +</template> + +<template data-name="Return attr(type(*)) from typed function"> + <style> + @function --f() returns <length> { + result: attr(data-42 type(*)); + } + #actual { width: --f(); } + #expected { width: 42px; } + </style> +</template> + +<template data-name="Return attr(type(*)) from untyped function"> + <style> + @function --f() { + result: attr(data-42 type(*)); + } + #actual { width: --f(); } + #expected { width: 42px; } + </style> +</template> + +<template data-name="attr() in default parameter value"> + <style> + @function --f(--a : attr(data-42 type(*))) { + result: var(--a); + } + #actual { width: --f(); } + #expected { width: 42px; } + </style> +</template> + +<template data-name="attr() in local variable"> + <style> + @function --f() { + --l: attr(data-42 type(*)); + result: var(--l); + } + #actual { width: --f(); } + #expected { width: 42px; } + </style> +</template> + +<!-- Invalid uses of attr() --> + +<template data-name="Returned url() is attr-tainted"> + <style> + @function --f() { + result: attr(data-cat type(*)); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<template data-name="Returned url() is attr-tainted, typed attr()"> + <style> + @function --f() { + result: attr(data-cat type(<url>)); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<template data-name="Returned url() is attr-tainted, typed return"> + <style> + @function --f() returns <url> { + result: attr(data-cat type(*)); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<template data-name="Returned url() is attr-tainted, local"> + <style> + @function --f() returns <url> { + --local: attr(data-cat type(*)); + result: var(--local); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<template data-name="Returned url() is attr-tainted, argument"> + <style> + @function --f(--arg) returns <url> { + result: var(--arg); + } + #actual { list-style-image: --f(attr(data-cat type(*))); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<template data-name="Returned url() is attr-tainted, default"> + <style> + @function --f(--arg: attr(data-cat type(*))) { + result: var(--arg); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<template data-name="Returned url() is attr-tainted, parent stack frame"> + <style> + @function --f() { + --x: attr(data-cat type(*)); + result: --g(); + } + @function --g() { + result: var(--x); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<template data-name="Returned url() is attr-tainted, initial"> + <style> + @function --f(--x: attr(data-cat type(*))) { + --x: initial; + result: --g(); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<template data-name="Returned url() is attr-tainted, inherit"> + <style> + @function --f() { + --x: attr(data-cat type(*)); + result: --g(); + } + @function --g() { + --x: inherit; + result: var(--x); + } + #actual { list-style-image: --f(); } + #expected { list-style-image: url(parent); } + </style> +</template> + +<script> + let templates = document.querySelectorAll('template'); + for (let template of templates) { + test((t) => { + t.add_cleanup(() => main.replaceChildren()); + main.append(template.content.cloneNode(true)); + for (let p of relevant_properties) { + assert_equals(getComputedStyle(actual).getPropertyValue(p), + getComputedStyle(expected).getPropertyValue(p)); + } + }, template.getAttribute('data-name')); + } +</script> diff --git a/tests/wpt/tests/css/css-mixins/function-in-media.html b/tests/wpt/tests/css/css-mixins/function-in-media.html new file mode 100644 index 00000000000..c5cc9dd53cb --- /dev/null +++ b/tests/wpt/tests/css/css-mixins/function-in-media.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<title>Custom Functions: @function inside @media</title> +<link rel="help" href="https://drafts.csswg.org/css-mixins-1"> +<link rel="help" href="https://drafts.csswg.org/css-conditional-3/#at-media"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + iframe { + width: 50px; + height: 50px; + } +</style> +<iframe id="iframe" srcdoc=" + <div id=target></div> + <style> + @media (width >= 50px) { + @function --f() { result: 50; } + } + @media (width >= 100px) { + @function --f() { result: 100; } + } + #target { + --actual: --f(); + } + </style> +"></iframe> + +<script> + function waitForLoad(w) { + return new Promise(resolve => w.addEventListener('load', resolve)); + } + + promise_test(async () => { + await waitForLoad(window); + const target = iframe.contentDocument.querySelector('#target'); + let actualValue = () => getComputedStyle(target).getPropertyValue('--actual'); + + assert_equals(actualValue(), '50', '--actual before resize'); + iframe.style.width = '100px'; + assert_equals(actualValue(), '100', '--actual after resize'); + iframe.style.width = ''; + assert_equals(actualValue(), '50', '--actual after resizing back to original'); + }); +</script> diff --git a/tests/wpt/tests/css/css-mixins/function-invalidation.html b/tests/wpt/tests/css/css-mixins/function-invalidation.html new file mode 100644 index 00000000000..925895d7138 --- /dev/null +++ b/tests/wpt/tests/css/css-mixins/function-invalidation.html @@ -0,0 +1,76 @@ +<!DOCTYPE html> +<title>CSS Custom Functions: Invalidation when @function rules change</title> +<link rel="help" href="https://drafts.csswg.org/css-mixins-1/#cssom"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<!-- This stylesheet will be mutated during testing. --> +<style id=mutable_style> + @function --f() { + result: 10px; + } +</style> + +<style> + #outer { + width: 42px; + } + #target { + width: --f(); + } +</style> + +<div id=outer> + <div> + <div id=target> + </div> + </div> +<div> + +<script> + // Adds a cleanup step to recreate `original_element` in-place + // (with the original text). + function add_cleanup(t, original_element) { + let original_text = original_element.textContent; + t.add_cleanup(() => { + let new_element = document.createElement('style'); + new_element.setAttribute('id', 'mutable_style'); + new_element.textContent = original_text; + original_element.parentElement.replaceChild(new_element, original_element); + }); + } + + test(t => { + add_cleanup(t, mutable_style); + let sheet = mutable_style.sheet; + assert_equals(getComputedStyle(target).width, '10px'); + sheet.insertRule('@function --f() { result: 20px; }', 1); + assert_equals(getComputedStyle(target).width, '20px'); + }, 'Appending a rule'); + + test(t => { + add_cleanup(t, mutable_style); + let sheet = mutable_style.sheet; + assert_equals(getComputedStyle(target).width, '10px'); + sheet.insertRule('@function --f() { result: 20px; }', 0); + assert_equals(getComputedStyle(target).width, '10px'); // No change. + }, 'Prepending a rule'); + + test(t => { + add_cleanup(t, mutable_style); + let sheet = mutable_style.sheet; + assert_equals(getComputedStyle(target).width, '10px'); + sheet.deleteRule(0); + assert_equals(getComputedStyle(target).width, '42px'); + }, 'Deleting a rule'); + + test(t => { + add_cleanup(t, mutable_style); + let sheet = mutable_style.sheet; + assert_equals(getComputedStyle(target).width, '10px'); + sheet.insertRule('@function --f() { result: 20px; }', 0); + assert_equals(getComputedStyle(target).width, '10px'); + sheet.deleteRule(1); + assert_equals(getComputedStyle(target).width, '20px'); + }, 'Prepending a rule, then deleting last'); +</script> diff --git a/tests/wpt/tests/css/css-mixins/function-layer.html b/tests/wpt/tests/css/css-mixins/function-layer.html new file mode 100644 index 00000000000..aa01a48dc46 --- /dev/null +++ b/tests/wpt/tests/css/css-mixins/function-layer.html @@ -0,0 +1,119 @@ +<!DOCTYPE html> +<title>Custom Functions: @function within @layer</title> +<link rel="help" href="https://drafts.csswg.org/css-mixins-1/#conditional-rules"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/utils.js"></script> + +<div id=target></div> +<div id=main></div> + +<!-- To pass, a test must produce matching computed values for --actual and + --expected on #target. --> + +<template data-name="Single function within anonymous layer"> + <style> + @layer { + @function --f() { result: 1px; } + } + #target { + --actual: --f(); + --expected: 1px; + } + </style> +</template> + +<template data-name="Last anonymous layer wins"> + <style> + @layer { + @function --f() { result: 1px; } + } + @layer { + @function --f() { result: 2px; } + } + #target { + --actual: --f(); + --expected: 2px; + } + </style> +</template> + +<template data-name="Unlayered styles win"> + <style> + @layer { + @function --f() { result: 1px; } + } + @layer { + @function --f() { result: 2px; } + } + @function --f() { result: 3px; } + #target { + --actual: --f(); + --expected: 3px; + } + </style> +</template> + +<template data-name="Unlayered styles win, reverse"> + <style> + @function --f() { result: 3px; } + @layer { + @function --f() { result: 1px; } + } + @layer { + @function --f() { result: 2px; } + } + #target { + --actual: --f(); + --expected: 3px; + } + </style> +</template> + +<template data-name="Single named layer"> + <style> + @layer base { + @function --f() { result: 10px; } + } + #target { + --actual: --f(); + --expected: 10px; + } + </style> +</template> + +<template data-name="Named layers"> + <style> + @layer base { + @function --f() { result: 10px; } + } + @layer theme { + @function --f() { result: 20px; } + } + #target { + --actual: --f(); + --expected: 20px; + } + </style> +</template> + +<template data-name="Named layers, reordered"> + <style> + @layer theme, base; + + @layer base { + @function --f() { result: 10px; } /* Winner */ + } + @layer theme { + @function --f() { result: 20px; } + } + #target { + --actual: --f(); + --expected: 10px; + } + </style> +</template> + +<script> + test_all_templates(); +</script> diff --git a/tests/wpt/tests/css/css-mixins/function-shadow.html b/tests/wpt/tests/css/css-mixins/function-shadow.html index 39883def4c6..b9db932b29b 100644 --- a/tests/wpt/tests/css/css-mixins/function-shadow.html +++ b/tests/wpt/tests/css/css-mixins/function-shadow.html @@ -241,6 +241,34 @@ </template> </div> +<div data-name="Function with same name in different scopes"> + <template shadowrootmode=open> + <style> + @function --a() { + result: 24px; + } + @function --b() { + result: --a(); /* 24px */ + } + </style> + <div> + <template shadowrootmode=open> + <style> + @function --a() { + result: --b(); /* Calls --b() in outer scope. */ + } + #target { + /* Nothing is in a cycle here. */ + --actual: --a(); + --expected: 24px; + } + </style> + <div id=target></div> + </template> + </div> + </template> +</div> + <script> test_all_shadows(); </script> diff --git a/tests/wpt/tests/css/css-overflow/keyboard-scroll.html b/tests/wpt/tests/css/css-overflow/keyboard-scroll.html new file mode 100644 index 00000000000..ac0b017ccb5 --- /dev/null +++ b/tests/wpt/tests/css/css-overflow/keyboard-scroll.html @@ -0,0 +1,107 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Keyboard scrolling targets the last clicked element</title> +<link rel="help" href=""> +<link rel="author" href="flackr@chromium.org"> +<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/testdriver-actions.js"></script> +<script src="/css/css-scroll-snap/support/common.js"></script> +<script src="/dom/events/scrolling/scroll_support.js"></script> +<style> + .scroller { + overflow: auto; + height: 200px; + border: 1px solid black; + } + .spacer { + height: 200vh; + } +</style> +<body id="body"> +<div class="scroller" id="outer"> + <div class="scroller" id="inner"> + <div id="target"><span>This is the targeted node</span></div> + <div class="spacer"></div> + </div> + <div class="spacer"></div> +</div> +<div class="spacer"></div> +</body> +<script> + +const target = document.getElementById("target"); +const outer = document.getElementById("outer"); +const inner = document.getElementById("inner"); +const scrollTargets = [document, outer, inner]; + +function raf() { + return new Promise((resolve) => { + requestAnimationFrame(resolve); + }); +} + +async function getKeyboardScrollingElement(test, clickTarget, onclick) { + const click_promise = waitForEvent("click", test, clickTarget); + await test_driver.click(clickTarget); + await click_promise; + await onclick(); + await raf(); + const scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scrollTargets); + await keyPress(document.body, "ArrowDown"); + return scrollEndPromise; +} + +function friendlyName(node) { + if (node == document) return "document"; + if (node.id) return `#${node.id}`; + return `<${node.tagName}>`; +} + +async function resetScroll() { + for (const scrollTarget of scrollTargets) { + const scroller = scrollTarget.scrollingElement || scrollTarget; + scroller.scrollTo(0, 0); + } + return raf(); +} + +promise_test(async (test) => { + test.add_cleanup(resetScroll); + const scrolled = await getKeyboardScrollingElement(test, target, async () => { + target.remove(); + test.add_cleanup(() => { + inner.insertBefore(target, inner.firstChild); + }); + }); + assert_equals(friendlyName(scrolled), "#inner"); +}, "Keyboard scrolling scrolls the scroller when clicked target is removed"); + +// Notably removing all children is a different code path than removing +// a single child. This is a regression test for https://crbug.com/40941145. +promise_test(async (test) => { + test.add_cleanup(resetScroll); + const scrolled = await getKeyboardScrollingElement(test, target.firstElementChild, async () => { + const previous = target.innerHTML; + target.innerHTML = ""; + test.add_cleanup(() => { + target.innerHTML = previous; + }); + }); + assert_equals(friendlyName(scrolled), "#inner"); +}, "Keyboard scrolling scrolls the scroller when clicked children are removed"); + +promise_test(async (test) => { + test.add_cleanup(resetScroll); + const scrolled = await getKeyboardScrollingElement(test, target, async () => { + inner.remove(); + test.add_cleanup(() => { + outer.insertBefore(inner, outer.firstChild); + }); + }); + assert_equals(friendlyName(scrolled), "#outer"); +}, "Keyboard scrolling scrolls the next nearest scroller if the clicked scroller is removed"); + +</script> diff --git a/tests/wpt/tests/css/css-overflow/scroll-marker-with-content-visibility-hidden-ancestor-crash.html b/tests/wpt/tests/css/css-overflow/scroll-marker-with-content-visibility-hidden-ancestor-crash.html new file mode 100644 index 00000000000..451e9e9709a --- /dev/null +++ b/tests/wpt/tests/css/css-overflow/scroll-marker-with-content-visibility-hidden-ancestor-crash.html @@ -0,0 +1,69 @@ +<!doctype html> +<html class="reftest-wait"> +<meta charset="utf-8"> +<title>::scroll-markers with content-visibility: hidden ancestors, getBoundingClientRect crash</title> +<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-marker-pseudo"> +<link rel="help" href="https://crbug.com/398717539"> +<link rel="author" href="mailto:vmpstr@chromium.org"> +<link rel="assert" content="Test should not crash when interacting with c-v hidden elements with scroll markers"> +<style> +#scroller { + position: relative; + width: 500px; + height: 200px; + overflow: auto; + scroll-marker-group: after; + columns: 1; + + &::scroll-marker-group { + height: 20px; + width: 200px; + } +} + +.wrapper { + height: 100%; + content-visibility: hidden; +} + +.item { + width: 100%; + height: 100%; + &::scroll-marker { + display: inline-block; + content: ""; + width: 10px; + height: 10px; + border: 1px solid black; + border-radius: 50%; + } + + &::scroll-marker:target-current { + background: blue; + } +} + +</style> + +<div id=scroller> + <div id=w1 class=wrapper><div id=e1 class=item>item 1</div></div> + <div class=wrapper><div class=item>item 2</div></div> + <div class=wrapper><div class=item>item 3</div></div> + <div class=wrapper><div class=item>item 4</div></div> + <div class=wrapper><div class=item>item 5</div></div> +</div> + +<script> +onload = requestAnimationFrame(() => requestAnimationFrame(() => { + e1.getBoundingClientRect(); + + requestAnimationFrame(() => { + w1.style.contentVisibility = "visible"; + requestAnimationFrame(() => { + w1.style.contentVisibility = "hidden"; + + requestAnimationFrame(() => { document.documentElement.className = "" }); + }); + }); +})); +</script> diff --git a/tests/wpt/tests/css/css-overflow/scroll-marker-with-content-visibility-hidden-crash.html b/tests/wpt/tests/css/css-overflow/scroll-marker-with-content-visibility-hidden-crash.html new file mode 100644 index 00000000000..7e6fee214ca --- /dev/null +++ b/tests/wpt/tests/css/css-overflow/scroll-marker-with-content-visibility-hidden-crash.html @@ -0,0 +1,65 @@ +<!doctype html> +<html class="reftest-wait"> +<meta charset="utf-8"> +<title>::scroll-markers with content-visibility: hidden ancestors, getBoundingClientRect crash</title> +<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-marker-pseudo"> +<link rel="help" href="https://crbug.com/398717539"> +<link rel="author" href="mailto:vmpstr@chromium.org"> +<link rel="assert" content="Test should not crash when interacting with c-v hidden elements with scroll markers"> +<style> +#scroller { + position: relative; + width: 500px; + height: 200px; + overflow: auto; + scroll-marker-group: after; + columns: 1; + + &::scroll-marker-group { + height: 20px; + width: 200px; + } +} + +.item { + content-visibility: hidden; + width: 100%; + height: 100%; + &::scroll-marker { + display: inline-block; + content: ""; + width: 10px; + height: 10px; + border: 1px solid black; + border-radius: 50%; + } + + &::scroll-marker:target-current { + background: blue; + } +} + +</style> + +<div id=scroller> + <div id=e1 class=item>item 1</div> + <div class=item>item 2</div> + <div class=item>item 3</div> + <div class=item>item 4</div> + <div class=item>item 5</div> +</div> + +<script> +onload = requestAnimationFrame(() => requestAnimationFrame(() => { + e1.getBoundingClientRect(); + + requestAnimationFrame(() => { + e1.style.contentVisibility = "visible"; + requestAnimationFrame(() => { + e1.style.contentVisibility = "hidden"; + + requestAnimationFrame(() => { document.documentElement.className = "" }); + }); + }); +})); +</script> diff --git a/tests/wpt/tests/css/css-scoping/host-has-internal-001.tentative.html b/tests/wpt/tests/css/css-scoping/host-has-internal-001.html index c2082de0ac3..c2082de0ac3 100644 --- a/tests/wpt/tests/css/css-scoping/host-has-internal-001.tentative.html +++ b/tests/wpt/tests/css/css-scoping/host-has-internal-001.html diff --git a/tests/wpt/tests/css/css-scoping/host-has-internal-002.tentative.html b/tests/wpt/tests/css/css-scoping/host-has-internal-002.html index 217ed9596c4..217ed9596c4 100644 --- a/tests/wpt/tests/css/css-scoping/host-has-internal-002.tentative.html +++ b/tests/wpt/tests/css/css-scoping/host-has-internal-002.html diff --git a/tests/wpt/tests/css/css-scoping/host-has-internal-003.tentative.html b/tests/wpt/tests/css/css-scoping/host-has-internal-003.html index 9c0a7248345..9c0a7248345 100644 --- a/tests/wpt/tests/css/css-scoping/host-has-internal-003.tentative.html +++ b/tests/wpt/tests/css/css-scoping/host-has-internal-003.html diff --git a/tests/wpt/tests/css/css-scroll-snap/input/snap-area-overflow-boundary-viewport-covering.tentative.html b/tests/wpt/tests/css/css-scroll-snap/input/snap-area-overflow-boundary-viewport-covering.tentative.html index fe2c38acda7..1c6caf224ac 100644 --- a/tests/wpt/tests/css/css-scroll-snap/input/snap-area-overflow-boundary-viewport-covering.tentative.html +++ b/tests/wpt/tests/css/css-scroll-snap/input/snap-area-overflow-boundary-viewport-covering.tentative.html @@ -77,6 +77,7 @@ const cleanup = () => { }; promise_test(async t => { + await waitForCompositorCommit(); t.add_cleanup(cleanup); scroller.scrollTo(0, 0); assert_equals(scroller.scrollTop, 0, "verify test pre-condition"); @@ -117,6 +118,7 @@ promise_test(async t => { }, "Keyboard scrolling with vertical snap-area overflow"); promise_test(async t => { + await waitForCompositorCommit(); scroller.scrollTo(0, 0); assert_equals(scroller.scrollTop, 0, "verify test pre-condition"); diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-002.tentative.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-002.html index 2b906985da1..1d1a93072f2 100644 --- a/tests/wpt/tests/css/css-sizing/stretch/block-height-002.tentative.html +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-002.html @@ -12,10 +12,9 @@ font: 20px/1 Ahem; } </style> -<p>This test asserts the behavior seemingly agreed upon through - https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This - is unlikely to be the final specified behavior, hence the test is marked - tentative.</p> +<p>These tests assert the behavior described at + https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601 +</p> <main> <!-- Example 9 diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-003.tentative.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-003.html index a469f8d5df2..a4de8d777ce 100644 --- a/tests/wpt/tests/css/css-sizing/stretch/block-height-003.tentative.html +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-003.html @@ -14,10 +14,9 @@ </style> <!-- -<p>This test asserts the behavior seemingly agreed upon through - https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This - is unlikely to be the final specified behavior, hence the test is marked - tentative.</p> +<p>These tests assert the behavior described at + https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601 +</p> --> <div class="surrounding-block"></div> diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-004.tentative.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-004.html index 1aa12ca0dcc..11013fbefa7 100644 --- a/tests/wpt/tests/css/css-sizing/stretch/block-height-004.tentative.html +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-004.html @@ -6,7 +6,7 @@ <script src='/resources/testharnessreport.js'></script> <script src="/resources/check-layout-th.js"></script> <meta name="assert" - content="demonstrate the behavior described in https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2422165458"> + content="margins of the stretched element are accounted for correctly in a variety of scenarios, mostly around siblings"> <style> .outer { @@ -20,17 +20,11 @@ height: stretch; margin: 10px; } - - p { - margin-top: 20px; - margin-bottom: 0px; - } </style> -<p>This test asserts the behavior seemingly agreed upon through - https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This - is unlikely to be the final specified behavior, hence the test is marked - tentative.</p> +<h2>These tests assert the behavior described at + https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601 +</h2> <p>Basic case: treat margins as 0.</p> <div class="outer"> @@ -40,54 +34,55 @@ </div> <p> - When resolving stretch, don't treat margins as 0 if there is a sibling on that - side. (Hand-wavy: we don't collapse margins through siblings for the purpose - of resolving stretched heights.)</p> -<p> - Then when actually doing margin collapsing, .inner's margins DON'T collapse - with .outer's because of the usual rule that margins don't collapse through - new formatting contexts. + When resolving stretch treat both block margins as 0 because the parent is + not a BFC and has no top or bottom content edge (i.e. border + padding = 0). + <br>But cyan's margins will not actually collapse through its IFC-siblings so + there is overflow: </p> <div class="outer"> <div style="overflow: hidden"></div> - <div class="inner" style="border: solid cyan;" data-expected-height="80" + <div class="inner" style="border: solid cyan;" data-expected-height="100" data-offset-y="10"> </div> <div style="overflow: hidden"></div> </div> -<p>When resolving stretch, don't treat margins as 0 if there is a sibling on - that side. (Hand-wavy: we don't collapse margins through siblings for the - purpose of resolving stretched heights.)</p> -<p> - Then when actually doing margin collapsing, .inner's margins DO collapse with - .outer's because they collapse through the empty siblings. -</p> <div class="outer"> <div></div> - <div class="inner" style="border: solid blue;" data-expected-height="80" + <div class="inner" style="border: solid blue;" data-expected-height="100" data-offset-y="0"> </div> <div></div> </div> -<p>Only treat the BOTTOM margin as 0. Margins do collapse, so top edges touch. -</p> <div class="outer"> <div></div> - <div class="inner" style="border: solid purple;" data-expected-height="90" + <div class="inner" style="border: solid purple;" data-expected-height="100" data-offset-y="0"> </div> </div> -<p>Only treat the TOP margin as 0. Margins do collapse, so top edges touch.</p> <div class="outer"> - <div class="inner" style="border: solid lime;" data-expected-height="90" + <div class="inner" style="border: solid lime;" data-expected-height="100" data-offset-y="0"> </div> <div></div> </div> +<p>Parent has non-zero bottom border, so only top margin is treated as 0:</p> +<div class="outer" style="border-bottom: 5px dashed blue;"> + <div class="inner" style="border: solid brown;" data-expected-height="90" + data-offset-y="0"> + </div> +</div> + +<p>Parent has non-zero top padding so only bottom margin is treated as 0:</p> +<div class="outer" style="padding-top: 5px;"> + <div class="inner" style="border: solid darkgreen;" data-expected-height="90" + data-offset-y="15"> <!-- 15 = 10px top margin + parent's padding--> + </div> +</div> + <p>Account for the margins when parent establishes a BFC.</p> <div class="outer" style="display: flow-root;"> <div class="inner" style="border: solid orange;" data-expected-height="80" diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-005.tentative.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-005.html index 28756c339f3..d15ca89079e 100644 --- a/tests/wpt/tests/css/css-sizing/stretch/block-height-005.tentative.html +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-005.html @@ -6,7 +6,7 @@ <script src='/resources/testharnessreport.js'></script> <script src="/resources/check-layout-th.js"></script> <meta name="assert" - content="preceding floats don't prevent margin adjoiningness for stretch sizing purposes"> + content="stretch sizing treating margins as 0 isn't affected by preceding floats"> <style> .outer { @@ -22,20 +22,12 @@ height: 30px; background: skyblue; } - - p { - margin-top: 20px; - margin-bottom: 0px; - } </style> -<p>This test asserts the behavior seemingly agreed upon through - https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This - is unlikely to be the final specified behavior, hence the test is marked - tentative.</p> +<p>These tests assert the behavior described at + https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601 +</p> -<p>New BFC fits next to float, so top margins will collapse, so we want the - stretched height to match .outer's height.</p> <div class="outer"> <div class="float"></div> <div @@ -44,8 +36,6 @@ </div> </div> -<p>New BFC does not fit next to float, so margins DON'T collapse, but for - simplicity we still ignore margins when stretch sizing</p> <div class="outer"> <div class="float"></div> <div @@ -54,8 +44,6 @@ </div> </div> -<p>In-flow child overlaps the float, so margins DO collapse, so we want the - stretched height to match .outer's height.</p> <div class="outer"> <div class="float"></div> <div @@ -64,8 +52,6 @@ </div> </div> -<p>In-flow child clears the float, so margins DON'T collapse, but for - simplicity we still ignore margins when stretch sizing</p> <div class="outer"> <div class="float"></div> <div diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-006.tentative.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-006.html index a25c415b87f..12968460751 100644 --- a/tests/wpt/tests/css/css-sizing/stretch/block-height-006.tentative.html +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-006.html @@ -16,13 +16,6 @@ } </style> -<!-- -<p>This test asserts the behavior seemingly agreed upon through - https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This - is unlikely to be the final specified behavior, hence the test is marked - tentative.</p> - --> - <p>Test passes if there is a filled green square and <strong>no red</strong>. </p> <div id="reference-overlapped-red"></div> diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-007.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-007.html new file mode 100644 index 00000000000..aad994baad3 --- /dev/null +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-007.html @@ -0,0 +1,126 @@ +<!DOCTYPE html> +<link rel="help" + href="https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing"> +<meta name="assert" + content="margins of the stretched element are accounted for correctly in various writing mode combinations and presence of borders"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> + +<style> + .container { + width: 50px; + height: 50px; + margin: 3px; + background: magenta; + position: relative; + } + + .child { + margin: 1px 3px 5px 7px; + background: cyan; + font-size: 10px; + } +</style> + +<div id="log"></div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="49" + data-offset-y="1" style="width: 20px; height: stretch;">1</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="1" style="width: stretch; height: 20px;">2</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="50" + data-offset-y="0" style="width: 20px; height: stretch;">3</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="0" style="width: stretch; height: 20px;">4</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="49" + data-offset-y="1" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">5</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="1" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">6</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="50" + data-offset-y="0" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">7</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="0" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">8</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="49" + data-offset-y="1" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">9</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="1" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">10</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="50" + data-offset-y="0" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">11</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="0" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">12</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="49" + data-offset-y="1" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">13</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="1" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">14</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="50" + data-offset-y="0" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">15</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="0" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">16</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="49" + data-offset-y="1" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">17</div> +</div> +<div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="1" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">18</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="50" + data-offset-y="0" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">19</div> +</div> +<div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="40" data-expected-height="20" + data-offset-y="0" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">20</div> +</div> + +<script> + checkLayout('.child'); +</script> diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-008.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-008.html new file mode 100644 index 00000000000..52ed193fc43 --- /dev/null +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-008.html @@ -0,0 +1,608 @@ +<!DOCTYPE html> +<link rel="help" + href="https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing"> +<meta name="assert" + content="margins of the stretched element are accounted for correctly in more writing mode combinations and presence of borders"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> + +<style> + .container { + width: 50px; + height: 50px; + margin: 3px; + background: magenta; + position: relative; + } + + .child { + margin: 1px 3px 5px 7px; + background: cyan; + font-size: 10px; + } +</style> + +<div id="log"></div> +<main id="main" style="display: flex; gap: 15px;"> + <div>vertical-rl + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: horizontal-tb; width: 20px; height: stretch;">1 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: horizontal-tb; width: stretch; height: 20px;">2 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: horizontal-tb; width: 20px; height: stretch;">3 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: horizontal-tb; width: stretch; height: 20px;">4 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">5 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">6 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">7 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">8 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">9 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">10 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">11 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">12 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">13 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">14 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">15 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">16 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">17 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">18 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">19 + </div> + </div> + </div> + <div style="writing-mode: vertical-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">20 + </div> + </div> + </div> + </div> + <div>vertical-lr + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: horizontal-tb; width: 20px; height: stretch;">21 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: horizontal-tb; width: stretch; height: 20px;">22 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: horizontal-tb; width: 20px; height: stretch;">23 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: horizontal-tb; width: stretch; height: 20px;">24 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">25 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">26 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">27 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">28 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">29 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">30 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">31 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">32 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">33 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">34 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">35 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">36 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">37 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">38 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">39 + </div> + </div> + </div> + <div style="writing-mode: vertical-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">40 + </div> + </div> + </div> + </div> + <div>sideways-rl + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: horizontal-tb; width: 20px; height: stretch;">41 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: horizontal-tb; width: stretch; height: 20px;">42 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: horizontal-tb; width: 20px; height: stretch;">43 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: horizontal-tb; width: stretch; height: 20px;">44 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">45 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">46 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">47 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">48 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">49 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">50 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">51 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">52 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">53 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">54 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">55 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">56 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">57 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">58 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">59 + </div> + </div> + </div> + <div style="writing-mode: sideways-rl;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">60 + </div> + </div> + </div> + </div> + <div>sideways-lr + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: horizontal-tb; width: 20px; height: stretch;">61 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: horizontal-tb; width: stretch; height: 20px;">62 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: horizontal-tb; width: 20px; height: stretch;">63 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: horizontal-tb; width: stretch; height: 20px;">64 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">65 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">66 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-rl; width: 20px; height: stretch;">67 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: vertical-rl; width: stretch; height: 20px;">68 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">69 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">70 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: vertical-lr; width: 20px; height: stretch;">71 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: vertical-lr; width: stretch; height: 20px;">72 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">73 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">74 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-rl; width: 20px; height: stretch;">75 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: sideways-rl; width: stretch; height: 20px;">76 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">77 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-top: 5px solid;"> + <div class="child" data-expected-width="50" data-expected-height="20" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">78 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="20" data-expected-height="44" + style="writing-mode: sideways-lr; width: 20px; height: stretch;">79 + </div> + </div> + </div> + <div style="writing-mode: sideways-lr;"> + <div class="container" style="border-right: 5px solid;"> + <div class="child" data-expected-width="47" data-expected-height="20" + style="writing-mode: sideways-lr; width: stretch; height: 20px;">80 + </div> + </div> + </div> + </div> +</main> + +<script> + checkLayout('.child'); + + // Add direction:rtl (which shouldn't impact the actual resolved + // box sizes that 'stretch' produces), and retest: + for (let container of document.querySelectorAll(".container")) { + container.style.direction = "rtl"; + } + checkLayout('.child'); + +</script> diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-009.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-009.html new file mode 100644 index 00000000000..91c7bc216d0 --- /dev/null +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-009.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<link rel="help" + href="https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/11044"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<meta name="assert" content="margin ignoring works with min-height:stretch"> + +<style> + #reference-overlapped-red { + position: absolute; + background-color: red; + width: 100px; + height: 100px; + z-index: -1; + } +</style> + +<p>Test passes if there is a filled green square and <strong>no red</strong>. +</p> +<div id="reference-overlapped-red"></div> + +<div style="height: 100px;"> + <div + style="width: 100px; min-height: stretch; margin-bottom: 50px; background: green;"> + </div> +</div> diff --git a/tests/wpt/tests/css/css-sizing/stretch/block-height-010.html b/tests/wpt/tests/css/css-sizing/stretch/block-height-010.html new file mode 100644 index 00000000000..9640693a8ef --- /dev/null +++ b/tests/wpt/tests/css/css-sizing/stretch/block-height-010.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<link rel="help" + href="https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/11044"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<meta name="assert" content="margin ignoring works with max-height:stretch"> + +<style> + #reference-overlapped-red { + position: absolute; + background-color: red; + width: 100px; + height: 100px; + z-index: -1; + } +</style> + +<p>Test passes if there is a filled green square and <strong>no red</strong>. +</p> +<div id="reference-overlapped-red"></div> + +<div style="height: 100px;"> + <div + style="width: 100px; height: 500px; max-height: stretch; margin-bottom: 50px; background: green;"> + </div> +</div> diff --git a/tests/wpt/tests/css/css-tables/fixed-layout-2.html b/tests/wpt/tests/css/css-tables/fixed-layout-2.html index 3b7f65feccf..8b805af7669 100644 --- a/tests/wpt/tests/css/css-tables/fixed-layout-2.html +++ b/tests/wpt/tests/css/css-tables/fixed-layout-2.html @@ -58,7 +58,7 @@ let sizeData = { "calc(10px + 100%)": true, "auto": false, "min-content": true, - "max-content": false, + "max-content": true, "fit-content": true, "calc-size(any, 10px + 100%)": true, @@ -69,8 +69,8 @@ let sizeData = { // These are non-standard, expect the most popular behavior among the supporting implementations. "-moz-available": true, "-webkit-fill-available": true, - "intrinsic": false, - "min-intrinsic": false, + "intrinsic": true, + "min-intrinsic": true, }; function checkSize(size, allowsFixed) { @@ -105,11 +105,11 @@ for (let [size, allowsFixed] of Object.entries(sizeData)) { if (CSS.supports("width", size)) { checkSize(size, allowsFixed); - // calc-size() should have the same behavior as its basis. + // calc-size() should trigger fixed table layout. // https://drafts.csswg.org/css-values-5/#calc-size let calcSize = "calc-size(" + size + ", size)"; if (CSS.supports("width", calcSize)) { - checkSize(calcSize, allowsFixed); + checkSize(calcSize, true); } } } diff --git a/tests/wpt/tests/css/css-text-decor/crashtests/pseudo-element-text-decoration-under-pseudo-first-line-crash.html b/tests/wpt/tests/css/css-text-decor/crashtests/pseudo-element-text-decoration-under-pseudo-first-line-crash.html new file mode 100644 index 00000000000..6f6c5ecac0b --- /dev/null +++ b/tests/wpt/tests/css/css-text-decor/crashtests/pseudo-element-text-decoration-under-pseudo-first-line-crash.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<link rel="help" href="https://crbug.com/392927981"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#text-decoration-line-property"> +<style> +li { + text-decoration: overline; +} +li::marker { + content: 'm'; +} +li:first-line { + text-decoration: underline; +} +</style> +<li>a</li> diff --git a/tests/wpt/tests/css/css-transforms/preserve3d-containing-block.html b/tests/wpt/tests/css/css-transforms/preserve3d-containing-block.html deleted file mode 100644 index fc74e3874c6..00000000000 --- a/tests/wpt/tests/css/css-transforms/preserve3d-containing-block.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS test: "transform-style: preserve-3d" should establish a containing block for all descendants</title> -<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#transform-style-property"> -<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> -<meta name="assert" content="The box should be green (not red) because the div establishes a containing block for all descendants."> -<style> -body { transform: scale(1); height: 0 } -div { background: red; width: 100px; height: 100px; } -div::before { content: ""; position: fixed; width: 100%; height: 100%; background: green; } -</style> -<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> -<div style="transform-style: preserve-3d"></div> diff --git a/tests/wpt/tests/css/css-transforms/transform-compound-001.html b/tests/wpt/tests/css/css-transforms/transform-compound-001.html index 1f5ed4ca07f..233bce908b9 100644 --- a/tests/wpt/tests/css/css-transforms/transform-compound-001.html +++ b/tests/wpt/tests/css/css-transforms/transform-compound-001.html @@ -9,6 +9,7 @@ <meta name="assert" content='Tests that applying multiple transforms to an element is the same as applying the transforms in the same order to nested elements.'> + <meta name=fuzzy content="maxDifference=0-30;totalPixels=0-500"> <link rel="match" href="transform-compound-ref.html"> <link rel="mismatch" href="transform-compound-notref-1.html"> <link rel="mismatch" href="transform-compound-notref-2.html"> @@ -28,7 +29,6 @@ background-color: gold; width: 200px; height: 100px; - border: 1px solid black; transform: translate(100px) scale(2) rotate(90deg) skewX(15deg); } </style> diff --git a/tests/wpt/tests/css/css-transforms/transform-compound-ref.html b/tests/wpt/tests/css/css-transforms/transform-compound-ref.html index 5122ad98c20..5a98a1384cd 100644 --- a/tests/wpt/tests/css/css-transforms/transform-compound-ref.html +++ b/tests/wpt/tests/css/css-transforms/transform-compound-ref.html @@ -21,7 +21,6 @@ background-color: gold; width: 200px; height: 100px; - border: 1px solid black; } </style> </head> diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-016.html b/tests/wpt/tests/css/css-ui/cgitor-image-png-016-manual.html index 3d7ad76b259..3d7ad76b259 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-016.html +++ b/tests/wpt/tests/css/css-ui/cgitor-image-png-016-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-017.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-017-manual.html index 03b6d6f4144..03b6d6f4144 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-017.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-017-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-019.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-019-manual.html index 86a33f7e1d1..86a33f7e1d1 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-019.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-019-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-023.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-023-manual.html index 397244e45e0..397244e45e0 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-023.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-023-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-024.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-024-manual.html index 986cd8c455b..986cd8c455b 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-024.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-024-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-025.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-025-manual.html index b584da62e1c..b584da62e1c 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-025.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-025-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-027.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-027-manual.html index febbad53165..febbad53165 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-027.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-027-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-028.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-028-manual.html index e572419dd3f..e572419dd3f 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-028.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-028-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-036.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-036-manual.html index 4dabbe3c33f..4dabbe3c33f 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-036.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-036-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-040.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-040-manual.html index 49473b31057..49473b31057 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-040.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-040-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-042.html b/tests/wpt/tests/css/css-ui/cgrsor-image-png-042-manual.html index e88ed4e23cd..e88ed4e23cd 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-042.html +++ b/tests/wpt/tests/css/css-ui/cgrsor-image-png-042-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-001.html b/tests/wpt/tests/css/css-ui/cursor-001-manual.html index 6f46a6bb2a8..6f46a6bb2a8 100644 --- a/tests/wpt/tests/css/css-ui/cursor-001.html +++ b/tests/wpt/tests/css/css-ui/cursor-001-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-002.html b/tests/wpt/tests/css/css-ui/cursor-002-manual.html index 029a5de9c24..029a5de9c24 100644 --- a/tests/wpt/tests/css/css-ui/cursor-002.html +++ b/tests/wpt/tests/css/css-ui/cursor-002-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-003.html b/tests/wpt/tests/css/css-ui/cursor-003-manual.html index f7dbbb94b62..f7dbbb94b62 100644 --- a/tests/wpt/tests/css/css-ui/cursor-003.html +++ b/tests/wpt/tests/css/css-ui/cursor-003-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-004.html b/tests/wpt/tests/css/css-ui/cursor-004-manual.html index 44c175c2e8b..44c175c2e8b 100644 --- a/tests/wpt/tests/css/css-ui/cursor-004.html +++ b/tests/wpt/tests/css/css-ui/cursor-004-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-005.html b/tests/wpt/tests/css/css-ui/cursor-005-manual.html index fc0d9e74c29..fc0d9e74c29 100644 --- a/tests/wpt/tests/css/css-ui/cursor-005.html +++ b/tests/wpt/tests/css/css-ui/cursor-005-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-006.html b/tests/wpt/tests/css/css-ui/cursor-006-manual.html index acfba8d330e..acfba8d330e 100644 --- a/tests/wpt/tests/css/css-ui/cursor-006.html +++ b/tests/wpt/tests/css/css-ui/cursor-006-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-007.html b/tests/wpt/tests/css/css-ui/cursor-007-manual.html index c93d7655b74..c93d7655b74 100644 --- a/tests/wpt/tests/css/css-ui/cursor-007.html +++ b/tests/wpt/tests/css/css-ui/cursor-007-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-008.html b/tests/wpt/tests/css/css-ui/cursor-008-manual.html index 290f10809cb..290f10809cb 100644 --- a/tests/wpt/tests/css/css-ui/cursor-008.html +++ b/tests/wpt/tests/css/css-ui/cursor-008-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-009.html b/tests/wpt/tests/css/css-ui/cursor-009-manual.html index 0c2baf8f23a..0c2baf8f23a 100644 --- a/tests/wpt/tests/css/css-ui/cursor-009.html +++ b/tests/wpt/tests/css/css-ui/cursor-009-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-010.html b/tests/wpt/tests/css/css-ui/cursor-010-manual.html index 0449c8999d6..0449c8999d6 100644 --- a/tests/wpt/tests/css/css-ui/cursor-010.html +++ b/tests/wpt/tests/css/css-ui/cursor-010-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-011.html b/tests/wpt/tests/css/css-ui/cursor-011-manual.html index bc0e73582a4..bc0e73582a4 100644 --- a/tests/wpt/tests/css/css-ui/cursor-011.html +++ b/tests/wpt/tests/css/css-ui/cursor-011-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-012.html b/tests/wpt/tests/css/css-ui/cursor-012-manual.html index 015863017c3..015863017c3 100644 --- a/tests/wpt/tests/css/css-ui/cursor-012.html +++ b/tests/wpt/tests/css/css-ui/cursor-012-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-013.html b/tests/wpt/tests/css/css-ui/cursor-013-manual.html index 72947f000b3..72947f000b3 100644 --- a/tests/wpt/tests/css/css-ui/cursor-013.html +++ b/tests/wpt/tests/css/css-ui/cursor-013-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-014.html b/tests/wpt/tests/css/css-ui/cursor-014-manual.html index a7fa465df82..a7fa465df82 100644 --- a/tests/wpt/tests/css/css-ui/cursor-014.html +++ b/tests/wpt/tests/css/css-ui/cursor-014-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-015.html b/tests/wpt/tests/css/css-ui/cursor-015-manual.html index 88e0a5cbfc2..88e0a5cbfc2 100644 --- a/tests/wpt/tests/css/css-ui/cursor-015.html +++ b/tests/wpt/tests/css/css-ui/cursor-015-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-016.html b/tests/wpt/tests/css/css-ui/cursor-016-manual.html index e4aa0465ddc..e4aa0465ddc 100644 --- a/tests/wpt/tests/css/css-ui/cursor-016.html +++ b/tests/wpt/tests/css/css-ui/cursor-016-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-017.html b/tests/wpt/tests/css/css-ui/cursor-017-manual.html index 99528fede3a..99528fede3a 100644 --- a/tests/wpt/tests/css/css-ui/cursor-017.html +++ b/tests/wpt/tests/css/css-ui/cursor-017-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-018.html b/tests/wpt/tests/css/css-ui/cursor-018-manual.html index daaa7f69e85..daaa7f69e85 100644 --- a/tests/wpt/tests/css/css-ui/cursor-018.html +++ b/tests/wpt/tests/css/css-ui/cursor-018-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-019.html b/tests/wpt/tests/css/css-ui/cursor-019-manual.html index 5be9de10b89..5be9de10b89 100644 --- a/tests/wpt/tests/css/css-ui/cursor-019.html +++ b/tests/wpt/tests/css/css-ui/cursor-019-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-020.html b/tests/wpt/tests/css/css-ui/cursor-020-manual.html index f079d0a56c4..f079d0a56c4 100644 --- a/tests/wpt/tests/css/css-ui/cursor-020.html +++ b/tests/wpt/tests/css/css-ui/cursor-020-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-auto-003.html b/tests/wpt/tests/css/css-ui/cursor-autg-003-manual.html index a3782dbef5a..a3782dbef5a 100644 --- a/tests/wpt/tests/css/css-ui/cursor-auto-003.html +++ b/tests/wpt/tests/css/css-ui/cursor-autg-003-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-auto-001.html b/tests/wpt/tests/css/css-ui/cursor-auto-001-manual.html index 2b2ee60cbcb..2b2ee60cbcb 100644 --- a/tests/wpt/tests/css/css-ui/cursor-auto-001.html +++ b/tests/wpt/tests/css/css-ui/cursor-auto-001-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-auto-002.html b/tests/wpt/tests/css/css-ui/cursor-auto-002-manual.html index dd0d5a1c051..dd0d5a1c051 100644 --- a/tests/wpt/tests/css/css-ui/cursor-auto-002.html +++ b/tests/wpt/tests/css/css-ui/cursor-auto-002-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-auto-004.html b/tests/wpt/tests/css/css-ui/cursor-auto-004-manual.html index 820a93303ce..820a93303ce 100644 --- a/tests/wpt/tests/css/css-ui/cursor-auto-004.html +++ b/tests/wpt/tests/css/css-ui/cursor-auto-004-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-auto-006.html b/tests/wpt/tests/css/css-ui/cursor-auto-006-manual.html index 7385beec8e6..7385beec8e6 100644 --- a/tests/wpt/tests/css/css-ui/cursor-auto-006.html +++ b/tests/wpt/tests/css/css-ui/cursor-auto-006-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-box-007.html b/tests/wpt/tests/css/css-ui/cursor-box-007-manual.html index 5fe0013b60c..5fe0013b60c 100644 --- a/tests/wpt/tests/css/css-ui/cursor-box-007.html +++ b/tests/wpt/tests/css/css-ui/cursor-box-007-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-content-area.html b/tests/wpt/tests/css/css-ui/cursor-content-area-manual.html index f0f0d4dc673..f0f0d4dc673 100644 --- a/tests/wpt/tests/css/css-ui/cursor-content-area.html +++ b/tests/wpt/tests/css/css-ui/cursor-content-area-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-hover-003.html b/tests/wpt/tests/css/css-ui/cursor-gover-003-manual.html index 4611be5279a..4611be5279a 100644 --- a/tests/wpt/tests/css/css-ui/cursor-hover-003.html +++ b/tests/wpt/tests/css/css-ui/cursor-gover-003-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-hover-001.html b/tests/wpt/tests/css/css-ui/cursor-hover-001-manual.html index 8e6bdc96c10..8e6bdc96c10 100644 --- a/tests/wpt/tests/css/css-ui/cursor-hover-001.html +++ b/tests/wpt/tests/css/css-ui/cursor-hover-001-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-003.html b/tests/wpt/tests/css/css-ui/cursor-image-003-manual.html index 4391fe3eabe..4391fe3eabe 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-003.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-003-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-004.html b/tests/wpt/tests/css/css-ui/cursor-image-004-manual.html index 3242e3cc6aa..3242e3cc6aa 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-004.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-004-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-005.html b/tests/wpt/tests/css/css-ui/cursor-image-005-manual.html index 32ac968342d..32ac968342d 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-005.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-005-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-005-nfs.html b/tests/wpt/tests/css/css-ui/cursor-image-005-nfs-manual.html index e7396d212d5..e7396d212d5 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-005-nfs.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-005-nfs-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-006.html b/tests/wpt/tests/css/css-ui/cursor-image-006-manual.html index c123a65f2a0..c123a65f2a0 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-006.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-006-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-008.html b/tests/wpt/tests/css/css-ui/cursor-image-008-manual.html index e5bb5c97bd4..e5bb5c97bd4 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-008.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-008-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-009.html b/tests/wpt/tests/css/css-ui/cursor-image-009-manual.html index 2336bd0744c..2336bd0744c 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-009.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-009-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-010.html b/tests/wpt/tests/css/css-ui/cursor-image-010-manual.html index 3627db18098..3627db18098 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-010.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-010-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-011.html b/tests/wpt/tests/css/css-ui/cursor-image-011-manual.html index 85defa67580..85defa67580 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-011.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-011-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-012.html b/tests/wpt/tests/css/css-ui/cursor-image-012-manual.html index 122b62cf861..122b62cf861 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-012.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-012-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-014.html b/tests/wpt/tests/css/css-ui/cursor-image-014-manual.html index 58b5311f60a..58b5311f60a 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-014.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-014-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-015.html b/tests/wpt/tests/css/css-ui/cursor-image-015-manual.html index 108bb2a137b..108bb2a137b 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-015.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-015-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-016.html b/tests/wpt/tests/css/css-ui/cursor-image-016-manual.html index a4ab6630f0c..a4ab6630f0c 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-016.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-016-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-017.html b/tests/wpt/tests/css/css-ui/cursor-image-017-manual.html index f60aec02d67..f60aec02d67 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-017.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-017-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-018.html b/tests/wpt/tests/css/css-ui/cursor-image-018-manual.html index 31caf408e0d..31caf408e0d 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-018.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-018-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-001.html b/tests/wpt/tests/css/css-ui/cursor-image-png-001-manual.html index 0a99ad2c3b0..0a99ad2c3b0 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-001.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-001-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-002.html b/tests/wpt/tests/css/css-ui/cursor-image-png-002-manual.html index bb48743f9c0..bb48743f9c0 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-002.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-002-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-003.html b/tests/wpt/tests/css/css-ui/cursor-image-png-003-manual.html index fbe96fc0635..fbe96fc0635 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-003.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-003-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-005.html b/tests/wpt/tests/css/css-ui/cursor-image-png-005-manual.html index 26842871c2c..26842871c2c 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-005.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-005-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-006.html b/tests/wpt/tests/css/css-ui/cursor-image-png-006-manual.html index bc6453d6c33..bc6453d6c33 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-006.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-006-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-007.html b/tests/wpt/tests/css/css-ui/cursor-image-png-007-manual.html index 93d0ba62335..93d0ba62335 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-007.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-007-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-008.html b/tests/wpt/tests/css/css-ui/cursor-image-png-008-manual.html index d9c29628188..d9c29628188 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-008.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-008-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-009.html b/tests/wpt/tests/css/css-ui/cursor-image-png-009-manual.html index b942a7a4b53..b942a7a4b53 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-009.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-009-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-010.html b/tests/wpt/tests/css/css-ui/cursor-image-png-010-manual.html index 3a65c1d5f01..3a65c1d5f01 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-010.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-010-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-011.html b/tests/wpt/tests/css/css-ui/cursor-image-png-011-manual.html index 9ad4b0101a4..9ad4b0101a4 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-011.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-011-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-012.html b/tests/wpt/tests/css/css-ui/cursor-image-png-012-manual.html index 437928699fc..437928699fc 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-012.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-012-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-013.html b/tests/wpt/tests/css/css-ui/cursor-image-png-013-manual.html index 75651f133e3..75651f133e3 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-013.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-013-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-014.html b/tests/wpt/tests/css/css-ui/cursor-image-png-014-manual.html index 00c1dc7edcd..00c1dc7edcd 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-014.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-014-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-020.html b/tests/wpt/tests/css/css-ui/cursor-image-png-020-manual.html index 3c51ed96e2c..3c51ed96e2c 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-020.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-020-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-021.html b/tests/wpt/tests/css/css-ui/cursor-image-png-021-manual.html index ea66fd7da3c..ea66fd7da3c 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-021.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-021-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-026.html b/tests/wpt/tests/css/css-ui/cursor-image-png-026-manual.html index e9b68de4d88..e9b68de4d88 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-026.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-026-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-029.html b/tests/wpt/tests/css/css-ui/cursor-image-png-029-manual.html index 9da6d4a5374..9da6d4a5374 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-029.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-029-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-030.html b/tests/wpt/tests/css/css-ui/cursor-image-png-030-manual.html index b35871390dc..b35871390dc 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-030.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-030-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-034.html b/tests/wpt/tests/css/css-ui/cursor-image-png-034-manual.html index 9331a90d91f..9331a90d91f 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-034.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-034-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-035.html b/tests/wpt/tests/css/css-ui/cursor-image-png-035-manual.html index 1bcffe82b5f..1bcffe82b5f 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-035.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-035-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-037.html b/tests/wpt/tests/css/css-ui/cursor-image-png-037-manual.html index dd744992019..dd744992019 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-037.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-037-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-038.html b/tests/wpt/tests/css/css-ui/cursor-image-png-038-manual.html index 6c7ac7fd07c..6c7ac7fd07c 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-038.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-038-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-039.html b/tests/wpt/tests/css/css-ui/cursor-image-png-039-manual.html index fd52b6b0136..fd52b6b0136 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-039.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-039-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-041.html b/tests/wpt/tests/css/css-ui/cursor-image-png-041-manual.html index d817844d061..d817844d061 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-041.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-041-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-043.html b/tests/wpt/tests/css/css-ui/cursor-image-png-043-manual.html index 0ab16a1fc6d..0ab16a1fc6d 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-043.html +++ b/tests/wpt/tests/css/css-ui/cursor-image-png-043-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-png-015.html b/tests/wpt/tests/css/css-ui/cursor-imgge-png-015-manual.html index 6109234178a..6109234178a 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-png-015.html +++ b/tests/wpt/tests/css/css-ui/cursor-imgge-png-015-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-image-007.html b/tests/wpt/tests/css/css-ui/cursor-imgie-007-manual.html index 6433142e3ce..6433142e3ce 100644 --- a/tests/wpt/tests/css/css-ui/cursor-image-007.html +++ b/tests/wpt/tests/css/css-ui/cursor-imgie-007-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-outline-area.html b/tests/wpt/tests/css/css-ui/cursor-outline-area-manual.html index d53ecdc4014..d53ecdc4014 100644 --- a/tests/wpt/tests/css/css-ui/cursor-outline-area.html +++ b/tests/wpt/tests/css/css-ui/cursor-outline-area-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-padding-area.html b/tests/wpt/tests/css/css-ui/cursor-padding-area-manual.html index aaa993024c4..aaa993024c4 100644 --- a/tests/wpt/tests/css/css-ui/cursor-padding-area.html +++ b/tests/wpt/tests/css/css-ui/cursor-padding-area-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-text-001.html b/tests/wpt/tests/css/css-ui/cursor-text-001-manual.html index d894c65b9da..d894c65b9da 100644 --- a/tests/wpt/tests/css/css-ui/cursor-text-001.html +++ b/tests/wpt/tests/css/css-ui/cursor-text-001-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-text-002.html b/tests/wpt/tests/css/css-ui/cursor-text-002-manual.html index 3aec77f4d9b..3aec77f4d9b 100644 --- a/tests/wpt/tests/css/css-ui/cursor-text-002.html +++ b/tests/wpt/tests/css/css-ui/cursor-text-002-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-x-y-001.html b/tests/wpt/tests/css/css-ui/cursor-x-y-001-manual.html index 16b147cc2d6..16b147cc2d6 100644 --- a/tests/wpt/tests/css/css-ui/cursor-x-y-001.html +++ b/tests/wpt/tests/css/css-ui/cursor-x-y-001-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-x-y-002.html b/tests/wpt/tests/css/css-ui/cursor-x-y-002-manual.html index 6aae01eaed3..6aae01eaed3 100644 --- a/tests/wpt/tests/css/css-ui/cursor-x-y-002.html +++ b/tests/wpt/tests/css/css-ui/cursor-x-y-002-manual.html diff --git a/tests/wpt/tests/css/css-ui/cursor-x-y-003.html b/tests/wpt/tests/css/css-ui/cursor-x-y-003-manual.html index cb3b7ae9df1..cb3b7ae9df1 100644 --- a/tests/wpt/tests/css/css-ui/cursor-x-y-003.html +++ b/tests/wpt/tests/css/css-ui/cursor-x-y-003-manual.html diff --git a/tests/wpt/tests/css/css-values/attr-all-types.html b/tests/wpt/tests/css/css-values/attr-all-types.html index 85fa172f39a..8dce4feb5f4 100644 --- a/tests/wpt/tests/css/css-values/attr-all-types.html +++ b/tests/wpt/tests/css/css-values/attr-all-types.html @@ -97,6 +97,10 @@ test_valid_attr('content', 'attr(data-foo type(<string>))', '"abc"', '"abc"'); test_valid_attr('content', 'attr(data-foo type(<string>),)', '"abc"', '"abc"'); test_valid_attr('content', 'attr(data-foo type(<string>))', '"attr(data-foo)"', '"attr(data-foo)"'); + test_valid_attr('content', 'attr(data-foo)', '', '""'); + test_valid_attr('font-family', 'attr(non-existent)', '', '""'); + test_valid_attr('font-family', 'attr(non-existent string)', '', ''); + test_invalid_attr('font-family', 'attr(non-existent type(<string>))', ''); test_valid_attr('animation-name', 'attr(data-foo type(<custom-ident>))', 'anim', 'anim'); test_valid_attr('animation-name', 'attr(data-foo type(<custom-ident>), anim-fallback)', '"anim"', 'anim-fallback'); diff --git a/tests/wpt/tests/css/css-values/calc-sibling-function-in-shadow-dom.html b/tests/wpt/tests/css/css-values/calc-sibling-function-in-shadow-dom.html index 54faa941797..92fb6ce3351 100644 --- a/tests/wpt/tests/css/css-values/calc-sibling-function-in-shadow-dom.html +++ b/tests/wpt/tests/css/css-values/calc-sibling-function-in-shadow-dom.html @@ -1,12 +1,18 @@ <!DOCTYPE html> <html> <head> - <title>sibling-index() within Shadow DOM</title> + <title>CSS Values Test: sibling-index() and sibling-count() in flat tree</title> <link rel="help" href="https://drafts.csswg.org/css-values-5/#tree-counting" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> </head> <body> + <style> + #host > * { + orphans: sibling-index(); + widows: sibling-count(); + } + </style> <div id="host"> <div>Some element.</div> <div>Some other element.</div> @@ -16,18 +22,20 @@ <script> test(() => { host.attachShadow({mode: 'open'}).innerHTML = ` - <style>slot::slotted(*) { z-index: sibling-index(); }</style> + <style> + slot::slotted(*) { + z-index: sibling-index(); + order: sibling-count(); + } + </style> <div> <div>Some text before the slot.</div> <slot></slot> </div> `; - - // The originating element for slot::slotted(*) - // is the <slot>, not the <div>. Note that there is - // a proposal to change this; see - // https://github.com/w3c/csswg-drafts/issues/9573. - // This should probably become '3' after that is fixed. - assert_equals(getComputedStyle(target).zIndex, '2'); - }, 'originating element in Shadow DOM'); + assert_equals(getComputedStyle(target).zIndex, '3'); + assert_equals(getComputedStyle(target).order, '3'); + assert_equals(getComputedStyle(target).orphans, '3'); + assert_equals(getComputedStyle(target).widows, '3'); + }, 'Host children have sibling-index() and sibling-count() based on assignedNodes order'); </script> diff --git a/tests/wpt/tests/css/css-values/calc-sibling-function.html b/tests/wpt/tests/css/css-values/calc-sibling-function.html index 368f305f6a5..5fe6e00a10b 100644 --- a/tests/wpt/tests/css/css-values/calc-sibling-function.html +++ b/tests/wpt/tests/css/css-values/calc-sibling-function.html @@ -12,7 +12,9 @@ left: calc(10% + 100px * sibling-index()); } #test::before { + content: ""; z-index: calc(sibling-index() * 2); + widows: calc(sibling-count() * 2); } </style> </head> @@ -41,8 +43,9 @@ test(() => { }, 'sibling-index() in calc() with percentage'); test(() => { - let style = getComputedStyle(document.getElementById('test'), ':before'); + let style = getComputedStyle(document.getElementById('test'), '::before'); assert_equals(style.zIndex, '4'); + assert_equals(style.widows, '10'); }, 'sibling-count on pseudo-element'); </script> </body> diff --git a/tests/wpt/tests/css/css-values/if-conditionals.html b/tests/wpt/tests/css/css-values/if-conditionals.html index 21ef0c58566..caead7864d5 100644 --- a/tests/wpt/tests/css/css-values/if-conditionals.html +++ b/tests/wpt/tests/css/css-values/if-conditionals.html @@ -512,13 +512,19 @@ 'false_value'); // media() queries in the condition - test_if(`if(media(screen and (max-width: 1px)): true_value; + test_if(`if(media(max-width: 1px): true_value; else: false_value)`, 'false_value'); - test_if(`if(media(screen and (height <= 999999px)): true_value; + test_if(`if(media((max-width: 1px)): true_value; + else: false_value)`, + 'false_value'); + test_if(`if(media(height <= 999999px): true_value; + else: false_value)`, + 'true_value'); + test_if(`if(media(min-color: 1): true_value; else: false_value)`, 'true_value'); - test_if(`if(media((min-color: 1)): true_value; + test_if(`if(media((min-color: 1) and (height <= 999999px)): true_value; else: false_value)`, 'true_value'); @@ -555,10 +561,10 @@ 'false_value'); // media(), style() and supports() queries in the condition - test_if(`if((media(screen and (min-width: 1px))) or (style(--x)): true_value; + test_if(`if((media(min-width: 1px)) or (style(--x)): true_value; else: false_value)`, 'true_value'); - test_if(`if((media(screen and (height <= 999999px))) and style(--non-existent): true_value; + test_if(`if((media(height <= 999999px)) and style(--non-existent): true_value; else: false_value)`, 'false_value'); test_if(`if((media((min-color: 1) and (height <= 999999px))) and (style(--x)): true_value; diff --git a/tests/wpt/tests/css/css-values/if-invalidation.html b/tests/wpt/tests/css/css-values/if-invalidation.html new file mode 100644 index 00000000000..feec1e526d1 --- /dev/null +++ b/tests/wpt/tests/css/css-values/if-invalidation.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<title>CSS Values and Units Test: if() invalidation</title> +<meta name="assert" content="Test if() invalidation"> +<link rel="help" href="https://drafts.csswg.org/css-values-5/#if-notation"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + html { + --x: 3; + } + #test { + --prop: if(style(--x: 3): true_value; else: false_value;); + } +</style> + +<html> + <body> + <div id="test"></div> + </body> +</html> + +<script> + setup({ single_test: true }); + let elem = document.getElementById('test'); + let old_value = window.getComputedStyle(elem).getPropertyValue('--prop'); + assert_equals(old_value, "true_value"); + + document.documentElement.style.setProperty('--x', '0'); + let new_value = window.getComputedStyle(elem).getPropertyValue('--prop'); + assert_equals( new_value, "false_value"); + assert_not_equals(new_value, old_value); + done(); +</script>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-values/if-media-invalidation.html b/tests/wpt/tests/css/css-values/if-media-invalidation.html index bababe5cd79..869f044e4e6 100644 --- a/tests/wpt/tests/css/css-values/if-media-invalidation.html +++ b/tests/wpt/tests/css/css-values/if-media-invalidation.html @@ -14,7 +14,7 @@ <div id=target></div> <style> #target { - --actual: if(media(screen and ((height < 100px) or ((height >= 200px) and (height < 300px)))): true_value; else: false_value;); + --actual: if(media((height < 100px) or ((height >= 200px) and (height < 300px))): true_value; else: false_value;); } </style> "></iframe> diff --git a/tests/wpt/tests/css/css-values/sibling-function-invalidation.html b/tests/wpt/tests/css/css-values/sibling-function-invalidation.html new file mode 100644 index 00000000000..74f4995f5f7 --- /dev/null +++ b/tests/wpt/tests/css/css-values/sibling-function-invalidation.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<title>CSS Values and Units Test: Invalidation for sibling-index() and sibling-count()</title> +<link rel="help" href="https://drafts.csswg.org/css-values-5/#tree-counting"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + #t1 { + width: calc(10px * sibling-index()); + height: 50px; + background: teal; + } +</style> +<div> + <div id="rm1"></div> + <div></div> + <div></div> + <div></div> + <div></div> + <div id="t1"></div> +</div> +<script> + test(() => assert_equals(t1.offsetWidth, 60), "Initially 6th sibling"); + test(() => { + rm1.remove(); + assert_equals(t1.offsetWidth, 50); + }, "5th sibling after removal"); +</script> + +<style> + #t2 { + width: 50px; + height: calc(10px * sibling-count()); + background: teal; + } +</style> +<div> + <div id="t2"></div> + <div></div> + <div></div> + <div></div> + <div></div> + <div id="rm2"></div> +</div> +<script> + test(() => assert_equals(t2.offsetHeight, 60), "Initially 6 siblings"); + test(() => { + rm2.remove(); + assert_equals(t2.offsetHeight, 50); + }, "5 siblings after removal"); +</script> diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-image-ref.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-image-ref.tentative.html deleted file mode 100644 index 8cf3d5eeafb..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-image-ref.tentative.html +++ /dev/null @@ -1,58 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Tree effects are captured as group style</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - * { - box-sizing: border-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - background: lightpink; - } - - @keyframes anim { - to { - border-image: linear-gradient(yellow, green) 20 / 10px; - } - } - - .animate { - animation-name: anim; - animation-duration: 1000s; - animation-play-state: paused; - animation-timing-function: steps(2, start); - } - - .target { - width: 100px; - height: 100px; - margin: 30px; - background: green; - overflow: hidden; - border: 2px solid; - border-image: linear-gradient(red, blue) 2 / 10px; - } - - .at-end.target { - border-image: linear-gradient(yellow, green) 20 / 10px; - } - - .override { - border: 8px groove; - outline: none; - border-radius: 2px; - background: grey; - border-image: linear-gradient(green, green) 8 / 3ppx; - animation: none; - } -</style> -<body> - <div class="passthrough target"></div> - <div class="at-end target"></div> - <div class="animate target"></div> - <div class="override target"></div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-image.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-image.tentative.html deleted file mode 100644 index ad48b639fc0..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-image.tentative.html +++ /dev/null @@ -1,104 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Tree effects are captured as group style</title> -<meta name=fuzzy content="maxDifference=0-10; totalPixels=0-200000"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="border-image-ref.tentative.html"> -<script src="/common/reftest-wait.js"></script> -<style> - * { - box-sizing: border-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - } - - .target { - width: 100px; - height: 100px; - margin: 30px; - background: green; - overflow: hidden; - border: 2px solid; - border-image: linear-gradient(red, blue) 2 / 10px; - } - - html.vt-new .target { - border-image: linear-gradient(yellow, green) 20 / 10px; - } - - html::view-transition-image-pair(*) { - inset: 5px; - } - - .override { - view-transition-name: override; - } - - .passthrough { - view-transition-name: passthrough; - } - .animate { - view-transition-name: animate; - } - .at-end { - view-transition-name: at-end; - } - - html::view-transition-group(*) { - animation-play-state: paused; - } - - html::view-transition-group(override) { - border: 8px groove; - outline: none; - border-radius: 2px; - background: grey; - border-image: linear-gradient(green, green) 8 / 3ppx; - animation: none; - } - - html::view-transition-group(animate), - html::view-transition-old(animate), - html::view-transition-new(animate) - { - animation-timing-function: steps(2, start); - animation-play-state: paused; - animation-duration: 100s; - } - html::view-transition-group(at-end), - html::view-transition-old(at-end), - html::view-transition-new(at-end) - { - animation-timing-function: steps(1, start); - animation-play-state: paused; - animation-duration: 100s; - } - html::view-transition-group(passthrough), - html::view-transition-old(passthrough), - html::view-transition-new(passthrough) - { - animation-timing-function: steps(1, end); - animation-play-state: paused; - animation-duration: 100s; - } - - html::view-transition { - background: lightpink; - } -</style> -<body> - <div class="passthrough target"></div> - <div class="at-end target"></div> - <div class="animate target"></div> - <div class="override target"></div> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-ref.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-ref.tentative.html deleted file mode 100644 index ca8ee775284..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-ref.tentative.html +++ /dev/null @@ -1,42 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Borders should not affect snapshot position</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - * { - box-sizing: border-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - } - - div { - width: 100px; - height: 100px; - position: absolute; - } - - .parent { - view-transition-name: parent; - border: 10px solid black; - background: green; - } - - .child { - top: 20px; - left: 20px; - width: 40px; - height: 40px; - background: yellow; - border: 2px dashed blue; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-inline-ref.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-inline-ref.html deleted file mode 100644 index 976c10cb414..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-inline-ref.html +++ /dev/null @@ -1,34 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Borders should not affect snapshot position</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - * { - box-sizing: content-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - } - - div { - position: absolute; - } - - .inline { - view-transition-name: parent; - border: 10px solid black; - background: green; - padding: 12px; - position: relative; - left: 100px; - top: 40px; - } -</style> -<body> - <span class="inline"> - ABC - </span> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-inline.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-inline.tentative.html deleted file mode 100644 index ca0be4179c6..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-inline.tentative.html +++ /dev/null @@ -1,49 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Borders should not affect snapshot position</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="border-offset-with-padding-inline-ref.html"> -<script src="/common/reftest-wait.js"></script> -<script src="resources/compute-test.js"></script> -<style> - * { - box-sizing: content-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - } - - div { - position: absolute; - } - - .inline { - view-transition-name: parent; - border: 10px solid black; - background: green; - padding: 12px; - position: relative; - left: 100px; - top: 40px; - } - - ::view-transition-old(*), - ::view-transition-new(*), - ::view-transition-group(*) { - animation-play-state: paused; - } -</style> -<body> - <span class="inline"> - ABC - </span> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-nested.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-nested.tentative.html deleted file mode 100644 index 446d35e3661..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding-nested.tentative.html +++ /dev/null @@ -1,59 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Borders should not affect snapshot position</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="border-offset-ref.tentative.html"> -<script src="/common/reftest-wait.js"></script> -<script src="resources/compute-test.js"></script> -<style> - html { - view-transition-name: none; - } - body { - margin: 0; - } - - div { - position: absolute; - } - - .parent { - view-transition-name: parent; - border: 10px solid black; - background: green; - padding: 20px; - width: 40px; - height: 40px; - box-sizing: content-box; - } - - .child { - width: 30px; - padding-left: 6px; - height: 36px; - background: yellow; - border: 2px dashed blue; - view-transition-group: parent; - } - - ::view-transition-old(*), - ::view-transition-new(*), - ::view-transition-group(*) { - animation-play-state: paused; - } - - ::view-transition-group(parent) { - overflow: clip; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding.tentative.html deleted file mode 100644 index e3255677506..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset-with-padding.tentative.html +++ /dev/null @@ -1,59 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Borders should not affect snapshot position</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="border-offset-ref.tentative.html"> -<script src="/common/reftest-wait.js"></script> -<script src="resources/compute-test.js"></script> -<style> - * { - box-sizing: content-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - } - - div { - position: absolute; - } - - .parent { - view-transition-name: parent; - border: 10px solid black; - background: green; - padding: 20px; - width: 40px; - height: 40px; - } - - .child { - width: 36px; - height: 36px; - background: yellow; - border: 2px dashed blue; - } - - ::view-transition-old(*), - ::view-transition-new(*), - ::view-transition-group(*) { - animation-play-state: paused; - } - - ::view-transition-group(parent) { - overflow: clip; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset.tentative.html deleted file mode 100644 index 7fb6a9a6224..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-offset.tentative.html +++ /dev/null @@ -1,60 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Borders should not affect snapshot position</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="border-offset-ref.tentative.html"> -<script src="/common/reftest-wait.js"></script> -<script src="resources/compute-test.js"></script> -<style> - * { - box-sizing: border-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - } - - div { - width: 100px; - height: 100px; - position: absolute; - } - - .parent { - view-transition-name: parent; - border: 10px solid black; - background: green; - } - - .child { - top: 20px; - left: 20px; - width: 40px; - height: 40px; - background: yellow; - border: 2px dashed blue; - } - - ::view-transition-old(*), - ::view-transition-new(*), - ::view-transition-group(*) { - animation-play-state: paused; - } - - ::view-transition-group(parent) { - overflow: clip; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-uneven-ref.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-uneven-ref.html deleted file mode 100644 index 15b27166371..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-uneven-ref.html +++ /dev/null @@ -1,38 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Uneven borders should be captured correctly</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - * { - box-sizing: border-box; - } - body { - margin: 0; - background: rebeccapurple; - } - - @keyframes anim { - to { - border: 5px solid blue; - border-right: 4px solid teal; - } - } - - .target { - width: 100px; - height: 100px; - view-transition-name: parent; - border-left: 10px solid black; - border-top: 20px groove pink; - border-bottom: 1px dashed orange; - border-right: 2px solid yellow; - background: green; - animation-name: anim; - animation-timing-function: steps(2, start); - animation-play-state: paused; - animation-duration: 10s; - } -</style> -<body> - <div class="target"></div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-uneven.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/border-uneven.tentative.html deleted file mode 100644 index eeec263e27a..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/border-uneven.tentative.html +++ /dev/null @@ -1,61 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> - <title>Uneven borders should be captured correctly</title> - <meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="border-uneven-ref.html"> -<script src="/common/reftest-wait.js"></script> -<script src="resources/compute-test.js"></script> -<style> - * { - box-sizing: border-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - } - - - .target { - width: 100px; - height: 100px; - view-transition-name: parent; - border-left: 10px solid black; - border-top: 20px groove pink; - border-bottom-width: 1px; - border-bottom-style: dashed; - border-bottom-color: orange; - border-right: 2px solid yellow; - background: green; - } - - .vt-new .target { - border: 5px solid blue; - border-right: 4px solid teal; - } - - ::view-transition { - background: rebeccapurple; - } - - ::view-transition-old(*), - ::view-transition-new(*), - ::view-transition-group(*) { - animation-play-state: paused; - } - - ::view-transition-group(parent) { - animation-timing-function: steps(2, start); - } -</style> -<body> - <div class="target"></div> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-decorations-ref.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/box-decorations-ref.tentative.html deleted file mode 100644 index 5221c7689af..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-decorations-ref.tentative.html +++ /dev/null @@ -1,78 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Box decorations are captured as group style</title> -<meta name=fuzzy content="maxDifference=0-10; totalPixels=0-200000"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - * { - box-sizing: border-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - background: lightpink; - } - - .target { - width: 100px; - height: 100px; - margin: 30px; - background: green; - overflow: hidden; - border: 3px solid yellow; - outline: 2px solid blue; - border-radius: 10px; - background-image: linear-gradient(orange, cyan); - box-shadow: -10px 10px lightcoral; - } - - .at-end { - border: 10px solid red; - outline: 5px solid green; - border-radius: 10px 20px 0 4px; - background-image: linear-gradient(pink, black); - box-shadow: 2px -15px lightslategray; - } - - @keyframes anim { - from { - border: 3px solid yellow; - outline: 2px solid blue; - border-radius: 10px; - background-image: linear-gradient(orange, cyan); - box-shadow: -10px 10px lightcoral; - } - to { - border: 10px solid red; - outline: 5px solid green; - border-radius: 10px 20px 0 4px; - background-image: linear-gradient(pink, black); - box-shadow: 2px -15px lightslategray; - } - } - - .animate { - animation-name: anim; - animation-duration: 1000s; - animation-play-state: paused; - animation-timing-function: steps(2, start); - } - - .override { - border: 1px groove blue; - outline: none; - border-radius: 2px; - background: grey; - background-image: none; - box-shadow: 3px 3px purple; - } - -</style> -<body> - <div class="passthrough target"></div> - <div class="at-end target"></div> - <div class="animate target"></div> - <div class="override target"></div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-decorations.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/box-decorations.tentative.html deleted file mode 100644 index 436ba4d3ded..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-decorations.tentative.html +++ /dev/null @@ -1,111 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Box decorations are captured as group style</title> -<meta name=fuzzy content="maxDifference=0-10; totalPixels=0-200000"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="box-decorations-ref.tentative.html"> -<script src="/common/reftest-wait.js"></script> -<style> - * { - box-sizing: border-box; - } - html { - view-transition-name: none; - } - body { - margin: 0; - } - - .target { - width: 100px; - height: 100px; - margin: 30px; - background: green; - overflow: hidden; - border: 3px solid yellow; - outline: 2px solid blue; - border-radius: 10px; - background-image: linear-gradient(orange, cyan); - box-shadow: -10px 10px lightcoral; - } - - html.vt-new .target { - border: 10px solid red; - outline: 5px solid green; - border-radius: 10px 20px 0 4px; - background-image: linear-gradient(pink, black); - box-shadow: 2px -15px lightslategray; - } - - html::view-transition-image-pair(*) { - inset: 5px; - } - - .override { - view-transition-name: override; - } - - .passthrough { - view-transition-name: passthrough; - } - .animate { - view-transition-name: animate; - } - .at-end { - view-transition-name: at-end; - } - - html::view-transition-group(*) { - animation-play-state: paused; - } - - html::view-transition-group(override) { - border: 1px groove blue; - outline: none; - border-radius: 2px; - background: grey; - box-shadow: 3px 3px purple; - animation: none; - } - - html::view-transition-group(animate), - html::view-transition-old(animate), - html::view-transition-new(animate) - { - animation-timing-function: steps(2, start); - animation-play-state: paused; - animation-duration: 100s; - } - html::view-transition-group(at-end), - html::view-transition-old(at-end), - html::view-transition-new(at-end) - { - animation-timing-function: steps(1, start); - animation-play-state: paused; - animation-duration: 100s; - } - html::view-transition-group(passthrough), - html::view-transition-old(passthrough), - html::view-transition-new(passthrough) - { - animation-timing-function: steps(1, end); - animation-play-state: paused; - animation-duration: 100s; - } - - html::view-transition { - background: lightpink; - } -</style> -<body> - <div class="passthrough target"></div> - <div class="at-end target"></div> - <div class="animate target"></div> - <div class="override target"></div> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-nested-ref.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-nested-ref.html deleted file mode 100644 index 6610adc9f71..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-nested-ref.html +++ /dev/null @@ -1,39 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Box model is copied to group style</title> -<meta name=fuzzy content="maxDifference=0-10; totalPixels=0-200000"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - * { - box-sizing: border-box; - } - - body { - background: rebeccapurple; - margin: 0; - } - - div { - width: 200px; - height: 200px; - background: green; - border: 10px solid blue; - padding: 48px; - } - - .child { - border: 32px solid yellow; - } - - .parent { - border-width: 15px; - padding-top: 27px; - padding-left: 100px; - overflow: clip; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-nested.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-nested.tentative.html deleted file mode 100644 index be8eea0cf70..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-nested.tentative.html +++ /dev/null @@ -1,66 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Box model is copied to group style</title> -<meta name=fuzzy content="maxDifference=0-10; totalPixels=0-200000"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="box-model-capture-nested-ref.html"> -<script src="/common/reftest-wait.js"></script> -<style> - * { - /* Will add tests for different sizing once the spec is resolved. */ - box-sizing: border-box; - } - - ::view-transition { - background: rebeccapurple; - } - - body { - margin: 0; - } - - div { - width: 200px; - height: 200px; - background: green; - border: 10px solid blue; - } - - - .parent { - view-transition-name: parent; - padding: 48px 48px 48px 100px; - overflow: clip; - } - - .child { - view-transition-name: child; - view-transition-group: parent; - border: 32px solid yellow; - padding: 48px; - } - - .vt-new .parent { - border-width: 20px; - padding: 6px 48px 48px 100px; - } - - ::view-transition-group(*) { - animation-play-state: paused; - animation-timing-function: steps(2, start); - } - - ::view-transition-new(*), ::view-transition-old(*) { - animation: none; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> - <script> - document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }).ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-ref.sub.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-ref.sub.html deleted file mode 100644 index 36401abca0d..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture-ref.sub.html +++ /dev/null @@ -1,75 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Box model is copied to group style</title> -<meta name=fuzzy content="maxDifference=0-10; totalPixels=0-200000"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - * { - box-sizing: {{GET[sizing]}}; - } - - body { - margin: 33px; - background: pink; - } - - .target { - width: 60px; - height: 60px; - padding: 15px; - border: 10px solid yellow; - outline: 5px solid blue; - background: green; - position: fixed; - left: 0; - } - - .target.at-end { - width: 200px; - height: 40px; - left: 300px; - padding-left: 25px; - border: 3px solid yellow; - outline: 8px solid blue; - left: 300px; - } - - .target.override { - width: 80px; - height: 80px; - padding-left: 30px; - padding-top: 0px; - border-width: 20px; - outline-width: 12px; - position: absolute; - left: 300px; - top: 300px; - box-sizing: content-box; - } - - @keyframes anim { - to { - width: 200px; - height: 40px; - padding-left: 25px; - border: 3px solid yellow; - outline: 8px solid blue; - left: 300px; - } - } - - .target.animate { - animation-name: anim; - animation-duration: 1000s; - animation-play-state: paused; - animation-timing-function: steps(2, start); - top: 180px; - } - -</style> -<body> - <div class="passthrough target"></div> - <div class="at-end target"></div> - <div class="animate target"></div> - <div class="override target"></div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture.tentative.sub.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture.tentative.sub.html deleted file mode 100644 index c4ca0dca97b..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/box-model-capture.tentative.sub.html +++ /dev/null @@ -1,124 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Box model is copied to group style</title> -<meta name=fuzzy content="maxDifference=0-10; totalPixels=0-200000"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="box-model-capture-ref.sub.html"> -<meta name="variant" content="?sizing=border-box"> -<meta name="variant" content="?sizing=content-box"> -<script src="/common/reftest-wait.js"></script> -<style> - * { - box-sizing: {{GET[sizing]}}; - } - - html { - view-transition-name: none; - } - body { - margin: 33px; - } - - .target { - width: 60px; - height: 60px; - padding: 15px; - border: 10px solid yellow; - outline: 5px solid blue; - background: green; - /* To avoid the elements affecting each other's position */ - position: absolute; - left: 0; - } - - .animate.target { - top: 180px; - } - - html.vt-new .target { - left: 300px; - width: 200px; - height: 40px; - padding-left: 25px; - border: 3px solid yellow; - outline: 8px solid blue; - } - - .override { - view-transition-name: override; - top: 300px; - left: 300px; - } - - .passthrough { - view-transition-name: passthrough; - } - .animate { - view-transition-name: animate; - } - .at-end { - view-transition-name: at-end; - } - - html::view-transition-group(*) { - animation-play-state: paused; - } - - html::view-transition-group(override) { - width: 80px; - height: 80px; - padding-left: 30px; - padding-top: 0px; - border-width: 20px; - outline-width: 12px; - box-sizing: content-box; - transform: none; - animation: none; - position: fixed; - top: 300px; - left: 300px; - } - - html::view-transition-group(animate), - html::view-transition-old(animate), - html::view-transition-new(animate) - { - animation-timing-function: steps(2, start); - animation-play-state: paused; - animation-duration: 100s; - } - html::view-transition-group(at-end), - html::view-transition-old(at-end), - html::view-transition-new(at-end) - { - animation-timing-function: steps(1, start); - animation-play-state: paused; - animation-duration: 100s; - } - html::view-transition-group(passthrough), - html::view-transition-old(passthrough), - html::view-transition-new(passthrough) - { - animation-timing-function: steps(1, end); - animation-play-state: paused; - animation-duration: 100s; - } - - html::view-transition { - background: pink; - } -</style> -<body> - <main> - <div class="passthrough target"></div> - <div class="at-end target"></div> - <div class="animate target"></div> - <div class="override target"></div> - </main> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/capture-mode-flat.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/capture-mode-flat.tentative.html deleted file mode 100644 index beed17c8973..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/capture-mode-flat.tentative.html +++ /dev/null @@ -1,45 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Capture mode: flat</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="nested-opacity-ref.html"> -<script src="/common/reftest-wait.js"></script> -<script src="../nested/resources/compute-test.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - background: green; - } - - .parent { - opacity: 0.4; - view-transition-name: parent; - view-transition-capture-mode: flat; - will-change: opacity; - } - - .child { - top: 50px; - left: 50px; - } - - ::view-transition-group(parent) { - animation-name: none; - opacity: 1; - } - ::view-transition-old(*), - ::view-transition-new(*) { - animation-play-state: paused; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/capture-mode-layered.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/capture-mode-layered.tentative.html deleted file mode 100644 index d1f190343b0..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/capture-mode-layered.tentative.html +++ /dev/null @@ -1,45 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Captured mode: layered</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="nested-opacity-ref.html"> -<script src="/common/reftest-wait.js"></script> -<script src="../nested/resources/compute-test.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - background: green; - } - - .parent { - opacity: 0.7; - view-transition-name: parent; - will-change: opacity; - view-transition-capture-mode: layered; - } - - .child { - top: 50px; - left: 50px; - } - - ::view-transition-group(parent) { - opacity: 0.4; - animation-name: none; - } - ::view-transition-old(*), - ::view-transition-new(*) { - animation-play-state: paused; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-backdrop-blend-animated.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-backdrop-blend-animated.tentative.html deleted file mode 100644 index 73100015cdd..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-backdrop-blend-animated.tentative.html +++ /dev/null @@ -1,45 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Opacity should apply to the whole group</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="nested-opacity-ref.html"> -<script src="/common/reftest-wait.js"></script> -<script src="../nested/resources/compute-test.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - background: green; - } - - .parent { - view-transition-name: parent; - } - - .vt-old .parent { - opacity: 0.4; - } - - .child { - view-transition-name: child; - view-transition-group: parent; - top: 50px; - left: 50px; - } - - ::view-transition-group(*), - ::view-transition-old(*), - ::view-transition-new(*) { - animation-play-state: paused; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-backdrop-blend.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-backdrop-blend.tentative.html deleted file mode 100644 index 0042d9676f2..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-backdrop-blend.tentative.html +++ /dev/null @@ -1,41 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Opacity should apply to the whole group</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="nested-opacity-ref.html"> -<script src="/common/reftest-wait.js"></script> -<script src="../nested/resources/compute-test.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - background: green; - } - - .parent { - view-transition-name: parent; - opacity: 0.4; - } - - .child { - view-transition-name: child; - view-transition-group: parent; - top: 50px; - left: 50px; - } - - ::view-transition-old(*), - ::view-transition-new(*) { - animation-play-state: paused; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-ref.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-ref.html deleted file mode 100644 index 7db20046e03..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-opacity-ref.html +++ /dev/null @@ -1,26 +0,0 @@ -<!DOCTYPE html> -<body> -<style> - body { - margin: 0; - } - - .parent { - opacity: .4; - } - .child { - left: 50px; - top: 50px; - } - div.green { - position: absolute; - width: 100px; - height: 100px; - background: green; - will-change: opacity; - } -</style> - <div class="green parent"> - <div class="green child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-overflow-ref.sub.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-overflow-ref.sub.html deleted file mode 100644 index 31e9f63529b..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-overflow-ref.sub.html +++ /dev/null @@ -1,38 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Overflow should clip nested elements</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - } - - .parent { - overflow: {{GET[overflow]}}; - overflow-clip-margin: {{GET[margin]}}; - contain: {{GET[contain]}}; - border-radius: {{GET[radius]}}; - background: green; - } - - .child { - background: blue; - top: 50px; - left: 50px; - } - - ::view-transition-old(*), - ::view-transition-new(*) { - animation-play-state: paused; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-overflow.tentative.sub.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-overflow.tentative.sub.html deleted file mode 100644 index e513e63fc61..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/nested-overflow.tentative.sub.html +++ /dev/null @@ -1,58 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Overflow should clip nested elements</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="nested-overflow-ref.sub.html"> -<meta name="variant" content="?overflow=hidden&margin=0&contain=none&radius=0"> -<meta name="variant" content="?overflow=visible&margin=0&contain=none&radius=0"> -<meta name="variant" content="?overflow=visible&margin=0&contain=paint&radius=0"> -<meta name="variant" content="?overflow=visible&margin=20px&contain=paint&radius=0"> -<meta name="variant" content="?overflow=clip&margin=0&contain=none&radius=0"> -<meta name="variant" content="?overflow=clip&margin=10px&contain=non&radius=0"> -<meta name="variant" content="?overflow=clip&margin=0&contain=none&radius=10px"> -<meta name="variant" content="?overflow=clip&margin=10px&contain=none&radius=3px"> -<meta name="variant" content="?overflow=hidden&margin=0&contain=none&radius=10px"> -<script src="/common/reftest-wait.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - } - - .parent { - view-transition-name: parent; - overflow: {{GET[overflow]}}; - contain: {{GET[contain]}}; - overflow-clip-margin: {{GET[margin]}}; - border-radius: {{GET[radius]}}; - background: green; - } - - .child { - view-transition-name: child; - view-transition-group: parent; - background: blue; - top: 50px; - left: 50px; - } - - ::view-transition-old(*), - ::view-transition-new(*) { - animation-play-state: paused; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> - <script> -onload = async() => { - document.startViewTransition().ready.then(() => takeScreenshot()); -} - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-capture-observable-when-flat.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-capture-observable-when-flat.tentative.html deleted file mode 100644 index 6d4ddbe86b1..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-capture-observable-when-flat.tentative.html +++ /dev/null @@ -1,44 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Captured opacity is applied as group style</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="nested-opacity-ref.html"> -<script src="/common/reftest-wait.js"></script> -<script src="../nested/resources/compute-test.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - background: green; - } - - .parent { - opacity: 0.7; - view-transition-name: parent; - will-change: opacity; - } - - .child { - top: 50px; - left: 50px; - } - - ::view-transition-group(parent) { - opacity: 0.4; - animation-name: none; - } - ::view-transition-old(*), - ::view-transition-new(*) { - animation-play-state: paused; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-computed-style.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-computed-style.tentative.html deleted file mode 100644 index f370b7b03d2..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-computed-style.tentative.html +++ /dev/null @@ -1,50 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Applied opacity should not be observable via getComputedStyle</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - background: green; - } - - .parent { - view-transition-name: parent; - opacity: 0.4; - } - - .child { - view-transition-name: child; - view-transition-group: parent; - top: 50px; - left: 50px; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> - <script> - promise_test(async t => { - const assert_opacity = label => { - assert_equals(getComputedStyle(parent).opacity, "0.4", label); - }; - const parent = document.querySelector(".parent"); - assert_opacity("before transition"); - const transition = document.startViewTransition(() => { - assert_opacity("in update callback"); - }); - await transition.ready; - assert_opacity("when ready"); - await transition.finished; - assert_opacity("when finished"); - }); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-resets-after-done.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-resets-after-done.tentative.html deleted file mode 100644 index 7616638dc5e..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-resets-after-done.tentative.html +++ /dev/null @@ -1,45 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Opacity should apply to the whole group</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="nested-opacity-ref.html"> -<script src="/common/reftest-wait.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - background: green; - } - - .parent { - view-transition-name: parent; - opacity: 0.4; - will-change: opacity; - } - - .child { - view-transition-name: child; - view-transition-group: parent; - top: 50px; - left: 50px; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> - <script> -onload = async () => { - const transition = document.startViewTransition(); - await transition.updateCallbackDone; - transition.skipTransition(); - await transition.finished; - takeScreenshot(); -}; - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-resets-after-skip.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-resets-after-skip.tentative.html deleted file mode 100644 index e7a11ebe331..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/opacity-resets-after-skip.tentative.html +++ /dev/null @@ -1,41 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Opacity should apply to the whole group</title> -<meta name=fuzzy content="maxDifference=0-255; totalPixels=0-515"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="nested-opacity-ref.html"> -<script src="/common/reftest-wait.js"></script> -<style> - body { - margin: 0; - } - div { - position: absolute; - width: 100px; - height: 100px; - background: green; - } - - .parent { - view-transition-name: parent; - opacity: 0.4; - will-change: opacity; - } - - .child { - view-transition-name: child; - view-transition-group: parent; - top: 50px; - left: 50px; - } -</style> -<body> - <div class="parent"> - <div class="child"></div> - </div> - <script> -onload = () => { - document.startViewTransition().finished.then(() => takeScreenshot()); -}; - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/parsing/view-transition-capture-mode-invalid.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/parsing/view-transition-capture-mode-invalid.tentative.html deleted file mode 100644 index 6bcd77cdae0..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/parsing/view-transition-capture-mode-invalid.tentative.html +++ /dev/null @@ -1,18 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"> -<title>CSS View Transitions Test: view-transition-capture-mode with invalid values</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/css/support/parsing-testcommon.js"></script> -</head> -<body> -<script> -test_invalid_value("view-transition-capture-mode", "none"); -test_invalid_value("view-transition-capture-mode", "auto"); -test_invalid_value("view-transition-capture-mode", "stuff"); -</script> -</body> -</html> diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/parsing/view-transition-capture-mode-valid.tentative.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/parsing/view-transition-capture-mode-valid.tentative.html deleted file mode 100644 index 2b739fcfe28..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/parsing/view-transition-capture-mode-valid.tentative.html +++ /dev/null @@ -1,18 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"> -<title>CSS View Transitions Test: view-transition-capture-mode with valid values</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/css/support/parsing-testcommon.js"></script> -</head> -<body> -<script> -test_valid_value("view-transition-capture-mode", "flat"); -test_valid_value("view-transition-capture-mode", "layered"); - -</script> -</body> -</html> diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/tree-effects-ref.sub.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/tree-effects-ref.sub.html deleted file mode 100644 index e068b2918f1..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/tree-effects-ref.sub.html +++ /dev/null @@ -1,39 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Tree effects are captured as group style</title> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<style> - body { - margin: 0; - background: lightpink; - } - - .target { - width: 100px; - height: 100px; - margin: 20px; - background: green; - will-change: {{GET[prop]}}; - } - - @keyframes anim { - from { {{GET[prop]}}: {{GET[old]}}; } - to { {{GET[prop]}}: {{GET[new]}}; } - } - - .passthrough { - {{GET[prop]}}: {{GET[old]}}; - } - - .animate { - animation-name: anim; - animation-timing-function: steps(1, start); - animation-play-state: paused; - animation-duration: 100s; - } -</style> -<body> - <div class="override target"></div> - <div class="passthrough target"></div> - <div class="animate target"></div> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/layered-capture/tree-effects.tentative.sub.html b/tests/wpt/tests/css/css-view-transitions/layered-capture/tree-effects.tentative.sub.html deleted file mode 100644 index 31bb324e633..00000000000 --- a/tests/wpt/tests/css/css-view-transitions/layered-capture/tree-effects.tentative.sub.html +++ /dev/null @@ -1,73 +0,0 @@ -<!DOCTYPE html> -<html class=reftest-wait> -<title>Tree effects are captured as group style</title> -<meta name=fuzzy content="maxDifference=0-10; totalPixels=0-200000"> -<meta name="variant" content="?prop=filter&old=blur(3px)&new=blur(10px)"> -<meta name="variant" content="?prop=opacity&old=0.3&new=1"> -<meta name="variant" content="?prop=clip-path&old=inset(10px 10px)&new=inset(20px 20px)"> -<meta name="variant" content="?prop=mask-image&old=linear-gradient(rgb(0 0 0 / 80%), transparent)&new=none"> -<meta name="variant" content="?prop=mask&old=linear-gradient(red,blue) luminance&new=none"> -<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> -<link rel="match" href="tree-effects-ref.sub.html"> -<script src="/common/reftest-wait.js"></script> -<style> - html { - view-transition-name: none; - } - body { - margin: 0; - } - - .target { - width: 100px; - height: 100px; - margin: 20px; - background: green; - {{GET[prop]}}: {{GET[old]}}; - } - - html.vt-new .target { - {{GET[prop]}}: {{GET[new]}}; - } - - .override { - view-transition-name: override; - } - - .passthrough { - view-transition-name: passthrough; - } - .animate { - view-transition-name: animate; - } - - html::view-transition-group(*) { - animation-play-state: paused; - } - - html::view-transition-group(override) { - {{GET[prop]}}: unset; - animation: none; - } - - html::view-transition-group(animate) { - animation-timing-function: steps(1, start); - animation-play-state: paused; - animation-duration: 100s; - } - - html::view-transition { - background: lightpink; - } -</style> -<body> - <div class="override target"></div> - <div class="passthrough target"></div> - <div class="animate target"></div> - <script> - const transition = document.startViewTransition(() => { - document.documentElement.classList.add("vt-new"); - }); - transition.ready.then(() => takeScreenshot()); - </script> -</body>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-view-transitions/nested/rounded-border-clipper-ref.html b/tests/wpt/tests/css/css-view-transitions/nested/rounded-border-clipper-ref.html new file mode 100644 index 00000000000..3a52919e253 --- /dev/null +++ b/tests/wpt/tests/css/css-view-transitions/nested/rounded-border-clipper-ref.html @@ -0,0 +1,25 @@ +<!doctype html> +<title>Nested View Transitions: Rounded border clipper</title> +<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> + +<style> +#clipper { + overflow: clip; + height: 200px; + width: 100px; + border-radius: 20px; +} + +.item { + will-change: transform; + background: green; + position: relative; + height: 50px; + top: 50px; +} +</style> + +<div id=clipper> + <div class=item></div> +</div> + diff --git a/tests/wpt/tests/css/css-view-transitions/nested/rounded-border-clipper.html b/tests/wpt/tests/css/css-view-transitions/nested/rounded-border-clipper.html new file mode 100644 index 00000000000..239bcdd791d --- /dev/null +++ b/tests/wpt/tests/css/css-view-transitions/nested/rounded-border-clipper.html @@ -0,0 +1,64 @@ +<!doctype html> +<html class=reftest-wait> +<title>Nested View Transitions: Rounded border clipper</title> +<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/"> +<link rel="match" href="rounded-border-clipper-ref.html"> +<script src="/common/reftest-wait.js"></script> +<script src="resources/compute-test.js"></script> +<script src="/dom/events/scrolling/scroll_support.js"></script> + +<style> +:root { view-transition-name: none } + +#clipper { + view-transition-group: contain; + view-transition-name: clipper; + overflow: clip; + height: 200px; + width: 100px; + border-radius: 20px; +} + +.item { + will-change: transform; + view-transition-name: item; + background: green; + position: relative; + height: 50px; +} + +.lower { + top: 50px; +} + +::view-transition-group(clipper) { + animation-play-state: paused; + overflow: clip; + border-radius: 20px; +} +</style> + +<div id=clipper> + <div id=item class=item></div> +</div> + +<script> + +async function runTest() { + await document.startViewTransition(() => item.classList.add("lower")).ready; + + let anims = document.documentElement.getAnimations({ subtree: true }); + let promises = anims.map(anim => { + if (anim.playState != "paused") { + return anim.finished; + } + }); + Promise.all(promises).then(takeScreenshot); +} + +onload = () => { + waitForCompositorReady().then(runTest); +} +</script> + + diff --git a/tests/wpt/tests/css/css-view-transitions/pseudo-get-computed-style.html b/tests/wpt/tests/css/css-view-transitions/pseudo-get-computed-style.html index 3e971885c39..60e032b1d98 100644 --- a/tests/wpt/tests/css/css-view-transitions/pseudo-get-computed-style.html +++ b/tests/wpt/tests/css/css-view-transitions/pseudo-get-computed-style.html @@ -8,7 +8,7 @@ <script src="/resources/testharnessreport.js"></script> <style> -div { +#target { width: 100px; height: 100px; background: blue; @@ -26,87 +26,90 @@ div { <div id=target></div> <script> -promise_test(() => { +promise_test(async () => { assert_implements(document.startViewTransition, "Missing document.startViewTransition"); - return new Promise(async (resolve, reject) => { - let transition = document.startViewTransition(() => { - assert_equals(getComputedStyle(document.documentElement, "::view-transition").position, "fixed", "::view-transition"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute", "container(target)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").mixBlendMode, "multiply", "container(target)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").textOrientation, "upright", "container(target)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").colorScheme, "dark light", "container(target)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(target)").position, "absolute", "wrapper(target)"); - - assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(target)").position, "absolute", "outgoing(target)"); - - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").position, "absolute", "container(root)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").mixBlendMode, "normal", "container(root)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(root)").position, "absolute", "wrapper(root)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(root)").position, "absolute", "outgoing(root)"); - - requestAnimationFrame(() => { - assert_equals(getComputedStyle(document.documentElement, "::view-transition").position, "fixed", "raf ::view-transition"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute", "raf container(target)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").mixBlendMode, "multiply", "raf container(target)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").textOrientation, "upright", "raf container(target)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").colorScheme, "dark light", "raf container(target)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(target)").position, "fixed", "raf wrapper(target)"); - - assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(target)").position, "absolute", "raf outgoing(target)"); - - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").position, "absolute", "raf container(root)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").mixBlendMode, "normal", "raf container(root)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(root)").position, "absolute", "raf wrapper(root)"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(root)").position, "absolute", "raf outgoing(root)"); - }); + let transition = document.startViewTransition(() => { + assert_equals(getComputedStyle(document.documentElement, "::view-transition").position, "fixed", "::view-transition"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute", "container(target)"); + // The position is set via the style rules, so it should be applied once + // we create the pseudo elements. + assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(target)").position, "fixed", "wrapper(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(target)").position, "absolute", "outgoing(target)"); + + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").position, "absolute", "container(root)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(root)").position, "absolute", "wrapper(root)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(root)").position, "absolute", "outgoing(root)"); + + // Per spec, we update pseudo-element styles when activating the + // transition, and this is after we invoke the update callback. Therefore, + // these computed values should be the default values at this moment. + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").textOrientation, "mixed", "container(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").colorScheme, "normal", "container(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").mixBlendMode, "normal", "container(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").mixBlendMode, "normal", "container(root)"); + + // After one frame, the activation of the view transition should be done, so + // we have updated the pseudo-element styles. + requestAnimationFrame(() => { + assert_equals(getComputedStyle(document.documentElement, "::view-transition").position, "fixed", "raf ::view-transition"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute", "raf container(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").mixBlendMode, "multiply", "raf container(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").textOrientation, "upright", "raf container(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").colorScheme, "dark light", "raf container(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(target)").position, "fixed", "raf wrapper(target)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(target)").position, "absolute", "raf outgoing(target)"); + + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").position, "absolute", "raf container(root)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").mixBlendMode, "normal", "raf container(root)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(root)").position, "absolute", "raf wrapper(root)"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(root)").position, "absolute", "raf outgoing(root)"); }); - await transition.finished; - resolve(); }); -}, "position property of pseudo elements"); + await transition.finished; +}, "properties of pseudo elements in update callback"); -promise_test(() => { +promise_test(async () => { assert_implements(document.startViewTransition, "Missing document.startViewTransition"); - return new Promise(async (resolve, reject) => { - let transition = document.startViewTransition(() => { - assert_equals(getComputedStyle(document.documentElement, "::view-transition").position, "fixed"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(target)").position, "absolute"); - - assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(target)").position, "absolute"); - - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").position, "absolute"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(root)").position, "absolute"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(root)").position, "absolute"); - - target.remove(); - }); - - await transition.ready; - + let transition = document.startViewTransition(() => { assert_equals(getComputedStyle(document.documentElement, "::view-transition").position, "fixed"); assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").mixBlendMode, "multiply"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").textOrientation, "upright"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").colorScheme, "dark light"); + // The position is set via the style rules, so it should be applied once + // we create the pseudo elements. assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(target)").position, "fixed"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(target)").position, "absolute"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-new(target)").position, "absolute"); assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").position, "absolute"); assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(root)").position, "absolute"); assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(root)").position, "absolute"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-new(root)").position, "absolute"); - assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute"); + target.remove(); + }); - await transition.finished; + await transition.ready; - // With custom ua sheets not applying to non-existing pseudo, the value should be the default (not absolute) - assert_not_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition").position, "fixed"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").mixBlendMode, "multiply"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").textOrientation, "upright"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").colorScheme, "dark light"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(target)").position, "fixed"); - resolve(); - }); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(target)").position, "absolute"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-new(target)").position, "absolute"); + + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(root)").position, "absolute"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(root)").position, "absolute"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(root)").position, "absolute"); + assert_equals(getComputedStyle(document.documentElement, "::view-transition-new(root)").position, "absolute"); + + assert_equals(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, "absolute"); + + await transition.finished; + + // The spec doesn't mention whether we should apply the custom ua sheets to + // the non-existing pseudo elements. In Chromium, it doesn't apply it, so it + // would be the default (i.e. static). However, in WebKit and Gecko, they + // still apply the costom ua sheets. Therefore, we accept both cases for now. + assert_in_array(getComputedStyle(document.documentElement, "::view-transition-group(target)").position, ["static", "absolute"]); }, "properties of pseudo elements outside of transition"); </script> diff --git a/tests/wpt/tests/css/css-view-transitions/start-view-transtion-skips-active.html b/tests/wpt/tests/css/css-view-transitions/start-view-transtion-skips-active.html new file mode 100644 index 00000000000..971c7b38d4c --- /dev/null +++ b/tests/wpt/tests/css/css-view-transitions/start-view-transtion-skips-active.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>startViewTranstion cancels active transition</title> + <link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/"> +</head> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<style> + :root { + view-transition-name: none; + } + #target { + width: 100px; + height: 100px; + background: blue; + contain: paint; + view-transition-name: target; + } + #target.update-1 { + height: 150px; + } + #target.update-2 { + height: 200px; + } +</style> + +<body> + <div id="target"></div> +</body> +<script> + promise_test(async t => { + let rejected_promise_tally = 0; + const target = document.getElementById("target"); + assert_implements(document.startViewTransition, + "Missing document.startViewTransition"); + + const verifyAbortedTransition = (promise) => { + return promise.then( + () => { assert_not_reached('transition aborted') }, + (reason) => { + assert_true(reason instanceof DOMException); + assert_equals(reason.code, DOMException.ABORT_ERR); + rejected_promise_tally++; + }); + }; + + const vt1 = document.startViewTransition(() => { + target.className = 'update-1'; + }); + const vt2 = document.startViewTransition(() => { + assert_equals(target.className, 'update-1'); + target.className = 'update-2'; + }); + const vt3 = document.startViewTransition(() => { + assert_equals(target.className, 'update-2'); + }); + + await verifyAbortedTransition(vt1.ready); + await verifyAbortedTransition(vt2.ready); + await vt3.ready; + + assert_equals(rejected_promise_tally, 2, + 'first 2 transitions are skipped'); + const sizeTransformAnimations = document.getAnimations().filter(a => { + return 'height' in a.effect.getKeyframes()[0]; + }); + assert_equals(sizeTransformAnimations.length, 1); + const startingHeight = + sizeTransformAnimations[0].effect.getKeyframes()[0].height; + + assert_equals(startingHeight, '200px', + 'Height change applied before capture'); + + }, 'Synchronously starting a view transition skips the previously active ' + + ' transition.'); + +</script> +</html> diff --git a/tests/wpt/tests/css/css-will-change/will-change-stacking-context-mask-image-1.html b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-mask-image-1.html new file mode 100644 index 00000000000..9a2e03d57af --- /dev/null +++ b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-mask-image-1.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS will-change: 'will-change: mask-image' creates a stacking context</title> +<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change"> +<link rel="help" href="http://www.w3.org/TR/css-masking/#the-mask-image"> +<link rel="match" href="green-square-100-by-100-ref.html"> +<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element."> +<style> +html, body { margin: 0; padding: 0; } +div { width: 100px; height: 100px } +#wc { will-change: mask-image; background: red } +#child { position: absolute; top: 0; left: 0; z-index: -1; background: green } +</style> +<body> + <div id="wc"> + <div id="child"> + </div> + </div> +</body> diff --git a/tests/wpt/tests/css/css-will-change/will-change-stacking-context-view-transition-name-1.html b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-view-transition-name-1.html new file mode 100644 index 00000000000..b6c64be1ccc --- /dev/null +++ b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-view-transition-name-1.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS will-change: 'will-change: view-transition-name' creates a stacking context</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/css-will-change-1/#will-change"> +<link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/#named-and-transitioning"> +<link rel="match" href="green-square-100-by-100-ref.html"> +<meta name="assert" content="If any non-initial value of a property would create a stacking context on the element, specifying that property in will-change must create a stacking context on the element."> +<style> +html, body { margin: 0; padding: 0; } +div { width: 100px; height: 100px } +#wc { will-change: view-transition-name; background: red } +#child { position: absolute; top: 0; left: 0; z-index: -1; background: green } +</style> +<body> + <div id="wc"> + <div id="child"> + </div> + </div> +</body> diff --git a/tests/wpt/tests/css/css-writing-modes/orthogonal-child-with-border.html b/tests/wpt/tests/css/css-writing-modes/orthogonal-child-with-border.html new file mode 100644 index 00000000000..877cce5a710 --- /dev/null +++ b/tests/wpt/tests/css/css-writing-modes/orthogonal-child-with-border.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html class="reftest-wait"> + <meta charset="utf-8"> + <link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-writing-modes/#orthogonal-flows"> + <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1949151"> + <link rel="match" href="../reference/ref-filled-green-100px-square.xht"> + <meta name="assert" content="Size of the outer div fits its orthogonal child (including borders) after a dynamic change."> + <style> + #outer { + position: absolute; + background: red; + writing-mode: vertical-lr; + } + #inner { + width: 100px; + border: 0px solid green; + border-width: 40px 20px 60px 30px; /* top + bottom borders = 100px */ + writing-mode: horizontal-tb; + } + </style> + + <script> + function run() { + inner.style.width = "50px"; /* left + right borders add a further 50px */ + document.documentElement.classList.remove("reftest-wait"); + } + </script> + + <body onload="run()"> + <p>Test passes if there is a filled green square and <strong>no red</strong>.</p> + + <div id="outer"> + <div id="inner"> + </div> + </div> + </body> +</html> diff --git a/tests/wpt/tests/css/css-writing-modes/orthogonal-child-with-padding.html b/tests/wpt/tests/css/css-writing-modes/orthogonal-child-with-padding.html new file mode 100644 index 00000000000..c8e9e35c5b5 --- /dev/null +++ b/tests/wpt/tests/css/css-writing-modes/orthogonal-child-with-padding.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html class="reftest-wait"> + <meta charset="utf-8"> + <link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-writing-modes/#orthogonal-flows"> + <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1949153"> + <link rel="match" href="../reference/ref-filled-green-100px-square.xht"> + <meta name="assert" content="Size of the outer div fits its orthogonal child (including padding) after a dynamic change."> + <style> + #outer { + position: absolute; + background: red; + } + #inner { + height: 50px; + min-width: 50px; + padding-left: 25px; + padding-right: 25px; + writing-mode: vertical-rl; + } + #mask { + position: absolute; + width: 100px; + height: 100px; + background: green; + } + </style> + + <script> + function run() { + inner.style.height = "100px"; + document.documentElement.classList.remove("reftest-wait"); + } + </script> + + <body onload="run()"> + <p>Test passes if there is a filled green square and <strong>no red</strong>.</p> + + <div id="outer"> + <div id="inner"> + </div> + </div> + <div id="mask"> + </div> + </body> +</html> diff --git a/tests/wpt/tests/css/cssom-view/scrollTo-zoom.html b/tests/wpt/tests/css/cssom-view/scrollTo-zoom.html new file mode 100644 index 00000000000..49ec4932503 --- /dev/null +++ b/tests/wpt/tests/css/cssom-view/scrollTo-zoom.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollto"> +<link rel="match" href="../reference/ref-nothing-below.xht" /> +<meta name="assert" content="This test checks scrollTo() with different zoom levels."> +<style> + .container { + position: relative; + width: 100px; + height: 100px; + overflow: scroll; + background: red; + scrollbar-width: none; + } + .container > div { + position: absolute; + left: 13px; + top: 27px; + width: 100px; + height: 100px; + background: white; + } +</style> +<body style="background: white;"> + <p>Test passes if there is nothing below.</p> + <div class="container" style="zoom: 0.9;"> + <div></div> + </div> + <div class="container" style="zoom: 1;"> + <div></div> + </div> + <div class="container" style="zoom: 1.11;"> + <div></div> + </div> + <div class="container" style="zoom: 1.5;"> + <div></div> + </div> + <script> + Array.prototype.forEach.call(document.getElementsByClassName("container"), (el) => { + el.scrollTo(13, 27); + }); + </script> +</body> diff --git a/tests/wpt/tests/css/cssom/resolved-border-width.html b/tests/wpt/tests/css/cssom/resolved-border-width.html new file mode 100644 index 00000000000..2e775dcccc4 --- /dev/null +++ b/tests/wpt/tests/css/cssom/resolved-border-width.html @@ -0,0 +1,19 @@ +<!doctype html> +<meta charset="utf-8"> +<link rel="help" href="https://drafts.csswg.org/cssom-1/#resolved-values"> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +<title>border-*-width returns computed rather than used values from getComputedStyle()</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<input type=checkbox style="border: 5px solid red"> +<input type=radio style="border: 5px solid red"> +<script> +for (let input of document.querySelectorAll("input")) { + test(() => { + let cs = getComputedStyle(input); + for (let prop of ["border-width", "border-top-width", "border-right-width", "border-bottom-width", "border-left-width"]) { + assert_equals(cs.getPropertyValue(prop), "5px", prop); + } + }, input.type); +} +</script> diff --git a/tests/wpt/tests/css/filter-effects/empty-element-with-filter-002.html b/tests/wpt/tests/css/filter-effects/empty-element-with-filter-002.html new file mode 100644 index 00000000000..50c3073d1fc --- /dev/null +++ b/tests/wpt/tests/css/filter-effects/empty-element-with-filter-002.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>CSS Filter Effects: ref filters on zero-sized block elements with no visible content</title> +<link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty"> +<link rel="match" href="reference/green-100x100.html"> +<meta name="assert" content="This test ensures we properly render filters on block elements that are zero-sized with no visible content."> +<style> + .flood { + width: 0px; + height: 0px; + filter: url(#f_flood); + } +</style> +<div class="flood"></div> +<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1"> + <defs> + <filter id="f_flood" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" x="0" y="0" width="100" height="100"> + <feFlood flood-color="green"/> + </filter> + </defs> +</svg> diff --git a/tests/wpt/tests/css/filter-effects/empty-element-with-filter-003.html b/tests/wpt/tests/css/filter-effects/empty-element-with-filter-003.html new file mode 100644 index 00000000000..b9e2cb95572 --- /dev/null +++ b/tests/wpt/tests/css/filter-effects/empty-element-with-filter-003.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>CSS Filter Effects: ref filters on zero-sized inline elements with no visible content</title> +<link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty"> +<link rel="match" href="reference/green-100x100.html"> +<meta name="assert" content="This test ensures we properly render filters on inline elements that are zero-sized with no visible content."> +<style> + .flood { + width: 0px; + height: 0px; + filter: url(#f_flood); + } +</style> +<span class="flood"></span> +<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1"> + <defs> + <filter id="f_flood" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" x="0" y="0" width="100" height="100"> + <feFlood flood-color="green"/> + </filter> + </defs> +</svg> diff --git a/tests/wpt/tests/css/filter-effects/filter-subregion-01.html b/tests/wpt/tests/css/filter-effects/filter-subregion-01.html index c2a0c18f6c4..e8582b17e37 100644 --- a/tests/wpt/tests/css/filter-effects/filter-subregion-01.html +++ b/tests/wpt/tests/css/filter-effects/filter-subregion-01.html @@ -4,6 +4,7 @@ <link rel="author" title="Chris Lilley" href="mailto:chris@w3.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterPrimitiveSubRegion"> <link rel="match" href="filter-subregion-01-ref.html"> +<meta name="fuzzy" content="maxDifference=0-5; totalPixels=0-1000"/> <p>Test passes if two semi-transparent green rectangles are on top of the blue boxes to the left, and one opaque green rectangle on the blue box to the right.</p> diff --git a/tests/wpt/tests/custom-elements/form-associated/ElementInternals-validation.html b/tests/wpt/tests/custom-elements/form-associated/ElementInternals-validation.html index 2b8fd6afadf..1dbf98a13bf 100644 --- a/tests/wpt/tests/custom-elements/form-associated/ElementInternals-validation.html +++ b/tests/wpt/tests/custom-elements/form-associated/ElementInternals-validation.html @@ -189,6 +189,15 @@ test(() => { }, 'validity and setValidity()'); test(() => { + const control = document.createElement('my-control'); + control.i.setValidity({badInput: true}, 'error message'); + const validity = control.i.validity; + assert_false(validity.customError); + assert_false(validity.valid); + assert_equals(control.i.validationMessage, 'error message'); +}, "validity.customError should be false if not explicitly set via setValidity()"); + +test(() => { document.body.insertAdjacentHTML('afterbegin', '<my-control><light-child></my-control>'); let control = document.body.firstChild; const flags = {valueMissing: true}; diff --git a/tests/wpt/tests/device-bound-session-credentials/clear-site-data.https.html b/tests/wpt/tests/device-bound-session-credentials/clear-site-data.https.html new file mode 100644 index 00000000000..2d6e42977d1 --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/clear-site-data.https.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>DBSC session ended with Clear-Site-Data</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="helper.js" type="module"></script> + +<script type="module"> + import { expireCookie, documentHasCookie, waitForCookie, addCookieAndSessionCleanup, setupShardedServerState } from "./helper.js"; + + promise_test(async t => { + const testId = await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // The server ends the session. + const end_session_response = await fetch('end_session_via_clear_site_data.py'); + assert_equals(end_session_response.status, 200); + // Need to set up the state again because all cookies were cleared. + await setupShardedServerState(testId); + + // Expire the cookie, and confirm it does not get refreshed. + expireCookie(expectedCookieAndAttributes); + assert_false(documentHasCookie(expectedCookieAndValue)); + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 401); + assert_false(documentHasCookie(expectedCookieAndValue)); + }, "An session ended with Clear-Site-Data: 'cookies' does not refresh cookies"); + + promise_test(async t => { + const testId = await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // The server ends the session. + const end_session_response = await fetch('end_session_via_clear_site_data.py', {method: 'POST', body: '"storage"'}); + assert_equals(end_session_response.status, 200); + // Need to set up the state again because all cookies were cleared. + await setupShardedServerState(testId); + + // Expire the cookie, and confirm it does not get refreshed. + expireCookie(expectedCookieAndAttributes); + assert_false(documentHasCookie(expectedCookieAndValue)); + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 401); + assert_false(documentHasCookie(expectedCookieAndValue)); + }, "An session ended with Clear-Site-Data: 'storage' does not refresh cookies") +</script> diff --git a/tests/wpt/tests/device-bound-session-credentials/clear_server_state_and_end_sessions.py b/tests/wpt/tests/device-bound-session-credentials/clear_server_state_and_end_sessions.py deleted file mode 100644 index f0174019e96..00000000000 --- a/tests/wpt/tests/device-bound-session-credentials/clear_server_state_and_end_sessions.py +++ /dev/null @@ -1,6 +0,0 @@ -import importlib -session_provider = importlib.import_module('device-bound-session-credentials.session_provider') - -def main(request, response): - session_provider.clear_server_state() - return (200, [("Clear-Site-Data", '"cookies"')], "") diff --git a/tests/wpt/tests/device-bound-session-credentials/configure_server.py b/tests/wpt/tests/device-bound-session-credentials/configure_server.py new file mode 100644 index 00000000000..6700fdef7b6 --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/configure_server.py @@ -0,0 +1,8 @@ +import json +import importlib +session_manager = importlib.import_module('device-bound-session-credentials.session_manager') + +def main(request, response): + request_body = json.loads(request.body.decode('utf-8')) + session_manager.find_for_request(request).configure_state_for_test(request_body) + return (200, response.headers, "") diff --git a/tests/wpt/tests/device-bound-session-credentials/create-session.https.html b/tests/wpt/tests/device-bound-session-credentials/create-session.https.html index 09c76b7e9ed..cddfd179797 100644 --- a/tests/wpt/tests/device-bound-session-credentials/create-session.https.html +++ b/tests/wpt/tests/device-bound-session-credentials/create-session.https.html @@ -1,18 +1,19 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>DBSC session-creating tests</title> +<title>DBSC create a basic session</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/common/get-host-info.sub.js"></script> <script src="helper.js" type="module"></script> <script type="module"> - import { expireCookie, documentHasCookie, waitForCookie, addCookieAndServerCleanup } from "./helper.js"; + import { expireCookie, documentHasCookie, waitForCookie, addCookieAndSessionCleanup, setupShardedServerState } from "./helper.js"; promise_test(async t => { + await setupShardedServerState(); const expectedCookieAndValue = "auth_cookie=abcdef0123"; const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; - addCookieAndServerCleanup(t, expectedCookieAndAttributes); + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); // Prompt starting a session, and wait until registration completes. const login_response = await fetch('login.py'); diff --git a/tests/wpt/tests/device-bound-session-credentials/end_session_via_clear_site_data.py b/tests/wpt/tests/device-bound-session-credentials/end_session_via_clear_site_data.py new file mode 100644 index 00000000000..29636973a58 --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/end_session_via_clear_site_data.py @@ -0,0 +1,7 @@ +import json + +def main(request, response): + types = request.body.decode('utf-8') + if types == "": + types = '"cookies"' + return (200, [("Clear-Site-Data", types)], "") diff --git a/tests/wpt/tests/device-bound-session-credentials/helper.js b/tests/wpt/tests/device-bound-session-credentials/helper.js index 24756220682..c4cfcfc1f75 100644 --- a/tests/wpt/tests/device-bound-session-credentials/helper.js +++ b/tests/wpt/tests/device-bound-session-credentials/helper.js @@ -23,11 +23,36 @@ export function expireCookie(cookieAndAttributes) { cookieAndAttributes + '; expires=Thu, 01 Jan 1970 00:00:00 UTC;'; } -export function addCookieAndServerCleanup(test, cookieAndAttributes) { +export function addCookieAndSessionCleanup(test, cookieAndAttributes) { // Clean up any set cookies once the test completes. test.add_cleanup(async () => { - const response = await fetch('clear_server_state_and_end_sessions.py'); + const response = await fetch('end_session_via_clear_site_data.py'); assert_equals(response.status, 200); expireCookie(cookieAndAttributes); }); } + +export async function configureServer(obj) { + const response = await fetch('configure_server.py', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify(obj), + }); + assert_equals(response.status, 200); +} + +export async function setupShardedServerState(testId) { + const obj = {}; + if (testId !== undefined) { + obj.testId = testId; + } + const response = await fetch('setup_sharded_server_state.py', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify(obj), + }); + assert_equals(response.status, 200); + const testIdCookie = + document.cookie.split(';').filter(item => item.includes('test_id'))[0]; + return testIdCookie.split('=')[1]; +} diff --git a/tests/wpt/tests/device-bound-session-credentials/login.py b/tests/wpt/tests/device-bound-session-credentials/login.py index 9934488283a..2e2d93a8e47 100644 --- a/tests/wpt/tests/device-bound-session-credentials/login.py +++ b/tests/wpt/tests/device-bound-session-credentials/login.py @@ -1,3 +1,11 @@ +import importlib +session_manager = importlib.import_module('device-bound-session-credentials.session_manager') + def main(request, response): - headers = [('Sec-Session-Registration', '(RS256);challenge="login_challenge_value";path="/device-bound-session-credentials/start_session.py"')] + authorization_value = session_manager.find_for_request(request).get_authorization_value() + authorization_header = "" + if authorization_value is not None: + authorization_header = ';authorization="' + authorization_value + '"' + + headers = [('Sec-Session-Registration', '(RS256);challenge="login_challenge_value";path="/device-bound-session-credentials/start_session.py"' + authorization_header)] return (200, headers, "") diff --git a/tests/wpt/tests/device-bound-session-credentials/not-secure-connection.html b/tests/wpt/tests/device-bound-session-credentials/not-secure-connection.html index e19f7379629..93736c0b596 100644 --- a/tests/wpt/tests/device-bound-session-credentials/not-secure-connection.html +++ b/tests/wpt/tests/device-bound-session-credentials/not-secure-connection.html @@ -7,12 +7,13 @@ <script src="helper.js" type="module"></script> <script type="module"> - import { expireCookie, waitForCookie, addCookieAndServerCleanup } from "./helper.js"; + import { expireCookie, waitForCookie, addCookieAndSessionCleanup, setupShardedServerState } from "./helper.js"; promise_test(async t => { + await setupShardedServerState(); const expectedCookieAndValue = "auth_cookie=abcdef0123"; const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; - addCookieAndServerCleanup(t, expectedCookieAndAttributes); + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); // Prompt starting a session, and wait until registration completes. const login_response = await fetch('login.py'); diff --git a/tests/wpt/tests/device-bound-session-credentials/refresh-replaces-config.https.html b/tests/wpt/tests/device-bound-session-credentials/refresh-replaces-config.https.html new file mode 100644 index 00000000000..1ac8096b5de --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/refresh-replaces-config.https.html @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>DBSC refresh sends back new session config</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="helper.js" type="module"></script> + +<script type="module"> + import { expireCookie, waitForCookie, addCookieAndSessionCleanup, configureServer, setupShardedServerState, documentHasCookie } from "./helper.js"; + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue1 = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes1 = `${expectedCookieAndValue1};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes1); + const expectedCookieAndValue2 = "other_cookie=ghijkl4567"; + const expectedCookieAndAttributes2 = `${expectedCookieAndValue2};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes2); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue1)); + + // Confirm that a request has the cookie set. + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 200); + // Confirm that a request does not have alternate cookie set. + const alternate_auth_response = await fetch('verify_authenticated.py', { + method: 'POST', + body: expectedCookieAndValue2 + }); + assert_equals(alternate_auth_response.status, 401); + + // Configure server to change the cookie in the session config on next refresh. + configureServer({ cookieNameAndValue: expectedCookieAndValue2 }); + + // Expire the first cookie and send a request, which triggers the refresh with the new session config. + expireCookie(expectedCookieAndAttributes1); + assert_false(documentHasCookie(expectedCookieAndValue1)); + const auth_response_after_expiry1 = await fetch('verify_authenticated.py'); + assert_equals(auth_response_after_expiry1.status, 401); + assert_false(documentHasCookie(expectedCookieAndValue1)); + + // Confirm the alternate cookie is set and included in requests. + assert_true(documentHasCookie(expectedCookieAndValue2)); + const alternate_auth_response_after_expiry1 = await fetch('verify_authenticated.py', { + method: 'POST', + body: expectedCookieAndValue2 + }); + assert_equals(alternate_auth_response_after_expiry1.status, 200); + + // Expire the second cookie. Confirm the second cookie is refreshed, and not the first. + expireCookie(expectedCookieAndAttributes2); + assert_false(documentHasCookie(expectedCookieAndValue2)); + const alternate_auth_response_after_expiry2 = await fetch('verify_authenticated.py', { + method: 'POST', + body: expectedCookieAndValue2 + }); + assert_equals(alternate_auth_response_after_expiry2.status, 200); + assert_true(documentHasCookie(expectedCookieAndValue2)); + assert_false(documentHasCookie(expectedCookieAndValue1)); +}, "Refresh can replace session config"); +</script>
\ No newline at end of file diff --git a/tests/wpt/tests/device-bound-session-credentials/refresh-with-continue-false.https.html b/tests/wpt/tests/device-bound-session-credentials/refresh-with-continue-false.https.html new file mode 100644 index 00000000000..9ebec220977 --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/refresh-with-continue-false.https.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>DBSC session ended with continue:false</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="helper.js" type="module"></script> + +<script type="module"> + import { expireCookie, documentHasCookie, waitForCookie, addCookieAndSessionCleanup, configureServer, setupShardedServerState } from "./helper.js"; + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + + // Configure server to end the session upon refresh. + configureServer({ shouldRefreshEndSession: true }); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // Confirm that a request has the cookie set. + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 200); + + // Expire the cookie. The server will end the session on attempted refresh. + expireCookie(expectedCookieAndAttributes); + assert_false(documentHasCookie(expectedCookieAndValue)); + const auth_response_after_expiry = await fetch('verify_authenticated.py'); + assert_equals(auth_response_after_expiry.status, 401); + assert_false(documentHasCookie(expectedCookieAndValue)); + }, "A session ended with continue:false does not refresh cookies"); +</script>
\ No newline at end of file diff --git a/tests/wpt/tests/device-bound-session-credentials/refresh_session.py b/tests/wpt/tests/device-bound-session-credentials/refresh_session.py index 4d83c86b47b..9b39118ce71 100644 --- a/tests/wpt/tests/device-bound-session-credentials/refresh_session.py +++ b/tests/wpt/tests/device-bound-session-credentials/refresh_session.py @@ -1,13 +1,23 @@ import importlib +import json jwt_helper = importlib.import_module('device-bound-session-credentials.jwt_helper') -session_provider = importlib.import_module('device-bound-session-credentials.session_provider') +session_manager = importlib.import_module('device-bound-session-credentials.session_manager') def main(request, response): session_id_header = request.headers.get("Sec-Session-Id") if session_id_header == None: return (400, response.headers, "") session_id = session_id_header.decode('utf-8') - session_key = session_provider.get_session_key(session_id) + test_session_manager = session_manager.find_for_request(request) + + if test_session_manager.get_should_refresh_end_session(): + response_body = { + "session_identifier": session_id, + "continue": False + } + return (200, response.headers, json.dumps(response_body)) + + session_key = test_session_manager.get_session_key(session_id) if session_key == None: return (400, response.headers, "") @@ -17,7 +27,10 @@ def main(request, response): jwt_header, jwt_payload, verified = jwt_helper.decode_jwt(request.headers.get("Sec-Session-Response").decode('utf-8'), session_key) + if test_session_manager.get_send_challenge_early(): + challenge = "early_challenge" + if not verified or jwt_payload.get("jti") != challenge: return (400, response.headers, "") - return session_provider.get_session_instructions_response(session_id, request) + return test_session_manager.get_session_instructions_response(session_id, request) diff --git a/tests/wpt/tests/device-bound-session-credentials/registration-sends-challenge.https.html b/tests/wpt/tests/device-bound-session-credentials/registration-sends-challenge.https.html new file mode 100644 index 00000000000..36aeb631fcd --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/registration-sends-challenge.https.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>DBSC registration sends back Sec-Session-Challenge</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="helper.js" type="module"></script> + +<script type="module"> + import { expireCookie, waitForCookie, addCookieAndSessionCleanup, configureServer, setupShardedServerState, documentHasCookie } from "./helper.js"; + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + + // Configure server to send back a challenge during registration. + configureServer({ registrationSendsChallenge: true }); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // Confirm that a request has the cookie set. + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 200); + + // Confirm that expiring the cookie still leads to a request with the cookie set (refresh occurs). + expireCookie(expectedCookieAndAttributes); + assert_false(documentHasCookie(expectedCookieAndValue)); + const auth_response_after_expiry = await fetch('verify_authenticated.py'); + assert_equals(auth_response_after_expiry.status, 200); + assert_true(documentHasCookie(expectedCookieAndValue)); +}, "Registration can send back Sec-Session-Challenge"); +</script>
\ No newline at end of file diff --git a/tests/wpt/tests/device-bound-session-credentials/request_early_challenge.py b/tests/wpt/tests/device-bound-session-credentials/request_early_challenge.py new file mode 100644 index 00000000000..e3e429ee76f --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/request_early_challenge.py @@ -0,0 +1,10 @@ +import importlib +session_manager = importlib.import_module('device-bound-session-credentials.session_manager') + +def main(request, response): + session_ids = session_manager.find_for_request(request).get_session_ids() + if len(session_ids) != 1: + return (500, "", "") + session_id_header = ';id="' + session_ids[0] + '"' + + return (200, [("Sec-Session-Challenge", '"early_challenge"' + session_id_header)], "") diff --git a/tests/wpt/tests/device-bound-session-credentials/session-cookie-has-no-attributes.https.html b/tests/wpt/tests/device-bound-session-credentials/session-cookie-has-no-attributes.https.html new file mode 100644 index 00000000000..9e526419307 --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/session-cookie-has-no-attributes.https.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>DBSC session cookie has only default attributes</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="helper.js" type="module"></script> + +<script type="module"> + import { expireCookie, documentHasCookie, waitForCookie, addCookieAndSessionCleanup, setupShardedServerState, configureServer } from "./helper.js"; + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + addCookieAndSessionCleanup(t, expectedCookieAndValue); + + // Configure server to set up a session with a cookie that has no attributes. + configureServer({ cookieHasNoAttributes: true }); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // Confirm that a request has the cookie set. + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 200); + + // Confirm that expiring the cookie still leads to a request with the cookie set (refresh occurs). + expireCookie(expectedCookieAndValue); + assert_false(documentHasCookie(expectedCookieAndValue)); + const auth_response_after_expiry = await fetch('verify_authenticated.py'); + assert_equals(auth_response_after_expiry.status, 200); + assert_true(documentHasCookie(expectedCookieAndValue)); + }, "An established session can refresh a cookie that has all default attributes"); +</script>
\ No newline at end of file diff --git a/tests/wpt/tests/device-bound-session-credentials/session_manager.py b/tests/wpt/tests/device-bound-session-credentials/session_manager.py new file mode 100644 index 00000000000..98eb120ed7c --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/session_manager.py @@ -0,0 +1,124 @@ +import json + +test_to_session_manager_mapping = {} + +def initialize_test(): + test_id = str(len(test_to_session_manager_mapping)) + test_to_session_manager_mapping[test_id] = SessionManager() + return test_id + +def find_for_request(request): + test_id = request.cookies.get(b'test_id').value.decode('utf-8') + manager = test_to_session_manager_mapping.get(test_id) + if manager == None: + raise Exception("Could not find manager for test_id: " + test_id) + return manager + +class SessionManager: + def __init__(self): + self.session_to_key_map = {} + self.should_refresh_end_session = False + self.authorization_value = None + self.send_challenge_early = False + self.cookie_has_no_attributes = False + self.scope_origin = None + self.registration_sends_challenge = False + self.cookie_name_and_value = "auth_cookie=abcdef0123" + + def create_new_session(self): + session_id = str(len(self.session_to_key_map)) + self.session_to_key_map[session_id] = None + return session_id + + def set_session_key(self, session_id, key): + if session_id not in self.session_to_key_map: + return False + self.session_to_key_map[session_id] = key + return True + + def get_session_key(self, session_id): + return self.session_to_key_map.get(session_id) + + def get_session_ids(self): + return list(self.session_to_key_map.keys()) + + def configure_state_for_test(self, configuration): + should_refresh_end_session = configuration.get("shouldRefreshEndSession") + if should_refresh_end_session is not None: + self.should_refresh_end_session = should_refresh_end_session + + authorization_value = configuration.get("authorizationValue") + if authorization_value is not None: + self.authorization_value = authorization_value + + send_challenge_early = configuration.get("sendChallengeEarly") + if send_challenge_early is not None: + self.send_challenge_early = send_challenge_early + + cookie_has_no_attributes = configuration.get("cookieHasNoAttributes") + if cookie_has_no_attributes is not None: + self.cookie_has_no_attributes = cookie_has_no_attributes + + scope_origin = configuration.get("scopeOrigin") + if scope_origin is not None: + self.scope_origin = scope_origin + + registration_sends_challenge = configuration.get("registrationSendsChallenge") + if registration_sends_challenge is not None: + self.registration_sends_challenge = registration_sends_challenge + + cookie_name_and_value = configuration.get("cookieNameAndValue") + if cookie_name_and_value is not None: + self.cookie_name_and_value = cookie_name_and_value + + def get_should_refresh_end_session(self): + return self.should_refresh_end_session + + def get_authorization_value(self): + return self.authorization_value + + def get_send_challenge_early(self): + return self.send_challenge_early + + def get_registration_sends_challenge(self): + return self.registration_sends_challenge + + def reset_registration_sends_challenge(self): + self.registration_sends_challenge = False + + def get_session_instructions_response(self, session_id, request): + cookie_parts = [self.cookie_name_and_value] + cookie_attributes = "" + if not self.cookie_has_no_attributes: + cookie_attributes = "Domain=" + request.url_parts.hostname + "; Path=/device-bound-session-credentials" + cookie_parts.append(cookie_attributes) + value_of_set_cookie = "; ".join(cookie_parts) + + scope_origin = "" + if self.scope_origin is not None: + scope_origin = self.scope_origin + + response_body = { + "session_identifier": session_id, + "refresh_url": "/device-bound-session-credentials/refresh_session.py", + "scope": { + "origin": scope_origin, + "include_site": True, + "scope_specification" : [ + { "type": "exclude", "domain": request.url_parts.hostname, "path": "/device-bound-session-credentials/request_early_challenge.py" }, + { "type": "exclude", "domain": request.url_parts.hostname, "path": "/device-bound-session-credentials/end_session_via_clear_site_data.py" }, + ] + }, + "credentials": [{ + "type": "cookie", + "name": self.cookie_name_and_value.split("=")[0], + "attributes": cookie_attributes + }] + } + headers = [ + ("Content-Type", "application/json"), + ("Cache-Control", "no-store"), + ("Set-Cookie", value_of_set_cookie) + ] + + return (200, headers, json.dumps(response_body)) diff --git a/tests/wpt/tests/device-bound-session-credentials/session_provider.py b/tests/wpt/tests/device-bound-session-credentials/session_provider.py deleted file mode 100644 index fe31b250969..00000000000 --- a/tests/wpt/tests/device-bound-session-credentials/session_provider.py +++ /dev/null @@ -1,46 +0,0 @@ -import json - -session_to_key_map = {} - -def create_new_session(): - session_id = str(len(session_to_key_map)) - session_to_key_map[session_id] = None - return session_id - -def set_session_key(session_id, key): - if session_id not in session_to_key_map: - return False - session_to_key_map[session_id] = key - return True - -def get_session_key(session_id): - return session_to_key_map.get(session_id) - -def clear_server_state(): - global session_to_key_map - session_to_key_map = {} - -def get_session_instructions_response(session_id, request): - refresh_url = "/device-bound-session-credentials/refresh_session.py" - - response_body = { - "session_identifier": session_id, - "refresh_url": refresh_url, - "scope": { - "include_site": True, - "scope_specification" : [ - { "type": "exclude", "domain": request.url_parts.hostname, "path": "/device-bound-session-credentials/clear_server_state_and_end_sessions.py" }, - ] - }, - "credentials": [{ - "type": "cookie", - "name": "auth_cookie", - "attributes": "Domain=" + request.url_parts.hostname + "; Path=/device-bound-session-credentials" - }] - } - headers = [ - ("Content-Type", "application/json"), - ("Cache-Control", "no-store"), - ("Set-Cookie", "auth_cookie=abcdef0123; Domain=" + request.url_parts.hostname + "; Path=/device-bound-session-credentials") - ] - return (200, headers, json.dumps(response_body)) diff --git a/tests/wpt/tests/device-bound-session-credentials/set-authorization.https.html b/tests/wpt/tests/device-bound-session-credentials/set-authorization.https.html new file mode 100644 index 00000000000..3cfe23331d1 --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/set-authorization.https.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>DBSC authorization value sent</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="helper.js" type="module"></script> + +<script type="module"> + import { expireCookie, documentHasCookie, waitForCookie, addCookieAndSessionCleanup, configureServer, setupShardedServerState } from "./helper.js"; + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + + // Configure server send back an authorization header for registration. + configureServer({ authorizationValue: "authcode" }); + + // Prompt starting a session, and wait until registration completes. + // The server will confirm that the authorization is sent in registration. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // Confirm that registration succeeded (cookie was set). + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 200); + }, "Session registration sends the authorization value"); +</script>
\ No newline at end of file diff --git a/tests/wpt/tests/device-bound-session-credentials/set-early-challenge.https.html b/tests/wpt/tests/device-bound-session-credentials/set-early-challenge.https.html new file mode 100644 index 00000000000..112c87d4aee --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/set-early-challenge.https.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>DBSC early challenge set</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="helper.js" type="module"></script> + +<script type="module"> + import { expireCookie, waitForCookie, addCookieAndSessionCleanup, configureServer, setupShardedServerState } from "./helper.js"; + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + + // Configure server send back an authorization header for registration. + configureServer({ sendChallengeEarly: true }); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // Set up a challenge in advance. + const challenge_response = await fetch('request_early_challenge.py'); + assert_equals(challenge_response.status, 200); + + // Trigger a refresh. The server will confirm the early challenge matches. + expireCookie(expectedCookieAndAttributes); + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 200); + }, "A challenge can be set ahead of time"); +</script>
\ No newline at end of file diff --git a/tests/wpt/tests/device-bound-session-credentials/set-scope-origin.https.html b/tests/wpt/tests/device-bound-session-credentials/set-scope-origin.https.html new file mode 100644 index 00000000000..2105e8745a3 --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/set-scope-origin.https.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>DBSC scope origin set</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="helper.js" type="module"></script> + +<script type="module"> + import { expireCookie, documentHasCookie, waitForCookie, addCookieAndSessionCleanup, setupShardedServerState, configureServer} from "./helper.js"; + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + + // Configure server to have the same scope origin as the upcoming request. + configureServer({ scopeOrigin: get_host_info().HTTPS_ORIGIN }); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // Confirm that a request has the cookie set. + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 200); + + // Confirm that expiring the cookie still leads to a request with the cookie set (refresh occurs). + expireCookie(expectedCookieAndAttributes); + assert_false(documentHasCookie(expectedCookieAndValue)); + const auth_response_after_expiry = await fetch('verify_authenticated.py'); + assert_equals(auth_response_after_expiry.status, 200); + assert_true(documentHasCookie(expectedCookieAndValue)); + }, "A request within the scope origin refreshes"); + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${get_host_info().ORIGINAL_HOST};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + + // Configure server to have a scope origin that does not match the upcoming request. + configureServer({ scopeOrigin: get_host_info().OTHER_ORIGIN }); + + // Prompt starting a session, and wait until registration completes. + const login_response = await fetch('login.py'); + assert_equals(login_response.status, 200); + assert_true(await waitForCookie(expectedCookieAndValue)); + + // Confirm that a request has the cookie set. + const auth_response = await fetch('verify_authenticated.py'); + assert_equals(auth_response.status, 200); + + // Confirm that expiring the cookie does not trigger refresh. + expireCookie(expectedCookieAndAttributes); + assert_false(documentHasCookie(expectedCookieAndValue)); + const auth_response_after_expiry = await fetch('verify_authenticated.py'); + assert_equals(auth_response_after_expiry.status, 401); + assert_false(documentHasCookie(expectedCookieAndValue)); + }, "A request outside the scope origin does not refresh"); +</script>
\ No newline at end of file diff --git a/tests/wpt/tests/device-bound-session-credentials/setup_sharded_server_state.py b/tests/wpt/tests/device-bound-session-credentials/setup_sharded_server_state.py new file mode 100644 index 00000000000..8e5f3a67134 --- /dev/null +++ b/tests/wpt/tests/device-bound-session-credentials/setup_sharded_server_state.py @@ -0,0 +1,12 @@ +import json +import importlib +session_manager = importlib.import_module('device-bound-session-credentials.session_manager') + +def main(request, response): + request_body = json.loads(request.body.decode('utf-8')) + + test_id = request_body.get("testId") + if test_id is None: + test_id = session_manager.initialize_test() + + return (200, [("Set-Cookie", "test_id=" + test_id)], "") diff --git a/tests/wpt/tests/device-bound-session-credentials/start_session.py b/tests/wpt/tests/device-bound-session-credentials/start_session.py index ce3f899562e..b9d745e3ed6 100644 --- a/tests/wpt/tests/device-bound-session-credentials/start_session.py +++ b/tests/wpt/tests/device-bound-session-credentials/start_session.py @@ -1,13 +1,22 @@ import importlib jwt_helper = importlib.import_module('device-bound-session-credentials.jwt_helper') -session_provider = importlib.import_module('device-bound-session-credentials.session_provider') +session_manager = importlib.import_module('device-bound-session-credentials.session_manager') def main(request, response): + test_session_manager = session_manager.find_for_request(request) + if test_session_manager.get_registration_sends_challenge(): + # Only send back a challenge on the first call. + test_session_manager.reset_registration_sends_challenge() + return (401, [('Sec-Session-Challenge', '"login_challenge_value"')], "") + jwt_header, jwt_payload, verified = jwt_helper.decode_jwt(request.headers.get("Sec-Session-Response").decode('utf-8')) - session_id = session_provider.create_new_session() - session_provider.set_session_key(session_id, jwt_payload.get('key')) + session_id = test_session_manager.create_new_session() + test_session_manager.set_session_key(session_id, jwt_payload.get('key')) if not verified or jwt_payload.get("jti") != "login_challenge_value": return (400, response.headers, "") - return session_provider.get_session_instructions_response(session_id, request) + if jwt_payload.get("authorization") != test_session_manager.get_authorization_value(): + return (400, response.headers, "") + + return test_session_manager.get_session_instructions_response(session_id, request) diff --git a/tests/wpt/tests/device-bound-session-credentials/verify_authenticated.py b/tests/wpt/tests/device-bound-session-credentials/verify_authenticated.py index a4207af3c7a..fa81f0f0d20 100644 --- a/tests/wpt/tests/device-bound-session-credentials/verify_authenticated.py +++ b/tests/wpt/tests/device-bound-session-credentials/verify_authenticated.py @@ -1,5 +1,10 @@ def main(request, response): - cookie = request.cookies.get(b'auth_cookie') - if cookie == None or cookie.value != b'abcdef0123': + expected_cookie_name_and_value = request.body + if expected_cookie_name_and_value == b"": + expected_cookie_name_and_value = b"auth_cookie=abcdef0123" + (expected_name, expected_value) = expected_cookie_name_and_value.split(b"=") + + cookie = request.cookies.get(expected_name) + if cookie == None or cookie.value != expected_value: return (401, response.headers, "") return (200, response.headers, "") diff --git a/tests/wpt/tests/dom/events/scrolling/scroll_support.js b/tests/wpt/tests/dom/events/scrolling/scroll_support.js index c94803aa78c..59deaf473db 100644 --- a/tests/wpt/tests/dom/events/scrolling/scroll_support.js +++ b/tests/wpt/tests/dom/events/scrolling/scroll_support.js @@ -46,12 +46,41 @@ function waitForDelayWithoutScrollEvent(eventTarget) { // Waits for the end of scrolling. Uses the "scrollend" event if available. // Otherwise, fall backs to waitForDelayWithoutScrollEvent(). -function waitForScrollEndFallbackToDelayWithoutScrollEvent(eventTarget) { - if (window.onscrollend !== undefined) { - return waitForScrollendEventNoTimeout(eventTarget); - } - return waitForScrollEvent(eventTarget).then(() => { - return waitForDelayWithoutScrollEvent(eventTarget); +function waitForScrollEndFallbackToDelayWithoutScrollEvent(eventTargets) { + return new Promise(resolve => { + if (!Array.isArray(eventTargets)) { + eventTargets = [eventTargets]; + } + let listeners = []; + const cleanup = () => { + for (const [eventTarget, eventName, listener] of listeners) { + eventTarget.removeEventListener(eventName, listener); + } + listeners = []; + } + const addListener = (eventTarget, eventName, listener) => { + listeners.push([eventTarget, eventName, listener]); + eventTarget.addEventListener(eventName, listener); + } + if (window.onscrollend !== undefined) { + // If scrollend is supported, wait for the first scrollend event. + for (const eventTarget of eventTargets) { + addListener(eventTarget, 'scrollend', () => { + cleanup(); + resolve(eventTarget); + }); + } + } else { + // Otherwise, wait for the first scroll event, then wait until that + // scroller finishes scrolling. + for (const eventTarget of eventTargets) { + addListener(eventTarget, 'scroll', async () => { + cleanup(); + await waitForDelayWithoutScrollEvent(eventTarget); + resolve(eventTarget); + }); + } + } }); } diff --git a/tests/wpt/tests/dom/nodes/moveBefore/tentative/object-crash-regression.html b/tests/wpt/tests/dom/nodes/moveBefore/tentative/object-crash-regression.html new file mode 100644 index 00000000000..def2b0391ff --- /dev/null +++ b/tests/wpt/tests/dom/nodes/moveBefore/tentative/object-crash-regression.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Object element moveBefore() regression test</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> + +<b id="p"><object> + +<script> +test(t => { + // Per https://crbug.com/373924127, simply moving an object element would + // crash, due to an internal subframe count mechanism getting out of sync. + p.moveBefore(p.lastChild, p.firstChild); +}, "Moving an object element does not crash"); +</script> diff --git a/tests/wpt/tests/dom/nodes/moveBefore/tentative/style-applies.html b/tests/wpt/tests/dom/nodes/moveBefore/tentative/style-applies.html new file mode 100644 index 00000000000..39f9a5feaac --- /dev/null +++ b/tests/wpt/tests/dom/nodes/moveBefore/tentative/style-applies.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<script src='/resources/testharness.js'></script> +<script src='/resources/testharnessreport.js'></script> +<body> +</body> +<script> +'use strict'; + +promise_test(async t => { + const link = document.createElement("link"); + link.href = "data:text/css,body{background: green}"; + link.rel = "stylesheet"; + t.add_cleanup(() => link.remove()); + document.body.append(link); + const backgroundColorBefore = getComputedStyle(document.body).backgroundColor; + document.body.moveBefore(link, null); + assert_equals(getComputedStyle(document.body).backgroundColor, backgroundColorBefore); +}, "Moving a style inside the document should not affect whether it's applied"); +</script> +</html> diff --git a/tests/wpt/tests/domparsing/idlharness.window.js b/tests/wpt/tests/domparsing/idlharness.window.js deleted file mode 100644 index f5f32b3bb58..00000000000 --- a/tests/wpt/tests/domparsing/idlharness.window.js +++ /dev/null @@ -1,18 +0,0 @@ -// META: script=/resources/WebIDLParser.js -// META: script=/resources/idlharness.js - -'use strict'; - -// https://w3c.github.io/DOM-Parsing/ - -idl_test( - ['DOM-Parsing'], - ['dom'], - idlArray => { - idlArray.add_objects({ - Element: ['document.createElement("div")'], - Range: ['new Range()'], - XMLSerializer: ['new XMLSerializer()'], - }) - } -); diff --git a/tests/wpt/tests/editing/edit-context/edit-context-focus.tentative.html b/tests/wpt/tests/editing/edit-context/edit-context-focus.tentative.html new file mode 100644 index 00000000000..5ede5f06bae --- /dev/null +++ b/tests/wpt/tests/editing/edit-context/edit-context-focus.tentative.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> +<head> +<title>EditContext: The activation is synced with the associated element being focused or not</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +</head> +<body> +<div>Test</div> +<button>Click</button> +<input type="text" value="" /> +<script> +promise_test(async () => { + const div = document.querySelector('div'); + const editContext = new EditContext(); + let firedTextUpdate = false; + editContext.addEventListener('textupdate', e => { + firedTextUpdate = true; + div.textContent = e.text; + }); + div.editContext = editContext; + div.focus(); + assert_equals(document.activeElement, div); + + const button = document.querySelector('button'); + const input = document.querySelector('input'); + button.addEventListener('focus', () => { + input.focus(); + }); + await test_driver.click(button); + // The focus is on the input element, editContext should be deactivated. + assert_equals(document.activeElement, input); + + const key = 'A'; + await (new test_driver.Actions() + .keyDown(key) + .keyUp(key) + .send()); + assert_false(firedTextUpdate); + assert_equals(div.textContent, 'Test'); + assert_equals(input.value, key); +}, `If an element with an associated EditContext loses focus, the EditContext is deactivated even when another focus change was triggered recursively.`); +</script> +</body> +</html> diff --git a/tests/wpt/tests/editing/edit-context/edit-context-input.tentative.html b/tests/wpt/tests/editing/edit-context/edit-context-input.tentative.html index 45fd1613fac..ea0eebc7698 100644 --- a/tests/wpt/tests/editing/edit-context/edit-context-input.tentative.html +++ b/tests/wpt/tests/editing/edit-context/edit-context-input.tentative.html @@ -245,6 +245,33 @@ iframe.remove(); }, 'EditContext constructed outside iframe can be used in iframe'); + promise_test(async function () { + const div = document.createElement("div"); + document.body.appendChild(div); + const editContext = new EditContext(); + div.editContext = editContext; + let textupdateEventCount = 0; + editContext.addEventListener("textupdate", e => { + textupdateEventCount++; + }); + + div.focus(); + await test_driver.send_keys(div, 'a'); + assert_equals(textupdateEventCount, 1); + assert_equals(div.innerHTML, ''); + + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + iframe.contentDocument.body.appendChild(div); + + div.focus(); + await test_driver.send_keys(div, 'b'); + assert_equals(textupdateEventCount, 2); + assert_equals(div.innerHTML, ''); + + iframe.remove(); + }, 'Textupdate event should be fired on edit context when the editor element is moved to an iframe'); + promise_test(async function() { const div = document.createElement("div"); const input = document.createElement("input"); diff --git a/tests/wpt/tests/editing/other/merge-span-with-style-after-backspace-having-contenteditable.html b/tests/wpt/tests/editing/other/merge-span-with-style-after-backspace-having-contenteditable.html index b76a44818ed..651ec1c56c8 100644 --- a/tests/wpt/tests/editing/other/merge-span-with-style-after-backspace-having-contenteditable.html +++ b/tests/wpt/tests/editing/other/merge-span-with-style-after-backspace-having-contenteditable.html @@ -11,7 +11,7 @@ </head> <body> <div contenteditable><h1><span style="background-color:red;">Back</span></h1> -<h1><span style="background-color: red;">space</span></h1></div> +<h1><span style="background-color: red;" id="space">space</span></h1></div> <script> "use strict"; @@ -27,6 +27,7 @@ function sendBackspaceKey() { promise_test(async () => { const editableDiv = document.querySelector("div[contenteditable]"); const spaceSpan = editableDiv.querySelectorAll('span')[1]; + await new test_driver.click(document.querySelector('#space')); const range = document.createRange(); const selection = window.getSelection(); const textNode = spaceSpan.firstChild; diff --git a/tests/wpt/tests/editing/other/merge-span-with-style-after-forwarddelete-having-contenteditable.html b/tests/wpt/tests/editing/other/merge-span-with-style-after-forwarddelete-having-contenteditable.html index 720180ba092..687f69816dd 100644 --- a/tests/wpt/tests/editing/other/merge-span-with-style-after-forwarddelete-having-contenteditable.html +++ b/tests/wpt/tests/editing/other/merge-span-with-style-after-forwarddelete-having-contenteditable.html @@ -2,7 +2,7 @@ <html> <head> <meta charset="utf-8"> -<title>Merge Span with style after backspace having contenteditable</title> +<title>Merge Span with style after forward delete having contenteditable</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/resources/testdriver.js"></script> @@ -10,7 +10,7 @@ <script src="/resources/testdriver-actions.js"></script> </head> <body> -<div contenteditable><h1><span style="background-color:red;">Back</span></h1> +<div contenteditable><h1><span style="background-color:red;" id="back">Back</span></h1> <h1><span style="background-color: red;">space</span></h1></div> <script> "use strict"; @@ -27,6 +27,7 @@ function sendDeleteKey() { promise_test(async () => { const editableDiv = document.querySelector("div[contenteditable]"); const spaceSpan = editableDiv.querySelectorAll('span')[0]; + await new test_driver.click(document.querySelector('#back')); const range = document.createRange(); const selection = window.getSelection(); const textNode = spaceSpan.firstChild; @@ -37,7 +38,7 @@ promise_test(async () => { await sendDeleteKey(); assert_equals( editableDiv.innerHTML, - "<h1><span style=\"background-color:red;\">Back</span><span style=\"background-color: red;\">space</span></h1>", + "<h1><span style=\"background-color:red;\" id=\"back\">Back</span><span style=\"background-color: red;\">space</span></h1>", "Style is not preserved for the span after pressing backspace in contenteditable" ); }, "waiting for command to execute"); diff --git a/tests/wpt/tests/editing/other/merge-span-with-style-after-pressing-enter-followed-by-backspace-in-contenteditable-div.html b/tests/wpt/tests/editing/other/merge-span-with-style-after-pressing-enter-followed-by-backspace-in-contenteditable-div.html index d0d62962bc0..5603edd95b2 100644 --- a/tests/wpt/tests/editing/other/merge-span-with-style-after-pressing-enter-followed-by-backspace-in-contenteditable-div.html +++ b/tests/wpt/tests/editing/other/merge-span-with-style-after-pressing-enter-followed-by-backspace-in-contenteditable-div.html @@ -2,7 +2,7 @@ <html> <head> <meta charset="utf-8"> -<title>Merge Span with style after backspace having contenteditable</title> +<title>Merge Span with style after pressing enter followed by backspace in contenteditable</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/resources/testdriver.js"></script> @@ -34,6 +34,7 @@ function sendEnterKey() { promise_test(async () => { const editableDiv = document.querySelector("div[contenteditable]"); const spaceSpan = editableDiv.querySelector('span'); + await new test_driver.click(document.querySelector('span')); const range = document.createRange(); const selection = window.getSelection(); const textNode = spaceSpan.firstChild; diff --git a/tests/wpt/tests/event-timing/idlharness.any.js b/tests/wpt/tests/event-timing/idlharness.any.js index b1b57a4bb17..4750111a505 100644 --- a/tests/wpt/tests/event-timing/idlharness.any.js +++ b/tests/wpt/tests/event-timing/idlharness.any.js @@ -12,9 +12,6 @@ idl_test( idl_array => { idl_array.add_objects({ Performance: ['performance'], - EventCounts: ['performance.eventCounts'], - InteractionCounts: ['performance.interactionCounts'], - // PerformanceEventTiming: [ TODO ] }); } ); diff --git a/tests/wpt/tests/event-timing/idlharness.window.js b/tests/wpt/tests/event-timing/idlharness.window.js new file mode 100644 index 00000000000..83dd8c5576e --- /dev/null +++ b/tests/wpt/tests/event-timing/idlharness.window.js @@ -0,0 +1,19 @@ +// META: global=window +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://wicg.github.io/event-timing/ + +'use strict'; + +idl_test( + ['event-timing'], + ['performance-timeline', 'hr-time', 'dom'], + idl_array => { + idl_array.add_objects({ + Performance: ['performance'], + EventCounts: ['performance.eventCounts'], + // PerformanceEventTiming: [ TODO ] + }); + } +); diff --git a/tests/wpt/tests/fetch/content-encoding/br/br-navigation.https.window.js b/tests/wpt/tests/fetch/content-encoding/br/br-navigation.https.window.js new file mode 100644 index 00000000000..6fbb42ad3ab --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/br/br-navigation.https.window.js @@ -0,0 +1,6 @@ +// META: script=../../../service-workers/service-worker/resources/test-helpers.sub.js + +promise_test(async t => { + const frame = await with_iframe('./resources/hello.html.br'); + assert_equals(frame.contentDocument.body.textContent, 'Hello world'); +}, `Naigation to br encoded page`); diff --git a/tests/wpt/tests/fetch/content-encoding/br/resources/hello.html.br b/tests/wpt/tests/fetch/content-encoding/br/resources/hello.html.br Binary files differnew file mode 100644 index 00000000000..eff82bcb41e --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/br/resources/hello.html.br diff --git a/tests/wpt/tests/fetch/content-encoding/br/resources/hello.html.br.headers b/tests/wpt/tests/fetch/content-encoding/br/resources/hello.html.br.headers new file mode 100644 index 00000000000..c001132850f --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/br/resources/hello.html.br.headers @@ -0,0 +1,2 @@ +Content-type: text/html +Content-Encoding: br diff --git a/tests/wpt/tests/fetch/content-encoding/gzip/gzip-navigation.https.window.js b/tests/wpt/tests/fetch/content-encoding/gzip/gzip-navigation.https.window.js new file mode 100644 index 00000000000..0ef68766098 --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/gzip/gzip-navigation.https.window.js @@ -0,0 +1,6 @@ +// META: script=../../../service-workers/service-worker/resources/test-helpers.sub.js + +promise_test(async t => { + const frame = await with_iframe('./resources/hello.html.gz'); + assert_equals(frame.contentDocument.body.textContent, 'Hello world'); +}, `Naigation to gzip encoded page`); diff --git a/tests/wpt/tests/fetch/content-encoding/gzip/resources/hello.html.gz b/tests/wpt/tests/fetch/content-encoding/gzip/resources/hello.html.gz Binary files differnew file mode 100644 index 00000000000..87140901396 --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/gzip/resources/hello.html.gz diff --git a/tests/wpt/tests/fetch/content-encoding/gzip/resources/hello.html.gz.headers b/tests/wpt/tests/fetch/content-encoding/gzip/resources/hello.html.gz.headers new file mode 100644 index 00000000000..937eff5d7d8 --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/gzip/resources/hello.html.gz.headers @@ -0,0 +1,2 @@ +Content-type: text/html +Content-Encoding: gzip diff --git a/tests/wpt/tests/fetch/content-encoding/zstd/resources/hello.html.zst b/tests/wpt/tests/fetch/content-encoding/zstd/resources/hello.html.zst Binary files differnew file mode 100644 index 00000000000..1e3598106fc --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/zstd/resources/hello.html.zst diff --git a/tests/wpt/tests/fetch/content-encoding/zstd/resources/hello.html.zst.headers b/tests/wpt/tests/fetch/content-encoding/zstd/resources/hello.html.zst.headers new file mode 100644 index 00000000000..45763963093 --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/zstd/resources/hello.html.zst.headers @@ -0,0 +1,2 @@ +Content-type: text/html +Content-Encoding: zstd diff --git a/tests/wpt/tests/fetch/content-encoding/zstd/zstd-navigation.https.window.js b/tests/wpt/tests/fetch/content-encoding/zstd/zstd-navigation.https.window.js new file mode 100644 index 00000000000..27cf25ae782 --- /dev/null +++ b/tests/wpt/tests/fetch/content-encoding/zstd/zstd-navigation.https.window.js @@ -0,0 +1,6 @@ +// META: script=../../../service-workers/service-worker/resources/test-helpers.sub.js + +promise_test(async t => { + const frame = await with_iframe('./resources/hello.html.zst'); + assert_equals(frame.contentDocument.body.textContent, 'Hello world'); +}, `Naigation to zstd encoded page`); diff --git a/tests/wpt/tests/fledge/tentative/generate-bid-browser-signals.https.window.js b/tests/wpt/tests/fledge/tentative/generate-bid-browser-signals.https.window.js index e0cbe96fd94..00c4bfdcc31 100644 --- a/tests/wpt/tests/fledge/tentative/generate-bid-browser-signals.https.window.js +++ b/tests/wpt/tests/fledge/tentative/generate-bid-browser-signals.https.window.js @@ -51,11 +51,6 @@ subsetTest(promise_test, async test => { // Remove deprecated field, if present. delete browserSignals.prevWins; - // encode/decode utf-8 are tested separately, and aren't - // suitable to equality testing. - delete browserSignals.encodeUtf8; - delete browserSignals.decodeUtf8; - if (!deepEquals(browserSignals, expectedBrowserSignals)) throw "Unexpected browserSignals: " + JSON.stringify(browserSignals);` }); diff --git a/tests/wpt/tests/fledge/tentative/real-time-reporting.https.window.js b/tests/wpt/tests/fledge/tentative/real-time-reporting.https.window.js index c2af09744c5..5ebd20d19ae 100644 --- a/tests/wpt/tests/fledge/tentative/real-time-reporting.https.window.js +++ b/tests/wpt/tests/fledge/tentative/real-time-reporting.https.window.js @@ -12,6 +12,21 @@ // The tests in this file focus on real time reporting. +const MAIN_PATH = '/.well-known/interest-group/real-time-report' + +// Creates an AuctionConfig with component auctions. +function createMultiSellerAuctionConfig( + uuid, seller, decisionLogicURL, componentAuctions, + auctionConfigOverrides = {}) { + return { + seller: seller, + decisionLogicURL: decisionLogicURL, + interestGroupBuyers: [], + componentAuctions: componentAuctions, + ...auctionConfigOverrides + }; +} + // Creates a bidding script located on "origin". The generateBid() method calls // real time reporting API and returns a bid of "bid". // The reportWin() method is empty. @@ -27,8 +42,9 @@ function createBiddingScriptURLForRealTimeReporting(origin = null, bid = 1) { // Creates a decision script that calls real time reporting API. // The reportResult() method is empty. -function createDecisionScriptURLForRealTimeReporting(uuid) { +function createDecisionScriptURLForRealTimeReporting(uuid, origin = null) { return createDecisionScriptURL(uuid, { + origin: origin === null ? new URL(BASE_URL).origin : origin, scoreAd: ` realTimeReporting.contributeToHistogram({ bucket: 200, priorityWeight: 1});` }); @@ -41,11 +57,10 @@ const delay = ms => new Promise(resolve => step_timeout(resolve, ms)); // received, returns the list of reports. Returns null if the timeout is reached // before a report is available. const pollReports = async (origin, wait_for = 1, timeout = 5000 /*ms*/) => { - const path = '/.well-known/interest-group/real-time-report'; let startTime = performance.now(); let payloads = []; while (performance.now() - startTime < timeout) { - const resp = await fetch(new URL(path, origin)); + const resp = await fetch(new URL(MAIN_PATH, origin)); const payload = await resp.arrayBuffer(); if (payload.byteLength > 0) { payloads = payloads.concat(payload); @@ -90,10 +105,6 @@ const verifyHistogram = (histogram, bucketSize, length) => { assert_equals(histogram.length, length); }; -const resetWptServer = () => Promise.all([ - resetReports('/.well-known/interest-group/real-time-report'), -]); - // Method to clear the stash. Takes the URL as parameter. const resetReports = url => { // The view of the stash is path-specific @@ -108,7 +119,7 @@ const resetReports = url => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - await resetWptServer(); + await resetReports(MAIN_PATH); await joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1, { biddingLogicURL: createBiddingScriptURLForRealTimeReporting(OTHER_ORIGIN1) }); @@ -128,7 +139,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - await resetWptServer(); + await resetReports(MAIN_PATH); await joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1, { biddingLogicURL: createBiddingScriptURLForRealTimeReporting(OTHER_ORIGIN1) }); @@ -150,7 +161,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - await resetWptServer(); + await resetReports(MAIN_PATH); await joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1, { biddingLogicURL: createBiddingScriptURLForRealTimeReporting(OTHER_ORIGIN1) }); @@ -171,7 +182,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - await resetWptServer(); + await resetReports(MAIN_PATH); await joinCrossOriginInterestGroup( test, uuid, OTHER_ORIGIN1, {biddingLogicURL: createBiddingScriptURL({origin: OTHER_ORIGIN1})}); @@ -191,7 +202,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - await resetWptServer(); + await resetReports(MAIN_PATH); await joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1, { biddingLogicURL: createBiddingScriptURLForRealTimeReporting(OTHER_ORIGIN1) }); @@ -208,7 +219,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - await resetWptServer(); + await resetReports(MAIN_PATH); await joinInterestGroup( test, uuid, {biddingLogicURL: createBiddingScriptURLForRealTimeReporting()}); @@ -226,7 +237,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - await resetWptServer(); + await resetReports(MAIN_PATH); await joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1, { biddingLogicURL: createBiddingScriptURLForRealTimeReporting(OTHER_ORIGIN1) }); @@ -251,7 +262,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - await resetWptServer(); + await resetReports(MAIN_PATH); await joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1, { biddingLogicURL: createBiddingScriptURLForRealTimeReporting(OTHER_ORIGIN1) }); @@ -272,3 +283,81 @@ subsetTest(promise_test, async test => { await pollReports(OTHER_ORIGIN2, /*wait_for=*/ 1, /*timeout=*/ 1000); assert_equals(reports2, null); }, 'Real time reporting one buyer opted-in but not the other.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await resetReports(MAIN_PATH); + await joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1, { + biddingLogicURL: createBiddingScriptURLForRealTimeReporting(OTHER_ORIGIN1) + }); + await runBasicFledgeTestExpectingNoWinner(test, uuid, { + decisionLogicURL: createDecisionScriptURL(uuid, { + scoreAd: ` + realTimeReporting.contributeToHistogram({ bucket: 200, priorityWeight: 1}); + return -1;` + }), + interestGroupBuyers: [OTHER_ORIGIN1], + sellerRealTimeReportingConfig: {type: 'default-local-reporting'}, + perBuyerRealTimeReportingConfig: + {[OTHER_ORIGIN1]: {type: 'default-local-reporting'}} + }); + const sellerReports = await pollReports(location.origin); + verifyReports(sellerReports); + + const buyerReports = await pollReports(OTHER_ORIGIN1); + verifyReports(buyerReports); +}, 'Real time reports are sent when all bids are rejected.'); + +// TODO(qingxinwu): script fetches failing cases. + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + let buyer = window.location.origin; + let componentSellerOptIn = OTHER_ORIGIN1; + let componentSellerNotOptIn = OTHER_ORIGIN2; + let topLevelSeller = OTHER_ORIGIN3; + await resetReports(MAIN_PATH); + await joinCrossOriginInterestGroup( + test, uuid, buyer, + {biddingLogicURL: createBiddingScriptURLForRealTimeReporting(buyer)}); + + const componentAuctions = [ + { + seller: componentSellerOptIn, + interestGroupBuyers: [buyer], + decisionLogicURL: createDecisionScriptURLForRealTimeReporting( + uuid, componentSellerOptIn), + sellerRealTimeReportingConfig: {type: 'default-local-reporting'}, + perBuyerRealTimeReportingConfig: + {[buyer]: {type: 'default-local-reporting'}} + }, + { + seller: componentSellerNotOptIn, + interestGroupBuyers: [buyer], + decisionLogicURL: createDecisionScriptURLForRealTimeReporting( + uuid, componentSellerNotOptIn), + } + ]; + let auctionConfig = createMultiSellerAuctionConfig( + uuid, topLevelSeller, + createDecisionScriptURLForRealTimeReporting(uuid, topLevelSeller), + componentAuctions, {}); + auctionConfig.sellerRealTimeReportingConfig = { + type: 'default-local-reporting' + }; + + await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig); + const reportsBuyer = await pollReports(buyer); + verifyReports(reportsBuyer); + + const reportsComponentSellerOptIn = await pollReports(componentSellerOptIn); + verifyReports(reportsComponentSellerOptIn); + + const reportsTopLevelSeller = await pollReports(topLevelSeller); + verifyReports(reportsTopLevelSeller); + + const reportsComponentSellerNotOptIn = await pollReports( + componentSellerOptIn, /*wait_for=*/ 1, /*timeout=*/ 1000); + assert_equals(reportsComponentSellerNotOptIn, null); +}, 'Real time reporting in a multi seller auction.'); diff --git a/tests/wpt/tests/fledge/tentative/utf8-helpers.https.window.js b/tests/wpt/tests/fledge/tentative/utf8-helpers.https.window.js index 7f5391f32c3..4a712bf6269 100644 --- a/tests/wpt/tests/fledge/tentative/utf8-helpers.https.window.js +++ b/tests/wpt/tests/fledge/tentative/utf8-helpers.https.window.js @@ -97,19 +97,19 @@ async function testConversionException(test, conversionBody) { subsetTest(promise_test, async test => { await testConversion( - test, `let result = browserSignals.encodeUtf8('ABC\u0490'); + test, `let result = protectedAudience.encodeUtf8('ABC\u0490'); assertByteArray(result, [65, 66, 67, 0xD2, 0x90])`); }, 'encodeUtf8 - basic'); subsetTest(promise_test, async test => { await testConversion( - test, `let result = browserSignals.encodeUtf8('A\uD800C'); + test, `let result = protectedAudience.encodeUtf8('A\uD800C'); assertByteArray(result, [65, 0xEF, 0xBF, 0xBD, 67])`); }, 'encodeUtf8 - mismatched surrogate gets replaced'); subsetTest(promise_test, async test => { await testConversion( - test, `let result = browserSignals.encodeUtf8('A\uD83D\uDE02C'); + test, `let result = protectedAudience.encodeUtf8('A\uD83D\uDE02C'); assertByteArray(result, [65, 0xF0, 0x9F, 0x98, 0x82, 67])`); }, 'encodeUtf8 - surrogate pair combined'); @@ -118,7 +118,7 @@ subsetTest(promise_test, async test => { let obj = { toString: () => "ABC" }; - let result = browserSignals.encodeUtf8(obj); + let result = protectedAudience.encodeUtf8(obj); assertByteArray(result, [65, 66, 67]) `; await testConversion(test, conversionBody); @@ -126,7 +126,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const conversionBody = ` - let result = browserSignals.encodeUtf8(); + let result = protectedAudience.encodeUtf8(); `; await testConversionException(test, conversionBody); }, 'encodeUtf8 - not enough arguments'); @@ -136,7 +136,7 @@ subsetTest(promise_test, async test => { let obj = { toString: () => { throw 'no go' } }; - let result = browserSignals.encodeUtf8(obj); + let result = protectedAudience.encodeUtf8(obj); `; await testConversionException(test, conversionBody); }, 'encodeUtf8 - custom string conversion failure'); @@ -144,7 +144,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const conversionBody = ` let input = new Uint8Array([65, 66, 0xD2, 0x90, 67]); - let result = browserSignals.decodeUtf8(input); + let result = protectedAudience.decodeUtf8(input); assertString(result, 'AB\u0490C'); `; await testConversion(test, conversionBody); @@ -153,7 +153,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const conversionBody = ` let input = new Uint8Array([65, 32, 0xD2]); - let result = browserSignals.decodeUtf8(input); + let result = protectedAudience.decodeUtf8(input); if (result.indexOf('\uFFFD') === -1) throw 'Should have replacement character'; `; @@ -163,7 +163,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const conversionBody = ` let input = new Uint8Array([65, 32, 0xED, 0xA0, 0x80, 66]); - let result = browserSignals.decodeUtf8(input); + let result = protectedAudience.decodeUtf8(input); if (result.indexOf('\uFFFD') === -1) throw 'Should have replacement character'; `; @@ -173,7 +173,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const conversionBody = ` let input = new Uint8Array([65, 0xF0, 0x9F, 0x98, 0x82, 67]); - let result = browserSignals.decodeUtf8(input); + let result = protectedAudience.decodeUtf8(input); assertString(result, 'A\uD83D\uDE02C'); `; await testConversion(test, conversionBody); @@ -186,9 +186,9 @@ subsetTest(promise_test, async test => { for (let i = 0; i < fullView.length; ++i) fullView[i] = 65 + i; let partialView = new Uint8Array(buffer, 2, 3); - assertString(browserSignals.decodeUtf8(fullView), + assertString(protectedAudience.decodeUtf8(fullView), 'ABCDEFGH'); - assertString(browserSignals.decodeUtf8(partialView), + assertString(protectedAudience.decodeUtf8(partialView), 'CDE'); `; await testConversion(test, conversionBody); @@ -196,14 +196,14 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const conversionBody = ` - let result = browserSignals.decodeUtf8(); + let result = protectedAudience.decodeUtf8(); `; await testConversionException(test, conversionBody); }, 'decodeUtf8 - not enough arguments'); subsetTest(promise_test, async test => { const conversionBody = ` - let result = browserSignals.decodeUtf8([65, 32, 66]); + let result = protectedAudience.decodeUtf8([65, 32, 66]); `; await testConversionException(test, conversionBody); }, 'decodeUtf8 - wrong type'); diff --git a/tests/wpt/tests/fullscreen/rendering/backdrop-object.html b/tests/wpt/tests/fullscreen/rendering/backdrop-object.html index 6a2855f3c9b..e733803deda 100644 --- a/tests/wpt/tests/fullscreen/rendering/backdrop-object.html +++ b/tests/wpt/tests/fullscreen/rendering/backdrop-object.html @@ -15,10 +15,15 @@ object::backdrop { <script> const object = document.querySelector("object"); -test_driver.bless('fullscreen') - .then(() => {object.data="/images/100px-green-rect.svg";}) - .then(() => new Promise((resolve) => object.addEventListener("load", resolve))) - .then(() => object.requestFullscreen()) - .then(() => new Promise((resolve) => document.addEventListener("fullscreenchange", resolve))) - .then(() => document.documentElement.classList.remove('reftest-wait')); + +Promise.all([ + new Promise((resolve) => { + object.addEventListener("load", resolve); + object.data = "/images/100px-green-rect.svg"; + }), + new Promise((resolve) => { + document.addEventListener("fullscreenchange", resolve); + test_driver.bless('fullscreen', () => object.requestFullscreen()); + }), +]).then(() => document.documentElement.classList.remove('reftest-wait')); </script> diff --git a/tests/wpt/tests/fullscreen/rendering/fullscreen-root-block-size.html b/tests/wpt/tests/fullscreen/rendering/fullscreen-root-block-size.html index 5138494d5d9..8c54fe58484 100644 --- a/tests/wpt/tests/fullscreen/rendering/fullscreen-root-block-size.html +++ b/tests/wpt/tests/fullscreen/rendering/fullscreen-root-block-size.html @@ -25,8 +25,7 @@ in fullscreen mode. } }); await trusted_click(); - await document.documentElement.requestFullscreen(); - await fullScreenChange(); + await Promise.all([document.documentElement.requestFullscreen(), fullScreenChange()]); assert_equals(document.fullscreenElement, document.documentElement); assert_true(document.documentElement.getBoundingClientRect().width > 0); }); diff --git a/tests/wpt/tests/html-aam/roles-contextual.html b/tests/wpt/tests/html-aam/roles-contextual.html index 4edcc12e8f2..793bdf1f413 100644 --- a/tests/wpt/tests/html-aam/roles-contextual.html +++ b/tests/wpt/tests/html-aam/roles-contextual.html @@ -12,7 +12,7 @@ <body> -<p>Tests contextual computedrole mappings defined in <a href="https://w3c.github.io/html-aam/">HTML-AAM</a>, where the returned computed role is expected to change based on the context. Most test names correspond to a unique ID defined in the spec.<p> +<p>Tests contextual computed role mappings defined in <a href="https://w3c.github.io/html-aam/">HTML-AAM</a>, where the returned computed role is expected to change based on the context. Most test names correspond to a unique ID defined in the spec.<p> <p>These should remain in alphabetical order.</code></p> @@ -50,6 +50,15 @@ <section aria-label="x"> <aside data-testname="el-aside-in-section" class="ex-generic">x</aside> <aside data-testname="el-aside-in-section-with-name" data-expectedrole="complementary" aria-label="x" class="ex">x</aside> + <aside data-testname="el-aside-in-section-aria-label-empty" class="ex-generic" aria-label="">x</aside> + <aside data-testname="el-aside-in-section-aria-label-whitespace" class="ex-generic" aria-label=" ">x</aside> + <aside data-testname="el-aside-in-section-aria-labelledby" data-expectedrole="complementary" class="ex" aria-labelledby="labelledby">x</aside> + <aside data-testname="el-aside-in-section-aria-labelledby-non-existing" class="ex-generic" aria-labelledby="non-existing">x</aside> + <aside data-testname="el-aside-in-section-aria-labelledby-empty" class="ex-generic" aria-labelledby="empty">x</aside> + <aside data-testname="el-aside-in-section-aria-labelledby-whitespace" class="ex-generic" aria-labelledby="space">x</aside> + <aside data-testname="el-aside-in-section-title" data-expectedrole="complementary" title="x" class="ex">x</aside> + <aside data-testname="el-aside-in-section-title-empty" class="ex-generic" title="">x</aside> + <aside data-testname="el-aside-in-section-title-whitespace" class="ex-generic" title=" ">x</aside> </section> <!-- el-footer --> @@ -62,10 +71,38 @@ <header data-testname="el-header-ancestorbody" data-expectedrole="banner" class="ex">x</header> <!-- main>header -> ./roles-contextual.tentative.html --> +<!-- el-img-empty-alt --> +<img data-testname="el-img-no-name" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="> +<!-- img empty alt -> ./roles.html --> +<img data-testname="el-img-empty-alt-aria-label" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-label="x"> +<img data-testname="el-img-empty-alt-aria-label-empty" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-label=""> +<img data-testname="el-img-empty-alt-aria-label-whitespace" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-label=" "> +<img data-testname="el-img-empty-alt-aria-labelledby" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-labelledby="labelledby"> +<img data-testname="el-img-empty-alt-aria-labelledby-non-existing" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-labelledby="non-existing"> +<img data-testname="el-img-empty-alt-aria-labelledby-empty" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-labelledby="empty"> +<img data-testname="el-img-empty-alt-aria-labelledby-whitespace" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-labelledby="space"> +<img data-testname="el-img-empty-alt-title" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt title="x"> +<img data-testname="el-img-empty-alt-title-empty" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt title=""> +<img data-testname="el-img-empty-alt-title-whitespace" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt title=" "> + + <!-- el-section --> <section data-testname="el-section" aria-label="x" data-expectedrole="region" class="ex">x</section> <section data-testname="el-section-no-name" class="ex-generic">x</section> +<section data-testname="el-section-aria-label-empty" class="ex-generic" aria-label="">x</section> +<section data-testname="el-section-aria-label-whitespace" class="ex-generic" aria-label=" ">x</section> +<section data-testname="el-section-aria-labelledby" data-expectedrole="region" class="ex" aria-labelledby="labelledby">x</section> +<section data-testname="el-section-aria-labelledby-non-existing" class="ex-generic" aria-labelledby="non-existing">x</section> +<section data-testname="el-section-aria-labelledby-empty" class="ex-generic" aria-labelledby="empty">x</section> +<section data-testname="el-section-aria-labelledby-whitespace" class="ex-generic" aria-labelledby="space">x</section> +<section data-testname="el-section-title" data-expectedrole="region" title="x" class="ex">x</section> +<section data-testname="el-section-title-empty" class="ex-generic" title="">x</section> +<section data-testname="el-section-title-whitespace" class="ex-generic" title=" ">x</section> +<!-- element to reference for aria-labelledby tests --> +<div id="labelledby">labelledby</div> +<div id="empty"></div> +<div id="space"> </div> <script> AriaUtils.verifyRolesBySelector(".ex"); diff --git a/tests/wpt/tests/html-aam/roles.html b/tests/wpt/tests/html-aam/roles.html index 2ab2d7d8c5c..9ef8e467bf1 100644 --- a/tests/wpt/tests/html-aam/roles.html +++ b/tests/wpt/tests/html-aam/roles.html @@ -94,6 +94,8 @@ <img alt data-testname="el-img-alt-no-value" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="> <img alt="" data-testname="el-img-empty-alt" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="> +<!-- img with empty alt but other naming mechanism -> ./roles-contextual.html --> + <input type="button" value="x" data-testname="el-input-button" data-expectedrole="button" class="ex"> <input type="checkbox" data-testname="el-input-checkbox" data-expectedrole="checkbox" class="ex"> <!-- todo: input type="color" --> diff --git a/tests/wpt/tests/html/browsers/origin/origin-keyed-agent-clusters/about-blank.https.sub.html b/tests/wpt/tests/html/browsers/origin/origin-keyed-agent-clusters/about-blank.https.sub.html index 556d528aa05..e96a5b4dd0b 100644 --- a/tests/wpt/tests/html/browsers/origin/origin-keyed-agent-clusters/about-blank.https.sub.html +++ b/tests/wpt/tests/html/browsers/origin/origin-keyed-agent-clusters/about-blank.https.sub.html @@ -52,12 +52,13 @@ async function insertAboutBlankIframe() { await setBothDocumentDomains(iframe.contentWindow); } -function createBlankIframe() { +async function createBlankIframe() { const iframe = document.createElement("iframe"); const promise = new Promise(resolve => { iframe.addEventListener("load", resolve); }); document.body.append(iframe); - return promise; + await promise; + return iframe; } </script> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.drawImage.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.drawImage.html index 3b55b2e923f..41691ff15dc 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.drawImage.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.drawImage.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.drawImage</title> <h1>2d.composite.grid.filter.no_shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.fillRect.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.fillRect.html index 7addb60d333..41c77addafb 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.fillRect.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.fillRect.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.fillRect</title> <h1>2d.composite.grid.filter.no_shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.pattern.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.pattern.html index 415b0b78b7e..f298e25fd58 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.pattern.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.no_shadow.pattern.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.pattern</title> <h1>2d.composite.grid.filter.no_shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.drawImage.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.drawImage.html index e9784a3dc70..1d4cad6d1f7 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.drawImage.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.drawImage.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.drawImage</title> <h1>2d.composite.grid.filter.shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.fillRect.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.fillRect.html index 784a068b717..f786fb5ecf5 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.fillRect.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.fillRect.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.fillRect</title> <h1>2d.composite.grid.filter.shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.pattern.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.pattern.html index e13bf471b94..c98180b0700 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.pattern.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.filter.shadow.pattern.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.pattern</title> <h1>2d.composite.grid.filter.shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.html index 42a331f7c9b..a7e009c486b 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.drawImage</title> <h1>2d.composite.grid.no_filter.no_shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.html index 8a01e7abb0c..2c44659aebb 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.fillRect</title> <h1>2d.composite.grid.no_filter.no_shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.pattern.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.pattern.html index 6c8d0e69cac..a6482276e88 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.pattern.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.no_shadow.pattern.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.pattern</title> <h1>2d.composite.grid.no_filter.no_shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.drawImage.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.drawImage.html index 625a613253f..6717b26813f 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.drawImage.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.drawImage.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.drawImage</title> <h1>2d.composite.grid.no_filter.shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.fillRect.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.fillRect.html index d01e7bc0ed6..9f2d77c6a2a 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.fillRect.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.fillRect.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.fillRect</title> <h1>2d.composite.grid.no_filter.shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.pattern.html b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.pattern.html index 7512b21b069..9be2a0ae783 100644 --- a/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.pattern.html +++ b/tests/wpt/tests/html/canvas/element/compositing/2d.composite.grid.no_filter.shadow.pattern.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.pattern</title> <h1>2d.composite.grid.no_filter.shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang-ref.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang-ref.html index fec2d7558ab..19e283985cc 100644 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang-ref.html +++ b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang-ref.html @@ -1,19 +1,37 @@ <!doctype HTML> <meta charset="utf-8"> -<title>HTML5 Canvas Test Reference: The lang attribute.</title> +<title>HTML5 Canvas Test Reference: The lang attribute.</title> <link rel="author" href="mailto:schenney@chromium.org"/> +<style> + #canvas-zh { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } +</style> <script> - function generateReference() { - var canvas = document.getElementById('canvas1'); + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); var ctx = canvas.getContext('2d'); - // The default for lang is inherit, so no need to set any text styles. ctx.font = '25px serif'; ctx.fillText('今骨直', 5, 50); } + function generateReference() { + drawText('zh'); + drawText('ja'); + } </script> <body onload="generateReference()"> - <canvas lang="zh-CN" id="canvas1" width="300" height="150"> + <canvas lang="zh-CN" id="canvas-zh" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas lang="ja" id="canvas-ja" width="300" height="100"> Browser does not support HTML5 Canvas. </canvas> </body> diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.dynamic.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.dynamic.html index 52c526b3703..ad23b2c2338 100644 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.dynamic.html +++ b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.dynamic.html @@ -36,4 +36,3 @@ Browser does not support HTML5 Canvas. </canvas> </body> - diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.empty-ref.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.empty-ref.html index 7f9f172fd45..fda8b02a344 100644 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.empty-ref.html +++ b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.empty-ref.html @@ -7,7 +7,8 @@ var canvas = document.getElementById('canvas1'); var ctx = canvas.getContext('2d'); - // The default for lang is inherit, so no need to set any text styles. + // With no lang defined anywhere, this reference will use the unknown + // language, whatever that might produce on the platform. ctx.font = '25px serif'; ctx.fillText('今骨直', 5, 50); } diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.empty.canvas.tentative.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.empty.canvas.html index 4db9fc716c3..d1b6e52f796 100644 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.empty.canvas.tentative.html +++ b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.empty.canvas.html @@ -1,5 +1,5 @@ <!doctype HTML> -<html lang="zh-CN"> +<html> <meta charset="utf-8"> <title>HTML5 Canvas Test: The empty string lang attribute uses the unknown language</title> <link rel="match" href="canvas.2d.lang.empty-ref.html" /> @@ -11,15 +11,16 @@ var canvas = document.getElementById('canvas1'); var ctx = canvas.getContext('2d'); + // An empty lang string should produce the same result as no language + // attribute at all, on the canvas element or document element. ctx.font = '25px serif'; ctx.lang = ''; ctx.fillText('今骨直', 5, 50); } </script> <body onload="runTest()"> - <canvas lang="zh-CN" id="canvas1" width="300" height="150"> + <canvas id="canvas1" width="300" height="150"> Browser does not support HTML5 Canvas. </canvas> </body> </html> - diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.tentative.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.html index a9b4a8f63f0..372cf8c04cd 100644 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.tentative.html +++ b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.html @@ -6,20 +6,38 @@ <link rel="author" href="mailto:schenney@chromium.org"/> <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> <meta name="assert" content="When the canvas context has a lang attribute, override the document." /> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> <script type="text/javascript"> - function runTest() { - var canvas = document.getElementById('canvas1'); + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); var ctx = canvas.getContext('2d'); ctx.font = '25px serif'; - ctx.lang = 'zh-CN'; + ctx.lang = language; ctx.fillText('今骨直', 5, 50); } + function runTest() { + drawText('zh-CN'); + drawText('ja'); + } </script> <body onload="runTest()"> - <canvas id="canvas1" width="300" height="150"> + <canvas id="canvas-zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas id="canvas-ja" width="300" height="100"> Browser does not support HTML5 Canvas. </canvas> </body> </html> - diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.canvas.tentative.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.canvas.tentative.html deleted file mode 100644 index 06fdf5001a3..00000000000 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.canvas.tentative.html +++ /dev/null @@ -1,24 +0,0 @@ -<!doctype HTML> -<html lang="en-US"> - <meta charset="utf-8"> - <title>HTML5 Canvas Test: The lang attribute inherits from the canvas rather than the document</title> - <link rel="match" href="canvas.2d.lang-ref.html" /> - <link rel="author" href="mailto:schenney@chromium.org"/> - <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> - <meta name="assert" content="When the canvas element has a lang attribute, override the document." /> - <script type="text/javascript"> - function runTest() { - var canvas = document.getElementById('canvas1'); - var ctx = canvas.getContext('2d'); - - ctx.font = '25px serif'; - ctx.fillText('今骨直', 5, 50); - } - </script> - <body onload="runTest()"> - <canvas lang="zh-CN" id="canvas1" width="300" height="150"> - Browser does not support HTML5 Canvas. - </canvas> - </body> -</html> - diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.disconnected.canvas.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.disconnected.canvas.html new file mode 100644 index 00000000000..7b28b1fb950 --- /dev/null +++ b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.disconnected.canvas.html @@ -0,0 +1,43 @@ +<!doctype HTML> +<html lang="en-US"> + <meta charset="utf-8"> + <title>HTML5 Canvas Test: The lang attribute inherits from a disconnected canvas element</title> + <link rel="match" href="canvas.2d.lang-ref.html"/> + <link rel="author" href="mailto:schenney@chromium.org"/> + <link rel="help" + href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> + <meta name="assert" content="Verify that a disconnected canvas uses the canvas lang."/> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> + <body> + <script type="text/javascript"> + function drawText(language) { + var canvas = document.createElement('canvas'); + canvas.setAttribute('width', '300'); + canvas.setAttribute('height', '100'); + canvas.setAttribute('id', 'canvas-' + language); + canvas.setAttribute('lang', language); + var ctx = canvas.getContext('2d'); + + // The default for direction is inherit + ctx.font = '25px serif'; + ctx.fillText('今骨直', 5, 50); + + document.body.appendChild(canvas); + } + + drawText('zh-CN'); + drawText('ja'); + </script> + </body> +</html> diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.disconnected.canvas.tentative.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.disconnected.canvas.tentative.html deleted file mode 100644 index dff0e5c8a41..00000000000 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.disconnected.canvas.tentative.html +++ /dev/null @@ -1,33 +0,0 @@ -<!doctype HTML> -<html lang="en-US"> - <meta charset="utf-8"> - <title>HTML5 Canvas Test: The lang attribute inherits from a disconnected canvas element</title> - <link rel="match" href="canvas.2d.lang-ref.html"/> - <link rel="author" href="mailto:schenney@chromium.org"/> - <link rel="help" - href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> - <meta name="assert" content="Verify that a disconnected canvas uses the canvas lang."/> - <style> - canvas { - position: absolute; - top: 8px; - left: 8px; - } - </style> - <body> - <script type="text/javascript"> - var canvas = document.createElement('canvas'); - canvas.setAttribute('lang', 'zh-CN'); - canvas.setAttribute('width', '300'); - canvas.setAttribute('height', '150'); - var ctx = canvas.getContext('2d'); - - // The default for direction is inherit - ctx.font = '25px serif'; - ctx.fillText('今骨直', 5, 50); - - document.body.appendChild(canvas); - </script> - </body> -</html> - diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.disconnected.canvas.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.disconnected.canvas.html new file mode 100644 index 00000000000..e6a463ae375 --- /dev/null +++ b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.disconnected.canvas.html @@ -0,0 +1,43 @@ +<!doctype HTML> +<html lang="zh-CN"> + <meta charset="utf-8"> + <title>HTML5 Canvas Test: The lang attribute inherits the document lang when disconnected</title> + <link rel="match" href="canvas.2d.lang-ref.html"/> + <link rel="author" href="mailto:schenney@chromium.org"/> + <link rel="help" + href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> + <meta name="assert" content="Verify that a disconnected canvas with no lang attribute uses the document lang."/> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> + <body> + <script type="text/javascript"> + function drawText(language) { + var canvas = document.createElement('canvas'); + canvas.setAttribute('width', '300'); + canvas.setAttribute('height', '100'); + canvas.setAttribute('id', 'canvas-' + language); + var ctx = canvas.getContext('2d'); + + // The default for direction is inherit + ctx.font = '25px serif'; + ctx.fillText('今骨直', 5, 50); + + document.body.appendChild(canvas); + } + + drawText('zh-CN'); + document.documentElement.setAttribute('lang', 'ja'); + drawText('ja'); + </script> + </body> +</html> diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.disconnected.canvas.tentative.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.disconnected.canvas.tentative.html deleted file mode 100644 index a13f87bbcb2..00000000000 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.disconnected.canvas.tentative.html +++ /dev/null @@ -1,32 +0,0 @@ -<!doctype HTML> -<html lang="zh-CN"> - <meta charset="utf-8"> - <title>HTML5 Canvas Test: The lang attribute inherits the document lang when disconnected</title> - <link rel="match" href="canvas.2d.lang-ref.html"/> - <link rel="author" href="mailto:schenney@chromium.org"/> - <link rel="help" - href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> - <meta name="assert" content="Verify that a disconnected canvas with no lang attribnute uses the document lang."/> - <style> - canvas { - position: absolute; - top: 8px; - left: 8px; - } - </style> - <body> - <script type="text/javascript"> - var canvas = document.createElement('canvas'); - canvas.setAttribute('width', '300'); - canvas.setAttribute('height', '150'); - var ctx = canvas.getContext('2d'); - - // The default for direction is inherit - ctx.font = '25px serif'; - ctx.fillText('今骨直', 5, 50); - - document.body.appendChild(canvas); - </script> - </body> -</html> - diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.tentative.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.tentative.html deleted file mode 100644 index 3ff36f34fdb..00000000000 --- a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.document.tentative.html +++ /dev/null @@ -1,24 +0,0 @@ -<!doctype HTML> -<html lang="zh-CN"> - <meta charset="utf-8"> - <title>HTML5 Canvas Test: The lang attribute inherits from the document when no lang on the canvas</title> - <link rel="match" href="canvas.2d.lang-ref.html" /> - <link rel="author" href="mailto:schenney@chromium.org"/> - <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> - <meta name="assert" content="When the canvas element has no lang attribute, inherit it from the document." /> - <script type="text/javascript"> - function runTest() { - var canvas = document.getElementById('canvas1'); - var ctx = canvas.getContext('2d'); - - // The default for lang is inherit, so no need to set any text styles. - ctx.font = '25px serif'; - ctx.fillText('今骨直', 5, 50); - } - </script> - <body onload="runTest()"> - <canvas id="canvas1" width="300" height="150"> - Browser does not support HTML5 Canvas. - </canvas> - </body> -</html> diff --git a/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.html b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.html new file mode 100644 index 00000000000..bb2e655e15a --- /dev/null +++ b/tests/wpt/tests/html/canvas/element/manual/text/canvas.2d.lang.inherit.html @@ -0,0 +1,46 @@ +<!doctype HTML> +<html lang="ja"> + <meta charset="utf-8"> + <title>HTML5 Canvas Test: The lang attribute inherits from the canvas rather than the document</title> + <link rel="match" href="canvas.2d.lang-ref.html" /> + <link rel="author" href="mailto:schenney@chromium.org"/> + <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> + <meta name="assert" content="When the canvas element has a lang attribute, override the document." /> + <style> + #canvas-zh { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> + <script> + function generateReference() { + // The 'canvas-zh' element has a lang attribute, use it. + var canvasZH = document.getElementById('canvas-zh'); + var ctxZH = canvasZH.getContext('2d'); + + ctxZH.font = '25px serif'; + ctxZH.fillText('今骨直', 5, 50); + + // The 'canvas-ja' element has no lang attribute, use the document lang. + var canvasJA = document.getElementById('canvas-ja'); + var ctxJA = canvasJA.getContext('2d'); + + ctxJA.font = '25px serif'; + ctxJA.fillText('今骨直', 5, 50); + } + </script> + <body onload="generateReference()"> + <canvas lang="zh-CN" id="canvas-zh" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas id="canvas-ja" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + </body> +</html> diff --git a/tests/wpt/tests/html/canvas/element/text/2d.text.direction.default.tentative.html b/tests/wpt/tests/html/canvas/element/text/2d.text.direction.default.html index 7c7a47148be..e1222c4d50b 100644 --- a/tests/wpt/tests/html/canvas/element/text/2d.text.direction.default.tentative.html +++ b/tests/wpt/tests/html/canvas/element/text/2d.text.direction.default.html @@ -1,14 +1,14 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> <meta charset="UTF-8"> -<title>Canvas test: 2d.text.direction.default.tentative</title> +<title>Canvas test: 2d.text.direction.default</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/html/canvas/resources/canvas-tests.js"></script> <link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css"> <body class="show_output"> -<h1>2d.text.direction.default.tentative</h1> +<h1>2d.text.direction.default</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/text/2d.text.direction.valid.tentative.html b/tests/wpt/tests/html/canvas/element/text/2d.text.direction.valid.html index 26593374e47..d2c7c2f0d45 100644 --- a/tests/wpt/tests/html/canvas/element/text/2d.text.direction.valid.tentative.html +++ b/tests/wpt/tests/html/canvas/element/text/2d.text.direction.valid.html @@ -1,14 +1,14 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> <meta charset="UTF-8"> -<title>Canvas test: 2d.text.direction.valid.tentative</title> +<title>Canvas test: 2d.text.direction.valid</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/html/canvas/resources/canvas-tests.js"></script> <link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css"> <body class="show_output"> -<h1>2d.text.direction.valid.tentative</h1> +<h1>2d.text.direction.valid</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/text/2d.text.lang.default.tentative.html b/tests/wpt/tests/html/canvas/element/text/2d.text.lang.default.html index e6e49e1803d..3830f0c97cf 100644 --- a/tests/wpt/tests/html/canvas/element/text/2d.text.lang.default.tentative.html +++ b/tests/wpt/tests/html/canvas/element/text/2d.text.lang.default.html @@ -1,14 +1,14 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> <meta charset="UTF-8"> -<title>Canvas test: 2d.text.lang.default.tentative</title> +<title>Canvas test: 2d.text.lang.default</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/html/canvas/resources/canvas-tests.js"></script> <link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css"> <body class="show_output"> -<h1>2d.text.lang.default.tentative</h1> +<h1>2d.text.lang.default</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/element/text/2d.text.lang.valid.tentative.html b/tests/wpt/tests/html/canvas/element/text/2d.text.lang.valid.html index 3876a3ecbb6..95673931030 100644 --- a/tests/wpt/tests/html/canvas/element/text/2d.text.lang.valid.tentative.html +++ b/tests/wpt/tests/html/canvas/element/text/2d.text.lang.valid.html @@ -1,14 +1,14 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> <meta charset="UTF-8"> -<title>Canvas test: 2d.text.lang.valid.tentative</title> +<title>Canvas test: 2d.text.lang.valid</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/html/canvas/resources/canvas-tests.js"></script> <link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css"> <body class="show_output"> -<h1>2d.text.lang.valid.tentative</h1> +<h1>2d.text.lang.valid</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.drawImage.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.drawImage.html index 33cdebbaf9a..7e67f7730c8 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.drawImage.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.drawImage.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.drawImage</title> <h1>2d.composite.grid.filter.no_shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.drawImage.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.drawImage.w.html index 1dd45863376..0e3999ea68c 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.drawImage.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.drawImage.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.drawImage</title> <h1>2d.composite.grid.filter.no_shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.fillRect.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.fillRect.html index b0e8021079e..832caa29c0d 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.fillRect.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.fillRect.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.fillRect</title> <h1>2d.composite.grid.filter.no_shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.fillRect.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.fillRect.w.html index ad95af2f11a..e38ae35adac 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.fillRect.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.fillRect.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.fillRect</title> <h1>2d.composite.grid.filter.no_shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.pattern.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.pattern.html index cb5578b3330..08b4f286034 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.pattern.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.pattern.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.pattern</title> <h1>2d.composite.grid.filter.no_shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.pattern.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.pattern.w.html index cba6b24442c..14c329f0e10 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.pattern.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.no_shadow.pattern.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.no_shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.no_shadow.pattern</title> <h1>2d.composite.grid.filter.no_shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.drawImage.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.drawImage.html index b7366604f1e..b6c2185b831 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.drawImage.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.drawImage.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.drawImage</title> <h1>2d.composite.grid.filter.shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.drawImage.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.drawImage.w.html index 1ab054dc492..01eb5418ab1 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.drawImage.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.drawImage.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.drawImage</title> <h1>2d.composite.grid.filter.shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.fillRect.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.fillRect.html index b3d10c8fdd3..579f4e87a26 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.fillRect.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.fillRect.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.fillRect</title> <h1>2d.composite.grid.filter.shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.fillRect.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.fillRect.w.html index cad533fb31f..ae4f71f49ba 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.fillRect.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.fillRect.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.fillRect</title> <h1>2d.composite.grid.filter.shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.pattern.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.pattern.html index ce9ec1859db..aee85b65087 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.pattern.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.pattern.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.pattern</title> <h1>2d.composite.grid.filter.shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.pattern.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.pattern.w.html index 6ea16577b03..e14f307d12a 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.pattern.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.filter.shadow.pattern.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.filter.shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.filter.shadow.pattern</title> <h1>2d.composite.grid.filter.shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.html index 3f3e9aa20f9..b435bbb0852 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.drawImage</title> <h1>2d.composite.grid.no_filter.no_shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.w.html index a71fa1898d8..0234582b970 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.drawImage.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.drawImage</title> <h1>2d.composite.grid.no_filter.no_shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.html index 5d4cd718736..4ca2adafd7d 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.fillRect</title> <h1>2d.composite.grid.no_filter.no_shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.w.html index b65d0781fea..484f5592d62 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.fillRect.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.fillRect</title> <h1>2d.composite.grid.no_filter.no_shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.pattern.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.pattern.html index 9fdc1046804..004ba2bae64 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.pattern.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.pattern.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.pattern</title> <h1>2d.composite.grid.no_filter.no_shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.pattern.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.pattern.w.html index c3b242623f9..bbce3999530 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.pattern.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.no_shadow.pattern.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.no_shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.no_shadow.pattern</title> <h1>2d.composite.grid.no_filter.no_shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.drawImage.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.drawImage.html index edbcce10449..51cd1c6227c 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.drawImage.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.drawImage.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.drawImage</title> <h1>2d.composite.grid.no_filter.shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.drawImage.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.drawImage.w.html index 65563217ebf..5c76fd5d725 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.drawImage.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.drawImage.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.drawImage-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.drawImage</title> <h1>2d.composite.grid.no_filter.shadow.drawImage</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.fillRect.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.fillRect.html index faac7dcaf64..8fbf3a9bdee 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.fillRect.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.fillRect.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.fillRect</title> <h1>2d.composite.grid.no_filter.shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.fillRect.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.fillRect.w.html index 68170021c0b..8c80e24aeb1 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.fillRect.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.fillRect.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.fillRect-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.fillRect</title> <h1>2d.composite.grid.no_filter.shadow.fillRect</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.pattern.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.pattern.html index f92d1b8ac7a..1cad90603ed 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.pattern.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.pattern.html @@ -3,7 +3,7 @@ <meta charset="UTF-8"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.pattern</title> <h1>2d.composite.grid.no_filter.shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.pattern.w.html b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.pattern.w.html index 898b5ff601e..70d12bc4c8b 100644 --- a/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.pattern.w.html +++ b/tests/wpt/tests/html/canvas/offscreen/compositing/2d.composite.grid.no_filter.shadow.pattern.w.html @@ -4,7 +4,7 @@ <html class="reftest-wait"> <link rel="stylesheet" href="/html/canvas/resources/canvas-grid-reftest.css"> <link rel="match" href="2d.composite.grid.no_filter.shadow.pattern-expected.html"> -<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-25392"> +<meta name=fuzzy content="maxDifference=0-4; totalPixels=0-33000"> <title>Canvas test: 2d.composite.grid.no_filter.shadow.pattern</title> <h1>2d.composite.grid.no_filter.shadow.pattern</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang-ref.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang-ref.html index b2c01b62a7b..aa13564fbba 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang-ref.html +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang-ref.html @@ -2,17 +2,36 @@ <meta charset="utf-8"> <title>HTML5 Canvas Test Reference: The lang attribute in an offscreen canvas</title> <link rel="author" href="mailto:schenney@chromium.org"/> +<style> + #canvas-zh { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } +</style> <script> - function runTest() { - var canvas = document.getElementById('canvas1'); + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); var ctx = canvas.getContext('2d'); ctx.font = '25px serif'; ctx.fillText('今骨直', 5, 50); } + function generateReference() { + drawText('zh'); + drawText('ja'); + } </script> -<body onload="runTest()"> - <canvas id="canvas1" lang="zh-CN" width="300" height="150"> +<body onload="generateReference()"> + <canvas lang="zh-CN" id="canvas-zh" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas lang="ja" id="canvas-ja" width="300" height="100"> Browser does not support HTML5 Canvas. </canvas> </body> diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang.tentative.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang.html index 3978ce83241..0179dad8fea 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang.tentative.html +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang.html @@ -6,26 +6,44 @@ <link rel="author" href="mailto:schenney@chromium.org"/> <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> <meta name="assert" content="An offscreen canvas respects the lang text attribute." /> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> <script type="text/javascript"> - function runTest() { - var canvas = document.getElementById('canvas1'); + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); var bitmap_ctx = canvas.getContext('bitmaprenderer'); - var offscreen = new OffscreenCanvas(300, 150); + var offscreen = new OffscreenCanvas(300, 100); var offscreen_ctx = offscreen.getContext('2d'); offscreen_ctx.font = '25px serif'; - offscreen_ctx.lang = 'zh-CN'; + offscreen_ctx.lang = language; offscreen_ctx.fillText('今骨直', 5, 50); const bitmap = offscreen.transferToImageBitmap(); bitmap_ctx.transferFromImageBitmap(bitmap); } + function runTest() { + drawText('zh-CN'); + drawText('ja'); + } </script> <body onload="runTest()"> - <canvas id="canvas1" width="300" height="150"> + <canvas id="canvas-zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas id="canvas-ja" width="300" height="100"> Browser does not support HTML5 Canvas. </canvas> </body> </html> - diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang.inherit.tentative.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang.inherit.html index 8c79d469314..5b027f6dae0 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang.inherit.tentative.html +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.lang.inherit.html @@ -6,12 +6,24 @@ <link rel="author" href="mailto:schenney@chromium.org"/> <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> <meta name="assert" content="An offscreen canvas inherits the lang from the document." /> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> <script type="text/javascript"> - function runTest() { - var canvas = document.getElementById('canvas1'); + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); var bitmap_ctx = canvas.getContext('bitmaprenderer'); - var offscreen = new OffscreenCanvas(300, 150); + var offscreen = new OffscreenCanvas(300, 100); var offscreen_ctx = offscreen.getContext('2d'); offscreen_ctx.font = '25px serif'; @@ -20,9 +32,19 @@ const bitmap = offscreen.transferToImageBitmap(); bitmap_ctx.transferFromImageBitmap(bitmap); } + + function runTest() { + drawText('zh-CN'); + document.documentElement.setAttribute('lang', 'ja'); + drawText('ja'); + } </script> <body onload="runTest()"> - <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas> + <canvas lang="zh-CN" id="canvas-zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas lang="ja" id="canvas-ja" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> </body> </html> - diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.html new file mode 100644 index 00000000000..049f5484058 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.html @@ -0,0 +1,43 @@ +<!doctype HTML> +<html lang="en-US"> + <meta charset="utf-8"> + <title>HTML5 Canvas Test: The lang attribute functions in a transferred offscreen</title> + <link rel="match" href="canvas.2d.offscreen.lang-ref.html" /> + <link rel="author" href="mailto:schenney@chromium.org"/> + <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> + <meta name="assert" content="Verify that setting lang in a transferred offscreen works." /> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> + <script type="text/javascript"> + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); + var ctx = canvas.transferControlToOffscreen().getContext('2d'); + + ctx.font = '25px serif'; + ctx.lang = language; + ctx.fillText('今骨直', 5, 50); + } + function runTest() { + drawText('zh-CN'); + drawText('ja'); + } + </script> + <body onload="runTest()"> + <canvas lang="zh-CN" id="canvas-zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas lang="ja" id="canvas-ja" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + </body> +</html> diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.document.tentative.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.document.html index 5c194d7dc79..732496c93b0 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.document.tentative.html +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.document.html @@ -6,20 +6,40 @@ <link rel="author" href="mailto:schenney@chromium.org"/> <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> <meta name="assert" content="An offscreen transferred from a canvas inherits the document language." /> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> <script type="text/javascript"> - function runTest() { - var canvas = document.getElementById('canvas1'); + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); var ctx = canvas.transferControlToOffscreen().getContext('2d'); // The default for lang is inherit ctx.font = '25px serif'; ctx.fillText('今骨直', 5, 50); } + + function runTest() { + drawText('zh-CN'); + document.documentElement.setAttribute('lang', 'ja'); + drawText('ja'); + } </script> <body onload="runTest()"> - <canvas id="canvas1" width="300" height="150"> + <canvas lang="zh-CN" id="canvas-zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas lang="ja" id="canvas-ja" width="300" height="100"> Browser does not support HTML5 Canvas. </canvas> </body> </html> - diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.html new file mode 100644 index 00000000000..9ffb6a49306 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.html @@ -0,0 +1,43 @@ +<!doctype HTML> +<html lang="en-US"> + <meta charset="utf-8"> + <title>HTML5 Canvas Test: The lang attribute inherits from the canvas in a transferred offscreen</title> + <link rel="match" href="canvas.2d.offscreen.lang-ref.html" /> + <link rel="author" href="mailto:schenney@chromium.org"/> + <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> + <meta name="assert" content="An offscreen transferred from a canvas element inherits the canvas language." /> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> + <script type="text/javascript"> + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); + var ctx = canvas.transferControlToOffscreen().getContext('2d'); + + // The default for lang is inherit + ctx.font = '25px serif'; + ctx.fillText('今骨直', 5, 50); + } + function runTest() { + drawText('zh-CN'); + drawText('ja'); + } + </script> + <body onload="runTest()"> + <canvas lang="zh-CN" id="canvas-zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas lang="ja" id="canvas-ja" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + </body> +</html> diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.tentative.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.tentative.html deleted file mode 100644 index 24f5f6402f6..00000000000 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.inherit.tentative.html +++ /dev/null @@ -1,25 +0,0 @@ -<!doctype HTML> -<html lang="en-US"> - <meta charset="utf-8"> - <title>HTML5 Canvas Test: The lang attribute inherits from the canvas in a transferred offscreen</title> - <link rel="match" href="canvas.2d.offscreen.lang-ref.html" /> - <link rel="author" href="mailto:schenney@chromium.org"/> - <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> - <meta name="assert" content="an offscreen transferred from a canvas element inherits the canvas language." /> - <script type="text/javascript"> - function runTest() { - var canvas = document.getElementById('canvas1'); - var ctx = canvas.transferControlToOffscreen().getContext('2d'); - - // The default for lang is inherit - ctx.font = '25px serif'; - ctx.fillText('今骨直', 5, 50); - } - </script> - <body onload="runTest()"> - <canvas lang = "zh-CN" id="canvas1" width="300" height="150"> - Browser does not support HTML5 Canvas. - </canvas> - </body> -</html> - diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.tentative.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.tentative.html deleted file mode 100644 index 6cdbeb50bd5..00000000000 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.transferred.lang.tentative.html +++ /dev/null @@ -1,25 +0,0 @@ -<!doctype HTML> -<html lang="en-US"> - <meta charset="utf-8"> - <title>HTML5 Canvas Test: The lang attribute inherits from the canvas in a transferred offscreen</title> - <link rel="match" href="canvas.2d.offscreen.lang-ref.html" /> - <link rel="author" href="mailto:schenney@chromium.org"/> - <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> - <meta name="assert" content="Verify that setting lang in a worker works." /> - <script type="text/javascript"> - function runTest() { - var canvas = document.getElementById('canvas1'); - var ctx = canvas.transferControlToOffscreen().getContext('2d'); - - ctx.font = '25px serif'; - ctx.lang = 'zh-CN'; - ctx.fillText('今骨直', 5, 50); - } - </script> - <body onload="runTest()"> - <canvas id="canvas1" width="300" height="150"> - Browser does not support HTML5 Canvas. - </canvas> - </body> -</html> - diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang-ref.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang-ref.html index 84f46ba99f6..82b6e731639 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang-ref.html +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang-ref.html @@ -1,10 +1,22 @@ <!doctype HTML> <meta charset="utf-8"> -<title>HTML5 Canvas Test Reference: The lang attribute in an offscreen canvas</title> +<title>HTML5 Canvas Test Reference: The lang attribute in an offscreen worker</title> <link rel="author" href="mailto:schenney@chromium.org"/> +<style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } +</style> <script> - function generateReference() { - var canvas = document.getElementById('canvas1'); + function drawText(language) { + var canvas = document.getElementById('canvas-' + language); var ctx = canvas.getContext('2d'); ctx.font = '25px serif'; @@ -13,9 +25,16 @@ ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 1, 1); } + function generateReference() { + drawText('zh-CN'); + drawText('ja'); + } </script> <body onload="generateReference()"> - <canvas id="canvas1" lang="zh-CN" width="300" height="150"> + <canvas id="canvas-zh-CN" lang="zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas id="canvas-ja" lang="ja" width="300" height="100"> Browser does not support HTML5 Canvas. </canvas> </body> diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.html new file mode 100644 index 00000000000..ed438c68f91 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.html @@ -0,0 +1,69 @@ +<!doctype HTML> +<html lang="en-US" class="reftest-wait"> + <meta charset="utf-8"> + <title>HTML5 Canvas Test: The lang attribute is respected in offscreen worker canvas</title> + <link rel="match" href="canvas.2d.offscreen.worker.lang-ref.html" /> + <link rel="author" href="mailto:schenney@chromium.org"/> + <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> + <meta name="assert" content="An offscreen canvas in a worker respects the lang text attribute." /> + <script src="/common/reftest-wait.js"></script> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> + <script type="text/javascript"> + function runTest() { + const placeholder_canvas_zh = document.createElement('canvas'); + placeholder_canvas_zh.setAttribute('width', '300'); + placeholder_canvas_zh.setAttribute('height', '100'); + const offscreen_zh = placeholder_canvas_zh.transferControlToOffscreen(); + + const worker_zh = new Worker('text-lang-worker-zh-CN.js'); + worker_zh.postMessage({canvas: offscreen_zh}, [offscreen_zh]); + + const placeholder_canvas_ja = document.createElement('canvas'); + placeholder_canvas_ja.setAttribute('width', '300'); + placeholder_canvas_ja.setAttribute('height', '100'); + const offscreen_ja = placeholder_canvas_ja.transferControlToOffscreen(); + + const worker_ja = new Worker('text-lang-worker-ja.js'); + worker_ja.postMessage({canvas: offscreen_ja}, [offscreen_ja]); + + const canvas_zh = document.getElementById('canvas-zh-CN'); + const ctx_zh = canvas_zh.getContext('2d', {willReadFrequently: true}); + const canvas_ja = document.getElementById('canvas-ja'); + const ctx_ja = canvas_ja.getContext('2d', {willReadFrequently: true}); + function checkResult() { + // Wait until frame propagates. + ctx_zh.drawImage(placeholder_canvas_zh, 0, 0); + const pixel_zh = ctx_zh.getImageData(0, 0, 1, 1).data; + ctx_ja.drawImage(placeholder_canvas_ja, 0, 0); + const pixel_ja = ctx_ja.getImageData(0, 0, 1, 1).data; + + if (pixel_zh[3] == 0 || pixel_ja[3] == 0) { + // Results not available, wait longer. + requestAnimationFrame(checkResult); + } else { + takeScreenshot(); + } + } + requestAnimationFrame(checkResult); + } + </script> + <body onload="runTest()"> + <canvas id="canvas-zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas id="canvas-ja" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + </body> +</html> diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.inherit.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.inherit.html new file mode 100644 index 00000000000..ca0d0ffeee6 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.inherit.html @@ -0,0 +1,71 @@ +<!doctype HTML> +<html class="reftest-wait"> + <meta charset="utf-8"> + <title>HTML5 Canvas Test: The lang attribute is inherited in offscreen worker canvas</title> + <link rel="match" href="canvas.2d.offscreen.worker.lang-ref.html" /> + <link rel="author" href="mailto:schenney@chromium.org"/> + <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> + <meta name="assert" content="An offscreen canvas in a worker inherits the lang attribute." /> + <script src="/common/reftest-wait.js"></script> + <style> + #canvas-zh-CN { + position: absolute; + top: 10px; + left: 10px; + } + #canvas-ja { + position: absolute; + top: 120px; + left: 10px; + } + </style> + <script type="text/javascript"> + function runTest() { + const placeholder_canvas_zh = document.createElement('canvas'); + placeholder_canvas_zh.setAttribute('width', '300'); + placeholder_canvas_zh.setAttribute('height', '100'); + placeholder_canvas_zh.setAttribute('lang', 'zh-CN'); + const offscreen_zh = placeholder_canvas_zh.transferControlToOffscreen(); + + const worker_zh = new Worker('text-lang-worker-inherit.js'); + worker_zh.postMessage({canvas: offscreen_zh}, [offscreen_zh]); + + const placeholder_canvas_ja = document.createElement('canvas'); + placeholder_canvas_ja.setAttribute('width', '300'); + placeholder_canvas_ja.setAttribute('height', '100'); + placeholder_canvas_zh.setAttribute('lang', 'ja'); + const offscreen_ja = placeholder_canvas_ja.transferControlToOffscreen(); + + const worker_ja = new Worker('text-lang-worker-inherit.js'); + worker_ja.postMessage({canvas: offscreen_ja}, [offscreen_ja]); + + const canvas_zh = document.getElementById('canvas-zh-CN'); + const ctx_zh = canvas_zh.getContext('2d', {willReadFrequently: true}); + const canvas_ja = document.getElementById('canvas-ja'); + const ctx_ja = canvas_ja.getContext('2d', {willReadFrequently: true}); + function checkResult() { + // Wait until frame propagates. + ctx_zh.drawImage(placeholder_canvas_zh, 0, 0); + const pixel_zh = ctx_zh.getImageData(0, 0, 1, 1).data; + ctx_ja.drawImage(placeholder_canvas_ja, 0, 0); + const pixel_ja = ctx_ja.getImageData(0, 0, 1, 1).data; + + if (pixel_zh[3] == 0 || pixel_ja[3] == 0) { + // Results not available, wait longer. + requestAnimationFrame(checkResult); + } else { + takeScreenshot(); + } + } + requestAnimationFrame(checkResult); + } + </script> + <body onload="runTest()"> + <canvas id="canvas-zh-CN" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + <canvas id="canvas-ja" width="300" height="100"> + Browser does not support HTML5 Canvas. + </canvas> + </body> +</html> diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.inherit.tentative.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.inherit.tentative.html deleted file mode 100644 index 5bbf9056668..00000000000 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.inherit.tentative.html +++ /dev/null @@ -1,43 +0,0 @@ -<!doctype HTML> -<html class="reftest-wait"> - <meta charset="utf-8"> - <title>HTML5 Canvas Test: The lang attribute is inherited in offscreen worker canvas</title> - <link rel="match" href="canvas.2d.offscreen.worker.lang-ref.html" /> - <link rel="author" href="mailto:schenney@chromium.org"/> - <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> - <meta name="assert" content="An offscreen canvas in a worker respects the lang attribute." /> - <script src="/common/reftest-wait.js"></script> - <script type="text/javascript"> - function runTest() { - const placeholder_canvas = document.createElement('canvas'); - placeholder_canvas.setAttribute('width', '300'); - placeholder_canvas.setAttribute('height', '150'); - placeholder_canvas.setAttribute('lang', 'zh-CN'); - const offscreen = placeholder_canvas.transferControlToOffscreen(); - - const worker = new Worker('text-lang-worker-inherit.js'); - worker.postMessage({canvas: offscreen}, [offscreen]); - - const canvas = document.getElementById('canvas1'); - const ctx = canvas.getContext('2d', {willReadFrequently: true}); - function checkResult() { - // Wait until frame propagates. - ctx.drawImage(placeholder_canvas, 0, 0); - const pixel = ctx.getImageData(0, 0, 1, 1).data; - - if (pixel[3] == 0) { - // Result not available, wait longer. - requestAnimationFrame(checkResult); - } else { - takeScreenshot(); - } - } - requestAnimationFrame(checkResult); - } - </script> - <body onload="runTest()"> - <canvas id="canvas1" width="300" height="150"> - Browser does not support HTML5 Canvas. - </canvas> - </body> -</html> diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.tentative.html b/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.tentative.html deleted file mode 100644 index c8a44ed739a..00000000000 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/canvas.2d.offscreen.worker.lang.tentative.html +++ /dev/null @@ -1,42 +0,0 @@ -<!doctype HTML> -<html lang="en-US"> - <meta charset="utf-8"> - <title>HTML5 Canvas Test: The lang attribute is respected in offscreen worker canvas</title> - <link rel="match" href="canvas.2d.offscreen.worker.lang-ref.html" /> - <link rel="author" href="mailto:schenney@chromium.org"/> - <link rel="help" href="https://html.spec.whatwg.org/multipage/canvas.html#text-styles"/> - <meta name="assert" content="An offscreen canvas in a worker respects the lang text attribute." /> - <script type="text/javascript"> - function runTest() { - const placeholder_canvas = document.createElement('canvas'); - placeholder_canvas.setAttribute('width', '300'); - placeholder_canvas.setAttribute('height', '150'); - const offscreen = placeholder_canvas.transferControlToOffscreen(); - - const worker = new Worker('text-lang-worker.js'); - worker.postMessage({canvas: offscreen}, [offscreen]); - - const canvas = document.getElementById('canvas1'); - const ctx = canvas.getContext('2d', {willReadFrequently: true}); - function checkResult() { - // Wait until frame propagates. - ctx.drawImage(placeholder_canvas, 0, 0); - const pixel = ctx.getImageData(0, 0, 1, 1).data; - - if (pixel[3] == 0) { - // Result not available, wait longer. - requestAnimationFrame(checkResult); - } else { - takeScreenshot(); - } - } - requestAnimationFrame(checkResult); - } - </script> - <body onload="runTest()"> - <canvas id="canvas1" width="300" height="150"> - Browser does not support HTML5 Canvas. - </canvas> - </body> -</html> - diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-inherit.js b/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-inherit.js index 604cc13ec90..20d96d94c93 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-inherit.js +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-inherit.js @@ -8,4 +8,4 @@ self.onmessage = function(e) { // Draw a single pixel, used to detect that the worker has completed. offscreen_ctx.fillStyle = '#0f0'; offscreen_ctx.fillRect(0, 0, 1, 1); -}
\ No newline at end of file +} diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-ja.js b/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-ja.js new file mode 100644 index 00000000000..585fc066ac3 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-ja.js @@ -0,0 +1,12 @@ +self.onmessage = function(e) { + const offscreen = e.data.canvas; + offscreen_ctx = offscreen.getContext('2d'); + + offscreen_ctx.font = '25px serif'; + offscreen_ctx.lang = 'ja'; + offscreen_ctx.fillText('今骨直', 5, 50); + + // Draw a single pixel, used to detect that the worker has completed. + offscreen_ctx.fillStyle = '#0f0'; + offscreen_ctx.fillRect(0, 0, 1, 1); +} diff --git a/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker.js b/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-zh-CN.js index 78b1d4ca7f1..cbededf3384 100644 --- a/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker.js +++ b/tests/wpt/tests/html/canvas/offscreen/manual/text/text-lang-worker-zh-CN.js @@ -9,4 +9,4 @@ self.onmessage = function(e) { // Draw a single pixel, used to detect that the worker has completed. offscreen_ctx.fillStyle = '#0f0'; offscreen_ctx.fillRect(0, 0, 1, 1); -}
\ No newline at end of file +} diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.default.tentative.html b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.default.html index 900ed14aaac..d70ddf2d955 100644 --- a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.default.tentative.html +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.default.html @@ -1,12 +1,12 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> <meta charset="UTF-8"> -<title>OffscreenCanvas test: 2d.text.direction.default.tentative</title> +<title>OffscreenCanvas test: 2d.text.direction.default</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/html/canvas/resources/canvas-tests.js"></script> -<h1>2d.text.direction.default.tentative</h1> +<h1>2d.text.direction.default</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.default.tentative.worker.js b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.default.worker.js index 98e96d948d7..f68fa1b2302 100644 --- a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.default.tentative.worker.js +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.default.worker.js @@ -1,5 +1,5 @@ // DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -// OffscreenCanvas test in a worker:2d.text.direction.default.tentative +// OffscreenCanvas test in a worker:2d.text.direction.default // Description: // Note: diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.valid.tentative.html b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.valid.html index 3a85e775aaf..3bb02204dd0 100644 --- a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.valid.tentative.html +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.valid.html @@ -1,12 +1,12 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> <meta charset="UTF-8"> -<title>OffscreenCanvas test: 2d.text.direction.valid.tentative</title> +<title>OffscreenCanvas test: 2d.text.direction.valid</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/html/canvas/resources/canvas-tests.js"></script> -<h1>2d.text.direction.valid.tentative</h1> +<h1>2d.text.direction.valid</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.valid.tentative.worker.js b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.valid.worker.js index 840f2527007..e8004232f69 100644 --- a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.valid.tentative.worker.js +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.direction.valid.worker.js @@ -1,5 +1,5 @@ // DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -// OffscreenCanvas test in a worker:2d.text.direction.valid.tentative +// OffscreenCanvas test in a worker:2d.text.direction.valid // Description: // Note: diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.default.tentative.html b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.default.html index 142535fcfb1..2f1021ca7b4 100644 --- a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.default.tentative.html +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.default.html @@ -1,12 +1,12 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> <meta charset="UTF-8"> -<title>OffscreenCanvas test: 2d.text.lang.default.tentative</title> +<title>OffscreenCanvas test: 2d.text.lang.default</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/html/canvas/resources/canvas-tests.js"></script> -<h1>2d.text.lang.default.tentative</h1> +<h1>2d.text.lang.default</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.default.tentative.worker.js b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.default.worker.js index a7b21d51cac..08a29cce4b4 100644 --- a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.default.tentative.worker.js +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.default.worker.js @@ -1,5 +1,5 @@ // DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -// OffscreenCanvas test in a worker:2d.text.lang.default.tentative +// OffscreenCanvas test in a worker:2d.text.lang.default // Description: // Note: diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.valid.tentative.html b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.valid.html index 1e1dd58c15a..ed8d5996a6a 100644 --- a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.valid.tentative.html +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.valid.html @@ -1,12 +1,12 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> <meta charset="UTF-8"> -<title>OffscreenCanvas test: 2d.text.lang.valid.tentative</title> +<title>OffscreenCanvas test: 2d.text.lang.valid</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/html/canvas/resources/canvas-tests.js"></script> -<h1>2d.text.lang.valid.tentative</h1> +<h1>2d.text.lang.valid</h1> <p class="desc"></p> diff --git a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.valid.tentative.worker.js b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.valid.worker.js index 17c8b0d5686..a79d302d166 100644 --- a/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.valid.tentative.worker.js +++ b/tests/wpt/tests/html/canvas/offscreen/text/2d.text.lang.valid.worker.js @@ -1,5 +1,5 @@ // DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -// OffscreenCanvas test in a worker:2d.text.lang.valid.tentative +// OffscreenCanvas test in a worker:2d.text.lang.valid // Description: // Note: diff --git a/tests/wpt/tests/html/canvas/tools/yaml/compositing.yaml b/tests/wpt/tests/html/canvas/tools/yaml/compositing.yaml index 9b57a02ca97..e8e2fe9101d 100644 --- a/tests/wpt/tests/html/canvas/tools/yaml/compositing.yaml +++ b/tests/wpt/tests/html/canvas/tools/yaml/compositing.yaml @@ -289,7 +289,7 @@ cr.set_source(filtered_foreground) cr.paint() - fuzzy: maxDifference=0-3; totalPixels=0-25392 + fuzzy: maxDifference=0-4; totalPixels=0-33000 variants_layout: - single_file - multi_files diff --git a/tests/wpt/tests/html/canvas/tools/yaml/text.yaml b/tests/wpt/tests/html/canvas/tools/yaml/text.yaml index 8be18ee3cdf..c572f00cb0c 100644 --- a/tests/wpt/tests/html/canvas/tools/yaml/text.yaml +++ b/tests/wpt/tests/html/canvas/tools/yaml/text.yaml @@ -134,11 +134,11 @@ ctx.font = 'italic 300 12px serif'; @assert ctx.font === 'italic 300 12px serif'; -- name: 2d.text.lang.default.tentative +- name: 2d.text.lang.default code: | @assert ctx.lang === 'inherit'; -- name: 2d.text.lang.valid.tentative +- name: 2d.text.lang.valid code: | ctx.lang = ''; @assert ctx.lang === ''; @@ -233,11 +233,11 @@ code: | @assert ctx.textBaseline === 'alphabetic'; -- name: 2d.text.direction.default.tentative +- name: 2d.text.direction.default code: | @assert ctx.direction === 'inherit'; -- name: 2d.text.direction.valid.tentative +- name: 2d.text.direction.valid code: | ctx.direction = 'ltr'; @assert ctx.direction === 'ltr'; diff --git a/tests/wpt/tests/html/dom/elements/the-innertext-and-outertext-properties/innertext-with-white-spaces.html b/tests/wpt/tests/html/dom/elements/the-innertext-and-outertext-properties/innertext-with-white-spaces.html new file mode 100644 index 00000000000..8619fce019a --- /dev/null +++ b/tests/wpt/tests/html/dom/elements/the-innertext-and-outertext-properties/innertext-with-white-spaces.html @@ -0,0 +1,508 @@ +<!doctype html> +<html> +<meta charset="utf-8"> +<meta name="variant" content="?white-space=normal"> +<meta name="variant" content="?white-space=pre"> +<meta name="variant" content="?white-space=pre-line"> +<meta name="variant" content="?white-space=pre-wrap"> +<meta name="variant" content="?white-space=normal&contenteditable=true"> +<meta name="variant" content="?white-space=pre&contenteditable=true"> +<meta name="variant" content="?white-space=pre-line&contenteditable=true"> +<meta name="variant" content="?white-space=pre-wrap&contenteditable=true"> +<meta name="variant" content="?white-space=normal&contenteditable=plaintext-only"> +<meta name="variant" content="?white-space=pre&contenteditable=plaintext-only"> +<meta name="variant" content="?white-space=pre-line&contenteditable=plaintext-only"> +<meta name="variant" content="?white-space=pre-wrap&contenteditable=plaintext-only"> +<title>Test invisible white-spaces do not appear in the result of `.innerText`</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/dom.html#the-innertext-idl-attribute"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/dom.html#rendered-text-collection-steps"><!-- Especially, this tests the step 4 --> +<link rel="help" href="https://drafts.csswg.org/css-text/#white-space-processing"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +"use strict"; + +const searchParams = new URLSearchParams(document.location.search); +const whiteSpace = searchParams.get("white-space"); +const isWhiteSpacesCollapsible = whiteSpace == "normal" || whiteSpace == "pre-line"; +const isNewLineCollapsible = whiteSpace == "normal"; +const contenteditable = searchParams.get("contenteditable"); + +addEventListener("DOMContentLoaded", () => { + const div = document.querySelector("div"); + div.style.whiteSpace = whiteSpace; + if (contenteditable) { + div.setAttribute("contenteditable", contenteditable); + } + for (const data of [ + // Leading white-spaces are invisible if they are collapsible. + { + desc: "Leading white-space should not appear if white-spaces are collapsible", + innerHTML: " abc", + expected: isWhiteSpacesCollapsible ? "abc" : " abc", + }, + { + desc: "Leading white-spaces should not appear if white-spaces are collapsible", + innerHTML: " abc", + expected: isWhiteSpacesCollapsible ? "abc" : " abc", + }, + { + desc: "Leading tab should not appear if white-spaces are collapsible", + innerHTML: "\tabc", + expected: isWhiteSpacesCollapsible ? "abc" : "\tabc", + }, + { + desc: "Leading tabs should not appear if white-spaces are collapsible", + innerHTML: "\t\tabc", + expected: isWhiteSpacesCollapsible ? "abc" : "\t\tabc", + }, + { + desc: "Leading linefeed should not appear if it's collapsible", + innerHTML: "\nabc", + expected: isNewLineCollapsible ? "abc" : "\nabc", + }, + { + desc: "Leading linefeeds should not appear if they are collapsible", + innerHTML: "\n\nabc", + expected: isNewLineCollapsible ? "abc" : "\n\nabc", + }, + { + desc: "Leading mixed white-spaces should not appear if they are collapsible", + innerHTML: " \n\t abc", + expected: isNewLineCollapsible + ? "abc" + : (isWhiteSpacesCollapsible + // Surrounding collapsible white-spaces of preformatted line break should be invisible. + ? "\nabc" + : " \n\t abc"), + }, + { + desc: "Leading CR should be normalized to LF and should not appear if linefeeds are collapsible", + innerHTML: "\rabc", + expected: isNewLineCollapsible ? "abc" : "\nabc", + }, + { + desc: "Leading CRs should be normalized to LFs and should not appear if linefeeds are collapsible", + innerHTML: "\r\rabc", + expected: isNewLineCollapsible ? "abc" : "\n\nabc", + }, + // Trailing white-spaces are invisible if they are collapsible. + { + desc: "Trailing white-space should not appear if white-spaces are collapsible", + innerHTML: "abc ", + expected: isWhiteSpacesCollapsible ? "abc" : "abc ", + }, + { + desc: "Trailing white-spaces should not appear if white-spaces are collapsible", + innerHTML: "abc ", + expected: isWhiteSpacesCollapsible ? "abc" : "abc ", + }, + { + desc: "Trailing tab should not appear if white-spaces are collapsible", + innerHTML: "abc\t", + expected: isWhiteSpacesCollapsible ? "abc" : "abc\t", + }, + { + desc: "Trailing tabs should not appear if white-spaces are collapsible", + innerHTML: "abc\t\t", + expected: isWhiteSpacesCollapsible ? "abc" : "abc\t\t", + }, + { + desc: "Trailing linefeed should not appear if it's collapsible", + innerHTML: "abc\n", + expected: isNewLineCollapsible ? "abc" : "abc\n", + }, + { + desc: "Trailing linefeeds should not appear if they are collapsible", + innerHTML: "abc\n\n", + expected: isNewLineCollapsible ? "abc" : "abc\n\n", + }, + { + desc: "Trailing mixed white-spaces should not appear if they are collapsible", + innerHTML: "abc\t \n ", + expected: isNewLineCollapsible + ? "abc" + : (isWhiteSpacesCollapsible + // Surrounding collapsible white-spaces of preformatted line break should be invisible. + ? "abc\n" + : "abc\t \n "), + }, + { + desc: "Trailing CR should be normalized to LF and should not appear if linefeeds are collapsible", + innerHTML: "abc\r", + expected: isNewLineCollapsible ? "abc" : "abc\n", + }, + { + desc: "Trailing CRs should be normalized to LFs and should not appear if linefeeds are collapsible", + innerHTML: "abc\r\r", + expected: isNewLineCollapsible ? "abc" : "abc\n\n", + }, + // Only white-spaces. + { + desc: "Only single collapsible space should be invisible", + innerHTML: " ", + expected: isWhiteSpacesCollapsible ? "" : " ", + }, + { + desc: "Only single collapsible tab should be invisible", + innerHTML: "\t", + expected: isWhiteSpacesCollapsible ? "" : "\t", + }, + { + desc: "Only single collapsible linefeed should be invisible", + innerHTML: "\n", + expected: isNewLineCollapsible ? "" : "\n", + }, + { + desc: "Only single collapsible CR should be invisible", + innerHTML: "\r", + expected: isNewLineCollapsible ? "" : "\n", + }, + { + desc: "Only multiple collapsible spaces should be invisible", + innerHTML: " ", + expected: isWhiteSpacesCollapsible ? "" : " ", + }, + { + desc: "Only multiple collapsible tabs should be invisible", + innerHTML: "\t\t\t", + expected: isWhiteSpacesCollapsible ? "" : "\t\t\t", + }, + { + desc: "Only multiple collapsible linefeeds should be invisible", + innerHTML: "\n\n\n", + expected: isNewLineCollapsible ? "" : "\n\n\n", + }, + { + desc: "Only multiple collapsible CRs should be invisible", + innerHTML: "\r\r\r", + expected: isNewLineCollapsible ? "" : "\n\n\n", + }, + // Between words. + { + desc: "Single collapsible tab should be converted to an ASCII space", + innerHTML: "abc\tdef", + expected: isWhiteSpacesCollapsible ? "abc def" : "abc\tdef", + }, + { + desc: "Single collapsible linefeed should be converted to an ASCII space", + innerHTML: "abc\ndef", + expected: isNewLineCollapsible ? "abc def" : "abc\ndef", + }, + { + desc: "Single collapsible CR should be converted to an ASCII space, or otherwise, a linefeed", + innerHTML: "abc\rdef", + expected: isNewLineCollapsible ? "abc def" : "abc\ndef", + }, + { + desc: "Multiple white-spaces between words may be invisible if they are collapsible", + innerHTML: "abc def", + expected: isWhiteSpacesCollapsible ? "abc def" : "abc def", + }, + { + desc: "Multiple mixed white-spaces between words may be invisible if they are collapsible #1", + innerHTML: "abc\t def", + expected: isWhiteSpacesCollapsible ? "abc def" : "abc\t def", + }, + { + desc: "Multiple mixed white-spaces between words may be invisible if they are collapsible #2", + innerHTML: "abc \tdef", + expected: isWhiteSpacesCollapsible ? "abc def" : "abc \tdef", + }, + { + desc: "Multiple mixed white-spaces between words may be invisible if they are collapsible #3", + innerHTML: "abc\n def", + expected: isNewLineCollapsible + ? "abc def" + : (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n def"), + }, + { + desc: "Multiple mixed white-spaces between words may be invisible if they are collapsible #4", + innerHTML: "abc \ndef", + expected: isNewLineCollapsible + ? "abc def" + : (isWhiteSpacesCollapsible ? "abc\ndef" : "abc \ndef"), + }, + // Before <br> + { + desc: "white-space before <br> should be invisible if it's collapsible", + innerHTML: "abc <br>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc \ndef", + }, + { + desc: "white-spaces before <br> should be invisible if they are collapsible", + innerHTML: "abc <br>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc \ndef", + }, + { + desc: "tab before <br> should be invisible if it's collapsible", + innerHTML: "abc\t<br>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\t\ndef", + }, + { + desc: "linefeed before <br> should be invisible if it's collapsible", + innerHTML: "abc\n<br>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + { + desc: "CR before <br> should be invisible if it's collapsible", + innerHTML: "abc\r<br>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + // After <br> + { + desc: "white-space after <br> should be invisible if it's collapsible", + innerHTML: "abc<br> def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n def", + }, + { + desc: "white-spaces after <br> should be invisible if they are collapsible", + innerHTML: "abc<br> def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n def", + }, + { + desc: "tab after <br> should be invisible if it's collapsible", + innerHTML: "abc<br>\tdef", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\tdef", + }, + { + desc: "linefeed after <br> should be invisible if it's collapsible", + innerHTML: "abc<br>\ndef", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + { + desc: "CR after <br> should be invisible if it's collapsible", + innerHTML: "abc<br>\rdef", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + // Between <br>s + { + desc: "white-space between <br>s should be invisible if it's collapsible", + innerHTML: "abc<br> <br>def", + expected: isWhiteSpacesCollapsible ? "abc\n\ndef" : "abc\n \ndef", + }, + { + desc: "white-spaces between <br>s should be invisible if they are collapsible", + innerHTML: "abc<br> <br>def", + expected: isWhiteSpacesCollapsible ? "abc\n\ndef" : "abc\n \ndef", + }, + { + desc: "tab between <br>s should be invisible if it's collapsible", + innerHTML: "abc<br>\t<br>def", + expected: isWhiteSpacesCollapsible ? "abc\n\ndef" : "abc\n\t\ndef", + }, + { + desc: "linefeed between <br>s should be invisible if it's collapsible", + innerHTML: "abc<br>\n<br>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\n\ndef" : "abc\n\n\ndef") + : "abc\n\n\ndef", + }, + { + desc: "CR between <br>s should be invisible if it's collapsible", + innerHTML: "abc<br>\r<br>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\n\ndef" : "abc\n\n\ndef") + : "abc\n\n\ndef", + }, + // Before <hr> + { + desc: "white-space before <hr> should be invisible if it's collapsible", + innerHTML: "abc <hr>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc \ndef", + }, + { + desc: "white-spaces before <hr> should be invisible if they are collapsible", + innerHTML: "abc <hr>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc \ndef", + }, + { + desc: "tab before <hr> should be invisible if it's collapsible", + innerHTML: "abc\t<hr>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\t\ndef", + }, + { + desc: "linefeed before <hr> should be invisible if it's collapsible", + innerHTML: "abc\n<hr>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + { + desc: "CR before <hr> should be invisible if it's collapsible", + innerHTML: "abc\r<hr>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + // After <hr> + { + desc: "white-space after <hr> should be invisible if it's collapsible", + innerHTML: "abc<hr> def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n def", + }, + { + desc: "white-spaces after <hr> should be invisible if they are collapsible", + innerHTML: "abc<hr> def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n def", + }, + { + desc: "tab after <hr> should be invisible if it's collapsible", + innerHTML: "abc<hr>\tdef", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\tdef", + }, + { + desc: "linefeed after <hr> should be invisible if it's collapsible", + innerHTML: "abc<hr>\ndef", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + { + desc: "CR after <hr> should be invisible if it's collapsible", + innerHTML: "abc<hr>\rdef", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + // Between <hr>s + { + desc: "white-space between <hr>s should be invisible if it's collapsible", + innerHTML: "abc<hr> <hr>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n \ndef", + }, + { + desc: "white-spaces between <hr>s should be invisible if they are collapsible", + innerHTML: "abc<hr> <hr>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n \ndef", + }, + { + desc: "tab between <hr>s should be invisible if it's collapsible", + innerHTML: "abc<hr>\t<hr>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\t\ndef", + }, + { + desc: "linefeed between <hr>s should be invisible if it's collapsible", + innerHTML: "abc<hr>\n<hr>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\n\ndef") + : "abc\n\n\ndef", + }, + { + desc: "CR between <hr>s should be invisible if it's collapsible", + innerHTML: "abc<hr>\r<hr>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\n\ndef") + : "abc\n\n\ndef", + }, + // Before <div> + { + desc: "white-space before <div> should be invisible if it's collapsible", + innerHTML: "abc <div></div>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc \ndef", + }, + { + desc: "white-spaces before <div> should be invisible if they are collapsible", + innerHTML: "abc <div></div>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc \ndef", + }, + { + desc: "tab before <div> should be invisible if it's collapsible", + innerHTML: "abc\t<div></div>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\t\ndef", + }, + { + desc: "linefeed before <div> should be invisible if it's collapsible", + innerHTML: "abc\n<div></div>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + { + desc: "CR before <div> should be invisible if it's collapsible", + innerHTML: "abc\r<div></div>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + // After <div> + { + desc: "white-space after <div> should be invisible if it's collapsible", + innerHTML: "abc<div></div> def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n def", + }, + { + desc: "white-spaces after <div> should be invisible if they are collapsible", + innerHTML: "abc<div></div> def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n def", + }, + { + desc: "tab after <div> should be invisible if it's collapsible", + innerHTML: "abc<div></div>\tdef", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\tdef", + }, + { + desc: "linefeed after <div> should be invisible if it's collapsible", + innerHTML: "abc<div></div>\ndef", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + { + desc: "CR after <div> should be invisible if it's collapsible", + innerHTML: "abc<div></div>\rdef", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\ndef") + : "abc\n\ndef", + }, + // Between <div>s + { + desc: "white-space between <div>s should be invisible if it's collapsible", + innerHTML: "abc<div></div> <div></div>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n \ndef", + }, + { + desc: "white-spaces between <div>s should be invisible if they are collapsible", + innerHTML: "abc<div></div> <div></div>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n \ndef", + }, + { + desc: "tab between <div>s should be invisible if it's collapsible", + innerHTML: "abc<div></div>\t<div></div>def", + expected: isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\t\ndef", + }, + { + desc: "linefeed between <div>s should be invisible if it's collapsible", + innerHTML: "abc<div></div>\n<div></div>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\n\ndef") + : "abc\n\n\ndef", + }, + { + desc: "CR between <div>s should be invisible if it's collapsible", + innerHTML: "abc<div></div>\r<div></div>def", + expected: isNewLineCollapsible + ? (isWhiteSpacesCollapsible ? "abc\ndef" : "abc\n\n\ndef") + : "abc\n\n\ndef", + }, + ]) { + test(() => { + div.innerHTML = data.innerHTML; + assert_equals(div.innerText, data.expected); + }, data.desc); + } +}, {once: true}); +</script> +</head> +<body> + <div></div> +</body> +</html> diff --git a/tests/wpt/tests/html/dom/idlharness.https.html b/tests/wpt/tests/html/dom/idlharness.https.html index d782118dbaf..bfecbbe57fd 100644 --- a/tests/wpt/tests/html/dom/idlharness.https.html +++ b/tests/wpt/tests/html/dom/idlharness.https.html @@ -50,6 +50,9 @@ idl_test( idlArray.add_untested_idls('typedef Window WindowProxy;'); idlArray.add_objects({ + Element: ['document.createElement("div")'], + Range: ['new Range()'], + XMLSerializer: ['new XMLSerializer()'], NodeList: ['document.getElementsByName("name")'], HTMLAllCollection: ['document.all'], HTMLFormControlsCollection: ['document.createElement("form").elements'], diff --git a/tests/wpt/tests/html/rendering/replaced-elements/embedded-content/iframe-frameborder.html b/tests/wpt/tests/html/rendering/replaced-elements/embedded-content/iframe-frameborder.html new file mode 100644 index 00000000000..3df33aede8d --- /dev/null +++ b/tests/wpt/tests/html/rendering/replaced-elements/embedded-content/iframe-frameborder.html @@ -0,0 +1,41 @@ +<!doctype html> +<meta charset=utf-8> +<title>Presentational hint for iframe frameborder</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> + +<div data-expect="0px"> + <iframe frameborder></iframe> + <iframe frameborder=0></iframe> + <iframe frameborder=-0></iframe> + <iframe frameborder=0.5></iframe> + <iframe frameborder=0.5e1></iframe> + <iframe frameborder=no></iframe> + <iframe frameborder=none></iframe> + <iframe frameborder=error></iframe> +</div> + +<div data-expect="2px"> + <iframe></iframe> + <iframe frameborder=1></iframe> + <iframe frameborder=-1></iframe> + <iframe frameborder=10></iframe> + <iframe frameborder=-10></iframe> +</div> + +<script> +const iframes = document.querySelectorAll('iframe'); +const borderWidthProps = ['border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width']; +for (const iframe of iframes) { + test(() => { + const computed = getComputedStyle(iframe); + const expectedBorderWidth = iframe.parentNode.dataset.expect; + for (const prop of borderWidthProps) { + assert_equals(computed.getPropertyValue(prop), expectedBorderWidth, prop); + } + assert_equals(computed.getPropertyValue('border-style'), 'inset', 'border-style'); + assert_equals(computed.getPropertyValue('border-color'), getComputedStyle(document.documentElement).color, 'border-color'); + }, iframe.outerHTML); +} +</script> diff --git a/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number-relayout-ref.html b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number-relayout-ref.html new file mode 100644 index 00000000000..aaec5e84640 --- /dev/null +++ b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number-relayout-ref.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing"> +<body> +<input id="inputa" style="field-sizing: content" type="number" value="12345"><input type="number"> +</body> diff --git a/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number-relayout.html b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number-relayout.html new file mode 100644 index 00000000000..06d0d576a8c --- /dev/null +++ b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number-relayout.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing"> +<link rel=match href="field-sizing-input-number-relayout-ref.html"> +<script src="/common/reftest-wait.js"></script> +<body> +<input id="inputa" style="field-sizing: content" type="number"><input type="number"> +<script> +requestAnimationFrame(() => { + inputa.value = ''; + requestAnimationFrame(() => { + inputa.value = 12345; + takeScreenshot(); + }); +}); +</script> +</body> +</html> diff --git a/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number.html b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number.html index 859d35197b0..6056f9320a5 100644 --- a/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number.html +++ b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-number.html @@ -53,12 +53,10 @@ function addTwoElements(source1, source2) { // A text <input> has approximately 20ch width by default. // A text <input> with field-sizing:content must be shorter than the default. assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth); - assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight); pair = addTwoElements(`<input type=${type} ${DISABLE}>`, `<input type=${type} ${DISABLE} value="123">`); assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth); - assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight); }, `${type}: Empty value`); test(() => { @@ -80,20 +78,17 @@ function addTwoElements(source1, source2) { pair = addElements(`<input type=${type} style="width:20ch; height:2lh" placeholder="${LONG_TEXT}">`); assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth); assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight); - }, `${type}: Explicit width and heigth`); + }, `${type}: Explicit width and height`); test(() => { let pair = addElements(`<input type=${type} style="width:20ch">`); assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth); - assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight); pair = addElements(`<input type=${type} style="width:20ch" value="${LONG_VALUE}">`); assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth); - assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight); pair = addElements(`<input type=${type} style="width:20ch" placeholder="${LONG_TEXT}">`); assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth); - assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight); }, `${type}: Explicit width and auto height`); test(() => { @@ -138,10 +133,8 @@ function addTwoElements(source1, source2) { container.innerHTML = `<input type=${type}>`; const element = container.firstChild; const w = element.offsetWidth; - const h = element.offsetHeight; element.classList.add('disable-default'); assert_less_than(element.offsetWidth, w); - assert_equals(element.offsetHeight, h); }, `${type}: Update field-sizing property dynamically`); }); diff --git a/tests/wpt/tests/html/rendering/widgets/field-sizing-input-text-relayout-ref.html b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-text-relayout-ref.html new file mode 100644 index 00000000000..19d977fee47 --- /dev/null +++ b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-text-relayout-ref.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing"> +<body> +<input id="inputa" style="field-sizing: content" value="12345"><input> +</body> diff --git a/tests/wpt/tests/html/rendering/widgets/field-sizing-input-text-relayout.html b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-text-relayout.html new file mode 100644 index 00000000000..64f8e52ab36 --- /dev/null +++ b/tests/wpt/tests/html/rendering/widgets/field-sizing-input-text-relayout.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing"> +<link rel=match href="field-sizing-input-text-relayout-ref.html"> +<script src="/common/reftest-wait.js"></script> +<body> +<input id="inputa" style="field-sizing: content" value=""><input> +<script> +requestAnimationFrame(() => { + inputa.value = ''; + requestAnimationFrame(() => { + inputa.value = '12345'; + takeScreenshot(); + }); +}); +</script> +</body> +</html> diff --git a/tests/wpt/tests/html/rendering/widgets/field-sizing-textarea-relayout-ref.html b/tests/wpt/tests/html/rendering/widgets/field-sizing-textarea-relayout-ref.html new file mode 100644 index 00000000000..f7167ed4c31 --- /dev/null +++ b/tests/wpt/tests/html/rendering/widgets/field-sizing-textarea-relayout-ref.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing"> +<body> +<textarea style="field-sizing: content">12345</textarea><textarea></textarea> +</body> diff --git a/tests/wpt/tests/html/rendering/widgets/field-sizing-textarea-relayout.html b/tests/wpt/tests/html/rendering/widgets/field-sizing-textarea-relayout.html new file mode 100644 index 00000000000..1e18bd20703 --- /dev/null +++ b/tests/wpt/tests/html/rendering/widgets/field-sizing-textarea-relayout.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing"> +<link rel=match href="field-sizing-textarea-relayout-ref.html"> +<meta name="fuzzy" content="maxDifference=153; totalPixels=2" /> +<script src="/common/reftest-wait.js"></script> +<body> +<textarea id="textarea" style="field-sizing: content"></textarea><textarea></textarea> +<script> +requestAnimationFrame(() => { + textarea.value = ''; + requestAnimationFrame(() => { + textarea.value = '12345'; + takeScreenshot(); + }); +}); +</script> +</body> +</html> diff --git a/tests/wpt/tests/html/semantics/forms/the-input-element/input-valueasnumber.html b/tests/wpt/tests/html/semantics/forms/the-input-element/input-valueasnumber.html index 1af75eafa3e..47e66c5e3bd 100644 --- a/tests/wpt/tests/html/semantics/forms/the-input-element/input-valueasnumber.html +++ b/tests/wpt/tests/html/semantics/forms/the-input-element/input-valueasnumber.html @@ -73,9 +73,13 @@ ["", NaN], ["0000-12", NaN], ["2019-00", NaN], - ["2019-12", 599] + ["2019-12", 599], + ["1969-12", -1], + ]); + testValueAsNumberSetter("month", monthInput, [ + [599, "2019-12"], + [-1, "1969-12"], ]); - testValueAsNumberSetter("month", monthInput, [[599, "2019-12"]]); const weekInput = document.getElementById("input_week"); testValueAsNumberGetter("week", weekInput, [ @@ -83,11 +87,13 @@ ["0000-W50", NaN], ["2019-W00", NaN], ["2019-W60", NaN], - ["2019-W50", 1575849600000] + ["2019-W50", 1575849600000], + ["1969-W20", -20217600000], ]); testValueAsNumberSetter("week", weekInput, [ [0, "1970-W01"], - [1575849600000, "2019-W50"] + [1575849600000, "2019-W50"], + [-20217600000, "1969-W20"], ]); const timeInput = document.getElementById("input_time"); diff --git a/tests/wpt/tests/html/semantics/forms/the-select-element/customizable-select/switch-picker-appearance.tentative.html b/tests/wpt/tests/html/semantics/forms/the-select-element/customizable-select/switch-picker-appearance.tentative.html index 95d2da1bbf7..6d768f4efd0 100644 --- a/tests/wpt/tests/html/semantics/forms/the-select-element/customizable-select/switch-picker-appearance.tentative.html +++ b/tests/wpt/tests/html/semantics/forms/the-select-element/customizable-select/switch-picker-appearance.tentative.html @@ -203,8 +203,6 @@ promise_test(async (t) => { t.add_cleanup(() => select2.removeAttribute('style')); select2.setAttribute('style','appearance:auto'); assert_equals(getComputedStyle(select2).appearance,'auto','appearance should still be auto from inline style'); - await new Promise(requestAnimationFrame); - await new Promise(requestAnimationFrame); assert_false(select2.matches(':open'),'Adding inline style should close the picker'); },'The select picker is closed if the <select> inline appearance value is changed while the picker is open'); </script> diff --git a/tests/wpt/tests/html/semantics/popovers/popover-focus-2.html b/tests/wpt/tests/html/semantics/popovers/popover-focus-2.html index 5fc8e7adf98..3c1c6bed95c 100644 --- a/tests/wpt/tests/html/semantics/popovers/popover-focus-2.html +++ b/tests/wpt/tests/html/semantics/popovers/popover-focus-2.html @@ -17,17 +17,17 @@ </div> <div popover id=popover1 style="top:100px"> <button id=inside_popover1 tabindex="0">Inside1</button> - <button id=invoker2 popovertarget=popover2 tabindex="0">Nested Invoker 2</button> + <button id=invoker2 tabindex="0">Nested Invoker 2</button> <button id=inside_popover2 tabindex="0">Inside2</button> </div> <button id=button2 tabindex="0">Button2</button> <div popover id=popover_no_invoker tabindex="0" style="top:300px"></div> - <button popovertarget=popover0 id=invoker0 tabindex="0">Invoker0</button> - <button popovertarget=popover1 id=invoker1 tabindex="0">Invoker1</button> + <button id=invoker0 tabindex="0">Invoker0</button> + <button id=invoker1 tabindex="0">Invoker1</button> <button id=button3 tabindex="0">Button3</button> <div popover id=popover2 style="top:200px"> <button id=inside_popover3 tabindex="0">Inside3</button> - <button id=invoker3 popovertarget=popover3 tabindex="0">Nested Invoker 3</button> + <button id=invoker3 tabindex="0">Nested Invoker 3</button> </div> <div popover id=popover3 style="top:300px"> Non-focusable popover @@ -53,7 +53,7 @@ async function verifyFocusOrder(order,description) { assert_equals(document.activeElement,control,`${description}: Step ${i+1} (backwards)`); } } -promise_test(async t => { +async function testPopoverFocusNavigation() { button1.focus(); assert_equals(document.activeElement,button1); await sendTab(); @@ -108,33 +108,110 @@ promise_test(async t => { assert_equals(document.activeElement,button4,'Focus should skip popovers'); button1.focus(); await verifyFocusOrder([button1, button2, invoker0, invoker1, inside_popover1, invoker2, inside_popover3, invoker3, inside_popover2, button3, button4],'set 2'); -}, "Popover focus navigation"); +} +promise_test(async t => { + invoker0.setAttribute('popovertarget', 'popover0'); + invoker1.setAttribute('popovertarget', 'popover1'); + invoker2.setAttribute('popovertarget', 'popover2'); + invoker3.setAttribute('popovertarget', 'popover3'); + t.add_cleanup(() => { + invoker0.removeAttribute('popovertarget'); + invoker1.removeAttribute('popovertarget'); + invoker2.removeAttribute('popovertarget'); + invoker3.removeAttribute('popovertarget'); + }); + await testPopoverFocusNavigation(); +}, "Popover focus navigation with declarative invocation"); + +promise_test(async t => { + const invoker0Click = () => { + popover0.togglePopover({ source: invoker0 }); + }; + invoker0.addEventListener('click', invoker0Click); + const invoker1Click = () => { + popover1.togglePopover({ source: invoker1 }); + }; + invoker1.addEventListener('click', invoker1Click); + const invoker2Click = () => { + popover2.togglePopover({ source: invoker2 }); + }; + invoker2.addEventListener('click', invoker2Click); + const invoker3Click = () => { + popover3.togglePopover({ source: invoker3 }); + }; + invoker3.addEventListener('click', invoker3Click); + t.add_cleanup(() => { + invoker0.removeEventListener('click', invoker0Click); + invoker1.removeEventListener('click', invoker1Click); + invoker2.removeEventListener('click', invoker2Click); + invoker3.removeEventListener('click', invoker3Click); + }); + await testPopoverFocusNavigation() +}, "Popover focus navigation with imperative invocation"); </script> -<button id=circular0 popovertarget=popover4 tabindex="0">Invoker</button> +<button id=circular0 tabindex="0">Invoker</button> <div id=popover4 popover> - <button id=circular1 autofocus popovertarget=popover4 popovertargetaction=hide tabindex="0"></button> - <button id=circular2 popovertarget=popover4 popovertargetaction=show tabindex="0"></button> - <button id=circular3 popovertarget=popover4 tabindex="0"></button> + <button id=circular1 autofocus popovertargetaction=hide tabindex="0"></button> + <button id=circular2 popovertargetaction=show tabindex="0"></button> + <button id=circular3 tabindex="0"></button> </div> <button id=circular4 tabindex="0">after</button> <script> -promise_test(async t => { +async function testCircularReferenceTabNavigation() { circular0.focus(); await sendEnter(); // Activate the invoker await verifyFocusOrder([circular0, circular1, circular2, circular3, circular4],'circular reference'); popover4.hidePopover(); -}, "Circular reference tab navigation"); +} +promise_test(async t => { + circular0.setAttribute('popovertarget', 'popover4'); + circular1.setAttribute('popovertarget', 'popover4'); + circular2.setAttribute('popovertarget', 'popover4'); + circular3.setAttribute('popovertarget', 'popover4'); + t.add_cleanup(() => { + circular0.removeAttribute('popovertarget'); + circular1.removeAttribute('popovertarget'); + circular2.removeAttribute('popovertarget'); + circular3.removeAttribute('popovertarget'); + }); + await testCircularReferenceTabNavigation(); +}, "Circular reference tab navigation with declarative invocation"); +promise_test(async t => { + const circular0Click = () => { + popover4.togglePopover({ source: circular0 }); + }; + circular0.addEventListener('click', circular0Click); + const circular1Click = () => { + popover4.hidePopover(); + }; + circular1.addEventListener('click', circular1Click); + const circular2Click = () => { + popover4.showPopover({ source: circular2 }); + }; + circular2.addEventListener('click', circular2Click); + const circular3Click = () => { + popover4.togglePopover({ source: circular3 }); + }; + circular3.addEventListener('click', circular3Click); + t.add_cleanup(() => { + circular0.removeEventListener('click', circular0Click); + circular1.removeEventListener('click', circular1Click); + circular2.removeEventListener('click', circular2Click); + circular3.removeEventListener('click', circular3Click); + }); + await testCircularReferenceTabNavigation(); +}, "Circular reference tab navigation with imperative invocation"); </script> <div id=focus-return1> - <button popovertarget=focus-return1-p popovertargetaction=show tabindex="0">Show popover</button> + <button popovertargetaction=show tabindex="0">Show popover</button> <div popover id=focus-return1-p> - <button popovertarget=focus-return1-p popovertargetaction=hide autofocus tabindex="0">Hide popover</button> + <button popovertargetaction=hide autofocus tabindex="0">Hide popover</button> </div> </div> <script> -promise_test(async t => { +async function testPopoverFocusReturn1() { const invoker = document.querySelector('#focus-return1>button'); const popover = document.querySelector('#focus-return1>[popover]'); const hideButton = popover.querySelector('[popovertargetaction=hide]'); @@ -146,16 +223,46 @@ promise_test(async t => { await sendEnter(); // Activate the hide invoker assert_false(popover.matches(':popover-open'), 'popover should be hidden by invoker'); assert_equals(document.activeElement,invoker,'Focus should be returned to the invoker'); -}, "Popover focus returns when popover is hidden by invoker"); +} +promise_test(async t => { + const invoker = document.querySelector('#focus-return1>button'); + const popover = document.querySelector('#focus-return1>[popover]'); + const hideButton = popover.querySelector('button'); + invoker.setAttribute('popovertarget', 'focus-return1-p'); + hideButton.setAttribute('popovertarget', 'focus-return1-p'); + t.add_cleanup(() => { + invoker.removeAttribute('popovertarget'); + hideButton.removeAttribute('popovertarget'); + }); + await testPopoverFocusReturn1(); +}, "Popover focus returns when popover is hidden by invoker with declarative invocation"); +promise_test(async t => { + const invoker = document.querySelector('#focus-return1>button'); + const popover = document.querySelector('#focus-return1>[popover]'); + const hideButton = popover.querySelector('button'); + const invokerClick = () => { + popover.showPopover({ source: invoker }); + }; + invoker.addEventListener('click', invokerClick); + const hideButtonClick = () => { + popover.hidePopover(); + }; + hideButton.addEventListener('click', hideButtonClick); + t.add_cleanup(() => { + invoker.removeEventListener('click', invokerClick); + hideButton.removeEventListener('click', hideButtonClick); + }); + await testPopoverFocusReturn1(); +}, "Popover focus returns when popover is hidden by invoker with imperative invocation"); </script> <div id=focus-return2> - <button popovertarget=focus-return2-p tabindex="0">Toggle popover</button> + <button tabindex="0">Toggle popover</button> <div popover id=focus-return2-p>Popover with <button tabindex="0">focusable element</button></div> <span tabindex=0>Other focusable element</span> </div> <script> -promise_test(async t => { +async function testPopoverFocusReturn2() { const invoker = document.querySelector('#focus-return2>button'); const popover = document.querySelector('#focus-return2>[popover]'); const otherElement = document.querySelector('#focus-return2>span'); @@ -171,18 +278,38 @@ promise_test(async t => { await sendEscape(); // Close the popover via ESC assert_false(popover.matches(':popover-open'), 'popover should be hidden'); assert_equals(document.activeElement,otherElement,'focus does not move because it was not inside the popover'); -}, "Popover focus only returns to invoker when focus is within the popover"); +} +promise_test(async t => { + const invoker = document.querySelector('#focus-return2>button'); + invoker.setAttribute('popovertarget', 'focus-return2-p'); + t.add_cleanup(() => { + invoker.removeAttribute('popovertarget'); + }); + await testPopoverFocusReturn2(); +}, "Popover focus only returns to invoker when focus is within the popover with declarative invocation"); +promise_test(async t => { + const invoker = document.querySelector('#focus-return2>button'); + const popover = document.querySelector('#focus-return2>[popover]'); + const invokerClick = () => { + popover.togglePopover({ source: invoker }); + }; + invoker.addEventListener('click', invokerClick); + t.add_cleanup(() => { + invoker.removeEventListener('click', invokerClick); + }); + await testPopoverFocusReturn2(); +}, "Popover focus only returns to invoker when focus is within the popover with imperative invocation"); </script> <div id=no-focus-candidate> - <button popovertarget=no-focus-candidate-p tabindex="0">Toggle popover</button> + <button tabindex="0">Toggle popover</button> <div popover id=no-focus-candidate-p> - Popover with <button tabindex="0" popovertarget=no-focus-candidate-p2>focusable element</button> + Popover with <button tabindex="0">focusable element</button> <div popover id=no-focus-candidate-p2>Nested popover with <button tabindex="0">focusable element</button></div> </div> </div> <script> -promise_test(async t => { +async function testNoFocusCandidate() { const invoker = document.querySelector('#no-focus-candidate>button'); const popover = document.querySelector('#no-focus-candidate>[popover]'); const nestedPopover = document.querySelector('#no-focus-candidate>[popover]>[popover]'); @@ -203,5 +330,43 @@ promise_test(async t => { nestedPopover.querySelector('button').focus(); await sendTab(); assert_equals(document.activeElement, document.body, 'no more focusable elements after the button'); -}, "Cases where the next focus candidate isn't in the direct parent scope"); +} +promise_test(async t => { + const invoker = document.querySelector('#no-focus-candidate>button'); + const popover = document.querySelector('#no-focus-candidate>[popover]'); + const nestedButton = popover.querySelector('button'); + const nestedPopover = document.querySelector('#no-focus-candidate>[popover]>[popover]'); + invoker.setAttribute('popovertarget', 'no-focus-candidate-p'); + nestedButton.setAttribute('popovertarget', 'no-focus-candidate-p2'); + t.add_cleanup(() => { + invoker.removeAttribute('popovertarget'); + nestedButton.removeAttribute('popovertarget'); + nestedButton.disabled = false; + popover.hidePopover(); + nestedPopover.hidePopover(); + }); + await testNoFocusCandidate(); +}, "Cases where the next focus candidate isn't in the direct parent scope with declarative invocation"); +promise_test(async t => { + const invoker = document.querySelector('#no-focus-candidate>button'); + const popover = document.querySelector('#no-focus-candidate>[popover]'); + const nestedButton = popover.querySelector('button'); + const nestedPopover = document.querySelector('#no-focus-candidate>[popover]>[popover]'); + const invokerClick = () => { + popover.togglePopover({ source: invoker }); + }; + invoker.addEventListener('click', invokerClick); + const nestedButtonClick = () => { + nestedPopover.togglePopover({ source: nestedButton }); + }; + nestedButton.addEventListener('click', nestedButtonClick); + t.add_cleanup(() => { + invoker.removeEventListener('click', invokerClick); + nestedButton.removeEventListener('click', nestedButtonClick); + nestedButton.disabled = false; + popover.hidePopover(); + nestedPopover.hidePopover(); + }); + await testNoFocusCandidate(); +}, "Cases where the next focus candidate isn't in the direct parent scope with imperative invocation"); </script> diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/button-event-dispatch-content-attribute.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/button-event-dispatch-content-attribute.html index ac1bdcd887d..a8b46b48a47 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/button-event-dispatch-content-attribute.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/button-event-dispatch-content-attribute.html @@ -5,9 +5,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <button @@ -24,17 +21,17 @@ <div popover id="popover" oncommand="return false"></div> <script> - promise_test(async function (t) { + test(function (t) { assert_true( typeof invokee.oncommand == "function", "invokee has an oncommand function", ); assert_equals(invokee.valueAsNumber, 0, "input is equal to 0"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_equals(invokee.valueAsNumber, 1, "input is equal to 1"); }, "oncommand content attribute works"); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(() => { invokerbutton.command = "--custom-command"; }); @@ -44,7 +41,7 @@ "invokee has an oncommand function", ); assert_false(popover.matches(":popover-open"), "popover is not open"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(popover.matches(":popover-open"), "popover is still not open"); }, "oncommand content with a value of false prevents default"); </script> diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/button-event-dispatch.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/button-event-dispatch.html index 80fabfbfc23..fc93696663c 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/button-event-dispatch.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/button-event-dispatch.html @@ -5,9 +5,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <div id="invokee"></div> @@ -26,10 +23,10 @@ invokerbutton.removeAttribute("type"); } - promise_test(async function (t) { + test(function (t) { let event = null; invokee.addEventListener("command", (e) => (event = e), { once: true }); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(event instanceof CommandEvent, "event is CommandEvent"); assert_equals(event.type, "command", "type"); assert_equals(event.bubbles, false, "bubbles"); @@ -40,13 +37,13 @@ assert_equals(event.source, invokerbutton, "source"); }, "event dispatches on click with addEventListener"); - promise_test(async function (t) { + test(function (t) { let event = null; t.add_cleanup(() => { invokee.oncommand = null; }); invokee.oncommand = (e) => (event = e); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(event instanceof CommandEvent, "event is CommandEvent"); assert_equals(event.type, "command", "type"); assert_equals(event.bubbles, false, "bubbles"); @@ -60,12 +57,12 @@ // valid custom invokeactions ["--foo", "--foo-", "--cAsE-cArRiEs", "--", "--a-", "--a-b", "---", "--show-picker"].forEach( (command) => { - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let event = null; invokee.addEventListener("command", (e) => (event = e), { once: true }); invokerbutton.command = command; - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(event instanceof CommandEvent, "event is CommandEvent"); assert_equals(event.type, "command", "type"); assert_equals(event.bubbles, false, "bubbles"); @@ -76,12 +73,12 @@ assert_equals(event.source, invokerbutton, "source"); }, `setting custom command property to ${command} (must include dash) sets event command`); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let event = null; invokee.addEventListener("command", (e) => (event = e), { once: true }); invokerbutton.setAttribute("command", command); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(event instanceof CommandEvent, "event is CommandEvent"); assert_equals(event.type, "command", "type"); assert_equals(event.bubbles, false, "bubbles"); @@ -96,26 +93,26 @@ // invalid custom invokeactions ["-foo", "-foo-", "foo-bar", "-foo bar", "—-emdash", "hidedocument"].forEach((command) => { - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let event = null; invokee.addEventListener("command", (e) => (event = e), { once: true }); invokerbutton.command = command; - await clickOn(invokerbutton); + invokerbutton.click(); assert_equals(event, null, "event should not have fired"); }, `setting custom command property to ${command} (no dash) did not dispatch an event`); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let event = null; invokee.addEventListener("command", (e) => (event = e), { once: true }); invokerbutton.setAttribute("command", command); - await clickOn(invokerbutton); + invokerbutton.click(); assert_equals(event, null, "event should not have fired"); }, `setting custom command attribute to ${command} (no dash) did not dispatch an event`); }); - promise_test(async function (t) { + test(function (t) { let called = false; invokerbutton.addEventListener( "click", @@ -131,53 +128,53 @@ }, { once: true }, ); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(called, "event was not called"); }, "event does not dispatch if click:preventDefault is called"); - promise_test(async function (t) { + test(function (t) { let event = null; invokee.addEventListener("command", (e) => (event = e), { once: true }); - await clickOn(invalidbutton); + invalidbutton.click(); assert_equals(event, null, "command should not have fired"); }, "event does not dispatch on input[type=button]"); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let called = false; invokee.addEventListener("command", (e) => (called = true), { once: true }); invokerbutton.setAttribute("disabled", ""); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(called, "event was not called"); }, "event does not dispatch if invoker is disabled"); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let called = false; invokee.addEventListener("command", (e) => (called = true), { once: true }); invokerbutton.setAttribute("form", "aform"); invokerbutton.removeAttribute("type"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(called, "event was not called"); }, "event does NOT dispatch if button is form associated, with implicit type"); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let called = false; invokee.addEventListener("command", (e) => (called = true), { once: true }); invokerbutton.setAttribute("form", "aform"); invokerbutton.setAttribute("type", "invalid"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(called, "event was not called"); }, "event does NOT dispatch if button is form associated, with explicit type=invalid"); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let event; invokee.addEventListener("command", (e) => (event = e), { once: true }); invokerbutton.setAttribute("form", "aform"); invokerbutton.setAttribute("type", "button"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(event instanceof CommandEvent, "event is CommandEvent"); assert_equals(event.type, "command", "type"); assert_equals(event.bubbles, false, "bubbles"); @@ -188,27 +185,27 @@ assert_equals(event.source, invokerbutton, "source"); }, "event dispatches if button is form associated, with explicit type=button"); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let called = false; invokee.addEventListener("command", (e) => (called = true), { once: true }); invokerbutton.setAttribute("form", "aform"); invokerbutton.setAttribute("type", "submit"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(called, "event was not called"); }, "event does NOT dispatch if button is form associated, with explicit type=submit"); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); let called = false; invokee.addEventListener("command", (e) => (called = true), { once: true }); invokerbutton.setAttribute("form", "aform"); invokerbutton.setAttribute("type", "reset"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(called, "event was called"); }, "event does NOT dispatch if button is form associated, with explicit type=reset"); - promise_test(async function (t) { + test(function (t) { svgInvokee = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svgInvokee.setAttribute("id", "svg-invokee"); t.add_cleanup(resetState); @@ -220,7 +217,7 @@ invokerbutton.setAttribute("commandfor", "svg-invokee"); invokerbutton.setAttribute("command", "--custom-command"); assert_equals(invokerbutton.commandForElement, svgInvokee); - await clickOn(invokerbutton); + invokerbutton.click(); assert_not_equals(event, null, "event was called"); assert_true(event instanceof CommandEvent, "event is CommandEvent"); assert_equals(event.source, invokerbutton, "event.invoker is set to right element"); diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/event-dispatch-shadow.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/event-dispatch-shadow.html index 9d9b9925978..2a2c306dc1d 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/event-dispatch-shadow.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/event-dispatch-shadow.html @@ -4,9 +4,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <div id="div"></div> diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/event-interface.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/event-interface.html index cc2b5c94ea2..9a36abb7fae 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/event-interface.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/event-interface.html @@ -4,9 +4,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <div id="div"></div> diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/generic-eventtarget-crash.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/generic-eventtarget-crash.html index b2179640ddf..212f54c26c5 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/generic-eventtarget-crash.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/generic-eventtarget-crash.html @@ -2,17 +2,17 @@ <meta charset="utf-8" /> <meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" /> <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> -<div id="invoker"></div> +<div id="target"></div> <script type="module"> - const invokeEvent = new InvokeEvent('invoke', { bubbles: true }); - document.body.addEventListener('invoke', e => { - e.invoker.toString(); + const commandEvent = new CommandEvent('command', { bubbles: true }); + document.body.addEventListener('command', e => { + e.source.toString(); }); - invoker.addEventListener('invoke', e => { - e.invoker.toString(); + target.addEventListener('command', e => { + e.source.toString(); }); - invoker.dispatchEvent(invokeEvent); + target.dispatchEvent(commandEvent); await Promise.resolve(); - invokeEvent.invoker.toString(); + commandEvent.source.toString(); </script> diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/idlharness.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/idlharness.html deleted file mode 100644 index e2a12b48c88..00000000000 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/idlharness.html +++ /dev/null @@ -1,16 +0,0 @@ -<!doctype html> -<meta charset="utf-8" /> -<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" /> -<link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> - -<script> - idl_test(["command-and-commandfor"], ["html", "dom"], (idl_array) => { - idl_array.add_objects({ - CommandEvent: ['new CommandEvent("invoke")'], - }); - }); -</script> diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-behavior-request-close.tentative.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-behavior-request-close.tentative.html index a98824741b0..e505c917d7c 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-behavior-request-close.tentative.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-behavior-request-close.tentative.html @@ -6,9 +6,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <!-- Merge the following tests into the main test file when the feature is stable --> @@ -32,8 +29,8 @@ ["request-close", /* test case sensitivity */ "reQuEst-Close"].forEach((command) => { ["property", "attribute"].forEach((setType) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.show(); assert_true(invokee.open, "invokee.open"); @@ -43,7 +40,7 @@ } else { containedinvoker.setAttribute("command", command); } - await clickOn(containedinvoker); + containedinvoker.click(); assert_equals(invokee.returnValue, ""); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); @@ -51,8 +48,8 @@ `invoking to request-close (with command ${setType} as ${command}) open dialog closes`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.show(); assert_true(invokee.open, "invokee.open"); @@ -63,7 +60,7 @@ containedinvoker.setAttribute("command", command); } containedinvoker.setAttribute("value", "foo"); - await clickOn(containedinvoker); + containedinvoker.click(); assert_equals(invokee.returnValue, "foo"); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); @@ -71,8 +68,8 @@ `invoking to request-close with value (with command ${setType} as ${command}) open dialog closes and sets returnValue`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.show(); assert_true(invokee.open, "invokee.open"); @@ -87,15 +84,15 @@ invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking to request-close (with command ${setType} as ${command}) open dialog with preventDefault is no-op`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.showModal(); assert_true(invokee.open, "invokee.open"); @@ -108,15 +105,15 @@ invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); }, `invoking to request-close (with command ${setType} as ${command}) open modal dialog with preventDefault is no-op`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.show(); assert_true(invokee.open, "invokee.open"); @@ -133,15 +130,15 @@ }, { once: true }, ); - await clickOn(containedinvoker); + containedinvoker.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking to request-close (with command ${setType} as ${command}) open dialog while changing command still closes`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.showModal(); assert_true(invokee.open, "invokee.open"); @@ -158,7 +155,7 @@ }, { once: true }, ); - await clickOn(containedinvoker); + containedinvoker.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, @@ -174,7 +171,7 @@ invokerbutton.setAttribute("command", "request-close"); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(containedinvoker); + containedinvoker.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, "invoking (as request-close) already closed dialog is noop"); @@ -182,8 +179,8 @@ // Open Popovers using Dialog actions ["request-close"].forEach((command) => { ["manual", "auto"].forEach((popoverState) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.setAttribute("popover", popoverState); invokee.showPopover(); @@ -197,7 +194,7 @@ invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true( invokee.matches(":popover-open"), "invokee :popover-open", @@ -212,8 +209,8 @@ // Elements being disconnected during invoke steps ["request-close"].forEach((command) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(() => { document.body.prepend(invokee); resetState(); @@ -231,36 +228,36 @@ once: true, }, ); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking (as ${command}) dialog that is removed is noop`, ); - promise_test( - async function (t) { + test( + function (t) { const invokerbutton = document.createElement("button"); invokerbutton.commandForElement = invokee; invokerbutton.setAttribute("command", command); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking (as ${command}) dialog from a detached invoker`, ); - promise_test( - async function (t) { + test( + function (t) { const invokerbutton = document.createElement("button"); const invokee = document.createElement("dialog"); invokerbutton.commandForElementt = invokee; invokerbutton.setAttribute("command", command); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-behavior.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-behavior.html index b75746e493a..041bc8536ac 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-behavior.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-behavior.html @@ -5,9 +5,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <dialog id="invokee"> @@ -31,8 +28,8 @@ ["show-modal", /* test case sensitivity */ "sHoW-mOdAl"].forEach( (command) => { ["property", "attribute"].forEach((setType) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); @@ -41,15 +38,15 @@ } else { invokerbutton.setAttribute("command", command); } - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); }, `invoking (with command ${setType} as ${command}) closed dialog opens as modal`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); @@ -61,15 +58,15 @@ } else { invokerbutton.setAttribute("command", command); } - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking (with command ${setType} as ${command}) closed dialog with preventDefault is noop`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); @@ -85,7 +82,7 @@ } else { invokerbutton.setAttribute("command", command); } - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); }, @@ -99,8 +96,8 @@ ["close", /* test case sensitivity */ "cLoSe"].forEach((command) => { ["property", "attribute"].forEach((setType) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.show(); assert_true(invokee.open, "invokee.open"); @@ -110,7 +107,7 @@ } else { containedinvoker.setAttribute("command", command); } - await clickOn(containedinvoker); + containedinvoker.click(); assert_equals(invokee.returnValue, ""); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); @@ -118,8 +115,8 @@ `invoking to close (with command ${setType} as ${command}) open dialog closes`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.show(); assert_true(invokee.open, "invokee.open"); @@ -130,7 +127,7 @@ containedinvoker.setAttribute("command", command); } containedinvoker.setAttribute("value", "foo"); - await clickOn(containedinvoker); + containedinvoker.click(); assert_equals(invokee.returnValue, "foo"); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); @@ -138,8 +135,8 @@ `invoking to close (with command ${setType} as ${command}) open dialog closes and sets returnValue`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.show(); assert_true(invokee.open, "invokee.open"); @@ -154,15 +151,15 @@ invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking to close (with command ${setType} as ${command}) open dialog with preventDefault is no-op`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.showModal(); assert_true(invokee.open, "invokee.open"); @@ -175,15 +172,15 @@ invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); }, `invoking to close (with command ${setType} as ${command}) open modal dialog with preventDefault is no-op`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.show(); assert_true(invokee.open, "invokee.open"); @@ -200,15 +197,15 @@ }, { once: true }, ); - await clickOn(containedinvoker); + containedinvoker.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking to close (with command ${setType} as ${command}) open dialog while changing command still closes`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.showModal(); assert_true(invokee.open, "invokee.open"); @@ -225,7 +222,7 @@ }, { once: true }, ); - await clickOn(containedinvoker); + containedinvoker.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, @@ -242,7 +239,7 @@ invokee.show(); assert_true(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, "invoking (as show-modal) open dialog is noop"); @@ -260,7 +257,7 @@ }, { once: true }, ); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); }, "invoking (as show-modal) open modal, while changing command still a no-op"); @@ -271,7 +268,7 @@ assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); invokee.setAttribute("popover", "auto"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); }, "invoking (as show-modal) closed popover dialog opens as modal"); @@ -283,7 +280,7 @@ invokerbutton.setAttribute("command", "close"); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(containedinvoker); + containedinvoker.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, "invoking (as close) already closed dialog is noop"); @@ -291,8 +288,8 @@ // Open Popovers using Dialog actions ["show-modal", "close"].forEach((command) => { ["manual", "auto"].forEach((popoverState) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.setAttribute("popover", popoverState); invokee.showPopover(); @@ -306,7 +303,7 @@ invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true( invokee.matches(":popover-open"), "invokee :popover-open", @@ -340,7 +337,7 @@ once: true, }, ); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, @@ -354,7 +351,7 @@ invokerbutton.setAttribute("command", command); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, @@ -369,7 +366,7 @@ invokerbutton.setAttribute("command", command); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-disconnect.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-disconnect.html index 355906ec37d..ef89d257473 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-disconnect.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-disconnect.html @@ -5,9 +5,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <dialog id="invokee"></dialog> @@ -15,8 +12,8 @@ <script> const invokee = document.getElementById('invokee'); - promise_test( - async function (t) { + test( + function (t) { assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); let fired = false; @@ -24,7 +21,7 @@ fired = true; invokee.remove(); }); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(fired, "command event fired"); assert_false(invokee.isConnected, "dialog no longer connected"); assert_false(invokee.open, "invokee.open"); diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-invalid-behavior.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-invalid-behavior.html index 01ef53d1c07..862bb1f4d7f 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-invalid-behavior.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-dialog-invalid-behavior.html @@ -5,9 +5,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <dialog id="invokee"> @@ -36,39 +33,39 @@ "toggle-popover", "show-picker", ].forEach((action) => { - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); invokerbutton.setAttribute("command", action); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking (as ${action}) on dialog does nothing`); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); containedinvoker.setAttribute("command", action); invokee.show(); assert_true(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.open, "invokee.open"); assert_false(invokee.matches(":modal"), "invokee :modal"); }, `invoking (as ${action}) on open dialog does nothing`); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); containedinvoker.setAttribute("command", action); invokee.showModal(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); }, `invoking (as ${action}) on open modal dialog does nothing`); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); containedinvoker.setAttribute("command", action); invokee.showModal(); @@ -81,7 +78,7 @@ }, { once: true }, ); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.open, "invokee.open"); assert_true(invokee.matches(":modal"), "invokee :modal"); }, `invoking (as ${action}) on open modal while changing the attributer does nothing`); @@ -90,8 +87,8 @@ // Open Popovers using Dialog actions ["show-modal", "close"].forEach((action) => { ["manual", "auto"].forEach((popoverState) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokee.setAttribute("popover", popoverState); invokee.showPopover(); @@ -105,7 +102,7 @@ invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true( invokee.matches(":popover-open"), "invokee :popover-open", diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-behavior.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-behavior.html index 7462ce6159a..77325b5f0f6 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-behavior.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-behavior.html @@ -5,9 +5,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <div id="invokee" popover> @@ -32,7 +29,7 @@ invokee.addEventListener("command", (e) => { invokerbutton.setAttribute('command', 'hide-popover'); }, { once: true, }); - await clickOn(invokerbutton); + invokerbutton.click(); t.add_cleanup(resetState); assert_true(invokee.matches(":popover-open")); }, "changing command attribute inside invokeevent doesn't impact the invocation"); @@ -45,26 +42,26 @@ "tOgGlE-pOpOvEr", "sHoW-pOpOvEr", ].forEach((command) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokerbutton.command = command; assert_false(invokee.matches(":popover-open")); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(invokee.matches(":popover-open")); }, `invoking (as ${command}) closed popover opens`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokerbutton.command = command; assert_false(invokee.matches(":popover-open")); invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.matches(":popover-open")); }, `invoking (as ${command}) closed popover with preventDefault does not open`, @@ -79,20 +76,20 @@ "tOgGlE-pOpOvEr", "hIdE-pOpOvEr", ].forEach((command) => { - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokerbutton.command = command; invokee.showPopover(); assert_true(invokee.matches(":popover-open")); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.matches(":popover-open")); }, `invoking (as ${command}) open popover closes`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); invokerbutton.command = command; invokee.showPopover(); @@ -100,26 +97,26 @@ invokee.addEventListener("command", (e) => e.preventDefault(), { once: true, }); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(invokee.matches(":popover-open")); }, `invoking (as ${command}) open popover with preventDefault does not close`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); containedinvoker.command = command; invokee.showPopover(); assert_true(invokee.matches(":popover-open")); - await clickOn(containedinvoker); + containedinvoker.click(); assert_false(invokee.matches(":popover-open")); }, `invoking (as ${command}) from within open popover closes`, ); - promise_test( - async function (t) { + test( + function (t) { t.add_cleanup(resetState); containedinvoker.command = command; invokee.showPopover(); @@ -127,7 +124,7 @@ once: true, }); assert_true(invokee.matches(":popover-open")); - await clickOn(containedinvoker); + containedinvoker.click(); assert_true(invokee.matches(":popover-open")); }, `invoking (as ${command}) from within open popover with preventDefault does not close`, @@ -135,21 +132,21 @@ }); // show-popover specific - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); invokerbutton.setAttribute("command", "show-popover"); invokee.showPopover(); assert_true(invokee.matches(":popover-open")); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(invokee.matches(":popover-open")); }, "invoking (as show-popover) open popover is noop"); // hide-popover specific - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); invokerbutton.setAttribute("command", "hide-popover"); assert_false(invokee.matches(":popover-open")); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.matches(":popover-open")); }, "invoking (as hide-popover) closed popover is noop"); </script> diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-disconnect.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-disconnect.html index 092032be335..6f6a1e29b7f 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-disconnect.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-disconnect.html @@ -5,9 +5,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <div id="invokee" popover></div> @@ -15,15 +12,15 @@ <script> const invokee = document.getElementById('invokee'); - promise_test( - async function (t) { + test( + function (t) { assert_false(invokee.matches(":popover-open"), "invokee :popover-open"); let fired = false; invokee.addEventListener('command', () => { fired = true; invokee.remove(); }); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(fired, "command event fired"); assert_false(invokee.isConnected, "popover no longer connected"); assert_false(invokee.matches(":popover-open"), "invokee :popover-open"); diff --git a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-invalid-behavior.html b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-invalid-behavior.html index 91efd92ba82..31b460b30ee 100644 --- a/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-invalid-behavior.html +++ b/tests/wpt/tests/html/semantics/the-button-element/command-and-commandfor/on-popover-invalid-behavior.html @@ -5,9 +5,6 @@ <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> <script src="resources/invoker-utils.js"></script> <div id="invokee" popover> @@ -27,20 +24,20 @@ // invalid actions on show-popover [null, "", "foo-bar", "showpopover", "show-modal", "show-picker", "open", "close"].forEach((command) => { - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); invokerbutton.command = command; assert_false(invokee.matches(":popover-open")); - await clickOn(invokerbutton); + invokerbutton.click(); assert_false(invokee.matches(":popover-open")); }, `invoking (as ${command}) on popover does nothing`); - promise_test(async function (t) { + test(function (t) { t.add_cleanup(resetState); invokerbutton.command = command; invokee.showPopover(); assert_true(invokee.matches(":popover-open")); - await clickOn(invokerbutton); + invokerbutton.click(); assert_true(invokee.matches(":popover-open")); }, `invoking (as ${command}) on open popover does nothing`); }); diff --git a/tests/wpt/tests/html/semantics/the-button-element/interest-target/interesttarget-user-select.tentative.html b/tests/wpt/tests/html/semantics/the-button-element/interest-target/interesttarget-user-select.tentative.html new file mode 100644 index 00000000000..0726d10da92 --- /dev/null +++ b/tests/wpt/tests/html/semantics/the-button-element/interest-target/interesttarget-user-select.tentative.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" href="mailto:masonf@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-ui/#propdef-user-select"> +<link rel="help" href="https://open-ui.org/components/interest-invokers.explainer"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src='/resources/testdriver-vendor.js'></script> + +<button interesttarget=foo>ABCDEFGHI<span id=inside>JKLMNOPQ</span>RSTUVWXYZ</button> +<div>Something after the button</div> +<div id=after>Something else</div> + +<script> +promise_test(async function() { + assert_equals(window.getSelection().toString(), "", "Nothing should start out selected"); + + await new test_driver.Actions() + .pointerMove(1, 1, {origin: after}) + .pointerDown({ button: 0 }) + .pointerMove(1, 1, {origin: inside}) + .pointerUp({ button: 0 }) + .send(); + const selection = window.getSelection().toString(); + assert_not_equals(selection, "", "Something should be selected"); + assert_true(selection.includes("Something after"),'The selection should include the outside text'); + assert_false(selection.includes("RSTUVWXYZ"),'The selection should not include the button text'); +}, "Buttons with `interesttarget` should not be user-selectable"); +</script> diff --git a/tests/wpt/tests/interfaces/DOM-Parsing.idl b/tests/wpt/tests/interfaces/DOM-Parsing.idl deleted file mode 100644 index af262607936..00000000000 --- a/tests/wpt/tests/interfaces/DOM-Parsing.idl +++ /dev/null @@ -1,10 +0,0 @@ -// GENERATED CONTENT - DO NOT EDIT -// Content was automatically extracted by Reffy into webref -// (https://github.com/w3c/webref) -// Source: DOM Parsing and Serialization (https://w3c.github.io/DOM-Parsing/) - -[Exposed=Window] -interface XMLSerializer { - constructor(); - DOMString serializeToString(Node root); -}; diff --git a/tests/wpt/tests/interfaces/SVG.idl b/tests/wpt/tests/interfaces/SVG.idl index 3a0b86126b5..5dff2947b51 100644 --- a/tests/wpt/tests/interfaces/SVG.idl +++ b/tests/wpt/tests/interfaces/SVG.idl @@ -419,10 +419,6 @@ interface SVGAnimatedPreserveAspectRatio { }; [Exposed=Window] -interface SVGPathElement : SVGGeometryElement { -}; - -[Exposed=Window] interface SVGRectElement : SVGGeometryElement { [SameObject] readonly attribute SVGAnimatedLength x; [SameObject] readonly attribute SVGAnimatedLength y; diff --git a/tests/wpt/tests/interfaces/html.idl b/tests/wpt/tests/interfaces/html.idl index f48fd370281..97fabdf80fa 100644 --- a/tests/wpt/tests/interfaces/html.idl +++ b/tests/wpt/tests/interfaces/html.idl @@ -1483,6 +1483,7 @@ interface mixin CanvasPathDrawingStyles { interface mixin CanvasTextDrawingStyles { // text + attribute DOMString lang; // (default: "inherit") attribute DOMString font; // (default 10px sans-serif) attribute CanvasTextAlign textAlign; // (default: "start") attribute CanvasTextBaseline textBaseline; // (default: "alphabetic") @@ -2369,6 +2370,13 @@ partial interface Range { }; [Exposed=Window] +interface XMLSerializer { + constructor(); + + DOMString serializeToString(Node root); +}; + +[Exposed=Window] interface Navigator { // objects implementing this interface also implement the interfaces given below }; diff --git a/tests/wpt/tests/interfaces/ppa.idl b/tests/wpt/tests/interfaces/ppa.idl index a00d2deba87..ef3eb360bdf 100644 --- a/tests/wpt/tests/interfaces/ppa.idl +++ b/tests/wpt/tests/interfaces/ppa.idl @@ -10,13 +10,12 @@ partial interface Navigator { enum PrivateAttributionProtocol { "dap-12-histogram", "tee-00" }; dictionary PrivateAttributionAggregationService { - required DOMString url; required DOMString protocol; }; [SecureContext, Exposed=Window] interface PrivateAttributionAggregationServices { - readonly setlike<PrivateAttributionAggregationService>; + readonly maplike<USVString, PrivateAttributionAggregationService>; }; [SecureContext, Exposed=Window] @@ -27,7 +26,7 @@ interface PrivateAttribution { dictionary PrivateAttributionImpressionOptions { required unsigned long histogramIndex; unsigned long filterData = 0; - required DOMString conversionSite; + required USVString conversionSite; unsigned long lifetimeDays = 30; }; @@ -37,19 +36,19 @@ partial interface PrivateAttribution { }; dictionary PrivateAttributionConversionOptions { - required DOMString aggregationService; + required USVString aggregationService; double epsilon = 1.0; required unsigned long histogramSize; + unsigned long lookbackDays; + unsigned long filterData; + sequence<USVString> impressionSites = []; + sequence<USVString> intermediarySites = []; + PrivateAttributionLogic logic = "last-touch"; unsigned long value = 1; unsigned long maxValue = 1; - - unsigned long lookbackDays; - unsigned long filterData; - sequence<DOMString> impressionSites = []; - sequence<DOMString> intermediarySites = []; }; dictionary PrivateAttributionConversionResult { diff --git a/tests/wpt/tests/interfaces/private-aggregation-api.idl b/tests/wpt/tests/interfaces/private-aggregation-api.idl index c89a4687abb..bc5eb740718 100644 --- a/tests/wpt/tests/interfaces/private-aggregation-api.idl +++ b/tests/wpt/tests/interfaces/private-aggregation-api.idl @@ -7,6 +7,8 @@ SecureContext] interface PrivateAggregation { undefined contributeToHistogram(PAHistogramContribution contribution); + undefined contributeToHistogramOnEvent(DOMString event, + record<DOMString, any> contribution); undefined enableDebugMode(optional PADebugModeOptions options = {}); }; diff --git a/tests/wpt/tests/interfaces/sanitizer-api.tentative.idl b/tests/wpt/tests/interfaces/sanitizer-api.tentative.idl deleted file mode 100644 index 4e597aeec7b..00000000000 --- a/tests/wpt/tests/interfaces/sanitizer-api.tentative.idl +++ /dev/null @@ -1,61 +0,0 @@ -// https://wicg.github.io/sanitizer-api/ - -enum SanitizerPresets { "default" }; -dictionary SetHTMLOptions { - (Sanitizer or SanitizerConfig or SanitizerPresets) sanitizer = "default"; -}; -dictionary SetHTMLUnsafeOptions { - (Sanitizer or SanitizerConfig or SanitizerPresets) sanitizer = {}; -}; - -[Exposed=Window] -interface Sanitizer { - constructor(optional (SanitizerConfig or SanitizerPresets) configuration = "default"); - - // Query configuration: - SanitizerConfig get(); - - // Modify a Sanitizer’s lists and fields: - undefined allowElement(SanitizerElementWithAttributes element); - undefined removeElement(SanitizerElement element); - undefined replaceElementWithChildren(SanitizerElement element); - undefined allowAttribute(SanitizerAttribute attribute); - undefined removeAttribute(SanitizerAttribute attribute); - undefined setComments(boolean allow); - undefined setDataAttributes(boolean allow); - - // Remove markup that executes script. May modify multiple lists: - undefined removeUnsafe(); -}; - -dictionary SanitizerElementNamespace { - required DOMString name; - DOMString? _namespace = "http://www.w3.org/1999/xhtml"; -}; - -// Used by "elements" -dictionary SanitizerElementNamespaceWithAttributes : SanitizerElementNamespace { - sequence<SanitizerAttribute> attributes; - sequence<SanitizerAttribute> removeAttributes; -}; - -typedef (DOMString or SanitizerElementNamespace) SanitizerElement; -typedef (DOMString or SanitizerElementNamespaceWithAttributes) SanitizerElementWithAttributes; - -dictionary SanitizerAttributeNamespace { - required DOMString name; - DOMString? _namespace = null; -}; -typedef (DOMString or SanitizerAttributeNamespace) SanitizerAttribute; - -dictionary SanitizerConfig { - sequence<SanitizerElementWithAttributes> elements; - sequence<SanitizerElement> removeElements; - sequence<SanitizerElement> replaceWithChildrenElements; - - sequence<SanitizerAttribute> attributes; - sequence<SanitizerAttribute> removeAttributes; - - boolean comments; - boolean dataAttributes; -}; diff --git a/tests/wpt/tests/interfaces/shared-storage.idl b/tests/wpt/tests/interfaces/shared-storage.idl index 941c7414c4f..e3e221a3aa7 100644 --- a/tests/wpt/tests/interfaces/shared-storage.idl +++ b/tests/wpt/tests/interfaces/shared-storage.idl @@ -71,6 +71,7 @@ dictionary SharedStorageSetMethodOptions : SharedStorageModifierMethodOptions { [Exposed=(Window,SharedStorageWorklet)] interface SharedStorage { + Promise<DOMString> get(DOMString key); Promise<any> set(DOMString key, DOMString value, optional SharedStorageSetMethodOptions options = {}); @@ -98,9 +99,6 @@ interface SharedStorage { readonly attribute SharedStorageWorklet worklet; [Exposed=SharedStorageWorklet] - Promise<DOMString> get(DOMString key); - - [Exposed=SharedStorageWorklet] Promise<unsigned long> length(); [Exposed=SharedStorageWorklet] diff --git a/tests/wpt/tests/interfaces/svg-paths.idl b/tests/wpt/tests/interfaces/svg-paths.idl new file mode 100644 index 00000000000..2f0813572a1 --- /dev/null +++ b/tests/wpt/tests/interfaces/svg-paths.idl @@ -0,0 +1,31 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into webref +// (https://github.com/w3c/webref) +// Source: SVG Paths (https://svgwg.org/specs/paths/) + +[LegacyNoInterfaceObject, Exposed=Window] +interface SVGPathSegment { + attribute DOMString type; + attribute FrozenArray<float> values; +}; + +dictionary SVGPathDataSettings { + boolean normalize = false; +}; + +interface mixin SVGPathData { + sequence<SVGPathSegment> getPathData(optional SVGPathDataSettings settings = {}); + undefined setPathData(sequence<SVGPathSegment> pathData); +}; + +[Exposed=Window] +interface SVGPathElement : SVGGeometryElement { + + readonly attribute SVGAnimatedNumber pathLength; + + float getTotalLength(); + DOMPoint getPointAtLength(float distance); + SVGPathSegment? getPathSegmentAtLength(float distance); +}; + +SVGPathElement includes SVGPathData; diff --git a/tests/wpt/tests/interfaces/turtledove.idl b/tests/wpt/tests/interfaces/turtledove.idl index 2f34d763722..b9f50d47885 100644 --- a/tests/wpt/tests/interfaces/turtledove.idl +++ b/tests/wpt/tests/interfaces/turtledove.idl @@ -18,6 +18,7 @@ dictionary AuctionAd { sequence<USVString> selectableBuyerAndSellerReportingIds; sequence<USVString> allowedReportingOrigins; DOMString adRenderId; + USVString creativeScanningMetadata; }; dictionary AuctionAdInterestGroupSize { @@ -106,6 +107,7 @@ dictionary AuctionAdConfig { USVString trustedScoringSignalsURL; long maxTrustedScoringSignalsURLLength; USVString trustedScoringSignalsCoordinator; + boolean sendCreativeScanningMetadata; sequence<USVString> interestGroupBuyers; Promise<any> auctionSignals; Promise<any> sellerSignals; @@ -218,12 +220,6 @@ dictionary PAExtendedHistogramContribution { bigint filteringId = 0; }; -[Exposed=InterestGroupScriptRunnerGlobalScope] -partial interface PrivateAggregation { - undefined contributeToHistogramOnEvent( - DOMString event, PAExtendedHistogramContribution contribution); -}; - [Exposed=InterestGroupBiddingAndScoringScriptRunnerGlobalScope] interface ForDebuggingOnly { undefined reportAdAuctionWin(USVString url); @@ -351,6 +347,8 @@ dictionary ScoringBrowserSignals { unsigned long crossOriginDataVersion; sequence<USVString> adComponents; boolean forDebuggingOnlyInCooldownOrLockout = false; + USVString creativeScanningMetadata; + sequence<USVString?> adComponentsCreativeScanningMetadata; }; dictionary ReportingBrowserSignals { diff --git a/tests/wpt/tests/interfaces/webaudio.idl b/tests/wpt/tests/interfaces/webaudio.idl index d14eb96820f..3b351f4d9e9 100644 --- a/tests/wpt/tests/interfaces/webaudio.idl +++ b/tests/wpt/tests/interfaces/webaudio.idl @@ -80,7 +80,6 @@ interface AudioContext : BaseAudioContext { readonly attribute double baseLatency; readonly attribute double outputLatency; [SecureContext] readonly attribute (DOMString or AudioSinkInfo) sinkId; - [SecureContext] readonly attribute AudioRenderCapacity renderCapacity; attribute EventHandler onsinkchange; attribute EventHandler onerror; AudioTimestamp getOutputTimestamp (); @@ -117,33 +116,6 @@ dictionary AudioTimestamp { }; [Exposed=Window] -interface AudioRenderCapacity : EventTarget { - undefined start(optional AudioRenderCapacityOptions options = {}); - undefined stop(); - attribute EventHandler onupdate; -}; - -dictionary AudioRenderCapacityOptions { - double updateInterval = 1; -}; - -[Exposed=Window] -interface AudioRenderCapacityEvent : Event { - constructor (DOMString type, optional AudioRenderCapacityEventInit eventInitDict = {}); - readonly attribute double timestamp; - readonly attribute double averageLoad; - readonly attribute double peakLoad; - readonly attribute double underrunRatio; -}; - -dictionary AudioRenderCapacityEventInit : EventInit { - double timestamp = 0; - double averageLoad = 0; - double peakLoad = 0; - double underrunRatio = 0; -}; - -[Exposed=Window] interface OfflineAudioContext : BaseAudioContext { constructor(OfflineAudioContextOptions contextOptions); constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate); diff --git a/tests/wpt/tests/interfaces/webnn.idl b/tests/wpt/tests/interfaces/webnn.idl index 63554edbffd..7c026d4c0a4 100644 --- a/tests/wpt/tests/interfaces/webnn.idl +++ b/tests/wpt/tests/interfaces/webnn.idl @@ -19,7 +19,7 @@ dictionary MLContextOptions { MLPowerPreference powerPreference = "default"; }; -[SecureContext, Exposed=(Window, DedicatedWorker)] +[SecureContext, Exposed=(Window, Worker)] interface ML { Promise<MLContext> createContext(optional MLContextOptions options = {}); Promise<MLContext> createContext(GPUDevice gpuDevice); @@ -31,7 +31,7 @@ dictionary MLContextLostInfo { DOMString message; }; -[SecureContext, Exposed=(Window, DedicatedWorker)] +[SecureContext, Exposed=(Window, Worker)] interface MLContext { undefined dispatch(MLGraph graph, MLNamedTensors inputs, MLNamedTensors outputs); @@ -71,7 +71,7 @@ dictionary MLSingleInputSupportLimits { MLSupportLimits output; }; -[SecureContext, Exposed=(Window, DedicatedWorker)] +[SecureContext, Exposed=(Window, Worker)] interface MLGraph { undefined destroy(); }; @@ -97,7 +97,7 @@ dictionary MLOperandDescriptor { required sequence<[EnforceRange] unsigned long> shape; }; -[SecureContext, Exposed=(Window, DedicatedWorker)] +[SecureContext, Exposed=(Window, Worker)] interface MLOperand { readonly attribute MLOperandDataType dataType; readonly attribute FrozenArray<unsigned long> shape; @@ -114,7 +114,7 @@ dictionary MLTensorDescriptor : MLOperandDescriptor { boolean writable = false; }; -[SecureContext, Exposed=(Window, DedicatedWorker)] +[SecureContext, Exposed=(Window, Worker)] interface MLTensor { readonly attribute MLOperandDataType dataType; readonly attribute FrozenArray<unsigned long> shape; @@ -126,7 +126,7 @@ interface MLTensor { typedef record<USVString, MLOperand> MLNamedOperands; -[SecureContext, Exposed=(Window, DedicatedWorker)] +[SecureContext, Exposed=(Window, Worker)] interface MLGraphBuilder { // Construct the graph builder from the context. constructor(MLContext context); diff --git a/tests/wpt/tests/interfaces/webrtc-encoded-transform.idl b/tests/wpt/tests/interfaces/webrtc-encoded-transform.idl index 0db2f2b9a81..8a6ba816016 100644 --- a/tests/wpt/tests/interfaces/webrtc-encoded-transform.idl +++ b/tests/wpt/tests/interfaces/webrtc-encoded-transform.idl @@ -75,6 +75,9 @@ dictionary RTCEncodedVideoFrameMetadata { sequence<unsigned long> contributingSources; long long timestamp; // microseconds unsigned long rtpTimestamp; + DOMHighResTimeStamp receiveTime; + DOMHighResTimeStamp captureTime; + DOMHighResTimeStamp senderCaptureTimeOffset; DOMString mimeType; }; @@ -98,6 +101,9 @@ dictionary RTCEncodedAudioFrameMetadata { sequence<unsigned long> contributingSources; short sequenceNumber; unsigned long rtpTimestamp; + DOMHighResTimeStamp receiveTime; + DOMHighResTimeStamp captureTime; + DOMHighResTimeStamp senderCaptureTimeOffset; DOMString mimeType; }; diff --git a/tests/wpt/tests/lint.ignore b/tests/wpt/tests/lint.ignore index a91efc0cf1a..1d552f3468a 100644 --- a/tests/wpt/tests/lint.ignore +++ b/tests/wpt/tests/lint.ignore @@ -51,6 +51,7 @@ TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.sxg TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.wbn TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.avif TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.annexb +TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.crx ## .gitignore W3C-TEST.ORG: .gitignore @@ -286,6 +287,7 @@ SET TIMEOUT: shadow-dom/scroll-to-the-fragment-in-shadow-tree.html SET TIMEOUT: shadow-dom/slotchange-event.html SET TIMEOUT: trusted-types/support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.js SET TIMEOUT: trusted-types/support/DOMWindowTimers-setTimeout-setInterval.js +SET TIMEOUT: trusted-types/support/trusted-types-reporting-for-DOMWindowTimers-setTimeout-setInterval.js SET TIMEOUT: user-timing/* SET TIMEOUT: web-animations/crashtests/reparent-animating-element-002.html SET TIMEOUT: web-animations/timing-model/animations/* @@ -401,6 +403,7 @@ SET TIMEOUT: requestidlecallback/deadline-after-expired-timer.html SET TIMEOUT: resources/* SET TIMEOUT: scheduler/tentative/current-task-signal-async-abort.any.js SET TIMEOUT: scheduler/tentative/current-task-signal-async-priority.any.js +SET TIMEOUT: screen-capture/tentative/getdisplaymedia-captured-surface-resolution.https.html SET TIMEOUT: speculation-rules/prerender/resources/activation-start.html SET TIMEOUT: speculation-rules/prerender/resources/prerender-response-code.html SET TIMEOUT: speculation-rules/prerender/resources/prerender-while-prerender-outer.html diff --git a/tests/wpt/tests/media-source/URL-createObjectURL-revoke.html b/tests/wpt/tests/media-source/URL-createObjectURL-revoke.html index c5e18d4fd58..5d15bda69d6 100644 --- a/tests/wpt/tests/media-source/URL-createObjectURL-revoke.html +++ b/tests/wpt/tests/media-source/URL-createObjectURL-revoke.html @@ -42,18 +42,15 @@ async_test(function(t) { var mediaSource = new MediaSource(); var url = window.URL.createObjectURL(mediaSource); setTimeout(function() { - mediaSource.addEventListener('sourceopen', - t.unreached_func("url should not reference MediaSource.")); + mediaSource.addEventListener('sourceopen', t.step_func_done(function(e) { + assert_equals(video.networkState, video.NETWORK_LOADING); + assert_equals(video.readyState, video.HAVE_NOTHING); + })); var video = document.createElement('video'); video.src = url; - video.addEventListener('error', t.step_func_done(function(e) { - assert_equals(e.target.error.code, - MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED, - 'Expected error code'); - assert_equals(mediaSource.readyState, 'closed'); - })); + video.addEventListener('error', t.unreached_func("no error events should be dispatched")); }, 0); -}, "Check auto-revoking behavior with URL.createObjectURL(MediaSource)."); +}, "Check no auto-revoking behavior with URL.createObjectURL(MediaSource)."); </script> </body> </html> diff --git a/tests/wpt/tests/media/recognition_context.mp3 b/tests/wpt/tests/media/recognition_context.mp3 Binary files differnew file mode 100644 index 00000000000..61a281b821e --- /dev/null +++ b/tests/wpt/tests/media/recognition_context.mp3 diff --git a/tests/wpt/tests/notifications/instance-checks.js b/tests/wpt/tests/notifications/instance-checks.js index 31ff0b87093..63f42500913 100644 --- a/tests/wpt/tests/notifications/instance-checks.js +++ b/tests/wpt/tests/notifications/instance-checks.js @@ -6,7 +6,10 @@ const notification_args = [ body: "This is a radio check.", tag: "radio_check999", icon: `${location.origin}/icon.png`, + requireInteraction: true, + silent: true, data: fakeCustomData, + actions: [{ action: "foo", title: "bar" }] } ]; @@ -17,24 +20,35 @@ function notification_instance_test(createFn, testTitle) { n = await createFn(t); }, `${testTitle}: Setup`); promise_test(async () => { - assert_equals("Radio check", n.title) + assert_equals(n.title, "Radio check") }, `${testTitle}: Attribute exists with expected value: title`) promise_test(async () => { - assert_equals("ltr", n.dir) + assert_equals(n.dir, "ltr") }, `${testTitle}: Attribute exists with expected value: dir`) promise_test(async () => { - assert_equals("aa", n.lang) + assert_equals(n.lang, "aa") }, `${testTitle}: Attribute exists with expected value: lang`) promise_test(async () => { - assert_equals("This is a radio check.", n.body) + assert_equals(n.body, "This is a radio check.") }, `${testTitle}: Attribute exists with expected value: body`) promise_test(async () => { - assert_equals("radio_check999", n.tag) + assert_equals(n.tag, "radio_check999") }, `${testTitle}: Attribute exists with expected value: tag`) promise_test(async () => { - assert_equals(`${location.origin}/icon.png`, n.icon) + assert_equals(n.icon, `${location.origin}/icon.png`) }, `${testTitle}: Attribute exists with expected value: icon`) promise_test(async () => { + assert_true(n.requireInteraction); + }, `${testTitle}: Attribute exists with expected value: requireInteraction`) + promise_test(async () => { + assert_true(n.silent); + }, `${testTitle}: Attribute exists with expected value: silent`) + promise_test(async () => { assert_custom_data(n.data); }, `${testTitle}: Attribute exists with expected value: data`) + promise_test(async () => { + for (const [i, action] of n.actions.entries()) { + assert_object_equals(action, notification_args[1].actions[i]); + } + }, `${testTitle}: Attribute exists with expected value: actions`) } diff --git a/tests/wpt/tests/notifications/registration-association.https.window.js b/tests/wpt/tests/notifications/registration-association.https.window.js index 53aed8d5bc8..e838257faa8 100644 --- a/tests/wpt/tests/notifications/registration-association.https.window.js +++ b/tests/wpt/tests/notifications/registration-association.https.window.js @@ -17,8 +17,8 @@ promise_test(async (t) => { await registration.showNotification("foo"); await registration.unregister(); - const newRegistration = await prepareActiveServiceWorker("noop-sw.js"); - const notifications = await newRegistration.getNotifications(); + registration = await prepareActiveServiceWorker("noop-sw.js"); + const notifications = await registration.getNotifications(); // The spec says notifications should be associated with service worker registration // and thus unregistering should dissociate the notification. @@ -29,3 +29,10 @@ promise_test(async (t) => { // > is not the empty string, is tag. assert_equals(notifications.length, 0, "Should return zero notification"); }, "A new SW registration gets no previous notification"); + +promise_test(async (t) => { + await registration.showNotification("foo"); + await registration.unregister(); + const notifications = await registration.getNotifications(); + assert_equals(notifications.length, 0, "Should return zero notification"); +}, "An unregistered SW registration gets no previous notification"); diff --git a/tests/wpt/tests/partitioned-popins/partitioned-popins.cookies-allowed.tentative.sub.https.window.js b/tests/wpt/tests/partitioned-popins/partitioned-popins.cookies-allowed.tentative.sub.https.window.js index be4b066373b..488fee084b3 100644 --- a/tests/wpt/tests/partitioned-popins/partitioned-popins.cookies-allowed.tentative.sub.https.window.js +++ b/tests/wpt/tests/partitioned-popins/partitioned-popins.cookies-allowed.tentative.sub.https.window.js @@ -12,9 +12,8 @@ // Step 5 (main-iframe) Write third-party cookies and report success. // Step 6 (main-window) Open partitioned popin for other origin. // Step 7 (popin) Check for first-/third-party cookies. -// Step 8 (popin-iframe) Check for first-/third-party cookies and report success. -// Step 9 (popin) Report success. -// Step 10 (main-window) Cleanup. +// Step 8 (popin) Report success. +// Step 9 (main-window) Cleanup. async_test(t => { const id = String(Math.random()); @@ -37,9 +36,9 @@ async_test(t => { window.open("https://{{hosts[alt][]}}:{{ports[https][0]}}/partitioned-popins/resources/partitioned-popins.cookies-popin.sub.py?id="+id, '_blank', 'popin'); break; case 'popin-read': - // Step 10 + // Step 9 // We want to see the same behavior a cross-site iframe would have, only SameSite=None available, with the ability to set additional cookies in the popin. - assert_equals(e.data.message, "ReadOnLoad:FirstPartyNone-ThirdPartyNone-,ReadOnFetch:FirstPartyNone-ThirdPartyNone-FirstPartyNonePopin-ThirdPartyNonePopin-,ReadOnDocument:FirstPartyNone-ThirdPartyNone-FirstPartyNonePopin-ThirdPartyNonePopin-,ReadOnFetchAfterRSA:FirstPartyNone-ThirdPartyNone-FirstPartyNonePopin-ThirdPartyNonePopin-FirstPartyNonePopinAfterRSA-ThirdPartyNonePopinAfterRSA-,ReadOnDocumentAfterRSA:FirstPartyNone-ThirdPartyNone-FirstPartyNonePopin-ThirdPartyNonePopin-FirstPartyNonePopinAfterRSA-ThirdPartyNonePopinAfterRSA-,ReadInPopinIframe:FirstPartyNone-ThirdPartyNone-,ReadInPopinIframeAfterRSA:FirstPartyNone-ThirdPartyNone-FirstPartyNoneAfterRSA-ThirdPartyNoneAfterRSA-"); + assert_equals(e.data.message, "ReadOnLoad:ThirdPartyNone-,ReadOnFetch:ThirdPartyNone-ThirdPartyNonePopin-,ReadOnDocument:ThirdPartyNone-ThirdPartyNonePopin-,ReadOnFetchAfterRSA:ThirdPartyNone-ThirdPartyNonePopin-ThirdPartyNonePopinAfterRSA-,ReadOnDocumentAfterRSA:ThirdPartyNone-ThirdPartyNonePopin-ThirdPartyNonePopinAfterRSA-"); t.done(); break; } diff --git a/tests/wpt/tests/partitioned-popins/partitioned-popins.cookies-blocked.tentative.sub.https.window.js b/tests/wpt/tests/partitioned-popins/partitioned-popins.cookies-blocked.tentative.sub.https.window.js index e6ed94adae9..70e189761cf 100644 --- a/tests/wpt/tests/partitioned-popins/partitioned-popins.cookies-blocked.tentative.sub.https.window.js +++ b/tests/wpt/tests/partitioned-popins/partitioned-popins.cookies-blocked.tentative.sub.https.window.js @@ -12,9 +12,8 @@ // Step 5 (main-iframe) Write third-party cookies and report success. // Step 6 (main-window) Open partitioned popin for other origin. // Step 7 (popin) Check for first-/third-party cookies. -// Step 8 (popin-iframe) Check for first-/third-party cookies and report success. -// Step 9 (popin) Report success. -// Step 10 (main-window) Cleanup. +// Step 8 (popin) Report success. +// Step 9 (main-window) Cleanup. async_test(t => { const id = String(Math.random()); @@ -37,10 +36,9 @@ async_test(t => { window.open("https://{{hosts[alt][]}}:{{ports[https][0]}}/partitioned-popins/resources/partitioned-popins.cookies-popin.sub.py?id="+id, '_blank', 'popin'); break; case 'popin-read': - // Step 10 + // Step 9 // We want to see the same behavior a cross-site iframe would have, only SameSite=None available, with the ability to set additional cookies in the popin. - // TODO(crbug.com/340606651): Once RSA is implemented we should see first-party cookies after the call. - assert_equals(e.data.message, "ReadOnLoad:ThirdPartyNone-,ReadOnFetch:ThirdPartyNone-ThirdPartyNonePopin-,ReadOnDocument:ThirdPartyNone-ThirdPartyNonePopin-,ReadOnFetchAfterRSA:ThirdPartyNone-ThirdPartyNonePopin-ThirdPartyNonePopinAfterRSA-,ReadOnDocumentAfterRSA:ThirdPartyNone-ThirdPartyNonePopin-ThirdPartyNonePopinAfterRSA-,ReadInPopinIframe:ThirdPartyNone-,ReadInPopinIframeAfterRSA:FirstPartyNone-ThirdPartyNone-FirstPartyNoneAfterRSA-ThirdPartyNoneAfterRSA-"); + assert_equals(e.data.message, "ReadOnLoad:ThirdPartyNone-,ReadOnFetch:ThirdPartyNone-ThirdPartyNonePopin-,ReadOnDocument:ThirdPartyNone-ThirdPartyNonePopin-,ReadOnFetchAfterRSA:ThirdPartyNone-ThirdPartyNonePopin-ThirdPartyNonePopinAfterRSA-,ReadOnDocumentAfterRSA:ThirdPartyNone-ThirdPartyNonePopin-ThirdPartyNonePopinAfterRSA-"); t.done(); break; } diff --git a/tests/wpt/tests/partitioned-popins/partitioned-popins.localStorage.tentative.sub.https.window.js b/tests/wpt/tests/partitioned-popins/partitioned-popins.localStorage.tentative.sub.https.window.js index 06fe2239fd3..84b7af43107 100644 --- a/tests/wpt/tests/partitioned-popins/partitioned-popins.localStorage.tentative.sub.https.window.js +++ b/tests/wpt/tests/partitioned-popins/partitioned-popins.localStorage.tentative.sub.https.window.js @@ -1,5 +1,6 @@ // META: script=/resources/testdriver.js // META: script=/resources/testdriver-vendor.js +// META: script=/storage-access-api/helpers.js 'use strict'; @@ -32,12 +33,14 @@ async_test(t => { break; case 'popin-read': // Step 8 - assert_equals(e.data.message, "Found:ThirdParty-"); + assert_equals(e.data.message, "Found:ThirdParty-FirstPartyRSA-"); t.done(); break; } })); - // Step 2 - window.open("https://{{hosts[alt][]}}:{{ports[https][0]}}/partitioned-popins/resources/partitioned-popins.localStorage-window.html?id="+id, '_blank', 'popup'); + MaybeSetStorageAccess("*", "*", "blocked").then(() => { + // Step 2 + window.open("https://{{hosts[alt][]}}:{{ports[https][0]}}/partitioned-popins/resources/partitioned-popins.localStorage-window.html?id="+id, '_blank', 'popup'); + }); }, "Verify Partitioned Popins only have access to third-party localStorage"); diff --git a/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.cookies-popin-iframe.html b/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.cookies-popin-iframe.html deleted file mode 100644 index 174e97d412c..00000000000 --- a/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.cookies-popin-iframe.html +++ /dev/null @@ -1,33 +0,0 @@ -<!doctype html> -<meta charset="utf-8"> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-vendor.js"></script> -<script src="/partitioned-popins/resources/cookie-helpers.js"></script> -<script> -(async function() { - test_driver.set_test_context(window.top.opener); - - // Step 9 (partitioned-popins/partitioned-popins.cookies-*.tentative.sub.https.window.js) - const id = (new URLSearchParams(window.location.search)).get("id"); - document.cookie = "ThirdPartyStrict=" + id + "; Partitioned; SameSite=Strict; Secure"; - document.cookie = "ThirdPartyLax=" + id + "; Partitioned; SameSite=Lax; Secure"; - document.cookie = "ThirdPartyNone=" + id + "; Partitioned; SameSite=None; Secure"; - let message = ",ReadInPopinIframe:"; - message += getCookieMessage(document.cookie, "FirstParty", "", id); - message += getCookieMessage(document.cookie, "ThirdParty", "", id); - await test_driver.set_permission({ name: 'storage-access' }, 'granted'); - await document.requestStorageAccess(); - document.cookie = "FirstPartyStrictAfterRSA=" + id + "; SameSite=Strict; Secure"; - document.cookie = "FirstPartyLaxAfterRSA=" + id + "; SameSite=Lax; Secure"; - document.cookie = "FirstPartyNoneAfterRSA=" + id + "; SameSite=None; Secure"; - document.cookie = "ThirdPartyStrictAfterRSA=" + id + "; Partitioned; SameSite=Strict; Secure"; - document.cookie = "ThirdPartyLaxAfterRSA=" + id + "; Partitioned; SameSite=Lax; Secure"; - document.cookie = "ThirdPartyNoneAfterRSA=" + id + "; Partitioned; SameSite=None; Secure"; - message += ",ReadInPopinIframeAfterRSA:"; - message += getCookieMessage(document.cookie, "FirstParty", "", id); - message += getCookieMessage(document.cookie, "ThirdParty", "", id); - message += getCookieMessage(document.cookie, "FirstParty", "AfterRSA", id); - message += getCookieMessage(document.cookie, "ThirdParty", "AfterRSA", id); - window.top.postMessage({type: "popin-iframe-read", message: message}, "*"); -})(); -</script> diff --git a/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.cookies-popin.sub.py b/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.cookies-popin.sub.py index 54188d320cf..887cff0cf59 100644 --- a/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.cookies-popin.sub.py +++ b/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.cookies-popin.sub.py @@ -19,7 +19,6 @@ def main(request, response): // Step 7 (partitioned-popins/partitioned-popins.cookies-*.tentative.sub.https.window.js) const id = (new URLSearchParams(window.location.search)).get("id"); - test_driver.set_test_context(window.top); let cookie_string_on_load = \"""" + cookie_string + b"""\"; let message = "ReadOnLoad:"; message += getCookieMessage(cookie_string_on_load, "FirstParty", "", id); @@ -43,7 +42,7 @@ def main(request, response): message += getCookieMessage(document.cookie, "FirstParty", "Popin", id); message += getCookieMessage(document.cookie, "ThirdParty", "Popin", id); await test_driver.set_permission({ name: 'storage-access' }, 'granted'); - await document.requestStorageAccess(); + await test_driver.bless("fake user interaction", () => document.requestStorageAccess()); document.cookie = "FirstPartyStrictPopinAfterRSA=" + id + "; SameSite=Strict; Secure"; document.cookie = "FirstPartyLaxPopinAfterRSA=" + id + "; SameSite=Lax; Secure"; document.cookie = "FirstPartyNonePopinAfterRSA=" + id + "; SameSite=None; Secure"; @@ -68,18 +67,8 @@ def main(request, response): message += getCookieMessage(document.cookie, "ThirdParty", "PopinAfterRSA", id); // Step 8 (partitioned-popins/partitioned-popins.cookies-*.tentative.sub.https.window.js) - window.addEventListener("message", e => { - switch (e.data.type) { - case 'popin-iframe-read': - message += e.data.message; - window.opener.postMessage({type: "popin-read", message: message}, "*"); - window.close(); - break; - } - }); - const iframe = document.createElement("iframe"); - iframe.src = "https://{{hosts[][]}}:{{ports[https][0]}}/partitioned-popins/resources/partitioned-popins.cookies-popin-iframe.html?id="+id; - document.body.appendChild(iframe); + window.opener.postMessage({type: "popin-read", message: message}, "*"); + window.close(); })(); </script> """ diff --git a/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.localStorage-popin.html b/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.localStorage-popin.html index 4ab2d4a5ff2..bd06309b3d9 100644 --- a/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.localStorage-popin.html +++ b/tests/wpt/tests/partitioned-popins/resources/partitioned-popins.localStorage-popin.html @@ -14,6 +14,11 @@ } else if (window.localStorage.getItem("third-party") == id) { message += "ThirdParty-"; } + await test_driver.set_permission({ name: 'storage-access' }, 'granted'); + let handle = await document.requestStorageAccess({localStorage: true}); + if (handle && handle.localStorage.getItem("first-party") == id) { + message += "FirstPartyRSA-"; + } window.opener.postMessage({type: "popin-read", message: message}, "*"); window.close(); })(); diff --git a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-default-permissions-policy.tentative.https.sub.html b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-default-permissions-policy.https.sub.html index 9ca1426040c..9ca1426040c 100644 --- a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-default-permissions-policy.tentative.https.sub.html +++ b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-default-permissions-policy.https.sub.html diff --git a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-by-permissions-policy-cross-origin.tentative.https.sub.html b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-by-permissions-policy-cross-origin.https.sub.html index a62ca0b581d..a62ca0b581d 100644 --- a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-by-permissions-policy-cross-origin.tentative.https.sub.html +++ b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-by-permissions-policy-cross-origin.https.sub.html diff --git a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-by-permissions-policy.tentative.https.sub.html b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-by-permissions-policy.https.sub.html index bd43848ec11..bd43848ec11 100644 --- a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-by-permissions-policy.tentative.https.sub.html +++ b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-by-permissions-policy.https.sub.html diff --git a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-tentative.html b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled.html index 3980fd1219c..3980fd1219c 100644 --- a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled-tentative.html +++ b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-disabled.html diff --git a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-enabled-tentative.sub.html b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-enabled.sub.html index 12700d0fdb1..12700d0fdb1 100644 --- a/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-enabled-tentative.sub.html +++ b/tests/wpt/tests/permissions-policy/experimental-features/focus-without-user-activation-enabled.sub.html diff --git a/tests/wpt/tests/sanitizer-api/idlharness.https.window.js b/tests/wpt/tests/sanitizer-api/idlharness.https.window.js index 384317b8e55..46141177339 100644 --- a/tests/wpt/tests/sanitizer-api/idlharness.https.window.js +++ b/tests/wpt/tests/sanitizer-api/idlharness.https.window.js @@ -2,7 +2,7 @@ // META: script=/resources/idlharness.js idl_test( - ['sanitizer-api.tentative'], + ['sanitizer-api'], ['html'], idl_array => { idl_array.add_objects({ diff --git a/tests/wpt/tests/sanitizer-api/sanitizer-config.tentative.html b/tests/wpt/tests/sanitizer-api/sanitizer-config.tentative.html index 2e8ec343f2c..438e1db7ead 100644 --- a/tests/wpt/tests/sanitizer-api/sanitizer-config.tentative.html +++ b/tests/wpt/tests/sanitizer-api/sanitizer-config.tentative.html @@ -110,7 +110,7 @@ test(t => { assert_equals(s.get().elements.length, 3); s.removeElement({name: "div"}); assert_equals(s.get().elements.length, 2); - s.replaceWithChildrenElement({name: "p", namespace: "http://www.w3.org/1999/xhtml"}); + s.replaceElementWithChildren({name: "p", namespace: "http://www.w3.org/1999/xhtml"}); assert_equals(s.get().elements.length, 1); assert_object_equals(s.get().elements[0], {name: "bla", namespace: "http://www.w3.org/1999/xhtml"}); @@ -121,7 +121,7 @@ test(t => { assert_equals(s.get().removeElements.length, 2); s.removeElement("bla"); assert_equals(s.get().removeElements.length, 3); - s.replaceWithChildrenElement({name: "div"}); + s.replaceElementWithChildren({name: "div"}); assert_equals(s.get().removeElements.length, 2); s.allowElement({name: "p", namespace: "http://www.w3.org/1999/xhtml"}); assert_equals(s.get().removeElements.length, 1); @@ -132,7 +132,7 @@ test(t => { test(t => { let s = new Sanitizer({replaceWithChildrenElements: ["div", "p"]}); assert_equals(s.get().replaceWithChildrenElements.length, 2); - s.replaceWithChildrenElement("bla"); + s.replaceElementWithChildren("bla"); assert_equals(s.get().replaceWithChildrenElements.length, 3); s.allowElement({name: "div"}); assert_equals(s.get().replaceWithChildrenElements.length, 2); diff --git a/tests/wpt/tests/sanitizer-api/sanitizer-names.tentative.html b/tests/wpt/tests/sanitizer-api/sanitizer-names.tentative.html index e16f685a91c..952d77f9192 100644 --- a/tests/wpt/tests/sanitizer-api/sanitizer-names.tentative.html +++ b/tests/wpt/tests/sanitizer-api/sanitizer-names.tentative.html @@ -27,23 +27,32 @@ "href", "span", ]; const attrs_invalid = [ + "", {name: ""}, ]; - const all_elems = elems_valid.concat(elems_invalid); - const all_attrs = attrs_valid.concat(attrs_invalid); for (const item of ["elements", "removeElements", "replaceWithChildrenElements"]) { test(t => { - const sanitizer = new Sanitizer({[item]: all_elems}); + const sanitizer = new Sanitizer({[item]: elems_valid}); assert_array_same(sanitizer.get()[item].map(x => x.name), elems_valid.map(x => "" + x)); }, `Element names in config item: ${item}`); + test(t => { + assert_throws_js(TypeError, _ => { + new Sanitizer({[item]: elems_valid.concat(elems_invalid)}); + }); + }, `Invalid element names in config item: ${item}`); } for (const item of ["attributes", "removeAttributes"]) { test(t => { - const sanitizer = new Sanitizer({[item]: all_attrs}); + const sanitizer = new Sanitizer({[item]: attrs_valid}); assert_array_same(sanitizer.get()[item].map(x => x.name), attrs_valid.map(x => "" + x)); }, `Attribute names in config item: ${item}`); + test(t => { + assert_throws_js(TypeError, _ => { + new Sanitizer({[item]: attrs_valid.concat(attrs_invalid)}); + }); + }, `Invalid attribute names in config item: ${item}`); } // Quick sanity tests for namespaced elements. diff --git a/tests/wpt/tests/sanitizer-api/sethtml-tree-construction.sub.dat b/tests/wpt/tests/sanitizer-api/sethtml-tree-construction.sub.dat index 0986112a233..d39447345f9 100644 --- a/tests/wpt/tests/sanitizer-api/sethtml-tree-construction.sub.dat +++ b/tests/wpt/tests/sanitizer-api/sethtml-tree-construction.sub.dat @@ -146,9 +146,8 @@ test <div>test</div><p>bla #config { "removeElements": ["div"], "elements": ["div"] } -#document -| <p> -| "bla" +#error +TypeError #data <p id='test'>Click.</p> @@ -220,9 +219,8 @@ test <div id='div' title='div'>DIV</div> #config { "elements": [{ "name": "div", "attributes": ["id"], "removeAttributes": ["id"] }]} -#document -| <div> -| "DIV" +#error +TypeError #data <div id='div' title='div'>DIV</div> @@ -272,9 +270,8 @@ test <p style='color: black'>Click.</p> #config { "removeAttributes": ["style"], "attributes": ["style"] } -#document -| <p> -| "Click." +#error +TypeError #data <template><script>test</script><div>hello</div></template> diff --git a/tests/wpt/tests/sanitizer-api/sethtml-tree-construction.tentative.html b/tests/wpt/tests/sanitizer-api/sethtml-tree-construction.tentative.html index 82b929b9a2d..359560d3285 100644 --- a/tests/wpt/tests/sanitizer-api/sethtml-tree-construction.tentative.html +++ b/tests/wpt/tests/sanitizer-api/sethtml-tree-construction.tentative.html @@ -18,7 +18,18 @@ promise_test(_ => { try { config = JSON.parse(testcase.config); } catch { } - div.setHTML(testcase.data, { sanitizer: config }); + try { + div.setHTML(testcase.data, { sanitizer: config }); + } catch (error) { + assert_equals( + error.name, testcase.error, + `Expect exception ${testcase.error}, but got ${error}.`); + return; // Early return in order to not trigger the subsequent + // assertions. + } + assert_false( + !!testcase.error, + `Expect exception ${testcase.error}, but nothing was thrown.`); assert_testcase(div, testcase); }, `Testcase #${index}, "${testcase.data}", config: "${testcase.config}".`); }); diff --git a/tests/wpt/tests/scheduler/tentative/yield/yield-scripted-subframe-propagation.html b/tests/wpt/tests/scheduler/tentative/yield/yield-scripted-subframe-propagation.html index 9b27518b0d9..d45cf3e7643 100644 --- a/tests/wpt/tests/scheduler/tentative/yield/yield-scripted-subframe-propagation.html +++ b/tests/wpt/tests/scheduler/tentative/yield/yield-scripted-subframe-propagation.html @@ -3,6 +3,13 @@ <script src="/resources/testharnessreport.js"></script> <script> + async function getResultsInOrder(promises) { + const results = []; + const tasks = promises.map(p => p.then(r => results.push(r))); + await Promise.all(tasks); + return results; + } + promise_test(async t => { await new Promise(resolve => window.onload = resolve); const iframe = document.createElement('iframe'); @@ -21,21 +28,21 @@ let task1 = scheduler.postTask( iframe.contentWindow.task, {priority: 'user-blocking'}); let task2 = scheduler.postTask(() => "outer", {priority: 'user-blocking'}); - let result = await Promise.all([task1, task2]); + let result = await getResultsInOrder([task1, task2]); assert_equals(result.toString(), "inner,outer", "Expected inner before outer for iframe task with main frame scheduler"); task1 = iframe.contentWindow.scheduler.postTask( iframe.contentWindow.task, {priority: 'user-blocking'}); task2 = scheduler.postTask(() => "outer", {priority: 'user-blocking'}); - result = await Promise.all([task1, task2]); + result = await getResultsInOrder([task1, task2]); assert_equals(result.toString(), "inner,outer", "Expected inner before outer for iframe task with iframe scheduler"); task1 = scheduler.postTask( async () => await iframe.contentWindow.task(), {priority: 'user-blocking'}); task2 = scheduler.postTask(() => "outer", {priority: 'user-blocking'}); - result = await Promise.all([task1, task2]); + result = await getResultsInOrder([task1, task2]); assert_equals(result.toString(), "inner,outer", "Expected inner before outer for iframe task called from main frame task"); }, 'Test scheduler.yield() uses propagated state in same origin frames'); diff --git a/tests/wpt/tests/screen-capture/tentative/getdisplaymedia-captured-surface-resolution.https.html b/tests/wpt/tests/screen-capture/tentative/getdisplaymedia-captured-surface-resolution.https.html index 85867c373b6..a1e7997ca69 100644 --- a/tests/wpt/tests/screen-capture/tentative/getdisplaymedia-captured-surface-resolution.https.html +++ b/tests/wpt/tests/screen-capture/tentative/getdisplaymedia-captured-surface-resolution.https.html @@ -21,6 +21,7 @@ return navigator.mediaDevices.getDisplayMedia(constraints); } + // On MacOS these tests need to be run with setTimeout for threading purposes. promise_test(async t => { var video = document.createElement("video"); const stream = await getDisplayMedia({ displaySurface: "monitor" }); @@ -42,7 +43,7 @@ assert_equals(capabilities.width.max, settings.physicalWidth); assert_equals(capabilities.height.max, settings.physicalHeight); }; - video.requestVideoFrameCallback(onFrame); + setTimeout(() => { video.requestVideoFrameCallback(onFrame); }, 100); }, "getDisplayMedia() and resolution for captured surface type monitor"); promise_test(async t => { @@ -52,6 +53,7 @@ const screenDetails = await window.getScreenDetails(); video.srcObject = stream; await video.play(); + t.add_cleanup(() => stopTracks(stream)); const onFrame = (now, metadata) => { const track = video.srcObject.getVideoTracks()[0]; @@ -66,8 +68,7 @@ assert_equals(capabilities.width.max, settings.physicalWidth); assert_equals(capabilities.height.max, settings.physicalHeight); }; - video.requestVideoFrameCallback(onFrame); - + setTimeout(() => { video.requestVideoFrameCallback(onFrame); }, 100); }, "getDisplayMedia() and resolution for captured surface type window"); promise_test(async t => { @@ -75,6 +76,7 @@ const stream = await getDisplayMedia({ displaySurface: "browser" }); video.srcObject = stream; await video.play(); + t.add_cleanup(() => stopTracks(stream)); const onFrame = (now, metadata) => { const track = video.srcObject.getVideoTracks()[0]; @@ -89,8 +91,7 @@ assert_equals(capabilities.width.max, settings.physicalWidth); assert_equals(capabilities.height.max, settings.physicalHeight); }; - video.requestVideoFrameCallback(onFrame); - + setTimeout(() => { video.requestVideoFrameCallback(onFrame); }, 100); }, "getDisplayMedia() and resolution for captured surface type browser"); promise_test(async t => { @@ -100,6 +101,7 @@ const screenDetails = await window.getScreenDetails(); video.srcObject = stream; await video.play(); + t.add_cleanup(() => stopTracks(stream)); const onFrame = async (now, metadata) => { const track = video.srcObject.getVideoTracks()[0]; @@ -125,7 +127,7 @@ assert_equals(capabilities.width.max, settings.physicalWidth); assert_equals(capabilities.height.max, settings.physicalHeight); }; - video.requestVideoFrameCallback(onFrame); + setTimeout(() => { video.requestVideoFrameCallback(onFrame); }, 100); }, "applyConstraints() should not change the physical and logical size of captured surface type monitor"); promise_test(async t => { @@ -135,6 +137,7 @@ const screenDetails = await window.getScreenDetails(); video.srcObject = stream; await video.play(); + t.add_cleanup(() => stopTracks(stream)); const onFrame = async (now, metadata) => { const track = video.srcObject.getVideoTracks()[0]; @@ -160,7 +163,7 @@ assert_equals(capabilities.width.max, settings.physicalWidth); assert_equals(capabilities.height.max, settings.physicalHeight); }; - video.requestVideoFrameCallback(onFrame); + setTimeout(() => { video.requestVideoFrameCallback(onFrame); }, 100); }, "applyConstraints() should not change the physical and logical size of captured surface type window"); promise_test(async t => { @@ -168,6 +171,7 @@ const stream = await getDisplayMedia({ displaySurface: "browser" }); video.srcObject = stream; await video.play(); + t.add_cleanup(() => stopTracks(stream)); const onFrame = async (now, metadata) => { const track = video.srcObject.getVideoTracks()[0]; @@ -193,7 +197,7 @@ assert_equals(capabilities.width.max, settings.physicalWidth); assert_equals(capabilities.height.max, settings.physicalHeight); }; - video.requestVideoFrameCallback(onFrame); + setTimeout(() => { video.requestVideoFrameCallback(onFrame); }, 100); }, "applyConstraints() should not change the physical and logical size of captured surface type browser"); diff --git a/tests/wpt/tests/scroll-animations/css/scroll-timeline-dynamic.tentative.html b/tests/wpt/tests/scroll-animations/css/scroll-timeline-dynamic.tentative.html index d1f143c7c19..34f3dddadc4 100644 --- a/tests/wpt/tests/scroll-animations/css/scroll-timeline-dynamic.tentative.html +++ b/tests/wpt/tests/scroll-animations/css/scroll-timeline-dynamic.tentative.html @@ -257,10 +257,11 @@ element.style.animationTimeline = '--timeline'; element.style.animationPlayState = 'paused'; - // Pausing should happen before the timeline is modified. (Tentative). + // Pausing should happen after the timeline was modified. // https://github.com/w3c/csswg-drafts/issues/5653 - await assert_width(element, '100px'); + await assert_width(element, '120px'); + // Changing the play state should not change the animation current time. element.style.animationPlayState = 'running'; await assert_width(element, '120px'); }, 'Switching timelines and pausing at the same time'); diff --git a/tests/wpt/tests/scroll-animations/view-timelines/view-timeline-get-current-time-range-name.html b/tests/wpt/tests/scroll-animations/view-timelines/view-timeline-get-current-time-range-name.tentative.html index 25e477e1a97..25e477e1a97 100644 --- a/tests/wpt/tests/scroll-animations/view-timelines/view-timeline-get-current-time-range-name.html +++ b/tests/wpt/tests/scroll-animations/view-timelines/view-timeline-get-current-time-range-name.tentative.html diff --git a/tests/wpt/tests/secure-payment-confirmation/enrollment-in-iframe.sub.https.html b/tests/wpt/tests/secure-payment-confirmation/enrollment-in-iframe.sub.https.html index 9a0f2093a1b..be7d5daf83b 100644 --- a/tests/wpt/tests/secure-payment-confirmation/enrollment-in-iframe.sub.https.html +++ b/tests/wpt/tests/secure-payment-confirmation/enrollment-in-iframe.sub.https.html @@ -105,9 +105,9 @@ promise_test(async t => { frame.contentWindow.postMessage({ userActivation: false }, '*'); const result = await resultPromise; - // Without a user activation, we expect a SecurityError. + // Without a user activation, we expect a NotAllowedError. assert_true(result.error instanceof DOMException); - assert_equals(result.error.name, 'SecurityError'); + assert_equals(result.error.name, 'NotAllowedError'); assert_not_own_property(result, 'id'); assert_not_own_property(result, 'rawId'); }, 'SPC enrollment in cross-origin iframe fails without user activation'); diff --git a/tests/wpt/tests/selection/crashtests/selection-detached-range-find-crash.html b/tests/wpt/tests/selection/crashtests/selection-detached-range-find-crash.html new file mode 100644 index 00000000000..e64446467da --- /dev/null +++ b/tests/wpt/tests/selection/crashtests/selection-detached-range-find-crash.html @@ -0,0 +1,21 @@ +<script> + document.addEventListener("DOMContentLoaded", () => { + let s = window.getSelection() + r = document.createRange() + r.selectNode(c) + s.addRange(r) + r.selectNode(a) + s.addRange(r) + window.getSelection().modify("move", "right", "line") + b.replaceWith(document.createElement("section")) + window.find("A") + }) + </script> + <del> + <strong id="a"></strong> + <menu> + <canvas> + <input/> + <mark> + <small id="b"> + <video id="c"> diff --git a/tests/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/error-message-event.https.html b/tests/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/error-message-event.https.html index fc8edb4b896..0a35cc7c39c 100644 --- a/tests/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/error-message-event.https.html +++ b/tests/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/error-message-event.https.html @@ -2,9 +2,10 @@ <html> <head> <title>Service Worker GlobalScope onerror event</title> +<meta name="timeout" content="long"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> - <script src="/common/get-host-info.sub.js"></script> +<script src="/common/get-host-info.sub.js"></script> </head> <body> <canvas id=canvas></canvas> diff --git a/tests/wpt/tests/service-workers/service-worker/controlled-dedicatedworker-postMessage.https.html b/tests/wpt/tests/service-workers/service-worker/controlled-dedicatedworker-postMessage.https.html index 7e2a604621d..5ef91dd1b11 100644 --- a/tests/wpt/tests/service-workers/service-worker/controlled-dedicatedworker-postMessage.https.html +++ b/tests/wpt/tests/service-workers/service-worker/controlled-dedicatedworker-postMessage.https.html @@ -1,5 +1,6 @@ <html> <head> +<meta name="timeout" content="long"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/test-helpers.sub.js"></script> diff --git a/tests/wpt/tests/service-workers/service-worker/controlled-iframe-postMessage.https.html b/tests/wpt/tests/service-workers/service-worker/controlled-iframe-postMessage.https.html index 8f39b7fdbf8..c3f390a5a45 100644 --- a/tests/wpt/tests/service-workers/service-worker/controlled-iframe-postMessage.https.html +++ b/tests/wpt/tests/service-workers/service-worker/controlled-iframe-postMessage.https.html @@ -1,5 +1,6 @@ <html> <head> +<meta name="timeout" content="long"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/test-helpers.sub.js"></script> diff --git a/tests/wpt/tests/service-workers/service-worker/navigation-preload/content-encoding.https.html b/tests/wpt/tests/service-workers/service-worker/navigation-preload/content-encoding.https.html new file mode 100644 index 00000000000..d6135d95c88 --- /dev/null +++ b/tests/wpt/tests/service-workers/service-worker/navigation-preload/content-encoding.https.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Navigation Preload with content encoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/test-helpers.sub.js"></script> +<script> +promise_test(t => { + var script = 'resources/content-encoding-worker.js'; + var scope = 'resources/content-encoding-scope.py'; + return service_worker_unregister_and_register(t, script, scope) + .then(registration => { + add_completion_callback(_ => registration.unregister()); + var worker = registration.installing; + return wait_for_state(t, worker, 'activated'); + }) + .then(_ => with_iframe(scope)) + .then(frame => { + assert_equals( + frame.contentDocument.body.textContent, + 'Hello World'); + }); + }, 'Navigation Preload must work with content encoding.'); + +</script> diff --git a/tests/wpt/tests/service-workers/service-worker/navigation-preload/resources/content-encoding-scope.py b/tests/wpt/tests/service-workers/service-worker/navigation-preload/resources/content-encoding-scope.py new file mode 100644 index 00000000000..bd9601d1578 --- /dev/null +++ b/tests/wpt/tests/service-workers/service-worker/navigation-preload/resources/content-encoding-scope.py @@ -0,0 +1,7 @@ +import gzip + +def main(request, response): + response.headers.set(b"Content-Type", b"text/html; charset=UTF-8") + response.headers.set(b"Content-Encoding", b"gzip") + response.content = gzip.compress(bytes(u"Hello World", 'utf-8')) + diff --git a/tests/wpt/tests/service-workers/service-worker/navigation-preload/resources/content-encoding-worker.js b/tests/wpt/tests/service-workers/service-worker/navigation-preload/resources/content-encoding-worker.js new file mode 100644 index 00000000000..f30e5ed274d --- /dev/null +++ b/tests/wpt/tests/service-workers/service-worker/navigation-preload/resources/content-encoding-worker.js @@ -0,0 +1,8 @@ +self.addEventListener('activate', event => { + event.waitUntil( + self.registration.navigationPreload.enable()); + }); + +self.addEventListener('fetch', event => { + event.respondWith(event.preloadResponse); + }); diff --git a/tests/wpt/tests/service-workers/service-worker/request-end-to-end.https.html b/tests/wpt/tests/service-workers/service-worker/request-end-to-end.https.html index a39ceadd9f3..82475eabc4a 100644 --- a/tests/wpt/tests/service-workers/service-worker/request-end-to-end.https.html +++ b/tests/wpt/tests/service-workers/service-worker/request-end-to-end.https.html @@ -29,12 +29,16 @@ promise_test(t => { 'TypeError.') assert_equals(result.credentials, 'include', 'request.credentials'); assert_equals(result.redirect, 'manual', 'request.redirect'); - assert_equals(result.headers['user-agent'], undefined, - 'Default User-Agent header should not be passed to ' + - 'onfetch event.') assert_equals(result.append_header_error, 'TypeError', 'Appending a new header to the request must throw a ' + 'TypeError.') + + // `assert_equals()` is not used here to create a stable failure + // baseline, because the User-Agent header would be version-dependent + // if set. + assert_true(result.headers['user-agent'] === undefined, + 'Default User-Agent header should not be passed to ' + + 'onfetch event.') }); }, 'Test FetchEvent.request passed to onfetch'); </script> diff --git a/tests/wpt/tests/shadow-dom/declarative/getinnerhtml.tentative.html b/tests/wpt/tests/shadow-dom/declarative/getinnerhtml.tentative.html deleted file mode 100644 index 139cba2a517..00000000000 --- a/tests/wpt/tests/shadow-dom/declarative/getinnerhtml.tentative.html +++ /dev/null @@ -1,81 +0,0 @@ -<!DOCTYPE html> -<title>getInnerHTML </title> -<link rel='author' href='mailto:masonf@chromium.org'> -<link rel='help' href='https://github.com/whatwg/dom/issues/831'> -<script src='/resources/testharness.js'></script> -<script src='/resources/testharnessreport.js'></script> -<script src='../../html/resources/common.js'></script> - -<body> - -<script> -function testElementType(allowsShadowDom, elementType, applyToShadow, mode, delegatesFocus) { - const t = test(t => { - // Create and attach element - let wrapper; - if (applyToShadow) { - const host = document.createElement('div'); - t.add_cleanup(function() { host.remove(); }); - document.body.appendChild(host); - wrapper = host.attachShadow({mode: 'open'}); - } else { - wrapper = document.createElement('div'); - t.add_cleanup(function() { wrapper.remove(); }); - document.body.appendChild(wrapper); - } - const element = document.createElement(elementType); - wrapper.appendChild(element); - - const isOpen = mode === 'open'; - if (allowsShadowDom) { - const delegatesAttr = delegatesFocus ? ' shadowrootdelegatesfocus=""' : ''; - const correctShadowHtml = `<template shadowrootmode="${mode}"${delegatesAttr}><slot></slot></template>`; - const correctHtml = `<${elementType}>${correctShadowHtml}</${elementType}>`; - const emptyElement = `<${elementType}></${elementType}>`; - const shadowRoot = element.attachShadow({mode: mode, delegatesFocus: delegatesFocus}); - shadowRoot.appendChild(document.createElement('slot')); - if (isOpen) { - // We can only test this for open roots - assert_equals(wrapper.getInnerHTML(),correctHtml,'The default for includeShadowRoots should be true'); - } else { - // Closed shadow roots should not be returned unless closedRoots contains the shadow root: - assert_equals(wrapper.getInnerHTML({includeShadowRoots: true}), emptyElement); - assert_equals(wrapper.getInnerHTML({includeShadowRoots: true, closedRoots: []}), emptyElement); - } - assert_equals(wrapper.getInnerHTML({includeShadowRoots: true, closedRoots: [shadowRoot]}),correctHtml); - // ClosedRoots are not included if includeShadowRoots is false: - assert_equals(wrapper.getInnerHTML({includeShadowRoots: false, closedRoots: [shadowRoot]}),emptyElement); - } else { - // For non-shadow hosts, getInnerHTML() should also match .innerHTML - assert_equals(wrapper.getInnerHTML({includeShadowRoots: true}),wrapper.innerHTML); - assert_equals(wrapper.getInnerHTML(),wrapper.innerHTML); - } - - // Either way, make sure getInnerHTML({includeShadowRoots: false}) matches .innerHTML - assert_equals(wrapper.getInnerHTML({includeShadowRoots: false}),wrapper.innerHTML,'getInnerHTML() with includeShadowRoots false should return the same as .innerHTML'); - - }, `${applyToShadow ? 'ShadowRoot' : 'Element'}.getInnerHTML() on <${elementType}>${allowsShadowDom ? `, with mode=${mode}, delegatesFocus=${delegatesFocus}.` : ''}`); -} - -function runAllTests() { - const allElements = [...HTML5_ELEMENTS, 'htmlunknown']; - const safelisted = HTML5_SHADOW_ALLOWED_ELEMENTS; - for (const elementName of allElements) { - const allowsShadowDom = safelisted.includes(elementName); - for (const applyToShadow of [false, true]) { - if (allowsShadowDom) { - for (const delegatesFocus of [false, true]) { - for (const mode of ['open', 'closed']) { - testElementType(true, elementName, applyToShadow, mode, delegatesFocus); - } - } - } else { - testElementType(false, elementName, applyToShadow); - } - } - } -} - -runAllTests(); - -</script> diff --git a/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/grid-order-with-position-absolute.html b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/grid-order-with-position-absolute.html index 239383dd6c4..a697d13001b 100644 --- a/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/grid-order-with-position-absolute.html +++ b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/grid-order-with-position-absolute.html @@ -19,15 +19,19 @@ } </style> -<div class="test-case" data-expect="c,b,a1,a2" - data-description="Items in position:absolute container are visited at the end of the focus sequence."> +<div class="test-case" data-expect="f,e,c,d,a,b" + data-description="Items in position:absolute container are visited at the end of the focus sequence. reading-order can override DOM order."> <div class="wrapper"> - <div style="order: 2; position:absolute; left:100px"> - <button id="a1">A1</button> - <button id="a2">A2</button> + <div style="order: 2; reading-order: 1; position:absolute; left:100px; top: 50px"> + <button id="a">A</button> + <button id="b">B</button> </div> - <div style="order:3"><button id="b">B</button></div> - <div style="order:1"><button id="c">C</button></div> + <div style="order: 2; position:absolute; left:100px"> + <button id="c">C</button> + <button id="d">D</button> + </div> + <div style="order:3"><button id="e">E</button></div> + <div style="order:1"><button id="f">F</button></div> </div> </div> diff --git a/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/grid-order-with-position-fixed.html b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/grid-order-with-position-fixed.html index bc496c47b4c..fdef20955b8 100644 --- a/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/grid-order-with-position-fixed.html +++ b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/grid-order-with-position-fixed.html @@ -19,15 +19,19 @@ } </style> -<div class="test-case" data-expect="c,b,a1,a2" - data-description="Items in position:fixed container are visited at the end of the focus sequence."> +<div class="test-case" data-expect="f,e,c,d,a,b" + data-description="Items in position:fixed container are visited at the end of the focus sequence. reading-order can override DOM order."> <div class="wrapper"> - <div style="order: 2; position:fixed; left:100px"> - <button id="a1">A1</button> - <button id="a2">A2</button> + <div style="order: 2; reading-order: 1; position:fixed; left:100px; top: 50px"> + <button id="a">A</button> + <button id="b">B</button> </div> - <div style="order:3"><button id="b">B</button></div> - <div style="order:1"><button id="c">C</button></div> + <div style="order: 2; position:fixed; left:100px"> + <button id="c">C</button> + <button id="d">D</button> + </div> + <div style="order:3"><button id="e">E</button></div> + <div style="order:1"><button id="f">F</button></div> </div> </div> diff --git a/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/normal.html b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/normal.html index 6f855b39351..54936e71082 100644 --- a/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/normal.html +++ b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/normal.html @@ -14,35 +14,49 @@ <style> .wrapper { - display: grid; reading-flow: normal; } +.grid { + display: grid; +} +.block { + display: block; +} </style> <div class="test-case" data-expect="t1-c,t1-d,t1-g1,t1-h2,t2-e,t2-f,t2-g2,a,b,g,h,h1" - data-description="Grid items with `order` property and tabindex. Focus should be in DOM tabindexed-order."> - <div class="wrapper"> - <button id="a" style="order: -1">Item A</button> - <button id="b" style="order: 0">Item B</button> + data-description="Grid items. Focus should be in DOM tabindexed-order."> + <div class="wrapper grid"> + <button id="a" tabindex="3" style="order: -1">Item A</button> + <button id="b" tabindex="3" style="order: 0">Item B</button> <button id="t1-c" tabindex="1" style="order: -1">Item C</button> </div> - <div class="wrapper"> + <div class="wrapper grid"> <button id="t1-d" tabindex="1" style="order: 1">Item D</button> <button id="t2-e" tabindex="2" style="order: 0">Item E</button> <button id="t2-f" tabindex="2" style="order: -1">Item F</button> </div> - <div class="wrapper"> - <div id="g" style="order: 2" tabindex="0">G + <div class="wrapper grid"> + <div id="g" style="order: 2" tabindex="3">G <div id="t1-g1" tabindex="1">Item G1</div> <div id="t2-g2" tabindex="2">Item G2</div> </div> - <div id="h" style="order: 1" tabindex="0">H - <div id="h1" tabindex="0">Item H1</div> + <div id="h" style="order: 1" tabindex="3">H + <div id="h1" tabindex="3">Item H1</div> <div id="t1-h2" tabindex="1">Item H2</div> </div> </div> </div> +<div class="test-case" data-expect="t5-c,t6-a,t6-b" + data-description="Block elements. Focus should be in DOM tabindexed-order."> + <div class="wrapper block"> + <button id="t6-a" style="order: 1; reading-order: 1" tabindex="6">Item A</button> + <button id="t6-b" style="order: -1; reading-order: -1" tabindex="6">Item B</button> + <button id="t5-c" style="order: 0; reading-order: 0" tabindex="5">Item C</button> + </div> +</div> + <script> runFocusTestCases(); </script> diff --git a/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/source-order-invalid.html b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/source-order-invalid.html new file mode 100644 index 00000000000..e08351b2098 --- /dev/null +++ b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/source-order-invalid.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>CSS Display: reading-flow with value source-order should not work</title> +<link rel="help" href="https://drafts.csswg.org/css-display-4/#reading-flow"> +<link rel="author" title="Di Zhang" href="mailto:dizhangg@chromium.org"> +<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/testdriver-actions.js"></script> +<script src='../../resources/shadow-dom.js'></script> +<script src="../../resources/focus-utils.js"></script> + +<style> +.wrapper { + display: inline; + reading-flow: source-order; +} +</style> + +<div class="test-case" data-expect="a,b,c" + data-description="Inline elements. Focus should be in DOM tabindexed-order."> + <div class="wrapper"> + <button id="a" style="reading-order: 1">Item A</button> + <button id="b" style="reading-order: -1">Item B</button> + <button id="c" style="reading-order: 0">Item C</button> + </div> +</div> + +<script> +runFocusTestCases(); +</script> diff --git a/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/source-order-valid.html b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/source-order-valid.html new file mode 100644 index 00000000000..f5ba87040ae --- /dev/null +++ b/tests/wpt/tests/shadow-dom/focus-navigation/reading-flow/tentative/source-order-valid.html @@ -0,0 +1,69 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>CSS Display: reading-flow with value source-order should work</title> +<link rel="help" href="https://drafts.csswg.org/css-display-4/#reading-flow"> +<link rel="author" title="Di Zhang" href="mailto:dizhangg@chromium.org"> +<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/testdriver-actions.js"></script> +<script src='../../resources/shadow-dom.js'></script> +<script src="../../resources/focus-utils.js"></script> + +<style> +.wrapper { + reading-flow: source-order; +} +</style> + +<div class="test-case" data-expect="b1,c1,a1" + data-description="Block elements. Focus should be in DOM tabindexed-order, but reading-order takes effect."> + <div class="wrapper" style="display: block"> + <button id="a1" style="reading-order: 1">Item A</button> + <button id="b1" style="reading-order: -1">Item B</button> + <button id="c1" style="reading-order: 0">Item C</button> + </div> +</div> + +<div class="test-case" data-expect="b2,c2,a2" + data-description="Block inline elements. Focus should be in DOM tabindexed-order, but reading-order takes effect."> + <div class="wrapper" style="display: block-inline"> + <button id="a2" style="reading-order: 1">Item A</button> + <button id="b2" style="reading-order: -1">Item B</button> + <button id="c2" style="reading-order: 0">Item C</button> + </div> +</div> + +<div class="test-case" data-expect="b3,c3,a3" + data-description="Flex elements. Focus should be in DOM tabindexed-order, but reading-order takes effect."> + <div class="wrapper" style="display: flex"> + <button id="a3" style="reading-order: 1; order: -1">Item A</button> + <button id="b3" style="reading-order: -1">Item B</button> + <button id="c3" style="reading-order: 0">Item C</button> + </div> +</div> + +<div class="test-case" data-expect="b4,c4,a4" + data-description="Grid elements. Focus should be in DOM tabindexed-order, but reading-order takes effect."> + <div class="wrapper" style="display: grid"> + <button id="a4" style="reading-order: 1; order: -1">Item A</button> + <button id="b4" style="reading-order: -1">Item B</button> + <button id="c4" style="reading-order: 0">Item C</button> + </div> +</div> + +<div class="test-case" data-expect="b5,c5,a5" + data-description="Flow root elements. Focus should be in DOM tabindexed-order, but reading-order takes effect."> + <div class="wrapper" style="display: flow-root"> + <button id="a5" style="reading-order: 1">Item A</button> + <button id="b5" style="reading-order: -1">Item B</button> + <button id="c5" style="reading-order: 0">Item C</button> + </div> +</div> + + +<script> +runFocusTestCases(); +</script> diff --git a/tests/wpt/tests/speech-api/SpeechRecognition-availableOnDevice.https.html b/tests/wpt/tests/speech-api/SpeechRecognition-availableOnDevice.https.html index fd8e75fdf90..db48f2a7a6f 100644 --- a/tests/wpt/tests/speech-api/SpeechRecognition-availableOnDevice.https.html +++ b/tests/wpt/tests/speech-api/SpeechRecognition-availableOnDevice.https.html @@ -14,13 +14,19 @@ promise_test(async (t) => { "availableOnDevice should return a Promise." ); - // Verify the resolved value is a boolean. + // Verify the resolved value is a string. const result = await resultPromise; assert_true( - typeof result === "boolean", - "The resolved value of the availableOnDevice promise should be a boolean." + typeof result === "string", + "The resolved value of the availableOnDevice promise should be a string." ); -}, "SpeechRecognition.availableOnDevice resolves with a boolean value."); + + assert_true( + result === "unavailable" || result === "downloadable" || + result === "downloading" || result === "available", + "The resolved value of the availableOnDevice promise should be a valid value." + ); +}, "SpeechRecognition.availableOnDevice resolves with a string value."); promise_test(async (t) => { const iframe = document.createElement("iframe"); diff --git a/tests/wpt/tests/speech-api/SpeechRecognition-recognitionContext-manual.https.html b/tests/wpt/tests/speech-api/SpeechRecognition-recognitionContext-manual.https.html new file mode 100644 index 00000000000..1039baa2825 --- /dev/null +++ b/tests/wpt/tests/speech-api/SpeechRecognition-recognitionContext-manual.https.html @@ -0,0 +1,85 @@ +<!DOCTYPE html> +<html lang="en"> +<title>SpeechRecognition RecognitionContext</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async function getAudioTrackFromFile(filePath) { + const audioContext = new AudioContext(); + const response = await fetch(filePath); + const arrayBuffer = await response.arrayBuffer(); + const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); + const source = audioContext.createBufferSource(); + source.buffer = audioBuffer; + + const destination = audioContext.createMediaStreamDestination(); + source.connect(destination); + source.start(); + + return destination.stream.getAudioTracks()[0]; +} + +promise_test(async (t) => { + // Verify the audio track for recognition context exists. + const audioTrack = await getAudioTrackFromFile("/media/recognition_context.mp3"); + assert_true( + audioTrack instanceof MediaStreamTrack, + "Audio track should be a valid MediaStreamTrack" + ); + + // Create the recognition context. + var list = new SpeechRecognitionPhraseList(); + list.addItem(new SpeechRecognitionPhrase("ASIC", 1.0)); + list.addItem(new SpeechRecognitionPhrase("FPGA", 1.0)); + var context = new SpeechRecognitionContext(list); + + // Create the first speech recognition with a mode that does not support + // recognition context. Note that this may vary between browsers in the future. + window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; + const recognition1 = new SpeechRecognition(); + recognition1.mode = "cloud-only"; + recognition1.lang = "en-US"; + recognition1.context = context; + + recognition1.onerror = function(event) { + assert_equals( + event.error, + "recognition-context-not-supported", + "First speech recognition should throw a recognition-context-not-supported error" + ); + }; + + recognition1.start(audioTrack); + + // Create the second speech recognition with a mode that supports recognition context. + const recognition2 = new SpeechRecognition(); + recognition2.mode = "ondevice-only"; + recognition2.lang = "en-US"; + recognition2.context = context; + + recognition2.onerror = function(event) { + // Currently WPT may not be able to detect that SODA is available and + // will throw a "language-not-supported" error here. + assert_unreached(); + }; + + const recognitionPromise = new Promise((resolve) => { + recognition2.onresult = (event) => { + const transcript = event.results[0][0].transcript; + resolve(transcript); + }; + }); + recognition2.start(audioTrack); + + const transcript = await recognitionPromise; + assert_equals( + transcript.toLowerCase(), + "the report confirmed that the asic's throughput and " + + "the fpga's latency were both below expectations", + "Second speech recognition should correctly recognize the phrases" + ); +}, "SpeechRecognition should recognize speech with the given recognition context."); +</script> +</html> diff --git a/tests/wpt/tests/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js b/tests/wpt/tests/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js index ce0d69cfaa5..82c9ec51f32 100644 --- a/tests/wpt/tests/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js +++ b/tests/wpt/tests/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js @@ -2,6 +2,7 @@ // META: script=/cookies/resources/cookie-helper.sub.js // META: script=/resources/testdriver.js // META: script=/resources/testdriver-vendor.js +// META: timeout=long 'use strict'; (async function() { diff --git a/tests/wpt/tests/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js b/tests/wpt/tests/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js index 8ffa9e178b1..e162e46dc9a 100644 --- a/tests/wpt/tests/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js +++ b/tests/wpt/tests/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js @@ -2,6 +2,7 @@ // META: script=/cookies/resources/cookie-helper.sub.js // META: script=/resources/testdriver.js // META: script=/resources/testdriver-vendor.js +// META: timeout=long 'use strict'; (async function() { diff --git a/tests/wpt/tests/storage-access-api/storage-access-headers.tentative.https.sub.window.js b/tests/wpt/tests/storage-access-api/storage-access-headers.tentative.https.sub.window.js index 10719750174..ebdef139a37 100644 --- a/tests/wpt/tests/storage-access-api/storage-access-headers.tentative.https.sub.window.js +++ b/tests/wpt/tests/storage-access-api/storage-access-headers.tentative.https.sub.window.js @@ -1,6 +1,7 @@ // META: script=helpers.js // META: script=/resources/testdriver.js // META: script=/resources/testdriver-vendor.js +// META: timeout=long "use strict"; // These are secure origins with different relations to the current document. diff --git a/tests/wpt/tests/subresource-integrity/subresource-integrity.html b/tests/wpt/tests/subresource-integrity/subresource-integrity.html index 355e1da1d75..5537b91abe7 100644 --- a/tests/wpt/tests/subresource-integrity/subresource-integrity.html +++ b/tests/wpt/tests/subresource-integrity/subresource-integrity.html @@ -53,6 +53,13 @@ ).execute(); new SRIScriptTest( + true, + "Same-origin with non-Base64 hash.", + `${same_origin_prefix}script.js?${token()}`, + "sha256-..." + ).execute(); + + new SRIScriptTest( false, "Same-origin with incorrect hash.", `${same_origin_prefix}script.js?${token()}`, @@ -246,6 +253,16 @@ new SRIStyleTest( style_tests, + true, + "Same-origin with non-Base64 integrity", + { + href: "style.css?4.5", + integrity: "sha256-..." + } + ); + + new SRIStyleTest( + style_tests, false, "Same-origin with incorrect hash.", { diff --git a/tests/wpt/tests/svg/extensibility/foreignObject/foreign-object-scale-scroll.html b/tests/wpt/tests/svg/extensibility/foreignObject/foreign-object-scale-scroll.html index 72ce40dc5c0..d79d85454b3 100644 --- a/tests/wpt/tests/svg/extensibility/foreignObject/foreign-object-scale-scroll.html +++ b/tests/wpt/tests/svg/extensibility/foreignObject/foreign-object-scale-scroll.html @@ -1,5 +1,6 @@ <!doctype html> <title>foreignObject with scale transform and overflow:scroll</title> +<meta name=fuzzy content="maxDifference=0-10;totalPixels=0-10"> <link rel="help" href="https://svgwg.org/svg2-draft/single-page.html#embedded-ForeignObjectElement"/> <link rel="match" href="foreign-object-scale-scroll-ref.html"> <svg width="400" height="400"> diff --git a/tests/wpt/tests/svg/geometry/svg-get-bounding-client-rect-in-non-rendered-elements.html b/tests/wpt/tests/svg/geometry/svg-get-bounding-client-rect-in-non-rendered-elements.html new file mode 100644 index 00000000000..41f3fb6bc90 --- /dev/null +++ b/tests/wpt/tests/svg/geometry/svg-get-bounding-client-rect-in-non-rendered-elements.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<title>Get Bounding Client Rect in Non-Rendered SVG elements</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="author" title="Divyansh Mangal" href="mailto:dmangal@microsoft.com"> +<svg width="100" height="20"> + <g display="none"> + <rect id="rect1" width="10" height="10" /> + </g> + <symbol id="symbol" width="10" height="10"> + <rect id="rect2" display="none" width="10" height="10" /> + </symbol> + <g> + <rect id="rect3" display="none" width="10" height="10" /> + </g> + <defs> + <rect id="rect4" width="10" height="10" /> + </defs> + <pattern> + <rect id="rect5" width="10" height="10" /> + </pattern> + <g> + <rect id="rect6" width="10" height="10" /> + </g> +</svg> +<script> + let rect1 = document.getElementById("rect1"), + rect2 = document.getElementById("rect2"), + rect3 = document.getElementById("rect3"), + rect4 = document.getElementById("rect4"); + rect5 = document.getElementById("rect5"), + rect6 = document.getElementById("rect6"), + symbol = document.getElementById("symbol"); + + test(function () { + assert_equals(rect1.getBoundingClientRect().width, 0, "rect1"); + assert_equals(rect2.getBoundingClientRect().width, 0, "rect2"); + assert_equals(rect3.getBoundingClientRect().width, 0, "rect3"); + assert_equals(rect4.getBoundingClientRect().width, 0, "rect4"); + assert_equals(rect5.getBoundingClientRect().width, 0, "rect5"); + assert_equals(rect6.getBoundingClientRect().width, 10, "rect6"); + assert_equals(symbol.getBoundingClientRect().width, 0, "symbol"); + + assert_equals(rect1.getBoundingClientRect().height, 0, "rect1"); + assert_equals(rect2.getBoundingClientRect().height, 0, "rect2"); + assert_equals(rect3.getBoundingClientRect().height, 0, "rect3"); + assert_equals(rect4.getBoundingClientRect().height, 0, "rect4"); + assert_equals(rect5.getBoundingClientRect().height, 0, "rect5"); + assert_equals(rect6.getBoundingClientRect().height, 10, "rect6"); + assert_equals(symbol.getBoundingClientRect().height, 0, "symbol"); + }, "Get Bounding Client Rect"); +</script> diff --git a/tests/wpt/tests/svg/painting/color-mix-currentcolor-fill-stroke-repaint.html b/tests/wpt/tests/svg/painting/color-mix-currentcolor-fill-stroke-repaint.html index 70e9013ac45..95c24f33f02 100644 --- a/tests/wpt/tests/svg/painting/color-mix-currentcolor-fill-stroke-repaint.html +++ b/tests/wpt/tests/svg/painting/color-mix-currentcolor-fill-stroke-repaint.html @@ -20,9 +20,11 @@ <script> addEventListener("load", () => { requestAnimationFrame(() => { - container.classList.add("green"); requestAnimationFrame(() => { - document.documentElement.classList.remove("reftest-wait"); + container.classList.add("green"); + requestAnimationFrame(() => { + document.documentElement.classList.remove("reftest-wait"); + }); }); }); }); diff --git a/tests/wpt/tests/svg/path/property/d-interpolation-within-document-referenced-via-background-image-ref.html b/tests/wpt/tests/svg/path/property/d-interpolation-within-document-referenced-via-background-image-ref.html new file mode 100644 index 00000000000..40021701ba7 --- /dev/null +++ b/tests/wpt/tests/svg/path/property/d-interpolation-within-document-referenced-via-background-image-ref.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<style> + +div { + display: inline-block; + width: 96px; + height: 96px; + background-repeat: no-repeat; + background-size: 100% 100%; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cstyle%3E path { fill: none; stroke-width: 2; stroke: black; } %3C/style%3E%3Cpath d='M2 2l20 0' /%3E%3C/svg%3E"); +} + +</style> +<div></div> diff --git a/tests/wpt/tests/svg/path/property/d-interpolation-within-document-referenced-via-background-image.html b/tests/wpt/tests/svg/path/property/d-interpolation-within-document-referenced-via-background-image.html new file mode 100644 index 00000000000..4704103f773 --- /dev/null +++ b/tests/wpt/tests/svg/path/property/d-interpolation-within-document-referenced-via-background-image.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Test the d property animates within a document loaded via "background-image: url()"</title> +<meta charset=utf-8> +<style> + +div { + display: inline-block; + width: 96px; + height: 96px; + background-repeat: no-repeat; + background-size: 100% 100%; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cstyle%3E path { fill: none; stroke-width: 2; stroke: black; animation: path 1s linear forwards paused; } @keyframes path { 0%25 { d: path('M2 2l20 0'); } 100%25 { stroke: green; d: path('M2 2l20 0'); } } %3C/style%3E%3Cpath d='M2 2l2 0' /%3E%3C/svg%3E"); +} + +</style> +<div></div> diff --git a/tests/wpt/tests/svg/struct/reftests/requiredextensions-empty-string.svg b/tests/wpt/tests/svg/struct/reftests/requiredextensions-empty-string.svg index 28f5da4a3e4..22efef20d31 100644 --- a/tests/wpt/tests/svg/struct/reftests/requiredextensions-empty-string.svg +++ b/tests/wpt/tests/svg/struct/reftests/requiredextensions-empty-string.svg @@ -1,6 +1,6 @@ <svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"> <title>requiredExtensions: present but empty attribute evaluates to false</title> <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#RequiredExtensionsAttribute"/> - <h:link rel="match" href="../scripted/blank.svg"/> + <h:link rel="match" href="../scripted/support/blank.svg"/> <rect width="100" height="100" fill="red" requiredExtensions=""/> </svg> diff --git a/tests/wpt/tests/svg/struct/scripted/autofocus-attribute.svg b/tests/wpt/tests/svg/struct/scripted/autofocus-attribute.svg index edf200c4c7b..13d779d758b 100644 --- a/tests/wpt/tests/svg/struct/scripted/autofocus-attribute.svg +++ b/tests/wpt/tests/svg/struct/scripted/autofocus-attribute.svg @@ -12,7 +12,7 @@ const SVG_NS = 'http://www.w3.org/2000/svg'; promise_test(async t => { - let w = window.open('blank.svg'); + let w = window.open('support/blank.svg'); await waitForLoad(w); t.add_cleanup(() => { w.close(); }); const svgA = w.document.createElementNS(SVG_NS, 'a'); @@ -24,7 +24,7 @@ promise_test(async t => { }, '<a> should support autofocus'); promise_test(async t => { - let w = window.open('blank.svg'); + let w = window.open('support/blank.svg'); await waitForLoad(w); t.add_cleanup(() => { w.close(); }); const path = w.document.createElementNS(SVG_NS, 'path'); @@ -37,7 +37,7 @@ promise_test(async t => { }, 'Renderable element with tabindex should support autofocus'); promise_test(async t => { - let w = window.open('blank.svg'); + let w = window.open('support/blank.svg'); await waitForLoad(w); t.add_cleanup(() => { w.close(); }); let element = w.document.createElementNS(SVG_NS, 'metadata'); diff --git a/tests/wpt/tests/svg/struct/scripted/blank.svg b/tests/wpt/tests/svg/struct/scripted/support/blank.svg index 9e560bdc5fe..9e560bdc5fe 100644 --- a/tests/wpt/tests/svg/struct/scripted/blank.svg +++ b/tests/wpt/tests/svg/struct/scripted/support/blank.svg diff --git a/tests/wpt/tests/tools/ci/tc/tasks/test.yml b/tests/wpt/tests/tools/ci/tc/tasks/test.yml index 947ecff2592..54cf522ebd8 100644 --- a/tests/wpt/tests/tools/ci/tc/tasks/test.yml +++ b/tests/wpt/tests/tools/ci/tc/tasks/test.yml @@ -127,14 +127,14 @@ components: - python3.8-dev - python3.8-venv - tox-python3_12: + tox-python3_13: env: - TOXENV: py312 + TOXENV: py313 PY_COLORS: "0" install: - - python3.12 - - python3.12-dev - - python3.12-venv + - python3.13 + - python3.13-dev + - python3.13-venv tests-affected: options: browser: @@ -471,13 +471,13 @@ tasks: run-job: - tools_unittest - - tools/ unittests (Python 3.12): + - tools/ unittests (Python 3.13): description: >- - Unit tests for tools running under Python 3.12, excluding wptrunner + Unit tests for tools running under Python 3.13, excluding wptrunner use: - wpt-base - trigger-pr - - tox-python3_12 + - tox-python3_13 command: ./tools/ci/ci_tools_unittest.sh env: HYPOTHESIS_PROFILE: ci @@ -507,13 +507,13 @@ tasks: run-job: - wpt_integration - - tools/ integration tests (Python 3.12): + - tools/ integration tests (Python 3.13): description: >- - Integration tests for tools running under Python 3.12 + Integration tests for tools running under Python 3.13 use: - wpt-base - trigger-pr - - tox-python3_12 + - tox-python3_13 command: ./tools/ci/ci_tools_integration_test.sh install: - libnss3-tools @@ -548,13 +548,13 @@ tasks: run-job: - resources_unittest - - resources/ tests (Python 3.12): + - resources/ tests (Python 3.13): description: >- - Tests for testharness.js and other files in resources/ under Python 3.12 + Tests for testharness.js and other files in resources/ under Python 3.13 use: - wpt-base - trigger-pr - - tox-python3_12 + - tox-python3_13 command: ./tools/ci/ci_resources_unittest.sh install: - libnss3-tools diff --git a/tests/wpt/tests/tools/ci/tc/tests/test_valid.py b/tests/wpt/tests/tools/ci/tc/tests/test_valid.py index 3b5f7c3e89c..1c205a5fc7f 100644 --- a/tests/wpt/tests/tools/ci/tc/tests/test_valid.py +++ b/tests/wpt/tests/tools/ci/tc/tests/test_valid.py @@ -177,11 +177,11 @@ def test_verify_payload(): ("pr_event.json", True, {".taskcluster.yml", ".travis.yml", "tools/ci/start.sh"}, ['lint', 'tools/ unittests (Python 3.8)', - 'tools/ unittests (Python 3.12)', + 'tools/ unittests (Python 3.13)', 'tools/ integration tests (Python 3.8)', - 'tools/ integration tests (Python 3.12)', + 'tools/ integration tests (Python 3.13)', 'resources/ tests (Python 3.8)', - 'resources/ tests (Python 3.12)', + 'resources/ tests (Python 3.13)', 'download-firefox-nightly', 'infrastructure/ tests', 'sink-task']), @@ -199,7 +199,7 @@ def test_verify_payload(): ("pr_event_tests_affected.json", True, {"resources/testharness.js"}, ['lint', 'resources/ tests (Python 3.8)', - 'resources/ tests (Python 3.12)', + 'resources/ tests (Python 3.13)', 'download-firefox-nightly', 'infrastructure/ tests', 'sink-task']), diff --git a/tests/wpt/tests/tools/docker/Dockerfile b/tests/wpt/tests/tools/docker/Dockerfile index 89365d45e1c..a936ad9167f 100644 --- a/tests/wpt/tests/tools/docker/Dockerfile +++ b/tests/wpt/tests/tools/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 # No interactive frontend during docker build ENV DEBIAN_FRONTEND=noninteractive \ diff --git a/tests/wpt/tests/tools/flake8.ini b/tests/wpt/tests/tools/flake8.ini index 9b745acccda..c3e55b51d9e 100644 --- a/tests/wpt/tests/tools/flake8.ini +++ b/tests/wpt/tests/tools/flake8.ini @@ -23,4 +23,5 @@ exclude = third_party, wptserve/docs/conf.py, wptserve/tests/functional/docroot/invalid.py + wptserve/wptserve/cgi/ max-line-length = 141 diff --git a/tests/wpt/tests/tools/manifest/requirements.txt b/tests/wpt/tests/tools/manifest/requirements.txt index 70ad0df0e95..ca872b12c41 100644 --- a/tests/wpt/tests/tools/manifest/requirements.txt +++ b/tests/wpt/tests/tools/manifest/requirements.txt @@ -1 +1 @@ -zstandard==0.22.0 +zstandard==0.23.0 diff --git a/tests/wpt/tests/tools/mypy.ini b/tests/wpt/tests/tools/mypy.ini index cc22a770b04..e05220f4bbe 100644 --- a/tests/wpt/tests/tools/mypy.ini +++ b/tests/wpt/tests/tools/mypy.ini @@ -6,7 +6,7 @@ # - All setup.py files (avoiding duplicate module named "setup") # - tools/wptserve/docs/conf.py (generated code) # - tools/wptserve/tests/ (deliberately invalid syntax) -exclude = (^tools/third_party/|/setup\.py$|^tools/wptserve/docs/conf.py|^tools/wptserve/tests/|^tools/third_party_modified/mozlog/) +exclude = (^tools/third_party/|/setup\.py$|^tools/wptserve/docs/conf.py|^tools/wptserve/tests/|^tools/third_party_modified/mozlog/|^tools/wptserve/wptserve/cgi/test_cgi\.py$) mypy_path = tools/wptrunner:tools/wptserve:tools/webdriver:tools/webtransport #check_untyped_defs = True disallow_any_generics = True @@ -36,6 +36,9 @@ ignore_missing_imports = True [mypy-Quartz.*] ignore_missing_imports = True +[mypy-cgi.*] +ignore_missing_imports = True + [mypy-github.*] ignore_missing_imports = True diff --git a/tests/wpt/tests/tools/requirements_mypy.txt b/tests/wpt/tests/tools/requirements_mypy.txt index a59476cd2e3..06fb778ea66 100644 --- a/tests/wpt/tests/tools/requirements_mypy.txt +++ b/tests/wpt/tests/tools/requirements_mypy.txt @@ -2,7 +2,6 @@ mypy==1.14.0 mypy-extensions==1.0.0 toml==0.10.2 tomli==2.0.1 -typed-ast==1.5.5 types-atomicwrites==1.4.5.1 types-python-dateutil==2.9.0.20240906 types-PyYAML==6.0.12.12 diff --git a/tests/wpt/tests/tools/serve/serve.py b/tests/wpt/tests/tools/serve/serve.py index 6d385b34ac6..d86e66a3743 100644 --- a/tests/wpt/tests/tools/serve/serve.py +++ b/tests/wpt/tests/tools/serve/serve.py @@ -1418,10 +1418,7 @@ def run(config_cls=ConfigBuilder, route_builder=None, mp_context=None, log_handl logger = get_logger("INFO", log_handlers) if mp_context is None: - if hasattr(multiprocessing, "get_context"): - mp_context = multiprocessing.get_context() - else: - mp_context = MpContext() + mp_context = multiprocessing.get_context("spawn") with build_config(logger, os.path.join(repo_root, "config.json"), diff --git a/tests/wpt/tests/tools/tox.ini b/tests/wpt/tests/tools/tox.ini index 61442932f35..8fd54b68939 100644 --- a/tests/wpt/tests/tools/tox.ini +++ b/tests/wpt/tests/tools/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py38,py39,py310,py311,py312,{py38,py39,py310,py311,py312}-{flake8,mypy} +envlist = py38,py39,py310,py311,py312,py313,{py38,py39,py310,py311,py312,py313}-{flake8,mypy} skipsdist=True skip_missing_interpreters=False diff --git a/tests/wpt/tests/tools/wave/tox.ini b/tests/wpt/tests/tools/wave/tox.ini index 88c76096f45..8bec61e2b80 100644 --- a/tests/wpt/tests/tools/wave/tox.ini +++ b/tests/wpt/tests/tools/wave/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py38,py39,py310,py311,py312 +envlist = py38,py39,py310,py311,py312,py312 skipsdist=True skip_missing_interpreters = False diff --git a/tests/wpt/tests/tools/wpt/tox.ini b/tests/wpt/tests/tools/wpt/tox.ini index b6e3dab2317..7c8ab17890f 100644 --- a/tests/wpt/tests/tools/wpt/tox.ini +++ b/tests/wpt/tests/tools/wpt/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py38,py39,py310,py311,py312 +envlist = py38,py39,py310,py311,py312,py312 skipsdist=True skip_missing_interpreters = False diff --git a/tests/wpt/tests/tools/wptrunner/requirements.txt b/tests/wpt/tests/tools/wptrunner/requirements.txt index 565055c6e3d..4074b20618a 100644 --- a/tests/wpt/tests/tools/wptrunner/requirements.txt +++ b/tests/wpt/tests/tools/wptrunner/requirements.txt @@ -4,7 +4,8 @@ mozinfo==1.2.3 # https://bugzilla.mozilla.org/show_bug.cgi?id=1621226 mozlog==8.0.0 mozprocess==1.3.1 packaging==24.0 -pillow==10.3.0 +pillow==10.4.0; python_version < '3.9' +pillow==11.1.0; python_version >= '3.9' requests==2.32.3 six==1.16.0 urllib3==2.2.2 diff --git a/tests/wpt/tests/tools/wptrunner/tox.ini b/tests/wpt/tests/tools/wptrunner/tox.ini index c380be12527..44fe708c86e 100644 --- a/tests/wpt/tests/tools/wptrunner/tox.ini +++ b/tests/wpt/tests/tools/wptrunner/tox.ini @@ -2,7 +2,7 @@ xfail_strict=true [tox] -envlist = py312-{base,chrome,firefox,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py38,py39,py310,py311}-base +envlist = py313-{base,chrome,firefox,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py38,py39,py310,py311,py312}-base skip_missing_interpreters = False [testenv] diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/chrome.py b/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/chrome.py index 7a57ef063a1..76bc652075e 100644 --- a/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/chrome.py +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/chrome.py @@ -44,18 +44,6 @@ __wptrunner__ = {"product": "chrome", from ..wpttest import Test -def debug_args(debug_info): - if debug_info.interactive: - # Keep in sync with: - # https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/tools/debug_renderer - return [ - "--no-sandbox", - "--disable-hang-monitor", - "--wait-for-debugger-on-navigation", - ] - return [] - - def check_args(**kwargs): require_arg(kwargs, "webdriver_binary") @@ -92,6 +80,11 @@ def executor_kwargs(logger, test_type, test_environment, run_info_data, subsuite chrome_options = capabilities["goog:chromeOptions"] if kwargs["binary"] is not None: chrome_options["binary"] = kwargs["binary"] + if kwargs["debug_test"]: + # Give debuggers like `rr` time to terminate gracefully and dump + # recordings or traces. Note that older `chromedriver` versions will + # fail to create a session if they don't recognize this capability. + chrome_options["quitGracefully"] = True # Here we set a few Chrome flags that are always passed. # ChromeDriver's "acceptInsecureCerts" capability only controls the current @@ -181,14 +174,13 @@ def executor_kwargs(logger, test_type, test_environment, run_info_data, subsuite if kwargs["enable_experimental"]: chrome_options["args"].extend(["--enable-experimental-web-platform-features"]) - # Copy over any other flags that were passed in via `--binary-arg` - for arg in kwargs.get("binary_args", []): + # Copy over any other flags that were passed in via `--binary-arg` or the + # subsuite config. + binary_args = kwargs.get("binary_args", []) + subsuite.config.get("binary_args", []) + for arg in binary_args: if arg not in chrome_options["args"]: chrome_options["args"].append(arg) - for arg in subsuite.config.get("binary_args", []): - if arg not in chrome_options["args"]: - chrome_options["args"].append(arg) # Pass the --headless=new flag to Chrome if WPT's own --headless flag was # set. '--headless' should always mean the new headless mode, as the old diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/headless_shell.py b/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/headless_shell.py index c20d4011eeb..b6f7a40f8a9 100644 --- a/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/headless_shell.py +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/headless_shell.py @@ -2,7 +2,7 @@ from .base import require_arg from .base import get_timeout_multiplier # noqa: F401 -from .chrome import ChromeBrowser, debug_args # noqa: F401 +from .chrome import ChromeBrowser # noqa: F401 from .chrome import executor_kwargs as chrome_executor_kwargs from ..executors.base import WdspecExecutor # noqa: F401 from ..executors.executorchrome import ( # noqa: F401 diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/wptlogging.py b/tests/wpt/tests/tools/wptrunner/wptrunner/wptlogging.py index 06b34dabdb6..50b1ca93298 100644 --- a/tests/wpt/tests/tools/wptrunner/wptrunner/wptlogging.py +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/wptlogging.py @@ -2,6 +2,8 @@ import logging from threading import Thread +from types import TracebackType +from typing import Optional, Type from mozlog import commandline, stdadapter, set_default_logger from mozlog.structuredlog import StructuredLogger, log_levels @@ -77,7 +79,7 @@ class QueueHandler(logging.Handler): def createLock(self): # The queue provides its own locking - self.lock = None + self.lock = NullRLock() def emit(self, record): msg = self.format(record) @@ -90,6 +92,25 @@ class QueueHandler(logging.Handler): self.queue.put(data) + +class NullRLock: + """Implementation of the threading.RLock API that doesn't actually acquire a lock, + for use in cases where there is another mechanism to provide the required + invariants.""" + + def acquire(self, blocking: bool = True, timeout: float = -1) -> bool: + return True + + def release(self) -> None: + return None + + def __enter__(self) -> bool: + return True + + def __exit__(self, t: Optional[Type[BaseException]], v: Optional[BaseException], tb: Optional[TracebackType]) -> None: + return None + + class LogQueueThread(Thread): """Thread for handling log messages from a queue""" def __init__(self, queue, logger): diff --git a/tests/wpt/tests/tools/wptserve/wptserve/cgi/LICENSE b/tests/wpt/tests/tools/wptserve/wptserve/cgi/LICENSE new file mode 100644 index 00000000000..f26bcf4d2de --- /dev/null +++ b/tests/wpt/tests/tools/wptserve/wptserve/cgi/LICENSE @@ -0,0 +1,279 @@ +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations, which became +Zope Corporation. In 2001, the Python Software Foundation (PSF, see +https://www.python.org/psf/) was formed, a non-profit organization +created specifically to own Python-related Intellectual Property. +Zope Corporation was a sponsoring member of the PSF. + +All Python releases are Open Source (see https://opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +Python software and documentation are licensed under the +Python Software Foundation License Version 2. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Version 2 +and the Zero-Clause BSD license. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. + + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION +---------------------------------------------------------------------- + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/tests/wpt/tests/tools/wptserve/wptserve/cgi/__init__.py b/tests/wpt/tests/tools/wptserve/wptserve/cgi/__init__.py new file mode 100644 index 00000000000..940f1727714 --- /dev/null +++ b/tests/wpt/tests/tools/wptserve/wptserve/cgi/__init__.py @@ -0,0 +1 @@ +from .cgi import * diff --git a/tests/wpt/tests/tools/wptserve/wptserve/cgi/cgi.py b/tests/wpt/tests/tools/wptserve/wptserve/cgi/cgi.py new file mode 100755 index 00000000000..12b6b4ce51c --- /dev/null +++ b/tests/wpt/tests/tools/wptserve/wptserve/cgi/cgi.py @@ -0,0 +1,1014 @@ +#! /usr/local/bin/python +# mypy: ignore-errors + +# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is +# intentionally NOT "/usr/bin/env python". On many systems +# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI +# scripts, and /usr/local/bin is the default directory where Python is +# installed, so /usr/bin/env would be unable to find python. Granted, +# binary installations by Linux vendors often install Python in +# /usr/bin. So let those vendors patch cgi.py to match their choice +# of installation. + +"""Support module for CGI (Common Gateway Interface) scripts. + +This module defines a number of utilities for use by CGI scripts +written in Python. + +The global variable maxlen can be set to an integer indicating the maximum size +of a POST request. POST requests larger than this size will result in a +ValueError being raised during parsing. The default value of this variable is 0, +meaning the request size is unlimited. +""" + +# History +# ------- +# +# Michael McLay started this module. Steve Majewski changed the +# interface to SvFormContentDict and FormContentDict. The multipart +# parsing was inspired by code submitted by Andreas Paepcke. Guido van +# Rossum rewrote, reformatted and documented the module and is currently +# responsible for its maintenance. +# + +__version__ = "2.6" + + +# Imports +# ======= + +from io import StringIO, BytesIO, TextIOWrapper +from collections.abc import Mapping +import sys +import os +import urllib.parse +from email.parser import FeedParser +from email.message import Message +import html +import locale +import tempfile +import warnings + +__all__ = ["MiniFieldStorage", "FieldStorage", "parse", "parse_multipart", + "parse_header", "test", "print_exception", "print_environ", + "print_form", "print_directory", "print_arguments", + "print_environ_usage"] + + +# Logging support +# =============== + +logfile = "" # Filename to log to, if not empty +logfp = None # File object to log to, if not None + +def initlog(*allargs): + """Write a log message, if there is a log file. + + Even though this function is called initlog(), you should always + use log(); log is a variable that is set either to initlog + (initially), to dolog (once the log file has been opened), or to + nolog (when logging is disabled). + + The first argument is a format string; the remaining arguments (if + any) are arguments to the % operator, so e.g. + log("%s: %s", "a", "b") + will write "a: b" to the log file, followed by a newline. + + If the global logfp is not None, it should be a file object to + which log data is written. + + If the global logfp is None, the global logfile may be a string + giving a filename to open, in append mode. This file should be + world writable!!! If the file can't be opened, logging is + silently disabled (since there is no safe place where we could + send an error message). + + """ + global log, logfile, logfp + warnings.warn("cgi.log() is deprecated as of 3.10. Use logging instead", + DeprecationWarning, stacklevel=2) + if logfile and not logfp: + try: + kwargs = {} + if sys.version_info > (3, 9): + kwargs["encoding"] = "locale" + logfp = open(logfile, "a", **kwargs) + except OSError: + pass + if not logfp: + log = nolog + else: + log = dolog + log(*allargs) + +def dolog(fmt, *args): + """Write a log message to the log file. See initlog() for docs.""" + logfp.write(fmt%args + "\n") + +def nolog(*allargs): + """Dummy function, assigned to log when logging is disabled.""" + pass + +def closelog(): + """Close the log file.""" + global log, logfile, logfp + logfile = '' + if logfp: + logfp.close() + logfp = None + log = initlog + +log = initlog # The current logging function + + +# Parsing functions +# ================= + +# Maximum input we will accept when REQUEST_METHOD is POST +# 0 ==> unlimited input +maxlen = 0 + +def parse(fp=None, environ=os.environ, keep_blank_values=0, + strict_parsing=0, separator='&'): + """Parse a query in the environment or from a file (default stdin) + + Arguments, all optional: + + fp : file pointer; default: sys.stdin.buffer + + environ : environment dictionary; default: os.environ + + keep_blank_values: flag indicating whether blank values in + percent-encoded forms should be treated as blank strings. + A true value indicates that blanks should be retained as + blank strings. The default false value indicates that + blank values are to be ignored and treated as if they were + not included. + + strict_parsing: flag indicating what to do with parsing errors. + If false (the default), errors are silently ignored. + If true, errors raise a ValueError exception. + + separator: str. The symbol to use for separating the query arguments. + Defaults to &. + """ + if fp is None: + fp = sys.stdin + + # field keys and values (except for files) are returned as strings + # an encoding is required to decode the bytes read from self.fp + if hasattr(fp,'encoding'): + encoding = fp.encoding + else: + encoding = 'latin-1' + + # fp.read() must return bytes + if isinstance(fp, TextIOWrapper): + fp = fp.buffer + + if not 'REQUEST_METHOD' in environ: + environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone + if environ['REQUEST_METHOD'] == 'POST': + ctype, pdict = parse_header(environ['CONTENT_TYPE']) + if ctype == 'multipart/form-data': + return parse_multipart(fp, pdict, separator=separator) + elif ctype == 'application/x-www-form-urlencoded': + clength = int(environ['CONTENT_LENGTH']) + if maxlen and clength > maxlen: + raise ValueError('Maximum content length exceeded') + qs = fp.read(clength).decode(encoding) + else: + qs = '' # Unknown content-type + if 'QUERY_STRING' in environ: + if qs: qs = qs + '&' + qs = qs + environ['QUERY_STRING'] + elif sys.argv[1:]: + if qs: qs = qs + '&' + qs = qs + sys.argv[1] + environ['QUERY_STRING'] = qs # XXX Shouldn't, really + elif 'QUERY_STRING' in environ: + qs = environ['QUERY_STRING'] + else: + if sys.argv[1:]: + qs = sys.argv[1] + else: + qs = "" + environ['QUERY_STRING'] = qs # XXX Shouldn't, really + return urllib.parse.parse_qs(qs, keep_blank_values, strict_parsing, + encoding=encoding, separator=separator) + + +def parse_multipart(fp, pdict, encoding="utf-8", errors="replace", separator='&'): + """Parse multipart input. + + Arguments: + fp : input file + pdict: dictionary containing other parameters of content-type header + encoding, errors: request encoding and error handler, passed to + FieldStorage + + Returns a dictionary just like parse_qs(): keys are the field names, each + value is a list of values for that field. For non-file fields, the value + is a list of strings. + """ + # RFC 2046, Section 5.1 : The "multipart" boundary delimiters are always + # represented as 7bit US-ASCII. + boundary = pdict['boundary'].decode('ascii') + ctype = "multipart/form-data; boundary={}".format(boundary) + headers = Message() + headers.set_type(ctype) + try: + headers['Content-Length'] = pdict['CONTENT-LENGTH'] + except KeyError: + pass + fs = FieldStorage(fp, headers=headers, encoding=encoding, errors=errors, + environ={'REQUEST_METHOD': 'POST'}, separator=separator) + return {k: fs.getlist(k) for k in fs} + +def _parseparam(s): + while s[:1] == ';': + s = s[1:] + end = s.find(';') + while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2: + end = s.find(';', end + 1) + if end < 0: + end = len(s) + f = s[:end] + yield f.strip() + s = s[end:] + +def parse_header(line): + """Parse a Content-type like header. + + Return the main content-type and a dictionary of options. + + """ + parts = _parseparam(';' + line) + key = parts.__next__() + pdict = {} + for p in parts: + i = p.find('=') + if i >= 0: + name = p[:i].strip().lower() + value = p[i+1:].strip() + if len(value) >= 2 and value[0] == value[-1] == '"': + value = value[1:-1] + value = value.replace('\\\\', '\\').replace('\\"', '"') + pdict[name] = value + return key, pdict + + +# Classes for field storage +# ========================= + +class MiniFieldStorage: + + """Like FieldStorage, for use when no file uploads are possible.""" + + # Dummy attributes + filename = None + list = None + type = None + file = None + type_options = {} + disposition = None + disposition_options = {} + headers = {} + + def __init__(self, name, value): + """Constructor from field name and value.""" + self.name = name + self.value = value + # self.file = StringIO(value) + + def __repr__(self): + """Return printable representation.""" + return "MiniFieldStorage(%r, %r)" % (self.name, self.value) + + +class FieldStorage: + + """Store a sequence of fields, reading multipart/form-data. + + This class provides naming, typing, files stored on disk, and + more. At the top level, it is accessible like a dictionary, whose + keys are the field names. (Note: None can occur as a field name.) + The items are either a Python list (if there's multiple values) or + another FieldStorage or MiniFieldStorage object. If it's a single + object, it has the following attributes: + + name: the field name, if specified; otherwise None + + filename: the filename, if specified; otherwise None; this is the + client side filename, *not* the file name on which it is + stored (that's a temporary file you don't deal with) + + value: the value as a *string*; for file uploads, this + transparently reads the file every time you request the value + and returns *bytes* + + file: the file(-like) object from which you can read the data *as + bytes* ; None if the data is stored a simple string + + type: the content-type, or None if not specified + + type_options: dictionary of options specified on the content-type + line + + disposition: content-disposition, or None if not specified + + disposition_options: dictionary of corresponding options + + headers: a dictionary(-like) object (sometimes email.message.Message or a + subclass thereof) containing *all* headers + + The class is subclassable, mostly for the purpose of overriding + the make_file() method, which is called internally to come up with + a file open for reading and writing. This makes it possible to + override the default choice of storing all files in a temporary + directory and unlinking them as soon as they have been opened. + + """ + def __init__(self, fp=None, headers=None, outerboundary=b'', + environ=os.environ, keep_blank_values=0, strict_parsing=0, + limit=None, encoding='utf-8', errors='replace', + max_num_fields=None, separator='&'): + """Constructor. Read multipart/* until last part. + + Arguments, all optional: + + fp : file pointer; default: sys.stdin.buffer + (not used when the request method is GET) + Can be : + 1. a TextIOWrapper object + 2. an object whose read() and readline() methods return bytes + + headers : header dictionary-like object; default: + taken from environ as per CGI spec + + outerboundary : terminating multipart boundary + (for internal use only) + + environ : environment dictionary; default: os.environ + + keep_blank_values: flag indicating whether blank values in + percent-encoded forms should be treated as blank strings. + A true value indicates that blanks should be retained as + blank strings. The default false value indicates that + blank values are to be ignored and treated as if they were + not included. + + strict_parsing: flag indicating what to do with parsing errors. + If false (the default), errors are silently ignored. + If true, errors raise a ValueError exception. + + limit : used internally to read parts of multipart/form-data forms, + to exit from the reading loop when reached. It is the difference + between the form content-length and the number of bytes already + read + + encoding, errors : the encoding and error handler used to decode the + binary stream to strings. Must be the same as the charset defined + for the page sending the form (content-type : meta http-equiv or + header) + + max_num_fields: int. If set, then __init__ throws a ValueError + if there are more than n fields read by parse_qsl(). + + """ + method = 'GET' + self.keep_blank_values = keep_blank_values + self.strict_parsing = strict_parsing + self.max_num_fields = max_num_fields + self.separator = separator + if 'REQUEST_METHOD' in environ: + method = environ['REQUEST_METHOD'].upper() + self.qs_on_post = None + if method == 'GET' or method == 'HEAD': + if 'QUERY_STRING' in environ: + qs = environ['QUERY_STRING'] + elif sys.argv[1:]: + qs = sys.argv[1] + else: + qs = "" + qs = qs.encode(locale.getpreferredencoding(), 'surrogateescape') + fp = BytesIO(qs) + if headers is None: + headers = {'content-type': + "application/x-www-form-urlencoded"} + if headers is None: + headers = {} + if method == 'POST': + # Set default content-type for POST to what's traditional + headers['content-type'] = "application/x-www-form-urlencoded" + if 'CONTENT_TYPE' in environ: + headers['content-type'] = environ['CONTENT_TYPE'] + if 'QUERY_STRING' in environ: + self.qs_on_post = environ['QUERY_STRING'] + if 'CONTENT_LENGTH' in environ: + headers['content-length'] = environ['CONTENT_LENGTH'] + else: + if not (isinstance(headers, (Mapping, Message))): + raise TypeError("headers must be mapping or an instance of " + "email.message.Message") + self.headers = headers + if fp is None: + self.fp = sys.stdin.buffer + # self.fp.read() must return bytes + elif isinstance(fp, TextIOWrapper): + self.fp = fp.buffer + else: + if not (hasattr(fp, 'read') and hasattr(fp, 'readline')): + raise TypeError("fp must be file pointer") + self.fp = fp + + self.encoding = encoding + self.errors = errors + + if not isinstance(outerboundary, bytes): + raise TypeError('outerboundary must be bytes, not %s' + % type(outerboundary).__name__) + self.outerboundary = outerboundary + + self.bytes_read = 0 + self.limit = limit + + # Process content-disposition header + cdisp, pdict = "", {} + if 'content-disposition' in self.headers: + cdisp, pdict = parse_header(self.headers['content-disposition']) + self.disposition = cdisp + self.disposition_options = pdict + self.name = None + if 'name' in pdict: + self.name = pdict['name'] + self.filename = None + if 'filename' in pdict: + self.filename = pdict['filename'] + self._binary_file = self.filename is not None + + # Process content-type header + # + # Honor any existing content-type header. But if there is no + # content-type header, use some sensible defaults. Assume + # outerboundary is "" at the outer level, but something non-false + # inside a multi-part. The default for an inner part is text/plain, + # but for an outer part it should be urlencoded. This should catch + # bogus clients which erroneously forget to include a content-type + # header. + # + # See below for what we do if there does exist a content-type header, + # but it happens to be something we don't understand. + if 'content-type' in self.headers: + ctype, pdict = parse_header(self.headers['content-type']) + elif self.outerboundary or method != 'POST': + ctype, pdict = "text/plain", {} + else: + ctype, pdict = 'application/x-www-form-urlencoded', {} + self.type = ctype + self.type_options = pdict + if 'boundary' in pdict: + self.innerboundary = pdict['boundary'].encode(self.encoding, + self.errors) + else: + self.innerboundary = b"" + + clen = -1 + if 'content-length' in self.headers: + try: + clen = int(self.headers['content-length']) + except ValueError: + pass + if maxlen and clen > maxlen: + raise ValueError('Maximum content length exceeded') + self.length = clen + if self.limit is None and clen >= 0: + self.limit = clen + + self.list = self.file = None + self.done = 0 + if ctype == 'application/x-www-form-urlencoded': + self.read_urlencoded() + elif ctype[:10] == 'multipart/': + self.read_multi(environ, keep_blank_values, strict_parsing) + else: + self.read_single() + + def __del__(self): + try: + self.file.close() + except AttributeError: + pass + + def __enter__(self): + return self + + def __exit__(self, *args): + self.file.close() + + def __repr__(self): + """Return a printable representation.""" + return "FieldStorage(%r, %r, %r)" % ( + self.name, self.filename, self.value) + + def __iter__(self): + return iter(self.keys()) + + def __getattr__(self, name): + if name != 'value': + raise AttributeError(name) + if self.file: + self.file.seek(0) + value = self.file.read() + self.file.seek(0) + elif self.list is not None: + value = self.list + else: + value = None + return value + + def __getitem__(self, key): + """Dictionary style indexing.""" + if self.list is None: + raise TypeError("not indexable") + found = [] + for item in self.list: + if item.name == key: found.append(item) + if not found: + raise KeyError(key) + if len(found) == 1: + return found[0] + else: + return found + + def getvalue(self, key, default=None): + """Dictionary style get() method, including 'value' lookup.""" + if key in self: + value = self[key] + if isinstance(value, list): + return [x.value for x in value] + else: + return value.value + else: + return default + + def getfirst(self, key, default=None): + """ Return the first value received.""" + if key in self: + value = self[key] + if isinstance(value, list): + return value[0].value + else: + return value.value + else: + return default + + def getlist(self, key): + """ Return list of received values.""" + if key in self: + value = self[key] + if isinstance(value, list): + return [x.value for x in value] + else: + return [value.value] + else: + return [] + + def keys(self): + """Dictionary style keys() method.""" + if self.list is None: + raise TypeError("not indexable") + return list(set(item.name for item in self.list)) + + def __contains__(self, key): + """Dictionary style __contains__ method.""" + if self.list is None: + raise TypeError("not indexable") + return any(item.name == key for item in self.list) + + def __len__(self): + """Dictionary style len(x) support.""" + return len(self.keys()) + + def __bool__(self): + if self.list is None: + raise TypeError("Cannot be converted to bool.") + return bool(self.list) + + def read_urlencoded(self): + """Internal: read data in query string format.""" + qs = self.fp.read(self.length) + if not isinstance(qs, bytes): + raise ValueError("%s should return bytes, got %s" \ + % (self.fp, type(qs).__name__)) + qs = qs.decode(self.encoding, self.errors) + if self.qs_on_post: + qs += '&' + self.qs_on_post + query = urllib.parse.parse_qsl( + qs, self.keep_blank_values, self.strict_parsing, + encoding=self.encoding, errors=self.errors, + max_num_fields=self.max_num_fields, separator=self.separator) + self.list = [MiniFieldStorage(key, value) for key, value in query] + self.skip_lines() + + FieldStorageClass = None + + def read_multi(self, environ, keep_blank_values, strict_parsing): + """Internal: read a part that is itself multipart.""" + ib = self.innerboundary + if not valid_boundary(ib): + raise ValueError('Invalid boundary in multipart form: %r' % (ib,)) + self.list = [] + if self.qs_on_post: + query = urllib.parse.parse_qsl( + self.qs_on_post, self.keep_blank_values, self.strict_parsing, + encoding=self.encoding, errors=self.errors, + max_num_fields=self.max_num_fields, separator=self.separator) + self.list.extend(MiniFieldStorage(key, value) for key, value in query) + + klass = self.FieldStorageClass or self.__class__ + first_line = self.fp.readline() # bytes + if not isinstance(first_line, bytes): + raise ValueError("%s should return bytes, got %s" \ + % (self.fp, type(first_line).__name__)) + self.bytes_read += len(first_line) + + # Ensure that we consume the file until we've hit our inner boundary + while (first_line.strip() != (b"--" + self.innerboundary) and + first_line): + first_line = self.fp.readline() + self.bytes_read += len(first_line) + + # Propagate max_num_fields into the sub class appropriately + max_num_fields = self.max_num_fields + if max_num_fields is not None: + max_num_fields -= len(self.list) + + while True: + parser = FeedParser() + hdr_text = b"" + while True: + data = self.fp.readline() + hdr_text += data + if not data.strip(): + break + if not hdr_text: + break + # parser takes strings, not bytes + self.bytes_read += len(hdr_text) + parser.feed(hdr_text.decode(self.encoding, self.errors)) + headers = parser.close() + + # Some clients add Content-Length for part headers, ignore them + if 'content-length' in headers: + del headers['content-length'] + + limit = None if self.limit is None \ + else self.limit - self.bytes_read + part = klass(self.fp, headers, ib, environ, keep_blank_values, + strict_parsing, limit, + self.encoding, self.errors, max_num_fields, self.separator) + + if max_num_fields is not None: + max_num_fields -= 1 + if part.list: + max_num_fields -= len(part.list) + if max_num_fields < 0: + raise ValueError('Max number of fields exceeded') + + self.bytes_read += part.bytes_read + self.list.append(part) + if part.done or self.bytes_read >= self.length > 0: + break + self.skip_lines() + + def read_single(self): + """Internal: read an atomic part.""" + if self.length >= 0: + self.read_binary() + self.skip_lines() + else: + self.read_lines() + self.file.seek(0) + + bufsize = 8*1024 # I/O buffering size for copy to file + + def read_binary(self): + """Internal: read binary data.""" + self.file = self.make_file() + todo = self.length + if todo >= 0: + while todo > 0: + data = self.fp.read(min(todo, self.bufsize)) # bytes + if not isinstance(data, bytes): + raise ValueError("%s should return bytes, got %s" + % (self.fp, type(data).__name__)) + self.bytes_read += len(data) + if not data: + self.done = -1 + break + self.file.write(data) + todo = todo - len(data) + + def read_lines(self): + """Internal: read lines until EOF or outerboundary.""" + if self._binary_file: + self.file = self.__file = BytesIO() # store data as bytes for files + else: + self.file = self.__file = StringIO() # as strings for other fields + if self.outerboundary: + self.read_lines_to_outerboundary() + else: + self.read_lines_to_eof() + + def __write(self, line): + """line is always bytes, not string""" + if self.__file is not None: + if self.__file.tell() + len(line) > 1000: + self.file = self.make_file() + data = self.__file.getvalue() + self.file.write(data) + self.__file = None + if self._binary_file: + # keep bytes + self.file.write(line) + else: + # decode to string + self.file.write(line.decode(self.encoding, self.errors)) + + def read_lines_to_eof(self): + """Internal: read lines until EOF.""" + while 1: + line = self.fp.readline(1<<16) # bytes + self.bytes_read += len(line) + if not line: + self.done = -1 + break + self.__write(line) + + def read_lines_to_outerboundary(self): + """Internal: read lines until outerboundary. + Data is read as bytes: boundaries and line ends must be converted + to bytes for comparisons. + """ + next_boundary = b"--" + self.outerboundary + last_boundary = next_boundary + b"--" + delim = b"" + last_line_lfend = True + _read = 0 + while 1: + + if self.limit is not None and 0 <= self.limit <= _read: + break + line = self.fp.readline(1<<16) # bytes + self.bytes_read += len(line) + _read += len(line) + if not line: + self.done = -1 + break + if delim == b"\r": + line = delim + line + delim = b"" + if line.startswith(b"--") and last_line_lfend: + strippedline = line.rstrip() + if strippedline == next_boundary: + break + if strippedline == last_boundary: + self.done = 1 + break + odelim = delim + if line.endswith(b"\r\n"): + delim = b"\r\n" + line = line[:-2] + last_line_lfend = True + elif line.endswith(b"\n"): + delim = b"\n" + line = line[:-1] + last_line_lfend = True + elif line.endswith(b"\r"): + # We may interrupt \r\n sequences if they span the 2**16 + # byte boundary + delim = b"\r" + line = line[:-1] + last_line_lfend = False + else: + delim = b"" + last_line_lfend = False + self.__write(odelim + line) + + def skip_lines(self): + """Internal: skip lines until outer boundary if defined.""" + if not self.outerboundary or self.done: + return + next_boundary = b"--" + self.outerboundary + last_boundary = next_boundary + b"--" + last_line_lfend = True + while True: + line = self.fp.readline(1<<16) + self.bytes_read += len(line) + if not line: + self.done = -1 + break + if line.endswith(b"--") and last_line_lfend: + strippedline = line.strip() + if strippedline == next_boundary: + break + if strippedline == last_boundary: + self.done = 1 + break + last_line_lfend = line.endswith(b'\n') + + def make_file(self): + """Overridable: return a readable & writable file. + + The file will be used as follows: + - data is written to it + - seek(0) + - data is read from it + + The file is opened in binary mode for files, in text mode + for other fields + + This version opens a temporary file for reading and writing, + and immediately deletes (unlinks) it. The trick (on Unix!) is + that the file can still be used, but it can't be opened by + another process, and it will automatically be deleted when it + is closed or when the current process terminates. + + If you want a more permanent file, you derive a class which + overrides this method. If you want a visible temporary file + that is nevertheless automatically deleted when the script + terminates, try defining a __del__ method in a derived class + which unlinks the temporary files you have created. + + """ + if self._binary_file: + return tempfile.TemporaryFile("wb+") + else: + return tempfile.TemporaryFile("w+", + encoding=self.encoding, newline = '\n') + + +# Test/debug code +# =============== + +def test(environ=os.environ): + """Robust test CGI script, usable as main program. + + Write minimal HTTP headers and dump all information provided to + the script in HTML form. + + """ + print("Content-type: text/html") + print() + sys.stderr = sys.stdout + try: + form = FieldStorage() # Replace with other classes to test those + print_directory() + print_arguments() + print_form(form) + print_environ(environ) + print_environ_usage() + def f(): + exec("testing print_exception() -- <I>italics?</I>") + def g(f=f): + f() + print("<H3>What follows is a test, not an actual exception:</H3>") + g() + except: + print_exception() + + print("<H1>Second try with a small maxlen...</H1>") + + global maxlen + maxlen = 50 + try: + form = FieldStorage() # Replace with other classes to test those + print_directory() + print_arguments() + print_form(form) + print_environ(environ) + except: + print_exception() + +def print_exception(type=None, value=None, tb=None, limit=None): + if type is None: + type, value, tb = sys.exc_info() + import traceback + print() + print("<H3>Traceback (most recent call last):</H3>") + list = traceback.format_tb(tb, limit) + \ + traceback.format_exception_only(type, value) + print("<PRE>%s<B>%s</B></PRE>" % ( + html.escape("".join(list[:-1])), + html.escape(list[-1]), + )) + del tb + +def print_environ(environ=os.environ): + """Dump the shell environment as HTML.""" + keys = sorted(environ.keys()) + print() + print("<H3>Shell Environment:</H3>") + print("<DL>") + for key in keys: + print("<DT>", html.escape(key), "<DD>", html.escape(environ[key])) + print("</DL>") + print() + +def print_form(form): + """Dump the contents of a form as HTML.""" + keys = sorted(form.keys()) + print() + print("<H3>Form Contents:</H3>") + if not keys: + print("<P>No form fields.") + print("<DL>") + for key in keys: + print("<DT>" + html.escape(key) + ":", end=' ') + value = form[key] + print("<i>" + html.escape(repr(type(value))) + "</i>") + print("<DD>" + html.escape(repr(value))) + print("</DL>") + print() + +def print_directory(): + """Dump the current directory as HTML.""" + print() + print("<H3>Current Working Directory:</H3>") + try: + pwd = os.getcwd() + except OSError as msg: + print("OSError:", html.escape(str(msg))) + else: + print(html.escape(pwd)) + print() + +def print_arguments(): + print() + print("<H3>Command Line Arguments:</H3>") + print() + print(sys.argv) + print() + +def print_environ_usage(): + """Dump a list of environment variables used by CGI as HTML.""" + print(""" +<H3>These environment variables could have been set:</H3> +<UL> +<LI>AUTH_TYPE +<LI>CONTENT_LENGTH +<LI>CONTENT_TYPE +<LI>DATE_GMT +<LI>DATE_LOCAL +<LI>DOCUMENT_NAME +<LI>DOCUMENT_ROOT +<LI>DOCUMENT_URI +<LI>GATEWAY_INTERFACE +<LI>LAST_MODIFIED +<LI>PATH +<LI>PATH_INFO +<LI>PATH_TRANSLATED +<LI>QUERY_STRING +<LI>REMOTE_ADDR +<LI>REMOTE_HOST +<LI>REMOTE_IDENT +<LI>REMOTE_USER +<LI>REQUEST_METHOD +<LI>SCRIPT_NAME +<LI>SERVER_NAME +<LI>SERVER_PORT +<LI>SERVER_PROTOCOL +<LI>SERVER_ROOT +<LI>SERVER_SOFTWARE +</UL> +In addition, HTTP headers sent by the server may be passed in the +environment as well. Here are some common variable names: +<UL> +<LI>HTTP_ACCEPT +<LI>HTTP_CONNECTION +<LI>HTTP_HOST +<LI>HTTP_PRAGMA +<LI>HTTP_REFERER +<LI>HTTP_USER_AGENT +</UL> +""") + + +# Utilities +# ========= + +def valid_boundary(s): + import re + if isinstance(s, bytes): + _vb_pattern = b"^[ -~]{0,200}[!-~]$" + else: + _vb_pattern = "^[ -~]{0,200}[!-~]$" + return re.match(_vb_pattern, s) + +# Invoke mainline +# =============== + +# Call test() when this file is run as a script (not imported as a module) +if __name__ == '__main__': + test() diff --git a/tests/wpt/tests/tools/wptserve/wptserve/cgi/test_cgi.py b/tests/wpt/tests/tools/wptserve/wptserve/cgi/test_cgi.py new file mode 100644 index 00000000000..63d171f9c80 --- /dev/null +++ b/tests/wpt/tests/tools/wptserve/wptserve/cgi/test_cgi.py @@ -0,0 +1,706 @@ +import os +import sys +import tempfile +import types +import unittest +import warnings +from collections import namedtuple +from io import StringIO, BytesIO + +from . import cgi + +# Inlined from Lib/test/support/__init__.py in Python 3.12 +def check__all__(test_case, module, name_of_module=None, extra=(), + not_exported=()): + """Assert that the __all__ variable of 'module' contains all public names. + + The module's public names (its API) are detected automatically based on + whether they match the public name convention and were defined in + 'module'. + + The 'name_of_module' argument can specify (as a string or tuple thereof) + what module(s) an API could be defined in in order to be detected as a + public API. One case for this is when 'module' imports part of its public + API from other modules, possibly a C backend (like 'csv' and its '_csv'). + + The 'extra' argument can be a set of names that wouldn't otherwise be + automatically detected as "public", like objects without a proper + '__module__' attribute. If provided, it will be added to the + automatically detected ones. + + The 'not_exported' argument can be a set of names that must not be treated + as part of the public API even though their names indicate otherwise. + + Usage: + import bar + import foo + import unittest + from test import support + + class MiscTestCase(unittest.TestCase): + def test__all__(self): + support.check__all__(self, foo) + + class OtherTestCase(unittest.TestCase): + def test__all__(self): + extra = {'BAR_CONST', 'FOO_CONST'} + not_exported = {'baz'} # Undocumented name. + # bar imports part of its API from _bar. + support.check__all__(self, bar, ('bar', '_bar'), + extra=extra, not_exported=not_exported) + + """ + + if name_of_module is None: + name_of_module = (module.__name__, ) + elif isinstance(name_of_module, str): + name_of_module = (name_of_module, ) + + expected = set(extra) + + for name in dir(module): + if name.startswith('_') or name in not_exported: + continue + obj = getattr(module, name) + if (getattr(obj, '__module__', None) in name_of_module or + (not hasattr(obj, '__module__') and + not isinstance(obj, types.ModuleType))): + expected.add(name) + test_case.assertCountEqual(module.__all__, expected) + + +class HackedSysModule: + # The regression test will have real values in sys.argv, which + # will completely confuse the test of the cgi module + argv = [] + stdin = sys.stdin + version_info = sys.version_info + +cgi.sys = HackedSysModule() + +class ComparableException: + def __init__(self, err): + self.err = err + + def __str__(self): + return str(self.err) + + def __eq__(self, anExc): + if not isinstance(anExc, Exception): + return NotImplemented + return (self.err.__class__ == anExc.__class__ and + self.err.args == anExc.args) + + def __getattr__(self, attr): + return getattr(self.err, attr) + +def do_test(buf, method): + env = {} + if method == "GET": + fp = None + env['REQUEST_METHOD'] = 'GET' + env['QUERY_STRING'] = buf + elif method == "POST": + fp = BytesIO(buf.encode('latin-1')) # FieldStorage expects bytes + env['REQUEST_METHOD'] = 'POST' + env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded' + env['CONTENT_LENGTH'] = str(len(buf)) + else: + raise ValueError("unknown method: %s" % method) + try: + return cgi.parse(fp, env, strict_parsing=1) + except Exception as err: + return ComparableException(err) + +parse_strict_test_cases = [ + ("", {}), + ("&", ValueError("bad query field: ''")), + ("&&", ValueError("bad query field: ''")), + # Should the next few really be valid? + ("=", {}), + ("=&=", {}), + # This rest seem to make sense + ("=a", {'': ['a']}), + ("&=a", ValueError("bad query field: ''")), + ("=a&", ValueError("bad query field: ''")), + ("=&a", ValueError("bad query field: 'a'")), + ("b=a", {'b': ['a']}), + ("b+=a", {'b ': ['a']}), + ("a=b=a", {'a': ['b=a']}), + ("a=+b=a", {'a': [' b=a']}), + ("&b=a", ValueError("bad query field: ''")), + ("b&=a", ValueError("bad query field: 'b'")), + ("a=a+b&b=b+c", {'a': ['a b'], 'b': ['b c']}), + ("a=a+b&a=b+a", {'a': ['a b', 'b a']}), + ("x=1&y=2.0&z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}), + ("Hbc5161168c542333633315dee1182227:key_store_seqid=400006&cuyer=r&view=bustomer&order_id=0bb2e248638833d48cb7fed300000f1b&expire=964546263&lobale=en-US&kid=130003.300038&ss=env", + {'Hbc5161168c542333633315dee1182227:key_store_seqid': ['400006'], + 'cuyer': ['r'], + 'expire': ['964546263'], + 'kid': ['130003.300038'], + 'lobale': ['en-US'], + 'order_id': ['0bb2e248638833d48cb7fed300000f1b'], + 'ss': ['env'], + 'view': ['bustomer'], + }), + + ("group_id=5470&set=custom&_assigned_to=31392&_status=1&_category=100&SUBMIT=Browse", + {'SUBMIT': ['Browse'], + '_assigned_to': ['31392'], + '_category': ['100'], + '_status': ['1'], + 'group_id': ['5470'], + 'set': ['custom'], + }) + ] + +# The behaviour of urllib.parse.parse_qs with empty input changed in Python 3.11 +if sys.version_info < (3, 11): + parse_strict_test_cases[0] = ("", ValueError("bad query field: ''")) + +def norm(seq): + return sorted(seq, key=repr) + +def first_elts(list): + return [p[0] for p in list] + +def first_second_elts(list): + return [(p[0], p[1][0]) for p in list] + +def gen_result(data, environ): + encoding = 'latin-1' + fake_stdin = BytesIO(data.encode(encoding)) + fake_stdin.seek(0) + form = cgi.FieldStorage(fp=fake_stdin, environ=environ, encoding=encoding) + + result = {} + for k, v in dict(form).items(): + result[k] = isinstance(v, list) and form.getlist(k) or v.value + + return result + +class CgiTests(unittest.TestCase): + + def test_parse_multipart(self): + fp = BytesIO(POSTDATA.encode('latin1')) + env = {'boundary': BOUNDARY.encode('latin1'), + 'CONTENT-LENGTH': '558'} + result = cgi.parse_multipart(fp, env) + expected = {'submit': [' Add '], 'id': ['1234'], + 'file': [b'Testing 123.\n'], 'title': ['']} + self.assertEqual(result, expected) + + def test_parse_multipart_without_content_length(self): + POSTDATA = '''--JfISa01 +Content-Disposition: form-data; name="submit-name" + +just a string + +--JfISa01-- +''' + fp = BytesIO(POSTDATA.encode('latin1')) + env = {'boundary': 'JfISa01'.encode('latin1')} + result = cgi.parse_multipart(fp, env) + expected = {'submit-name': ['just a string\n']} + self.assertEqual(result, expected) + + def test_parse_multipart_invalid_encoding(self): + BOUNDARY = "JfISa01" + POSTDATA = """--JfISa01 +Content-Disposition: form-data; name="submit-name" +Content-Length: 3 + +\u2603 +--JfISa01""" + fp = BytesIO(POSTDATA.encode('utf8')) + env = {'boundary': BOUNDARY.encode('latin1'), + 'CONTENT-LENGTH': str(len(POSTDATA.encode('utf8')))} + result = cgi.parse_multipart(fp, env, encoding="ascii", + errors="surrogateescape") + expected = {'submit-name': ["\udce2\udc98\udc83"]} + self.assertEqual(result, expected) + self.assertEqual("\u2603".encode('utf8'), + result["submit-name"][0].encode('utf8', 'surrogateescape')) + + def test_fieldstorage_properties(self): + fs = cgi.FieldStorage() + self.assertFalse(fs) + self.assertIn("FieldStorage", repr(fs)) + self.assertEqual(list(fs), list(fs.keys())) + fs.list.append(namedtuple('MockFieldStorage', 'name')('fieldvalue')) + self.assertTrue(fs) + + def test_fieldstorage_invalid(self): + self.assertRaises(TypeError, cgi.FieldStorage, "not-a-file-obj", + environ={"REQUEST_METHOD":"PUT"}) + self.assertRaises(TypeError, cgi.FieldStorage, "foo", "bar") + fs = cgi.FieldStorage(headers={'content-type':'text/plain'}) + self.assertRaises(TypeError, bool, fs) + + def test_strict(self): + for orig, expect in parse_strict_test_cases: + # Test basic parsing + d = do_test(orig, "GET") + self.assertEqual(d, expect, "Error parsing %s method GET" % repr(orig)) + d = do_test(orig, "POST") + self.assertEqual(d, expect, "Error parsing %s method POST" % repr(orig)) + + env = {'QUERY_STRING': orig} + fs = cgi.FieldStorage(environ=env) + if isinstance(expect, dict): + # test dict interface + self.assertEqual(len(expect), len(fs)) + self.assertCountEqual(expect.keys(), fs.keys()) + ##self.assertEqual(norm(expect.values()), norm(fs.values())) + ##self.assertEqual(norm(expect.items()), norm(fs.items())) + self.assertEqual(fs.getvalue("nonexistent field", "default"), "default") + # test individual fields + for key in expect.keys(): + expect_val = expect[key] + self.assertIn(key, fs) + if len(expect_val) > 1: + self.assertEqual(fs.getvalue(key), expect_val) + else: + self.assertEqual(fs.getvalue(key), expect_val[0]) + + def test_separator(self): + parse_semicolon = [ + ("x=1;y=2.0", {'x': ['1'], 'y': ['2.0']}), + ("x=1;y=2.0;z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}), + (";", ValueError("bad query field: ''")), + (";;", ValueError("bad query field: ''")), + ("=;a", ValueError("bad query field: 'a'")), + (";b=a", ValueError("bad query field: ''")), + ("b;=a", ValueError("bad query field: 'b'")), + ("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}), + ("a=a+b;a=b+a", {'a': ['a b', 'b a']}), + ] + for orig, expect in parse_semicolon: + env = {'QUERY_STRING': orig} + fs = cgi.FieldStorage(separator=';', environ=env) + if isinstance(expect, dict): + for key in expect.keys(): + expect_val = expect[key] + self.assertIn(key, fs) + if len(expect_val) > 1: + self.assertEqual(fs.getvalue(key), expect_val) + else: + self.assertEqual(fs.getvalue(key), expect_val[0]) + + def test_log(self): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', category=DeprecationWarning) + cgi.log("Testing") + + cgi.logfp = StringIO() + cgi.initlog("%s", "Testing initlog 1") + cgi.log("%s", "Testing log 2") + self.assertEqual(cgi.logfp.getvalue(), "Testing initlog 1\nTesting log 2\n") + if os.path.exists(os.devnull): + cgi.logfp = None + cgi.logfile = os.devnull + cgi.initlog("%s", "Testing log 3") + self.addCleanup(cgi.closelog) + cgi.log("Testing log 4") + + def test_fieldstorage_readline(self): + # FieldStorage uses readline, which has the capacity to read all + # contents of the input file into memory; we use readline's size argument + # to prevent that for files that do not contain any newlines in + # non-GET/HEAD requests + class TestReadlineFile: + def __init__(self, file): + self.file = file + self.numcalls = 0 + + def readline(self, size=None): + self.numcalls += 1 + if size: + return self.file.readline(size) + else: + return self.file.readline() + + def __getattr__(self, name): + file = self.__dict__['file'] + a = getattr(file, name) + if not isinstance(a, int): + setattr(self, name, a) + return a + + f = TestReadlineFile(tempfile.TemporaryFile("wb+")) + self.addCleanup(f.close) + f.write(b'x' * 256 * 1024) + f.seek(0) + env = {'REQUEST_METHOD':'PUT'} + fs = cgi.FieldStorage(fp=f, environ=env) + self.addCleanup(fs.file.close) + # if we're not chunking properly, readline is only called twice + # (by read_binary); if we are chunking properly, it will be called 5 times + # as long as the chunksize is 1 << 16. + self.assertGreater(f.numcalls, 2) + f.close() + + def test_fieldstorage_multipart(self): + #Test basic FieldStorage multipart parsing + env = { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary={}'.format(BOUNDARY), + 'CONTENT_LENGTH': '558'} + fp = BytesIO(POSTDATA.encode('latin-1')) + fs = cgi.FieldStorage(fp, environ=env, encoding="latin-1") + self.assertEqual(len(fs.list), 4) + expect = [{'name':'id', 'filename':None, 'value':'1234'}, + {'name':'title', 'filename':None, 'value':''}, + {'name':'file', 'filename':'test.txt', 'value':b'Testing 123.\n'}, + {'name':'submit', 'filename':None, 'value':' Add '}] + for x in range(len(fs.list)): + for k, exp in expect[x].items(): + got = getattr(fs.list[x], k) + self.assertEqual(got, exp) + + def test_fieldstorage_multipart_leading_whitespace(self): + env = { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary={}'.format(BOUNDARY), + 'CONTENT_LENGTH': '560'} + # Add some leading whitespace to our post data that will cause the + # first line to not be the innerboundary. + fp = BytesIO(b"\r\n" + POSTDATA.encode('latin-1')) + fs = cgi.FieldStorage(fp, environ=env, encoding="latin-1") + self.assertEqual(len(fs.list), 4) + expect = [{'name':'id', 'filename':None, 'value':'1234'}, + {'name':'title', 'filename':None, 'value':''}, + {'name':'file', 'filename':'test.txt', 'value':b'Testing 123.\n'}, + {'name':'submit', 'filename':None, 'value':' Add '}] + for x in range(len(fs.list)): + for k, exp in expect[x].items(): + got = getattr(fs.list[x], k) + self.assertEqual(got, exp) + + def test_fieldstorage_multipart_non_ascii(self): + #Test basic FieldStorage multipart parsing + env = {'REQUEST_METHOD':'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary={}'.format(BOUNDARY), + 'CONTENT_LENGTH':'558'} + for encoding in ['iso-8859-1','utf-8']: + fp = BytesIO(POSTDATA_NON_ASCII.encode(encoding)) + fs = cgi.FieldStorage(fp, environ=env,encoding=encoding) + self.assertEqual(len(fs.list), 1) + expect = [{'name':'id', 'filename':None, 'value':'\xe7\xf1\x80'}] + for x in range(len(fs.list)): + for k, exp in expect[x].items(): + got = getattr(fs.list[x], k) + self.assertEqual(got, exp) + + def test_fieldstorage_multipart_maxline(self): + # Issue #18167 + maxline = 1 << 16 + self.maxDiff = None + def check(content): + data = """---123 +Content-Disposition: form-data; name="upload"; filename="fake.txt" +Content-Type: text/plain + +%s +---123-- +""".replace('\n', '\r\n') % content + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'multipart/form-data; boundary=-123', + 'REQUEST_METHOD': 'POST', + } + self.assertEqual(gen_result(data, environ), + {'upload': content.encode('latin1')}) + check('x' * (maxline - 1)) + check('x' * (maxline - 1) + '\r') + check('x' * (maxline - 1) + '\r' + 'y' * (maxline - 1)) + + def test_fieldstorage_multipart_w3c(self): + # Test basic FieldStorage multipart parsing (W3C sample) + env = { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary={}'.format(BOUNDARY_W3), + 'CONTENT_LENGTH': str(len(POSTDATA_W3))} + fp = BytesIO(POSTDATA_W3.encode('latin-1')) + fs = cgi.FieldStorage(fp, environ=env, encoding="latin-1") + self.assertEqual(len(fs.list), 2) + self.assertEqual(fs.list[0].name, 'submit-name') + self.assertEqual(fs.list[0].value, 'Larry') + self.assertEqual(fs.list[1].name, 'files') + files = fs.list[1].value + self.assertEqual(len(files), 2) + expect = [{'name': None, 'filename': 'file1.txt', 'value': b'... contents of file1.txt ...'}, + {'name': None, 'filename': 'file2.gif', 'value': b'...contents of file2.gif...'}] + for x in range(len(files)): + for k, exp in expect[x].items(): + got = getattr(files[x], k) + self.assertEqual(got, exp) + + def test_fieldstorage_part_content_length(self): + BOUNDARY = "JfISa01" + POSTDATA = """--JfISa01 +Content-Disposition: form-data; name="submit-name" +Content-Length: 5 + +Larry +--JfISa01""" + env = { + 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'multipart/form-data; boundary={}'.format(BOUNDARY), + 'CONTENT_LENGTH': str(len(POSTDATA))} + fp = BytesIO(POSTDATA.encode('latin-1')) + fs = cgi.FieldStorage(fp, environ=env, encoding="latin-1") + self.assertEqual(len(fs.list), 1) + self.assertEqual(fs.list[0].name, 'submit-name') + self.assertEqual(fs.list[0].value, 'Larry') + + def test_field_storage_multipart_no_content_length(self): + fp = BytesIO(b"""--MyBoundary +Content-Disposition: form-data; name="my-arg"; filename="foo" + +Test + +--MyBoundary-- +""") + env = { + "REQUEST_METHOD": "POST", + "CONTENT_TYPE": "multipart/form-data; boundary=MyBoundary", + "wsgi.input": fp, + } + fields = cgi.FieldStorage(fp, environ=env) + + self.assertEqual(len(fields["my-arg"].file.read()), 5) + + def test_fieldstorage_as_context_manager(self): + fp = BytesIO(b'x' * 10) + env = {'REQUEST_METHOD': 'PUT'} + with cgi.FieldStorage(fp=fp, environ=env) as fs: + content = fs.file.read() + self.assertFalse(fs.file.closed) + self.assertTrue(fs.file.closed) + self.assertEqual(content, 'x' * 10) + with self.assertRaisesRegex(ValueError, 'I/O operation on closed file'): + fs.file.read() + + _qs_result = { + 'key1': 'value1', + 'key2': ['value2x', 'value2y'], + 'key3': 'value3', + 'key4': 'value4' + } + def testQSAndUrlEncode(self): + data = "key2=value2x&key3=value3&key4=value4" + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', + 'QUERY_STRING': 'key1=value1&key2=value2y', + 'REQUEST_METHOD': 'POST', + } + v = gen_result(data, environ) + self.assertEqual(self._qs_result, v) + + def test_max_num_fields(self): + # For application/x-www-form-urlencoded + data = '&'.join(['a=a']*11) + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', + 'REQUEST_METHOD': 'POST', + } + + with self.assertRaises(ValueError): + cgi.FieldStorage( + fp=BytesIO(data.encode()), + environ=environ, + max_num_fields=10, + ) + + # For multipart/form-data + data = """---123 +Content-Disposition: form-data; name="a" + +3 +---123 +Content-Type: application/x-www-form-urlencoded + +a=4 +---123 +Content-Type: application/x-www-form-urlencoded + +a=5 +---123-- +""" + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'multipart/form-data; boundary=-123', + 'QUERY_STRING': 'a=1&a=2', + 'REQUEST_METHOD': 'POST', + } + + # 2 GET entities + # 1 top level POST entities + # 1 entity within the second POST entity + # 1 entity within the third POST entity + with self.assertRaises(ValueError): + cgi.FieldStorage( + fp=BytesIO(data.encode()), + environ=environ, + max_num_fields=4, + ) + cgi.FieldStorage( + fp=BytesIO(data.encode()), + environ=environ, + max_num_fields=5, + ) + + def testQSAndFormData(self): + data = """---123 +Content-Disposition: form-data; name="key2" + +value2y +---123 +Content-Disposition: form-data; name="key3" + +value3 +---123 +Content-Disposition: form-data; name="key4" + +value4 +---123-- +""" + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'multipart/form-data; boundary=-123', + 'QUERY_STRING': 'key1=value1&key2=value2x', + 'REQUEST_METHOD': 'POST', + } + v = gen_result(data, environ) + self.assertEqual(self._qs_result, v) + + def testQSAndFormDataFile(self): + data = """---123 +Content-Disposition: form-data; name="key2" + +value2y +---123 +Content-Disposition: form-data; name="key3" + +value3 +---123 +Content-Disposition: form-data; name="key4" + +value4 +---123 +Content-Disposition: form-data; name="upload"; filename="fake.txt" +Content-Type: text/plain + +this is the content of the fake file + +---123-- +""" + environ = { + 'CONTENT_LENGTH': str(len(data)), + 'CONTENT_TYPE': 'multipart/form-data; boundary=-123', + 'QUERY_STRING': 'key1=value1&key2=value2x', + 'REQUEST_METHOD': 'POST', + } + result = self._qs_result.copy() + result.update({ + 'upload': b'this is the content of the fake file\n' + }) + v = gen_result(data, environ) + self.assertEqual(result, v) + + def test_parse_header(self): + self.assertEqual( + cgi.parse_header("text/plain"), + ("text/plain", {})) + self.assertEqual( + cgi.parse_header("text/vnd.just.made.this.up ; "), + ("text/vnd.just.made.this.up", {})) + self.assertEqual( + cgi.parse_header("text/plain;charset=us-ascii"), + ("text/plain", {"charset": "us-ascii"})) + self.assertEqual( + cgi.parse_header('text/plain ; charset="us-ascii"'), + ("text/plain", {"charset": "us-ascii"})) + self.assertEqual( + cgi.parse_header('text/plain ; charset="us-ascii"; another=opt'), + ("text/plain", {"charset": "us-ascii", "another": "opt"})) + self.assertEqual( + cgi.parse_header('attachment; filename="silly.txt"'), + ("attachment", {"filename": "silly.txt"})) + self.assertEqual( + cgi.parse_header('attachment; filename="strange;name"'), + ("attachment", {"filename": "strange;name"})) + self.assertEqual( + cgi.parse_header('attachment; filename="strange;name";size=123;'), + ("attachment", {"filename": "strange;name", "size": "123"})) + self.assertEqual( + cgi.parse_header('form-data; name="files"; filename="fo\\"o;bar"'), + ("form-data", {"name": "files", "filename": 'fo"o;bar'})) + + def test_all(self): + not_exported = { + "logfile", "logfp", "initlog", "dolog", "nolog", "closelog", "log", + "maxlen", "valid_boundary"} + check__all__(self, cgi, not_exported=not_exported) + + +BOUNDARY = "---------------------------721837373350705526688164684" + +POSTDATA = """-----------------------------721837373350705526688164684 +Content-Disposition: form-data; name="id" + +1234 +-----------------------------721837373350705526688164684 +Content-Disposition: form-data; name="title" + + +-----------------------------721837373350705526688164684 +Content-Disposition: form-data; name="file"; filename="test.txt" +Content-Type: text/plain + +Testing 123. + +-----------------------------721837373350705526688164684 +Content-Disposition: form-data; name="submit" + + Add\x20 +-----------------------------721837373350705526688164684-- +""" + +POSTDATA_NON_ASCII = """-----------------------------721837373350705526688164684 +Content-Disposition: form-data; name="id" + +\xe7\xf1\x80 +-----------------------------721837373350705526688164684 +""" + +# http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4 +BOUNDARY_W3 = "AaB03x" +POSTDATA_W3 = """--AaB03x +Content-Disposition: form-data; name="submit-name" + +Larry +--AaB03x +Content-Disposition: form-data; name="files" +Content-Type: multipart/mixed; boundary=BbC04y + +--BbC04y +Content-Disposition: file; filename="file1.txt" +Content-Type: text/plain + +... contents of file1.txt ... +--BbC04y +Content-Disposition: file; filename="file2.gif" +Content-Type: image/gif +Content-Transfer-Encoding: binary + +...contents of file2.gif... +--BbC04y-- +--AaB03x-- +""" + +if __name__ == '__main__': + unittest.main() diff --git a/tests/wpt/tests/tools/wptserve/wptserve/request.py b/tests/wpt/tests/tools/wptserve/wptserve/request.py index 9207b4dbf4b..087d6fbb490 100644 --- a/tests/wpt/tests/tools/wptserve/wptserve/request.py +++ b/tests/wpt/tests/tools/wptserve/wptserve/request.py @@ -1,7 +1,6 @@ # mypy: allow-untyped-defs import base64 -import cgi import tempfile from http.cookies import BaseCookie @@ -10,6 +9,7 @@ from typing import Dict, List, TypeVar from urllib.parse import parse_qsl, urlsplit from . import stash +from . import cgi from .utils import HTTPException, isomorphic_encode, isomorphic_decode KT = TypeVar('KT') diff --git a/tests/wpt/tests/trusted-types/DedicatedWorker-block-eval-function-constructor.html b/tests/wpt/tests/trusted-types/DedicatedWorker-block-eval-function-constructor.html new file mode 100644 index 00000000000..5671e8ec481 --- /dev/null +++ b/tests/wpt/tests/trusted-types/DedicatedWorker-block-eval-function-constructor.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<link rel="help" href="https://w3c.github.io/webappsec-csp/#can-compile-strings"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/helper.sub.js"></script> +<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'"> +<script> + const testSetupPolicy = trustedTypes.createPolicy("p", + { createScriptURL: s => s } + ); + + fetch_tests_from_worker(new Worker( + testSetupPolicy.createScriptURL("support/block-eval-function-constructor-worker.js") + )); +</script> diff --git a/tests/wpt/tests/trusted-types/DedicatedWorker-constructor-from-DedicatedWorker.html b/tests/wpt/tests/trusted-types/DedicatedWorker-constructor-from-DedicatedWorker.html new file mode 100644 index 00000000000..86612b9d1d1 --- /dev/null +++ b/tests/wpt/tests/trusted-types/DedicatedWorker-constructor-from-DedicatedWorker.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <script> + fetch_tests_from_worker(new Worker( + "support/WorkerGlobalScope-worker-constructor.js")); + </script> +</body> +</html> diff --git a/tests/wpt/tests/trusted-types/WorkerGlobalScope-worker-constructor.html b/tests/wpt/tests/trusted-types/DedicatedWorker-constructor-from-SharedWorker.html index 8964c72780b..b0bb773a608 100644 --- a/tests/wpt/tests/trusted-types/WorkerGlobalScope-worker-constructor.html +++ b/tests/wpt/tests/trusted-types/DedicatedWorker-constructor-from-SharedWorker.html @@ -7,9 +7,6 @@ </head> <body> <script> - fetch_tests_from_worker(new Worker( - "support/WorkerGlobalScope-worker-constructor.js")); - fetch_tests_from_worker(new SharedWorker( "support/WorkerGlobalScope-worker-constructor.js")); </script> diff --git a/tests/wpt/tests/trusted-types/DedicatedWorker-constructor.https.html b/tests/wpt/tests/trusted-types/DedicatedWorker-constructor.https.html new file mode 100644 index 00000000000..4c39bd319c0 --- /dev/null +++ b/tests/wpt/tests/trusted-types/DedicatedWorker-constructor.https.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + +const test_url = "support/WorkerGlobalScope-importScripts.https.js" +const trusted_url = trustedTypes.createPolicy("anythinggoes", { + createScriptURL: x => x}).createScriptURL(test_url); +const default_url = "support/WorkerGlobalScope-importScripts.potato.js" + +test(() => { + try { + new Worker(trusted_url); + } catch (e) { + assert_unreached("Worker creation failed: " + e); + } +}, "Create Worker via ScriptTestUrl"); + +test(() => { + assert_throws_js(TypeError, () => new Worker(test_url)); +}, "Block Worker creation via string"); + +// Tests with default policy. +let seenTrustedTypeName; +let seenSinkName; +function resetSeenArguments() { + seenTrustedTypeName = undefined; + seenSinkName = undefined; +} + +trustedTypes.createPolicy("default", { + createScriptURL: (input, trustedTypeName, sinkName) => { + seenTrustedTypeName = trustedTypeName; + seenSinkName = sinkName; + return input.replace("potato", "https"); + } +}); + +test(t => { + t.add_cleanup(resetSeenArguments); + new Worker(default_url); + assert_equals(seenTrustedTypeName, "TrustedScriptURL"); + assert_equals(seenSinkName, "Worker constructor"); +}, "Create Worker via string with default policy."); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/DedicatedWorker-eval.html b/tests/wpt/tests/trusted-types/DedicatedWorker-eval.html new file mode 100644 index 00000000000..68db7d3540d --- /dev/null +++ b/tests/wpt/tests/trusted-types/DedicatedWorker-eval.html @@ -0,0 +1,30 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id=log></div> + +<script> + +// To test workers, we need to importScripts source files in the workers. +// We need to set up one policy that will blindly pass through URLs for use in the test +// setup, and then have additional policies for the actual test cases. +// +// For the same reason we cannot use the otherwise preferred 'META: workers' +// tag +// (https://web-platform-tests.org/writing-tests/testharness.html#tests-for-other-or-multiple-globals-any-js), +// since that test setup would be blocked as soon as trusted types enforcement +// is enabled. +const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { + createScriptURL: x => x}); +const test_url = + test_setup_policy.createScriptURL("support/WorkerGlobalScope-eval.https.js"); + +fetch_tests_from_worker(new Worker(test_url)); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/DedicatedWorker-importScripts.html b/tests/wpt/tests/trusted-types/DedicatedWorker-importScripts.html new file mode 100644 index 00000000000..2e916f4e6b8 --- /dev/null +++ b/tests/wpt/tests/trusted-types/DedicatedWorker-importScripts.html @@ -0,0 +1,31 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id=log></div> + +<script> + +// To test workers, we need to importScripts source files in the workers. +// Since the point of this test is to test blocking of importScripts, we need +// to set up one policy that will blindly pass through URLs for use in the test +// setup, and then have additional policies for the actual test cases. +// +// For the same reason we cannot use the otherwise preferred 'META: workers' +// tag +// (https://web-platform-tests.org/writing-tests/testharness.html#tests-for-other-or-multiple-globals-any-js), +// since that test setup would be blocked as soon as trusted types enforcement +// is enabled. +const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { + createScriptURL: x => x}); +const test_url = + test_setup_policy.createScriptURL("support/WorkerGlobalScope-importScripts.https.js"); + +fetch_tests_from_worker(new Worker(test_url)); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/DedicatedWorker-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/DedicatedWorker-setTimeout-setInterval.html new file mode 100644 index 00000000000..7bb4f32ec54 --- /dev/null +++ b/tests/wpt/tests/trusted-types/DedicatedWorker-setTimeout-setInterval.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/helper.sub.js"></script> + <link rel="help" href="https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps"> +</head> +<body> + <!-- "META: global=worker" + (https://web-platform-tests.org/writing-tests/testharness.html#tests-for-other-or-multiple-globals-any-js) + can't be used here because constructing the worker would require a trusted type. + --> + <script> + let test_setup_policy = trustedTypes.createPolicy("p", { + createScriptURL: x => x + }); + + fetch_tests_from_worker(new Worker(test_setup_policy.createScriptURL( + "support/DOMWindowTimers-setTimeout-setInterval-worker.js"))); + </script> +</body> +</html> diff --git a/tests/wpt/tests/trusted-types/ServiceWorker-block-eval-function-constructor.https.html b/tests/wpt/tests/trusted-types/ServiceWorker-block-eval-function-constructor.https.html new file mode 100644 index 00000000000..e093782ef45 --- /dev/null +++ b/tests/wpt/tests/trusted-types/ServiceWorker-block-eval-function-constructor.https.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<link rel="help" href="https://w3c.github.io/webappsec-csp/#can-compile-strings"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/helper.sub.js"></script> +<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'"> +<script> + const testSetupPolicy = trustedTypes.createPolicy("p", + { createScriptURL: s => s } + ); + + // Cargo-culted from code generated from "META: worker". + (async function() { + const scope = 'support/some/scope/for/this/test'; + let reg = await navigator.serviceWorker.getRegistration(scope); + if (reg) await reg.unregister(); + reg = await navigator.serviceWorker.register(testSetupPolicy.createScriptURL("support/block-eval-function-constructor-worker.js"), {scope}); + fetch_tests_from_worker(reg.installing); + })(); +</script> diff --git a/tests/wpt/tests/trusted-types/ServiceWorker-eval.https.html b/tests/wpt/tests/trusted-types/ServiceWorker-eval.https.html new file mode 100644 index 00000000000..d4a807f2f9b --- /dev/null +++ b/tests/wpt/tests/trusted-types/ServiceWorker-eval.https.html @@ -0,0 +1,28 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id=log></div> + +<script> + +const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { + createScriptURL: x => x}); +const test_url = + test_setup_policy.createScriptURL("support/WorkerGlobalScope-eval.https.js"); + +// Cargo-culted from code generated from "META: worker". +(async function() { + const scope = 'support/some/scope/for/this/test'; + let reg = await navigator.serviceWorker.getRegistration(scope); + if (reg) await reg.unregister(); + reg = await navigator.serviceWorker.register(test_url, {scope}); + fetch_tests_from_worker(reg.installing); +})(); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/WorkerGlobalScope-importScripts.html b/tests/wpt/tests/trusted-types/ServiceWorker-importScripts.https.html index d6e5d9b43d4..69d205fb939 100644 --- a/tests/wpt/tests/trusted-types/WorkerGlobalScope-importScripts.html +++ b/tests/wpt/tests/trusted-types/ServiceWorker-importScripts.https.html @@ -25,20 +25,14 @@ const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { const test_url = test_setup_policy.createScriptURL("support/WorkerGlobalScope-importScripts.https.js"); -fetch_tests_from_worker(new Worker(test_url)); - -fetch_tests_from_worker(new SharedWorker(test_url)); - // Cargo-culted from code generated from "META: worker". -if ('serviceWorker' in navigator) { - (async function() { - const scope = 'support/some/scope/for/this/test'; - let reg = await navigator.serviceWorker.getRegistration(scope); - if (reg) await reg.unregister(); - reg = await navigator.serviceWorker.register(test_url, {scope}); - fetch_tests_from_worker(reg.installing); - })(); -} +(async function() { + const scope = 'support/some/scope/for/this/test'; + let reg = await navigator.serviceWorker.getRegistration(scope); + if (reg) await reg.unregister(); + reg = await navigator.serviceWorker.register(test_url, {scope}); + fetch_tests_from_worker(reg.installing); +})(); </script> </body> diff --git a/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-DedicatedWorker.https.html b/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-DedicatedWorker.https.html new file mode 100644 index 00000000000..1ad58573aa1 --- /dev/null +++ b/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-DedicatedWorker.https.html @@ -0,0 +1,25 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id=log></div> + +<script> + +// This test checks ServiceWorkerContainer.register() from Worker scopes and +// follows the same logic as WorkerGlobalScope-importScripts/eval. For the case +// when it's called from Window scope, see ServiceWorkerContainer-register.https.html. + +const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { + createScriptURL: x => x}); +const test_url = + test_setup_policy.createScriptURL("support/ServiceWorkerContainer-register.https.js"); + +fetch_tests_from_worker(new Worker(test_url)); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-ServiceWorker.https.html b/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-ServiceWorker.https.html new file mode 100644 index 00000000000..7bc1ee7469d --- /dev/null +++ b/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-ServiceWorker.https.html @@ -0,0 +1,31 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id=log></div> + +<script> + +// This test checks ServiceWorkerContainer.register() from Worker scopes and +// follows the same logic as WorkerGlobalScope-importScripts/eval. For the case +// when it's called from Window scope, see ServiceWorkerContainer-register.https.html. + +const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { + createScriptURL: x => x}); +const test_url = + test_setup_policy.createScriptURL("support/ServiceWorkerContainer-register.https.js"); + +(async function() { + const scope = 'support/some/scope/for/this/test'; + let reg = await navigator.serviceWorker.getRegistration(scope); + if (reg) await reg.unregister(); + reg = await navigator.serviceWorker.register(test_url, {scope}); + fetch_tests_from_worker(reg.installing); +})(); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-Worker.https.html b/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-SharedWorker.https.html index a808c0c12b5..f4bf99dc0b6 100644 --- a/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-Worker.https.html +++ b/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register-from-SharedWorker.https.html @@ -12,26 +12,14 @@ // This test checks ServiceWorkerContainer.register() from Worker scopes and // follows the same logic as WorkerGlobalScope-importScripts/eval. For the case -// when it's called from Window scope, see worker-constructor.https.html. +// when it's called from Window scope, see ServiceWorkerContainer-register.https.html. const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { createScriptURL: x => x}); const test_url = test_setup_policy.createScriptURL("support/ServiceWorkerContainer-register.https.js"); -fetch_tests_from_worker(new Worker(test_url)); - fetch_tests_from_worker(new SharedWorker(test_url)); -if ('serviceWorker' in navigator) { - (async function() { - const scope = 'support/some/scope/for/this/test'; - let reg = await navigator.serviceWorker.getRegistration(scope); - if (reg) await reg.unregister(); - reg = await navigator.serviceWorker.register(test_url, {scope}); - fetch_tests_from_worker(reg.installing); - })(); -} - </script> </body> diff --git a/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register.https.html b/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register.https.html new file mode 100644 index 00000000000..4dc691d603b --- /dev/null +++ b/tests/wpt/tests/trusted-types/ServiceWorkerContainer-register.https.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + +const test_url = "support/WorkerGlobalScope-importScripts.https.js" +const trusted_url = trustedTypes.createPolicy("anythinggoes", { + createScriptURL: x => x}).createScriptURL(test_url); +const default_url = "support/WorkerGlobalScope-importScripts.potato.js" + +async function service_worker(url) { + const scope = 'support/some/scope/for/this/test'; + const reg = await navigator.serviceWorker.getRegistration(scope); + if (reg) await reg.unregister(); + return await navigator.serviceWorker.register(url, {scope}); +} + +promise_test(t => { + return service_worker(trusted_url); +}, "Create ServiceWorker via ScriptTestUrl"); + +promise_test(t => { + return promise_rejects_js(t, TypeError, service_worker(test_url)); +}, "Block ServiceWorker creation via String"); + +// Tests with default policy. +let seenTrustedTypeName; +let seenSinkName; +function resetSeenArguments() { + seenTrustedTypeName = undefined; + seenSinkName = undefined; +} + +promise_test(async t => { + trustedTypes.createPolicy("default", { + createScriptURL: (input, trustedTypeName, sinkName) => { + seenTrustedTypeName = trustedTypeName; + seenSinkName = sinkName; + return input.replace("potato", "https"); + } + }); + t.add_cleanup(resetSeenArguments); + await service_worker(default_url); + assert_equals(seenTrustedTypeName, "TrustedScriptURL"); + assert_equals(seenSinkName, "ServiceWorkerContainer register"); +}, "Create ServiceWorker via string with default policy."); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/block-eval-function-constructor.html b/tests/wpt/tests/trusted-types/SharedWorker-block-eval-function-constructor.html index a7d61c86dc0..ca288ad1e79 100644 --- a/tests/wpt/tests/trusted-types/block-eval-function-constructor.html +++ b/tests/wpt/tests/trusted-types/SharedWorker-block-eval-function-constructor.html @@ -4,16 +4,11 @@ <script src="/resources/testharnessreport.js"></script> <script src="support/helper.sub.js"></script> <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'"> -<script src="support/block-eval-function-constructor.js"></script> <script> const testSetupPolicy = trustedTypes.createPolicy("p", { createScriptURL: s => s } ); - fetch_tests_from_worker(new Worker( - testSetupPolicy.createScriptURL("support/block-eval-function-constructor-worker.js") - )); - fetch_tests_from_worker(new SharedWorker( testSetupPolicy.createScriptURL("support/block-eval-function-constructor-worker.js") )); diff --git a/tests/wpt/tests/trusted-types/SharedWorker-constructor.https.html b/tests/wpt/tests/trusted-types/SharedWorker-constructor.https.html new file mode 100644 index 00000000000..cd495d7400e --- /dev/null +++ b/tests/wpt/tests/trusted-types/SharedWorker-constructor.https.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + +const test_url = "support/WorkerGlobalScope-importScripts.https.js" +const trusted_url = trustedTypes.createPolicy("anythinggoes", { + createScriptURL: x => x}).createScriptURL(test_url); +const default_url = "support/WorkerGlobalScope-importScripts.potato.js" + +test(() => { + try { + new SharedWorker(trusted_url); + } catch (e) { + assert_unreached("SharedWorker creation failed: " + e); + } +}, "Create SharedWorker via ScriptTestUrl"); + +test(() => { + assert_throws_js(TypeError, () => new SharedWorker(test_url)); +}, "Block SharedWorker creation via string"); + +// Tests with default policy. +let seenTrustedTypeName; +let seenSinkName; +function resetSeenArguments() { + seenTrustedTypeName = undefined; + seenSinkName = undefined; +} + +trustedTypes.createPolicy("default", { + createScriptURL: (input, trustedTypeName, sinkName) => { + seenTrustedTypeName = trustedTypeName; + seenSinkName = sinkName; + return input.replace("potato", "https"); + } +}); + +test(t => { + t.add_cleanup(resetSeenArguments); + new SharedWorker(default_url); + assert_equals(seenTrustedTypeName, "TrustedScriptURL"); + assert_equals(seenSinkName, "SharedWorker constructor"); +}, "Create SharedWorker via string with default policy."); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/SharedWorker-eval.html b/tests/wpt/tests/trusted-types/SharedWorker-eval.html new file mode 100644 index 00000000000..26cfd64cc35 --- /dev/null +++ b/tests/wpt/tests/trusted-types/SharedWorker-eval.html @@ -0,0 +1,30 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id=log></div> + +<script> + +// To test workers, we need to importScripts source files in the workers. +// We need to set up one policy that will blindly pass through URLs for use in the test +// setup, and then have additional policies for the actual test cases. +// +// For the same reason we cannot use the otherwise preferred 'META: workers' +// tag +// (https://web-platform-tests.org/writing-tests/testharness.html#tests-for-other-or-multiple-globals-any-js), +// since that test setup would be blocked as soon as trusted types enforcement +// is enabled. +const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { + createScriptURL: x => x}); +const test_url = + test_setup_policy.createScriptURL("support/WorkerGlobalScope-eval.https.js"); + +fetch_tests_from_worker(new SharedWorker(test_url)); + +</script> +</body> diff --git a/tests/wpt/tests/trusted-types/WorkerGlobalScope-eval.html b/tests/wpt/tests/trusted-types/SharedWorker-importScripts.html index cdec742cb21..5bdf6050775 100644 --- a/tests/wpt/tests/trusted-types/WorkerGlobalScope-eval.html +++ b/tests/wpt/tests/trusted-types/SharedWorker-importScripts.html @@ -23,22 +23,9 @@ const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { createScriptURL: x => x}); const test_url = - test_setup_policy.createScriptURL("support/WorkerGlobalScope-eval.https.js"); - -fetch_tests_from_worker(new Worker(test_url)); + test_setup_policy.createScriptURL("support/WorkerGlobalScope-importScripts.https.js"); fetch_tests_from_worker(new SharedWorker(test_url)); -// Cargo-culted from code generated from "META: worker". -if ('serviceWorker' in navigator) { - (async function() { - const scope = 'support/some/scope/for/this/test'; - let reg = await navigator.serviceWorker.getRegistration(scope); - if (reg) await reg.unregister(); - reg = await navigator.serviceWorker.register(test_url, {scope}); - fetch_tests_from_worker(reg.installing); - })(); -} - </script> </body> diff --git a/tests/wpt/tests/trusted-types/DOMWindowTimers-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/SharedWorker-setTimeout-setInterval.html index 3ecaa5234c6..be31fe72bee 100644 --- a/tests/wpt/tests/trusted-types/DOMWindowTimers-setTimeout-setInterval.html +++ b/tests/wpt/tests/trusted-types/SharedWorker-setTimeout-setInterval.html @@ -13,15 +13,11 @@ (https://web-platform-tests.org/writing-tests/testharness.html#tests-for-other-or-multiple-globals-any-js) can't be used here because constructing the worker would require a trusted type. --> - <script src="support/DOMWindowTimers-setTimeout-setInterval.js"></script> <script> let test_setup_policy = trustedTypes.createPolicy("p", { createScriptURL: x => x }); - fetch_tests_from_worker(new Worker(test_setup_policy.createScriptURL( - "support/DOMWindowTimers-setTimeout-setInterval-worker.js"))); - fetch_tests_from_worker(new SharedWorker(test_setup_policy.createScriptURL( "support/DOMWindowTimers-setTimeout-setInterval-worker.js"))); </script> diff --git a/tests/wpt/tests/trusted-types/Window-block-eval-function-constructor.html b/tests/wpt/tests/trusted-types/Window-block-eval-function-constructor.html new file mode 100644 index 00000000000..c35e7bcc1a8 --- /dev/null +++ b/tests/wpt/tests/trusted-types/Window-block-eval-function-constructor.html @@ -0,0 +1,7 @@ +<!DOCTYPE html> +<link rel="help" href="https://w3c.github.io/webappsec-csp/#can-compile-strings"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/helper.sub.js"></script> +<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'"> +<script src="support/block-eval-function-constructor.js"></script> diff --git a/tests/wpt/tests/trusted-types/Window-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/Window-setTimeout-setInterval.html new file mode 100644 index 00000000000..9327926804f --- /dev/null +++ b/tests/wpt/tests/trusted-types/Window-setTimeout-setInterval.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/helper.sub.js"></script> + <link rel="help" href="https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps"> +</head> +<body> + <script src="support/DOMWindowTimers-setTimeout-setInterval.js"></script> +</body> +</html> diff --git a/tests/wpt/tests/trusted-types/block-string-assignment-to-DedicatedWorker-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/block-string-assignment-to-DedicatedWorker-setTimeout-setInterval.html new file mode 100644 index 00000000000..c4e438252ac --- /dev/null +++ b/tests/wpt/tests/trusted-types/block-string-assignment-to-DedicatedWorker-setTimeout-setInterval.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/helper.sub.js"></script> + +<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> +<body> +<script> + const testSetupPolicy = trustedTypes.createPolicy("p", + { createScriptURL: s => s } + ); + + fetch_tests_from_worker(new Worker( + testSetupPolicy.createScriptURL( + "support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval-worker.js" + + ))); +</script> diff --git a/tests/wpt/tests/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/block-string-assignment-to-SharedWorker-setTimeout-setInterval.html index d80e34e7823..76488908ed2 100644 --- a/tests/wpt/tests/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.html +++ b/tests/wpt/tests/trusted-types/block-string-assignment-to-SharedWorker-setTimeout-setInterval.html @@ -5,19 +5,11 @@ <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> <body> -<script src="support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.js"> -</script> <script> const testSetupPolicy = trustedTypes.createPolicy("p", { createScriptURL: s => s } ); - fetch_tests_from_worker(new Worker( - testSetupPolicy.createScriptURL( - "support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval-worker.js" - - ))); - fetch_tests_from_worker(new SharedWorker( testSetupPolicy.createScriptURL( "support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval-worker.js" diff --git a/tests/wpt/tests/trusted-types/block-string-assignment-to-Window-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/block-string-assignment-to-Window-setTimeout-setInterval.html new file mode 100644 index 00000000000..98c2ed7eca6 --- /dev/null +++ b/tests/wpt/tests/trusted-types/block-string-assignment-to-Window-setTimeout-setInterval.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/helper.sub.js"></script> + +<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> +<body> +<script src="support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.js"> +</script> diff --git a/tests/wpt/tests/trusted-types/block-text-node-insertion-into-script-element.html b/tests/wpt/tests/trusted-types/block-text-node-insertion-into-script-element.html index adadfe5a7ad..65b40b933ff 100644 --- a/tests/wpt/tests/trusted-types/block-text-node-insertion-into-script-element.html +++ b/tests/wpt/tests/trusted-types/block-text-node-insertion-into-script-element.html @@ -4,12 +4,13 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/block-text-node-insertion.js"></script> + <script src="support/csp-violations.js"></script> <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <meta http-equiv="Content-Security-Policy" content="connect-src 'none'"> </head> <body> <div id="container"></div> <script id="script1">"hello world!";</script> -<script id="trigger"></script> <script> var container = document.querySelector("#container"); const policy_dict = { @@ -19,23 +20,26 @@ const policy = trustedTypes.createPolicy("policy", policy_dict); + let seenSinks; + function clearSeenSinks() { seenSinks = []; } + clearSeenSinks(); const policy_dict_default = { createScript: (s, _, sink) => { - assert_equals(sink, 'HTMLScriptElement text'); + seenSinks.push(sink); return (s.includes("fail") ? null : s.replace("default", "count")); }, createHTML: (s, _, sink) => { - if (sink) { - assert_equals(sink, 'Element innerHTML'); - } + seenSinks.push(sink); return s.replace(/2/g, "3"); }, }; + function createScriptElement() { return document.createElement("script"); } + // Original report: - promise_test(t => { + promise_test(async t => { // Setup: Create a <script> element with a <p> child. - let s = document.createElement("script"); + let s = createScriptElement(); // Sanity check: Element child content (<p>) doesn't count as source text. let p = document.createElement("p"); @@ -45,99 +49,93 @@ assert_equals(s.text, ""); // Try to insertAdjacentText into the <script>, starting from the <p> - p.insertAdjacentText("beforebegin", - "postMessage('beforebegin should be blocked', '*');"); + await checkMessage(_ => + p.insertAdjacentText("beforebegin", + "postMessage('beforebegin should be blocked', '*');") + ); assert_true(s.text.includes("postMessage")); - p.insertAdjacentText("afterend", - "postMessage('afterend should be blocked', '*');"); + await checkMessage(_ => + p.insertAdjacentText("afterend", + "postMessage('afterend should be blocked', '*');") + ); assert_true(s.text.includes("after")); - return checkMessage(); }, "Regression test: Bypass via insertAdjacentText, initial comment."); - const script_elements = { - "script": doc => doc.createElement("script"), - }; - for (let [element, create_element] of Object.entries(script_elements)) { - // Like the "Original Report" test case above, but avoids use of the "text" - // accessor that <svg:script> doesn't support. - promise_test(t => { - let s = create_element(document); - - // Sanity check: Element child content (<p>) doesn't count as source text. - let p = document.createElement("p"); - p.textContent = "hello('world');"; - s.appendChild(p); - container.appendChild(s); - - // Try to insertAdjacentText into the <script>, starting from the <p> + // Like the "Original Report" test case above, but avoids use of the "text" + // accessor that <svg:script> doesn't support. + promise_test(async t => { + let s = createScriptElement(); + + // Sanity check: Element child content (<p>) doesn't count as source text. + let p = document.createElement("p"); + p.textContent = "hello('world');"; + s.appendChild(p); + container.appendChild(s); + + // Try to insertAdjacentText into the <script>, starting from the <p> + await checkMessage(_ => p.insertAdjacentText("beforebegin", - "postMessage('beforebegin should be blocked', '*');"); - assert_true(s.textContent.includes("postMessage")); + "postMessage('beforebegin should be blocked', '*');") + ); + assert_true(s.textContent.includes("postMessage")); + await checkMessage(_ => p.insertAdjacentText("afterend", - "postMessage('afterend should be blocked', '*');"); - assert_true(s.textContent.includes("after")); - return checkMessage(); - }, "Regression test: Bypass via insertAdjacentText, initial comment. " + element); - - // Variant: Create a <script> element and create & insert a text node. Then - // insert it into the document container to make it live. - promise_test(t => { - // Setup: Create a <script> element, and insert text via a text node. - let s = create_element(document); - let text = document.createTextNode("postMessage('appendChild with a " + - "text node should be blocked', '*');"); - s.appendChild(text); - container.appendChild(s); - return checkMessage(); - }, "Regression test: Bypass via appendChild into off-document script element" + element); - - // Variant: Create a <script> element and insert it into the document. Then - // create a text node and insert it into the live <script> element. - promise_test(t => { - // Setup: Create a <script> element, insert it into the doc, and then create - // and insert text via a text node. - let s = create_element(document); - container.appendChild(s); - let text = document.createTextNode("postMessage('appendChild with a live " + - "text node should be blocked', '*');"); - s.appendChild(text); - return checkMessage(); - }, "Regression test: Bypass via appendChild into live script element " + element); - } - - promise_test(t => { - return checkSecurityPolicyViolationEvent(); - }, "Prep for subsequent tests: Clear SPV event queue."); + "postMessage('afterend should be blocked', '*');") + ); + assert_true(s.textContent.includes("after")); + }, "Regression test: Bypass via insertAdjacentText, textContent."); + + // Variant: Create a <script> element and create & insert a text node. Then + // insert it into the document container to make it live. + promise_test(async t => { + // Setup: Create a <script> element, and insert text via a text node. + let s = createScriptElement(); + let text = document.createTextNode("postMessage('appendChild with a " + + "text node should be blocked', '*');"); + s.appendChild(text); + await checkMessage(_ => container.appendChild(s)); + }, "Regression test: Bypass via appendChild into off-document script element."); + + // Variant: Create a <script> element and insert it into the document. Then + // create a text node and insert it into the live <script> element. + promise_test(async t => { + // Setup: Create a <script> element, insert it into the doc, and then create + // and insert text via a text node. + let s = createScriptElement(); + container.appendChild(s); + let text = document.createTextNode("postMessage('appendChild with a live " + + "text node should be blocked', '*');"); + await checkMessage(_ => s.appendChild(text)); + }, "Regression test: Bypass via appendChild into live script element."); - promise_test(t => { + promise_test(async t => { const inserted_script = document.getElementById("script1"); - assert_throws_js(TypeError, _ => { - inserted_script.innerHTML = "2+2"; - }); - - let new_script = document.createElement("script"); - assert_throws_js(TypeError, _ => { - new_script.innerHTML = "2+2"; - container.appendChild(new_script); - }); + await trusted_type_violation_for(TypeError, _ => + inserted_script.innerHTML = "2+2" + ); + + let new_script = createScriptElement(); + await trusted_type_violation_for(TypeError, _ => + new_script.innerHTML = "2+2" + ); + container.appendChild(new_script); const trusted_html = policy.createHTML("2*4"); assert_equals("" + trusted_html, "3*4"); - inserted_script.innerHTML = trusted_html; + await no_trusted_type_violation_for(_ => + inserted_script.innerHTML = trusted_html + ); assert_equals(inserted_script.textContent, "3*4"); - new_script = document.createElement("script"); + new_script = createScriptElement(); new_script.innerHTML = trusted_html; - container.appendChild(new_script); + await trusted_type_violation_without_exception_for(_ => + container.appendChild(new_script) + ); assert_equals(inserted_script.textContent, "3*4"); - - // We expect 3 SPV events: two for the two assert_throws_js cases, and one - // for script element, which will be rejected at the time of execution. - return checkSecurityPolicyViolationEvent(3); }, "Spot tests around script + innerHTML interaction."); - // Create default policy. Wrapped in a promise_test to ensure it runs only // after the other tests. let default_policy; @@ -146,50 +144,65 @@ return Promise.resolve(); }, "Prep for subsequent tests: Create default policy."); - for (let [element, create_element] of Object.entries(script_elements)) { - promise_test(t => { - let s = create_element(document); - let text = document.createTextNode("postMessage('default', '*');"); - s.appendChild(text); - container.appendChild(s); - - return Promise.all([checkMessage(1), - checkSecurityPolicyViolationEvent(0)]); - }, "Test that default policy applies. " + element); - - promise_test(t => { - let s = create_element(document); - let text = document.createTextNode("fail"); - s.appendChild(text); - container.appendChild(s); - return Promise.all([checkMessage(0), - checkSecurityPolicyViolationEvent(1)]); - }, "Test a failing default policy. " + element); - } - - promise_test(t => { + promise_test(async t => { + t.add_cleanup(clearSeenSinks); + let s = createScriptElement(); + let text = document.createTextNode("postMessage('default', '*');"); + s.appendChild(text); + await no_trusted_type_violation_for(async _ => + await checkMessage(_ => container.appendChild(s), 1) + ); + assert_array_equals(seenSinks, ["HTMLScriptElement text"]); + }, "Test that default policy applies."); + + promise_test(async t => { + t.add_cleanup(clearSeenSinks); + let s = createScriptElement(); + let text = document.createTextNode("fail"); + s.appendChild(text); + await trusted_type_violation_without_exception_for(async _ => + await checkMessage(_ => container.appendChild(s), 0) + ); + assert_array_equals(seenSinks, ["HTMLScriptElement text"]); + }, "Test a failing default policy."); + + promise_test(async t => { + t.add_cleanup(clearSeenSinks); const inserted_script = document.getElementById("script1"); - inserted_script.innerHTML = "2+2"; + await no_trusted_type_violation_for(_ => + inserted_script.innerHTML = "2+2" + ); + assert_array_equals(seenSinks, ["Element innerHTML"]); + clearSeenSinks(); assert_equals(inserted_script.textContent, "3+3"); - let new_script = document.createElement("script"); - new_script.innerHTML = "2+2"; - container.appendChild(new_script); + let new_script = createScriptElement(); + await no_trusted_type_violation_for(_ => { + new_script.innerHTML = "2+2"; + container.appendChild(new_script); + }); + assert_array_equals(seenSinks, ["Element innerHTML", "HTMLScriptElement text"]); + clearSeenSinks(); assert_equals(inserted_script.textContent, "3+3"); const trusted_html = default_policy.createHTML("2*4"); assert_equals("" + trusted_html, "3*4"); - inserted_script.innerHTML = trusted_html; + await no_trusted_type_violation_for(_ => + inserted_script.innerHTML = trusted_html + ); + assert_array_equals(seenSinks, [undefined]); + clearSeenSinks(); assert_equals(inserted_script.textContent, "3*4"); - new_script = document.createElement("script"); - new_script.innerHTML = trusted_html; - container.appendChild(new_script); + new_script = createScriptElement(); + await no_trusted_type_violation_for(_ => { + new_script.innerHTML = trusted_html; + container.appendChild(new_script); + }); + assert_array_equals(seenSinks, ["HTMLScriptElement text"]); + clearSeenSinks(); assert_equals(inserted_script.textContent, "3*4"); - - return checkSecurityPolicyViolationEvent(0); }, "Spot tests around script + innerHTML interaction with default policy."); </script> </body> </html> - diff --git a/tests/wpt/tests/trusted-types/block-text-node-insertion-into-svg-script-element.html b/tests/wpt/tests/trusted-types/block-text-node-insertion-into-svg-script-element.html index 5f0fb78f9bd..f4ff2435035 100644 --- a/tests/wpt/tests/trusted-types/block-text-node-insertion-into-svg-script-element.html +++ b/tests/wpt/tests/trusted-types/block-text-node-insertion-into-svg-script-element.html @@ -4,136 +4,111 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/block-text-node-insertion.js"></script> + <script src="support/csp-violations.js"></script> + <script src="support/namespaces.js"></script> <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <meta http-equiv="Content-Security-Policy" content="connect-src 'none'"> </head> <body> <div id="container"></div> -<script id="script1">"hello world!";</script> -<script id="trigger"></script> +<svg><script id="script1">"hello world!";</script></svg> <script> var container = document.querySelector("#container"); const policy_dict = { createScript: s => (s.includes("fail") ? null : s.replace("default", "count")), createHTML: s => s.replace(/2/g, "3"), }; + const policy = trustedTypes.createPolicy("policy", policy_dict); + let seenSinks; + function clearSeenSinks() { seenSinks = []; } + clearSeenSinks(); const policy_dict_default = { createScript: (s, _, sink) => { - assert_equals(sink, 'SVGScriptElement text'); + seenSinks.push(sink); return (s.includes("fail") ? null : s.replace("default", "count")); }, createHTML: (s, _, sink) => { - if (sink) { - assert_equals(sink, 'Element innerHTML'); - } + seenSinks.push(sink); return s.replace(/2/g, "3"); }, }; - const script_elements = { - "svg:script": doc => doc.createElementNS("http://www.w3.org/2000/svg", "script"), - }; + function createScriptElement() { return document.createElementNS(NSURI_SVG, "script"); } - // Original report: - promise_test(t => { - // Setup: Create a <script> element with a <p> child. - let s = document.createElement("script"); + // Like the "Original Report" test case above, but avoids use of the "text" + // accessor that <svg:script> doesn't support. + promise_test(async t => { + let s = createScriptElement(); // Sanity check: Element child content (<p>) doesn't count as source text. let p = document.createElement("p"); - p.text = "hello('world');"; + p.textContent = "hello('world');"; s.appendChild(p); container.appendChild(s); - assert_equals(s.text, ""); // Try to insertAdjacentText into the <script>, starting from the <p> - p.insertAdjacentText("beforebegin", - "postMessage('beforebegin should be blocked', '*');"); - assert_true(s.text.includes("postMessage")); - p.insertAdjacentText("afterend", - "postMessage('afterend should be blocked', '*');"); - assert_true(s.text.includes("after")); - return checkMessage(); - }, "Regression test: Bypass via insertAdjacentText, initial comment."); - - for (let [element, create_element] of Object.entries(script_elements)) { - // Like the "Original Report" test case above, but avoids use of the "text" - // accessor that <svg:script> doesn't support. - promise_test(t => { - let s = create_element(document); - - // Sanity check: Element child content (<p>) doesn't count as source text. - let p = document.createElement("p"); - p.textContent = "hello('world');"; - s.appendChild(p); - container.appendChild(s); - - // Try to insertAdjacentText into the <script>, starting from the <p> + await checkMessage(_ => p.insertAdjacentText("beforebegin", - "postMessage('beforebegin should be blocked', '*');"); - assert_true(s.textContent.includes("postMessage")); + "postMessage('beforebegin should be blocked', '*');") + ); + assert_true(s.textContent.includes("postMessage")); + await checkMessage(_ => p.insertAdjacentText("afterend", - "postMessage('afterend should be blocked', '*');"); - assert_true(s.textContent.includes("after")); - return checkMessage(); - }, "Regression test: Bypass via insertAdjacentText, initial comment. " + element); - - // Variant: Create a <script> element and create & insert a text node. Then - // insert it into the document container to make it live. - promise_test(t => { - // Setup: Create a <script> element, and insert text via a text node. - let s = create_element(document); - let text = document.createTextNode("postMessage('appendChild with a " + - "text node should be blocked', '*');"); - s.appendChild(text); - container.appendChild(s); - return checkMessage(); - }, "Regression test: Bypass via appendChild into off-document script element" + element); - - // Variant: Create a <script> element and insert it into the document. Then - // create a text node and insert it into the live <script> element. - promise_test(t => { - // Setup: Create a <script> element, insert it into the doc, and then create - // and insert text via a text node. - let s = create_element(document); - container.appendChild(s); - let text = document.createTextNode("postMessage('appendChild with a live " + - "text node should be blocked', '*');"); - s.appendChild(text); - return checkMessage(); - }, "Regression test: Bypass via appendChild into live script element " + element); - } - - promise_test(t => { - return checkSecurityPolicyViolationEvent(); - }, "Prep for subsequent tests: Clear SPV event queue."); + "postMessage('afterend should be blocked', '*');") + ); + assert_true(s.textContent.includes("after")); + }, "Regression test: Bypass via insertAdjacentText, textContent. svg:script"); + + // Variant: Create a <script> element and create & insert a text node. Then + // insert it into the document container to make it live. + promise_test(async t => { + // Setup: Create a <script> element, and insert text via a text node. + let s = createScriptElement(); + let text = document.createTextNode("postMessage('appendChild with a " + + "text node should be blocked', '*');"); + s.appendChild(text); + await checkMessage(_ => container.appendChild(s)); + }, "Regression test: Bypass via appendChild into off-document script element. svg:script"); + + // Variant: Create a <script> element and insert it into the document. Then + // create a text node and insert it into the live <script> element. + promise_test(async t => { + // Setup: Create a <script> element, insert it into the doc, and then create + // and insert text via a text node. + let s = createScriptElement(); + container.appendChild(s); + let text = document.createTextNode("postMessage('appendChild with a live " + + "text node should be blocked', '*');"); + await checkMessage(_ => s.appendChild(text)); + }, "Regression test: Bypass via appendChild into live script element. svg:script"); - promise_test(t => { + promise_test(async t => { const inserted_script = document.getElementById("script1"); - assert_throws_js(TypeError, _ => { - inserted_script.innerHTML = "2+2"; - }); - - let new_script = document.createElement("script"); - assert_throws_js(TypeError, _ => { - new_script.innerHTML = "2+2"; - container.appendChild(new_script); - }); + await trusted_type_violation_for(TypeError, _ => + inserted_script.innerHTML = "2+2" + ); + + let new_script = createScriptElement(); + await trusted_type_violation_for(TypeError, _ => + new_script.innerHTML = "2+2" + ); + container.appendChild(new_script); const trusted_html = policy.createHTML("2*4"); assert_equals("" + trusted_html, "3*4"); - inserted_script.innerHTML = trusted_html; + await no_trusted_type_violation_for(_ => + inserted_script.innerHTML = trusted_html + ); assert_equals(inserted_script.textContent, "3*4"); - new_script = document.createElement("script"); + new_script = createScriptElement(); new_script.innerHTML = trusted_html; - container.appendChild(new_script); + await trusted_type_violation_without_exception_for(_ => + container.appendChild(new_script) + ); assert_equals(inserted_script.textContent, "3*4"); - - // We expect 3 SPV events: two for the two assert_throws_js cases, and one - // for script element, which will be rejected at the time of execution. - return checkSecurityPolicyViolationEvent(3); }, "Spot tests around script + innerHTML interaction."); // Create default policy. Wrapped in a promise_test to ensure it runs only @@ -144,48 +119,64 @@ return Promise.resolve(); }, "Prep for subsequent tests: Create default policy."); - for (let [element, create_element] of Object.entries(script_elements)) { - promise_test(t => { - let s = create_element(document); - let text = document.createTextNode("postMessage('default', '*');"); - s.appendChild(text); - container.appendChild(s); - - return Promise.all([checkMessage(1), - checkSecurityPolicyViolationEvent(0)]); - }, "Test that default policy applies. " + element); - - promise_test(t => { - let s = create_element(document); - let text = document.createTextNode("fail"); - s.appendChild(text); - container.appendChild(s); - return Promise.all([checkMessage(0), - checkSecurityPolicyViolationEvent(1)]); - }, "Test a failing default policy. " + element); - } - - promise_test(t => { + promise_test(async t => { + t.add_cleanup(clearSeenSinks); + let s = createScriptElement(); + let text = document.createTextNode("postMessage('default', '*');"); + s.appendChild(text); + await no_trusted_type_violation_for(async _ => + await checkMessage(_ => container.appendChild(s), 1) + ); + assert_array_equals(seenSinks, ["SVGScriptElement text"]); + }, "Test that default policy applies. svg:script"); + + promise_test(async t => { + t.add_cleanup(clearSeenSinks); + let s = createScriptElement(); + let text = document.createTextNode("fail"); + s.appendChild(text); + await trusted_type_violation_without_exception_for(async _ => + await checkMessage(_ => container.appendChild(s), 0) + ); + assert_array_equals(seenSinks, ["SVGScriptElement text"]); + }, "Test a failing default policy. svg:script"); + + promise_test(async t => { + t.add_cleanup(clearSeenSinks); const inserted_script = document.getElementById("script1"); - inserted_script.innerHTML = "2+2"; + await no_trusted_type_violation_for(_ => + inserted_script.innerHTML = "2+2" + ); + assert_array_equals(seenSinks, ["Element innerHTML"]); + clearSeenSinks(); assert_equals(inserted_script.textContent, "3+3"); - let new_script = document.createElement("script"); - new_script.innerHTML = "2+2"; - container.appendChild(new_script); + let new_script = createScriptElement(); + await no_trusted_type_violation_for(_ => { + new_script.innerHTML = "2+2"; + container.appendChild(new_script); + }); + assert_array_equals(seenSinks, ["Element innerHTML", "SVGScriptElement text"]); + clearSeenSinks(); assert_equals(inserted_script.textContent, "3+3"); const trusted_html = default_policy.createHTML("2*4"); assert_equals("" + trusted_html, "3*4"); - inserted_script.innerHTML = trusted_html; + await no_trusted_type_violation_for(_ => + inserted_script.innerHTML = trusted_html + ); + assert_array_equals(seenSinks, [undefined]); + clearSeenSinks(); assert_equals(inserted_script.textContent, "3*4"); - new_script = document.createElement("script"); - new_script.innerHTML = trusted_html; - container.appendChild(new_script); + new_script = createScriptElement(); + await no_trusted_type_violation_for(_ => { + new_script.innerHTML = trusted_html; + container.appendChild(new_script); + }); + assert_array_equals(seenSinks, ["SVGScriptElement text"]); + clearSeenSinks(); assert_equals(inserted_script.textContent, "3*4"); - - return checkSecurityPolicyViolationEvent(0); }, "Spot tests around script + innerHTML interaction with default policy."); </script> </body> diff --git a/tests/wpt/tests/trusted-types/inheriting-csp-for-local-schemes.html b/tests/wpt/tests/trusted-types/inheriting-csp-for-local-schemes.html new file mode 100644 index 00000000000..de065f0d06e --- /dev/null +++ b/tests/wpt/tests/trusted-types/inheriting-csp-for-local-schemes.html @@ -0,0 +1,127 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<link rel="help" href="https://w3c.github.io/webappsec-csp/#security-inherit-csp"> +<!-- + The following policies from inheriting-csp-for-local-schemes.html.headers + should be inherited by the subframes using local schemes: + - Content-Security-Policy: trusted-types allowedPolicy passThrough + - Content-Security-Policy: require-trusted-types-for 'script' + --> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + const passThroughPolicy = trustedTypes.createPolicy("passThrough", { + createHTML: s => s + }); + + function postMessageAndWaitReplyFromIframe(iframe, data) { + return new Promise(resolve => { + window.addEventListener("message", e => resolve(e.data), {once: true}); + iframe.contentWindow.postMessage(data, '*'); + }); + } + const subframeHTML = `<!DOCTYPE html> +<script>onmessage = (event) => { + try { + switch(event.data.fn) { + case 'setInnerHTML': + document.createElement("div").innerHTML = event.data.arg; + break; + case 'createPolicy': + trustedTypes.createPolicy(event.data.arg); + break; + } + parent.postMessage(null, '*'); + } catch(e) { + parent.postMessage(e, '*'); + } +}\u003C/script>` + + let iframes = []; + + let iframe1 = document.createElement("iframe"); + iframe1.dataset.urlType = "srcdoc"; + iframe1.dataset.inherits = true; + iframe1.srcdoc = passThroughPolicy.createHTML(`<p>srcdoc</p>${subframeHTML}`); + iframes.push(iframe1); + + let iframe2 = document.createElement("iframe"); + iframe2.dataset.urlType = "data"; + iframe2.dataset.inherits = true; + iframe2.src = `data:text/html,<p>data</p>${subframeHTML}`; + iframes.push(iframe2); + + let iframe3 = document.createElement("iframe"); + iframe3.dataset.urlType = "blob"; + iframe3.dataset.inherits = true; + iframe3.src = URL.createObjectURL(new Blob([`<p>blob</p>${subframeHTML}`], + {type: 'text/html'})); + iframes.push(iframe3); + + let iframe4 = document.createElement("iframe"); + iframe4.dataset.urlType = "about:blank"; + iframe4.dataset.inherits = true; + iframe4.src = "about:blank"; + iframe4.onload = _ => { + let iframeDocument = iframe4.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(passThroughPolicy.createHTML( + `<p>overwritten about:blank</p>${subframeHTML}`)); + iframeDocument.close(); + } + iframes.push(iframe4); + + let iframe5 = document.createElement("iframe"); + iframe5.dataset.urlType = "blank.html"; + iframe5.dataset.inherits = false; + iframe5.src = "/common/blank.html"; + iframe5.onload = _ => { + let iframeDocument = iframe5.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(passThroughPolicy.createHTML( + `<p>overwritten blank.html</p>${subframeHTML}`)); + iframeDocument.close(); + } + iframes.push(iframe5); + + document.addEventListener("DOMContentLoaded", _ => + iframes.forEach(iframe => document.body.appendChild(iframe)) + ); + + promise_setup(_ => new Promise(resolve => + window.addEventListener("load", resolve))); + + iframes.forEach(iframe => { + const inherits = iframe.dataset.inherits === "true"; + const whetherItIsInherited = `${inherits ? "should" : "should not"} be inherited`; + + promise_test(async _ => { + let exception = await postMessageAndWaitReplyFromIframe(iframe, { + fn: "setInnerHTML", arg: "unsafe"}); + if (inherits) { + assert_not_equals(exception, null); + assert_true(exception instanceof TypeError); + } else { + assert_equals(exception, null); + } + }, `require-trusted-types-for directive ${whetherItIsInherited} in local ${iframe.dataset.urlType} frames`); + + promise_test(async _ => { + let exception1 = await postMessageAndWaitReplyFromIframe(iframe, { + fn: "createPolicy", arg: "allowedPolicy", + }); + assert_equals(exception1, null); + + let exception2 = await postMessageAndWaitReplyFromIframe(iframe, { + fn: "createPolicy", arg: "forbiddenPolicy", + }); + if (inherits) { + assert_not_equals(exception2, null); + assert_true(exception2 instanceof TypeError); + } else { + assert_equals(exception2, null); + } + }, `trusted-types directive ${whetherItIsInherited} in local ${iframe.dataset.urlType} frames`); + }); +</script> diff --git a/tests/wpt/tests/trusted-types/inheriting-csp-for-local-schemes.html.headers b/tests/wpt/tests/trusted-types/inheriting-csp-for-local-schemes.html.headers new file mode 100644 index 00000000000..a4e416b2bca --- /dev/null +++ b/tests/wpt/tests/trusted-types/inheriting-csp-for-local-schemes.html.headers @@ -0,0 +1,2 @@ +Content-Security-Policy: trusted-types allowedPolicy passThrough +Content-Security-Policy: require-trusted-types-for 'script' diff --git a/tests/wpt/tests/trusted-types/resources/block-text-node-insertion.js b/tests/wpt/tests/trusted-types/resources/block-text-node-insertion.js index 1b924aaf7f3..e9797756417 100644 --- a/tests/wpt/tests/trusted-types/resources/block-text-node-insertion.js +++ b/tests/wpt/tests/trusted-types/resources/block-text-node-insertion.js @@ -14,8 +14,7 @@ // - includes "count": Count these, and later check against expect_count. // - includes "done": Unregister the event handler and finish the test. // - all else: Reject, as this is probably an error in the test. - function checkMessage(expect_count) { - postMessage("done", "*"); + function checkMessage(fn, expect_count) { return new Promise((resolve, reject) => { let count = 0; globalThis.addEventListener("message", function handler(e) { @@ -35,26 +34,7 @@ reject("unexpected message received: " + e.data); } }); + fn(); + postMessage("done", "*"); }); } - - function checkSecurityPolicyViolationEvent(expect_count) { - return new Promise((resolve, reject) => { - let count = 0; - document.addEventListener("securitypolicyviolation", e => { - if (e.sample.includes("trigger")) { - if (expect_count && count != expect_count) { - reject( - `'trigger' received, but unexpected counts: expected ${expect_count} != actual ${count}`); - } else { - resolve(); - } - } else { - count = count + 1; - } - }); - try { - document.getElementById("trigger").text = "trigger fail"; - } catch(e) { } - }); - }
\ No newline at end of file diff --git a/tests/wpt/tests/trusted-types/should-sink-type-mismatch-violation-be-blocked-by-csp-001.html b/tests/wpt/tests/trusted-types/should-sink-type-mismatch-violation-be-blocked-by-csp-001.html new file mode 100644 index 00000000000..5662c64ac4e --- /dev/null +++ b/tests/wpt/tests/trusted-types/should-sink-type-mismatch-violation-be-blocked-by-csp-001.html @@ -0,0 +1,133 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./support/csp-violations.js"></script> +<script> + promise_test(async t => { + let results = await trySendingPlainStringToTrustedTypeSink( + ["script"], + `\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'invalid',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)` + ); + assert_equals(results.length, 1); + assert_true(results[0].exception instanceof TypeError); + assert_equals(results[0].violatedPolicies.length, 5); + }, `Multiple enforce require-trusted-types-for directives.`); + + promise_test(async t => { + let results = await trySendingPlainStringToTrustedTypeSink( + ["script"], + `\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'invalid',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)` + ); + assert_equals(results.length, 1); + assert_equals(results[0].exception, null); + assert_equals(results[0].violatedPolicies.length, 5); + }, `Multiple report-only require-trusted-types-for directives.`); + + promise_test(async t => { + let results = await trySendingPlainStringToTrustedTypeSink( + ["script"], + `\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'unknown',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)` + ); + assert_equals(results.length, 1); + assert_true(results[0].exception instanceof TypeError); + assert_equals(results[0].violatedPolicies.length, 5); + }, `One violated report-only require-trusted-types-for directive followed by multiple enforce directives`); + + promise_test(async t => { + let results = await trySendingPlainStringToTrustedTypeSink( + ["script"], + `\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'unknown',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)` + ); + assert_equals(results.length, 1); + assert_true(results[0].exception instanceof TypeError); + assert_equals(results[0].violatedPolicies.length, 5); + }, `One violated enforce require-trusted-types-for directive followed by multiple report-only directives`); + + + promise_test(async t => { + let results = await trySendingPlainStringToTrustedTypeSink( + ["script"], + `\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy,require-trusted-types-for 'script',True)|\ +header(Content-Security-Policy-Report-Only,require-trusted-types-for 'script',True)` + ); + assert_equals(results.length, 1); + assert_true(results[0].exception instanceof TypeError); + + let violations = results[0].violatedPolicies.sort(); + assert_equals(violations.length, 6); + assert_equals(violations[0].disposition, "enforce"); + assert_equals(violations[0].policy, "require-trusted-types-for 'script'") + assert_equals(violations[1].disposition, "enforce"); + assert_equals(violations[1].policy, "require-trusted-types-for 'script'") + assert_equals(violations[2].disposition, "enforce"); + assert_equals(violations[2].policy, "require-trusted-types-for 'script'") + assert_equals(violations[3].disposition, "report"); + assert_equals(violations[3].policy, "require-trusted-types-for 'script'") + assert_equals(violations[4].disposition, "report"); + assert_equals(violations[4].policy, "require-trusted-types-for 'script'") + assert_equals(violations[5].disposition, "report"); + assert_equals(violations[5].policy, "require-trusted-types-for 'script'") + }, `Mixing enforce and report-only require-trusted-types-for directives.`); + + promise_test(async t => { + let results = await trySendingPlainStringToTrustedTypeSink( + ["script"], + "header(Content-Security-Policy,require-trusted-types-for 'script'%09'script'%0A'script'%0C'script'%0D'script'%20'script',True)", + ); + assert_equals(results.length, 1); + assert_true(results[0].exception instanceof TypeError); + assert_equals(results[0].violatedPolicies.length, 1); + }, `directive "require-trusted-types-for 'script'%09'script'%0A'script'%0C'script'%0D'script'%20'script'" (required-ascii-whitespace)`); + + promise_test(async t => { + let results = await trySendingPlainStringToTrustedTypeSink( + ["script"], + "header(Content-Security-Policy,require-trusted-types-for 'script''script' 'script',True)", + ); + assert_equals(results.length, 1); + assert_equals(results[0].exception, null); + assert_equals(results[0].violatedPolicies.length, 0); + }, `invalid directive "require-trusted-types-for 'script''script'" (no ascii-whitespace)`); + + // https://github.com/w3c/trusted-types/issues/580 + promise_test(async t => { + let results = await trySendingPlainStringToTrustedTypeSink( + ["script"], + "header(Content-Security-Policy,require-trusted-types-for 'script' 'invalid',True)", + ); + assert_equals(results.length, 1); + assert_true(results[0].exception instanceof TypeError); + assert_equals(results[0].violatedPolicies.length, 1); + }, `directive "require-trusted-types-for 'script' 'invalid'" (unknown sink group)`); +</script> diff --git a/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-001.html b/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-001.html new file mode 100644 index 00000000000..6e51bd5ef19 --- /dev/null +++ b/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-001.html @@ -0,0 +1,348 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<meta name="timeout" content="long"> +<link rel="help" href="https://w3c.github.io/trusted-types/dist/spec/#should-block-create-policy"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./support/csp-violations.js"></script> +<script> + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "tt-policy-name", "tt-policy-name", "C", "C"], + "header(Content-Security-Policy,trusted-types tt-policy-name,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + let duplicate = index % 2; + if (result.name === "tt-policy-name" && !duplicate) { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single enforce policy with directive "trusted-type tt-policy-name"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "tt-policy-name", "tt-policy-name", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + let duplicate = index % 2; + if (result.name === "tt-policy-name" && !duplicate) { + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single report-only policy with directive "trusted-type tt-policy-name"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy,trusted-types *,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + let duplicate = index % 2; + if (!duplicate) { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single enforce policy with directive "trusted-type *"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types *,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + let duplicate = index % 2; + if (!duplicate) { + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single report-only policy with directive "trusted-type *"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy,trusted-types 'none',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + }); + }, `single enforce policy with directive "trusted-type 'none'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types 'none',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 1); + }); + }, `single report-only policy with directive "trusted-type 'none'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy,trusted-types 'allow-duplicates',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + }); + }, `single enforce policy with directive "trusted-type 'allow-duplicates'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types 'allow-duplicates',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 1); + }); + }, `single report-only policy with directive "trusted-type 'allow-duplicates'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "tt-policy-name", "tt-policy-name", "C", "C"], + "header(Content-Security-Policy,trusted-types tt-policy-name 'allow-duplicates',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + if (result.name === "tt-policy-name") { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single enforce policy with directive "trusted-type tt-policy-name 'allow-duplicates'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "tt-policy-name", "tt-policy-name", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name 'allow-duplicates',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + if (result.name === "tt-policy-name") { + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single report-only policy with directive "trusted-type tt-policy-name 'allow-duplicates'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy,trusted-types * 'allow-duplicates',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + }); + }, `single enforce policy with directive "trusted-type * 'allow-duplicates'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types * 'allow-duplicates',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + }); + }, `single report-only policy with directive "trusted-type * 'allow-duplicates'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy,trusted-types 'none' 'allow-duplicates',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + }); + }, `single enforce policy with directive "trusted-type 'none' 'allow-duplicates'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types 'none' 'allow-duplicates',True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 1); + }); + }, `single report-only policy with directive "trusted-type 'none' 'allow-duplicates'"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "tt-policy-name", "tt-policy-name", "C", "C"], + "header(Content-Security-Policy,trusted-types 'none' tt-policy-name,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + let duplicate = index % 2; + if (result.name === "tt-policy-name" && !duplicate) { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single enforce policy with directive "trusted-type 'none' tt-policy-name"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "tt-policy-name", "tt-policy-name", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types 'none' tt-policy-name,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + let duplicate = index % 2; + if (result.name === "tt-policy-name" && !duplicate) { + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single report-only policy with directive "trusted-type 'none' tt-policy-name"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy,trusted-types 'none' *,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + let duplicate = index % 2; + if (!duplicate) { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single enforce policy with directive "trusted-type 'none' *"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types 'none' *,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + let duplicate = index % 2; + if (!duplicate) { + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single report-only policy with directive "trusted-type 'none' *"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy,trusted-types tt-policy-name *,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + let duplicate = index % 2; + if (!duplicate) { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single enforce policy with directive "trusted-type tt-policy-name *"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["A", "A", "B", "B", "C", "C"], + "header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name *,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + let duplicate = index % 2; + if (!duplicate) { + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single report-only policy with directive "trusted-type tt-policy-name *"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["tt-policy-name1", "tt-policy-name1", "tt-policy-name2", "tt-policy-name2", "tt-policy-name3", "tt-policy-name3"], + "header(Content-Security-Policy,trusted-types tt-policy-name1 tt-policy-name2 tt-policy-name3,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + let duplicate = index % 2; + if (!duplicate) { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_true(result.exception instanceof TypeError); + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single enforce policy with directive "trusted-type tt-policy-name1 tt-policy-name2 tt-policy-name3"`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["tt-policy-name1", "tt-policy-name1", "tt-policy-name2", "tt-policy-name2", "tt-policy-name3", "tt-policy-name3"], + "header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name1 tt-policy-name2 tt-policy-name3,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + let duplicate = index % 2; + if (!duplicate) { + assert_equals(result.violatedPolicies.length, 0); + } else { + assert_equals(result.violatedPolicies.length, 1); + } + }); + }, `single report-only policy with directive "trusted-type tt-policy-name1 tt-policy-name2 tt-policy-name3"`); + +</script> diff --git a/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-002.html b/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-002.html new file mode 100644 index 00000000000..ef1a4bde378 --- /dev/null +++ b/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-002.html @@ -0,0 +1,95 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<meta name="timeout" content="long"> +<link rel="help" href="https://w3c.github.io/trusted-types/dist/spec/#should-block-create-policy"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./support/csp-violations.js"></script> +<script> + // These are valid values for tt-policy-name per the spec's ABNF. + // https://w3c.github.io/trusted-types/dist/spec/#tt-policy-name + const validTrustedTypePolicyNames = [ + "1", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "0123456789", + "policy-name", + "policy=name", + "policy_name", + "policy/name", + "policy@name", + "policy.name", + "policy%name", + "policy#name", + "6xY/2x=3Y..." + ]; + validTrustedTypePolicyNames.forEach(trustedTypePolicyName => { + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + [trustedTypePolicyName], + `header(Content-Security-Policy,trusted-types ${encodeURIComponent(trustedTypePolicyName)},True)` + ); + assert_equals(results.length, 1); + assert_equals(results[0].name, trustedTypePolicyName); + assert_equals(results[0].exception, null); + assert_equals(results[0].violatedPolicies.length, 0); + }, `valid tt-policy-name name "${trustedTypePolicyName}"`); + }); + + // These are invalid values for tt-policy-name per the spec's ABNF. + // https://w3c.github.io/trusted-types/dist/spec/#tt-policy-name + const invalidTrustedTypePolicyNames = [ + // Space not accepted in tt-policy-name. This is treated as allowing names + // "policy" and "name" and so forbids creation of "policy name". + "policy name", + // '*' is not accepted in tt-policy-name. This could be treated as + // tt-wildcard, but tt-expressions must be separated by a + // required-ascii-whitespace. + "policy*name", + // '$', '?' '!' and non-ASCII letters are not accepted in tt-policy-name. + "policy$name", + "policy?name", + "policy!name", + "política", + ]; + invalidTrustedTypePolicyNames.forEach(trustedTypePolicyName => { + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + [trustedTypePolicyName], + `header(Content-Security-Policy,trusted-types ${encodeURIComponent(trustedTypePolicyName)},True)` + ); + assert_equals(results.length, 1); + assert_equals(results[0].name, trustedTypePolicyName); + // https://w3c.github.io/trusted-types/dist/spec/#create-trusted-type-policy-algorithm + // https://w3c.github.io/trusted-types/dist/spec/#should-block-create-policy + assert_true(results[0].exception instanceof TypeError, "createPolicy() should throw a TypeError."); + assert_equals(results[0].violatedPolicies.length, 1, "createPolicy() should trigger a violation report."); + }, `invalid tt-policy-name name "${trustedTypePolicyName}"`); + }); + + // tt-expressions can separated by any ASCII whitespace per the spec's ABNF: + // https://w3c.github.io/trusted-types/dist/spec/#serialized-tt-configuration + // https://w3c.github.io/webappsec-csp/#grammardef-required-ascii-whitespace + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["_TTP1_", "_TTP2_", "_TTP3_", "_TTP4_", "_TTP5_", "_TTP6_"], + "header(Content-Security-Policy,trusted-types _TTP1_%09_TTP2_%0A_TTP3_%0C_TTP4_%0D_TTP5_%20_TTP6_,True)" + ); + assert_equals(results.length, 6); + results.forEach((result, index) => { + assert_equals(result.exception, null); + assert_equals(result.violatedPolicies.length, 0); + }); + }, `directive "trusted-type _TTP1_%09_TTP2_%0A_TTP3_%0C_TTP4_%0D_TTP5_%20_TTP6_" (required-ascii-whitespace)`); + + // tt-expressions must be separated by a required-ascii-whitespace: + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["_TTP_"], + "header(Content-Security-Policy,trusted-types _TTP_*,True)" + ); + assert_equals(results.length, 1); + assert_true(results[0].exception instanceof TypeError); + assert_equals(results[0].violatedPolicies.length, 1); + }, `invalid directive "trusted-type _TTP" (no ascii whitespace)`); +</script> diff --git a/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-003.html b/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-003.html new file mode 100644 index 00000000000..55f1479e3db --- /dev/null +++ b/tests/wpt/tests/trusted-types/should-trusted-type-policy-creation-be-blocked-by-csp-003.html @@ -0,0 +1,179 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<meta name="timeout" content="long"> +<link rel="help" href="https://w3c.github.io/trusted-types/dist/spec/#should-block-create-policy"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./support/csp-violations.js"></script> +<script> + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["tt-policy-name"], + `\ +header(Content-Security-Policy,trusted-types tt-policy-name,True)|\ +header(Content-Security-Policy,trusted-types *,True)|\ +header(Content-Security-Policy,trusted-types tt-policy-name tt-policy-name,True)|\ +header(Content-Security-Policy,trusted-types tt-policy-name *,True)|\ +header(Content-Security-Policy,trusted-types * tt-policy-name,True)|\ +header(Content-Security-Policy,trusted-types * *,True)|\ +header(Content-Security-Policy,trusted-types tt-policy-name none,True)|\ +header(Content-Security-Policy,trusted-types none tt-policy-name,True)|\ +header(Content-Security-Policy,trusted-types * none,True)|\ +header(Content-Security-Policy,trusted-types none *,True)|\ +` + ); + assert_equals(results.length, 1); + assert_equals(results[0].exception, null); + assert_equals(results[0].violatedPolicies.length, 0); + }, `Multiple non-violated enforce trusted-types directives.`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["tt-policy-name"], + `\ +header(Content-Security-Policy-Report-Only,trusted-types A,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types B,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types C,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types D,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types E,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name,True) +` + ); + assert_equals(results.length, 1); + + assert_equals(results[0].exception, null); + let violations = results[0].violatedPolicies.sort(); + assert_equals(violations.length, 5); + assert_equals(violations[0].disposition, "report"); + assert_equals(violations[0].policy, "trusted-types A") + assert_equals(violations[1].disposition, "report"); + assert_equals(violations[1].policy, "trusted-types B") + assert_equals(violations[2].disposition, "report"); + assert_equals(violations[2].policy, "trusted-types C") + assert_equals(violations[3].disposition, "report"); + assert_equals(violations[3].policy, "trusted-types D") + assert_equals(violations[4].disposition, "report"); + assert_equals(violations[4].policy, "trusted-types E") + }, `Multiple report-only trusted-types directives.`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["tt-policy-name"], + `\ +header(Content-Security-Policy-Report-Only,trusted-types A,True)|\ +header(Content-Security-Policy,trusted-types B,True)|\ +header(Content-Security-Policy,trusted-types C,True)|\ +header(Content-Security-Policy,trusted-types tt-policy-name,True)|\ +header(Content-Security-Policy,trusted-types D,True)|\ +header(Content-Security-Policy,trusted-types E,True)|\ +header(Content-Security-Policy,trusted-types tt-policy-name,True) +` + ); + assert_equals(results.length, 1); + + assert_true(results[0].exception instanceof TypeError); + let violations = results[0].violatedPolicies.sort(); + assert_equals(violations.length, 5); + assert_equals(violations[0].disposition, "enforce"); + assert_equals(violations[0].policy, "trusted-types B") + assert_equals(violations[1].disposition, "enforce"); + assert_equals(violations[1].policy, "trusted-types C") + assert_equals(violations[2].disposition, "enforce"); + assert_equals(violations[2].policy, "trusted-types D") + assert_equals(violations[3].disposition, "enforce"); + assert_equals(violations[3].policy, "trusted-types E") + assert_equals(violations[4].disposition, "report"); + assert_equals(violations[4].policy, "trusted-types A") + }, `One violated report-only trusted-types directive followed by multiple enforce directives.`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["tt-policy-name"], + `\ +header(Content-Security-Policy,trusted-types A,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types B,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types C,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types D,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types E,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name,True) +` + ); + assert_equals(results.length, 1); + + assert_true(results[0].exception instanceof TypeError); + let violations = results[0].violatedPolicies.sort(); + assert_equals(violations.length, 5); + assert_equals(violations[0].disposition, "enforce"); + assert_equals(violations[0].policy, "trusted-types A") + assert_equals(violations[1].disposition, "report"); + assert_equals(violations[1].policy, "trusted-types B") + assert_equals(violations[2].disposition, "report"); + assert_equals(violations[2].policy, "trusted-types C") + assert_equals(violations[3].disposition, "report"); + assert_equals(violations[3].policy, "trusted-types D") + assert_equals(violations[4].disposition, "report"); + assert_equals(violations[4].policy, "trusted-types E") + }, `One violated enforce trusted-types directive followed by multiple report-only directives.`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["tt-policy-name"], + `\ +header(Content-Security-Policy,trusted-types tt-policy-name,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name,True)|\ +header(Content-Security-Policy,trusted-types other-policy-name,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types other-policy-name,True)|\ +header(Content-Security-Policy,trusted-types *,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types *,True)|\ +header(Content-Security-Policy,trusted-types 'none',True)|\ +header(Content-Security-Policy-Report-Only,trusted-types 'none',True)|\ +header(Content-Security-Policy,trusted-types tt-policy-name 'allow-duplicates',True)|\ +header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name 'allow-duplicates',True)` + ); + assert_equals(results.length, 1); + assert_true(results[0].exception instanceof TypeError); + + let violations = results[0].violatedPolicies.sort(); + assert_equals(violations.length, 4); + assert_equals(violations[0].disposition, "enforce"); + assert_equals(violations[0].policy, "trusted-types other-policy-name") + assert_equals(violations[1].disposition, "enforce"); + assert_equals(violations[1].policy, "trusted-types 'none'") + assert_equals(violations[2].disposition, "report"); + assert_equals(violations[2].policy, "trusted-types other-policy-name") + assert_equals(violations[3].disposition, "report"); + assert_equals(violations[3].policy, "trusted-types 'none'") + }, `Mixing enforce and report-only policies with trusted-types directives`); + + promise_test(async t => { + let results = await tryCreatingTrustedTypePoliciesWithCSP( + ["tt-policy-name", "tt-policy-name"], + `\ +header(Content-Security-Policy,trusted-types tt-policy-name,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name,True)|\ +header(Content-Security-Policy,trusted-types *,True)|\ +header(Content-Security-Policy-Report-Only,trusted-types *,True)|\ +header(Content-Security-Policy,trusted-types tt-policy-name 'allow-duplicates',True)|\ +header(Content-Security-Policy-Report-Only,trusted-types tt-policy-name 'allow-duplicates',True)` + ); + assert_equals(results.length, 2); + + assert_equals(results[0].exception, null); + assert_equals(results[0].violatedPolicies.length, 0); + + assert_true(results[1].exception instanceof TypeError); + let violations = results[1].violatedPolicies.sort(); + assert_equals(violations.length, 4); + assert_equals(violations[0].disposition, "enforce"); + assert_equals(violations[0].policy, "trusted-types tt-policy-name") + assert_equals(violations[1].disposition, "enforce"); + assert_equals(violations[1].policy, "trusted-types *") + assert_equals(violations[2].disposition, "report"); + assert_equals(violations[2].policy, "trusted-types tt-policy-name") + assert_equals(violations[3].disposition, "report"); + assert_equals(violations[3].policy, "trusted-types *") + }, `Mixing enforce and report-only policies with trusted-types directives (duplicate policy)`); + +</script> diff --git a/tests/wpt/tests/trusted-types/support/block-eval-function-constructor.js b/tests/wpt/tests/trusted-types/support/block-eval-function-constructor.js index 83bb6063883..e2794cdc52d 100644 --- a/tests/wpt/tests/trusted-types/support/block-eval-function-constructor.js +++ b/tests/wpt/tests/trusted-types/support/block-eval-function-constructor.js @@ -5,7 +5,7 @@ function resetSinkName() { compilationSink = null; } trustedTypes.createPolicy("default", { createScript: (s, _, sink) => { compilationSink = sink; - return `modified '${s}'`; + return `${s} // modified`; }}); test(t => { diff --git a/tests/wpt/tests/trusted-types/support/create-trusted-type-policies.html b/tests/wpt/tests/trusted-types/support/create-trusted-type-policies.html new file mode 100644 index 00000000000..b7039a701a3 --- /dev/null +++ b/tests/wpt/tests/trusted-types/support/create-trusted-type-policies.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<script src="./csp-violations.js"></script> +<script> +const params = new URLSearchParams(window.location.search); +const maxPolicyCount = 10; +let results = []; +async function tryCreatePolicy(name) { + let {violations, exception} = await trusted_type_violations_and_exception_for(_ => { + window.trustedTypes.createPolicy(name) + }); + return { + name: name, + exception: exception, + violatedPolicies: violations.map(v => { + return { policy: v.originalPolicy, disposition: v.disposition}; + }), + }; +} +(async function () { + for (name of params.get("policyNames").split(",", maxPolicyCount)) { + results.push(await tryCreatePolicy(name)); + } + parent.postMessage(results); +})(); +</script> diff --git a/tests/wpt/tests/trusted-types/support/csp-violations.js b/tests/wpt/tests/trusted-types/support/csp-violations.js index c70d7bbecf9..49649f45cd6 100644 --- a/tests/wpt/tests/trusted-types/support/csp-violations.js +++ b/tests/wpt/tests/trusted-types/support/csp-violations.js @@ -39,10 +39,12 @@ function trusted_type_violations_and_exception_for(fn) { } // Force a connect-src violation. WebKit additionally throws a SecurityError // so ignore that. See https://bugs.webkit.org/show_bug.cgi?id=286744 + // Firefox throws a NS_ERROR_CONTENT_BLOCKED exception, so ignore that too. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1951698 try { - new EventSource("/common/blank.html"); + new WebSocket("ws:/common/blank.html"); } catch(e) { - if (!e instanceof DOMException || e.name !== "SecurityError") { + if ((!e instanceof DOMException || e.name !== "SecurityError") && e.name !== "NS_ERROR_CONTENT_BLOCKED") { throw e; } } @@ -84,3 +86,33 @@ function clipSampleIfNeeded(sample) { return sample.substring(0, clippedSampleLength); } + +function tryCreatingTrustedTypePoliciesWithCSP(policyNames, cspHeaders) { + return new Promise(resolve => { + window.addEventListener("message", event => { + resolve(event.data); + }, {once: true}); + let iframe = document.createElement("iframe"); + let url = `/trusted-types/support/create-trusted-type-policies.html?policyNames=${policyNames.map(name => encodeURIComponent(name)).toString()}`; + url += "&pipe=header(Content-Security-Policy,connect-src 'none')" + if (cspHeaders) + url += `|${cspHeaders}`; + iframe.src = url; + document.head.appendChild(iframe); + }); +} + +function trySendingPlainStringToTrustedTypeSink(sinkGroups, cspHeaders) { + return new Promise(resolve => { + window.addEventListener("message", event => { + resolve(event.data); + }, {once: true}); + let iframe = document.createElement("iframe"); + let url = `/trusted-types/support/send-plain-string-to-trusted-type-sink.html?sinkGroups=${sinkGroups.map(name => encodeURIComponent(name)).toString()}`; + url += "&pipe=header(Content-Security-Policy,connect-src 'none')" + if (cspHeaders) + url += `|${cspHeaders}`; + iframe.src = url; + document.head.appendChild(iframe); + }); +} diff --git a/tests/wpt/tests/trusted-types/support/send-plain-string-to-trusted-type-sink.html b/tests/wpt/tests/trusted-types/support/send-plain-string-to-trusted-type-sink.html new file mode 100644 index 00000000000..73b297a7205 --- /dev/null +++ b/tests/wpt/tests/trusted-types/support/send-plain-string-to-trusted-type-sink.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<script src="./csp-violations.js"></script> +<script> +const params = new URLSearchParams(window.location.search); +const maxSinkGroupCount = 10; +let results = []; +async function trySendPlainStringToTrustedTypeSink(sinkGroup) { + let {violations, exception} = await trusted_type_violations_and_exception_for(_ => { + switch (sinkGroup) { + case "script": + document.createElement("div").innerHTML = "unsafe"; + break; + default: + throw "unknown sink group"; + break; + } + }); + return { + sinkGroup: sinkGroup, + exception: exception, + violatedPolicies: violations.map(v => { + return { policy: v.originalPolicy, disposition: v.disposition}; + }), + }; +} +(async function (sinkGroup) { + for (let sinkGroup of params.get("sinkGroups").split(",", maxSinkGroupCount)) { + results.push(await trySendPlainStringToTrustedTypeSink(sinkGroup)); + } + parent.postMessage(results); +})(); +</script> diff --git a/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-DOMWindowTimers-setTimeout-setInterval.js b/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-DOMWindowTimers-setTimeout-setInterval.js new file mode 100644 index 00000000000..15a18304496 --- /dev/null +++ b/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-DOMWindowTimers-setTimeout-setInterval.js @@ -0,0 +1,35 @@ +const globalThisStr = getGlobalThisStr(); +// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps, +// step 9.6.1.1. +const expectedSinkPrefix = globalThisStr.includes("Window") ? "Window" : "WorkerGlobalScope"; + +const policy = trustedTypes.createPolicy("dummy", { createScript: x => x }); +const input = ';'.repeat(100); + +promise_test(async t => { + await no_trusted_type_violation_for(_ => + setTimeout(policy.createScript(input)) + ); +}, "No violation reported for setTimeout with TrustedScript."); + +promise_test(async t => { + await no_trusted_type_violation_for(_ => + setInterval(policy.createScript(input)) + ); +}, "No violation reported for setInterval with TrustedScript."); + +promise_test(async t => { + let violation = await trusted_type_violation_for(TypeError, _ => + setTimeout(input) + ); + assert_equals(violation.blockedURI, "trusted-types-sink"); + assert_equals(violation.sample, `${expectedSinkPrefix} setTimeout|${clipSampleIfNeeded(input)}`); +}, "Violation report for setTimeout with plain string."); + +promise_test(async t => { + let violation = await trusted_type_violation_for(TypeError, _ => + setInterval(input) + ); + assert_equals(violation.blockedURI, "trusted-types-sink"); + assert_equals(violation.sample, `${expectedSinkPrefix} setInterval|${clipSampleIfNeeded(input)}`); +}, "Violation report for setInterval with plain string.");
\ No newline at end of file diff --git a/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-setTimeout-setInterval-worker.js b/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-setTimeout-setInterval-worker.js new file mode 100644 index 00000000000..7c65802c9ef --- /dev/null +++ b/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-setTimeout-setInterval-worker.js @@ -0,0 +1,11 @@ +const testSetupPolicy = trustedTypes.createPolicy("p", { createScriptURL: s => s }); + +importScripts(testSetupPolicy.createScriptURL("/resources/testharness.js")); +importScripts(testSetupPolicy.createScriptURL("helper.sub.js")); +importScripts(testSetupPolicy.createScriptURL("csp-violations.js")); + +importScripts(testSetupPolicy.createScriptURL( + "trusted-types-reporting-for-DOMWindowTimers-setTimeout-setInterval.js" +)); + +done(); diff --git a/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-setTimeout-setInterval-worker.js.headers b/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-setTimeout-setInterval-worker.js.headers new file mode 100644 index 00000000000..54d8b1d4c12 --- /dev/null +++ b/tests/wpt/tests/trusted-types/support/trusted-types-reporting-for-setTimeout-setInterval-worker.js.headers @@ -0,0 +1,2 @@ +Content-Security-Policy: require-trusted-types-for 'script'; +Content-Security-Policy: connect-src 'none'
\ No newline at end of file diff --git a/tests/wpt/tests/trusted-types/trusted-types-reporting-for-DedicatedWorker-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/trusted-types-reporting-for-DedicatedWorker-setTimeout-setInterval.html new file mode 100644 index 00000000000..7e44a12fd2d --- /dev/null +++ b/tests/wpt/tests/trusted-types/trusted-types-reporting-for-DedicatedWorker-setTimeout-setInterval.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> + fetch_tests_from_worker(new Worker( + "support/trusted-types-reporting-for-setTimeout-setInterval-worker.js" + )); +</script> diff --git a/tests/wpt/tests/trusted-types/trusted-types-reporting-for-SharedWorker-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/trusted-types-reporting-for-SharedWorker-setTimeout-setInterval.html new file mode 100644 index 00000000000..7c97f644873 --- /dev/null +++ b/tests/wpt/tests/trusted-types/trusted-types-reporting-for-SharedWorker-setTimeout-setInterval.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> + fetch_tests_from_worker(new SharedWorker( + "support/trusted-types-reporting-for-setTimeout-setInterval-worker.js" + )); +</script> diff --git a/tests/wpt/tests/trusted-types/trusted-types-reporting-for-Window-setTimeout-setInterval.html b/tests/wpt/tests/trusted-types/trusted-types-reporting-for-Window-setTimeout-setInterval.html new file mode 100644 index 00000000000..87e26060ab7 --- /dev/null +++ b/tests/wpt/tests/trusted-types/trusted-types-reporting-for-Window-setTimeout-setInterval.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/helper.sub.js"></script> +<script src="support/csp-violations.js"></script> + +<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; connect-src 'none';"> +<body> +<script src="support/trusted-types-reporting-for-DOMWindowTimers-setTimeout-setInterval.js"> +</script> diff --git a/tests/wpt/tests/trusted-types/worker-constructor.https.html b/tests/wpt/tests/trusted-types/worker-constructor.https.html deleted file mode 100644 index 3118f2f9107..00000000000 --- a/tests/wpt/tests/trusted-types/worker-constructor.https.html +++ /dev/null @@ -1,106 +0,0 @@ -<!doctype html> -<html> -<head> - <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> -</head> -<body> -<script> - -const test_url = "support/WorkerGlobalScope-importScripts.https.js" -const trusted_url = trustedTypes.createPolicy("anythinggoes", { - createScriptURL: x => x}).createScriptURL(test_url); -const default_url = "support/WorkerGlobalScope-importScripts.potato.js" - -async function service_worker(url) { - if (!('serviceWorker' in navigator)) return Promise.resolve(); - - const scope = 'support/some/scope/for/this/test'; - const reg = await navigator.serviceWorker.getRegistration(scope); - if (reg) await reg.unregister(); - return await navigator.serviceWorker.register(url, {scope}); -} - -// Most tests below don't need promises, but the ones related to -// ServiceWorkers do. Since we can't mix promise and non-promise tests, -// we'll just run the non-promise tests in the main function and return -// an empty-resolved promise for those. -// Since an active default policy will affect all subsequent DOM operations, -// we're wrapping policy creation in a promise_test. Together, this will -// force proper serialization of all tests. -// -// Generally, we don't actually care what the workers here do, we'll merely -// check whether creation succeeds. - -promise_test(t => { - new Worker(trusted_url); - return Promise.resolve(); -}, "Create Worker via ScriptTestUrl"); - -promise_test(t => { - new SharedWorker(trusted_url); - return Promise.resolve(); -}, "Create SharedWorker via ScriptTestUrl"); - -promise_test(t => { - return service_worker(trusted_url); -}, "Create ServiceWorker via ScriptTestUrl"); - -promise_test(t => { - assert_throws_js(TypeError, () => new Worker(test_url)); - return Promise.resolve(); -}, "Block Worker creation via string"); - -promise_test(t => { - assert_throws_js(TypeError, () => new SharedWorker(test_url)); - return Promise.resolve(); -}, "Block SharedWorker creation via string"); - -promise_test(t => { - return promise_rejects_js(t, TypeError, service_worker(test_url)); -}, "Block ServiceWorker creation via String"); - -// Tests with default policy. -let seenTrustedTypeName; -let seenSinkName; -function resetSeenArguments() { - seenTrustedTypeName = undefined; - seenSinkName = undefined; -} - -promise_test(t => { - trustedTypes.createPolicy("default", { - createScriptURL: (input, trustedTypeName, sinkName) => { - seenTrustedTypeName = trustedTypeName; - seenSinkName = sinkName; - return input.replace("potato", "https"); - }}); - return Promise.resolve(); -}, "Setup default policy."); - -promise_test(t => { - t.add_cleanup(resetSeenArguments); - new Worker(default_url); - assert_equals(seenTrustedTypeName, "TrustedScriptURL"); - assert_equals(seenSinkName, "Worker constructor"); - return Promise.resolve(); -}, "Create Worker via string with default policy."); - -promise_test(t => { - t.add_cleanup(resetSeenArguments); - new SharedWorker(default_url); - assert_equals(seenTrustedTypeName, "TrustedScriptURL"); - assert_equals(seenSinkName, "SharedWorker constructor"); - return Promise.resolve(); -}, "Create SharedWorker via string with default policy."); - -promise_test(async t => { - t.add_cleanup(resetSeenArguments); - await service_worker(default_url); - assert_equals(seenTrustedTypeName, "TrustedScriptURL"); - assert_equals(seenSinkName, "ServiceWorkerContainer register"); -}, "Create ServiceWorker via string with default policy."); - -</script> -</body> diff --git a/tests/wpt/tests/url/IdnaTestV2-removed.window.js b/tests/wpt/tests/url/IdnaTestV2-removed.window.js new file mode 100644 index 00000000000..0f70f84816a --- /dev/null +++ b/tests/wpt/tests/url/IdnaTestV2-removed.window.js @@ -0,0 +1,21 @@ +promise_test(() => fetch("resources/IdnaTestV2-removed.json").then(res => res.json()).then(runTests), "Loading data…"); + +function runTests(idnaTests) { + for (const idnaTest of idnaTests) { + if (typeof idnaTest === "string") { + continue // skip comments + } + + test(() => { + if (idnaTest.output === null) { + assert_throws_js(TypeError, () => new URL(`https://${idnaTest.input}/x`)); + } else { + const url = new URL(`https://${idnaTest.input}/x`); + assert_equals(url.host, idnaTest.output); + assert_equals(url.hostname, idnaTest.output); + assert_equals(url.pathname, "/x"); + assert_equals(url.href, `https://${idnaTest.output}/x`); + } + }, `ToASCII("${idnaTest.input}")${idnaTest.comment ? " " + idnaTest.comment : ""}`); + } +} diff --git a/tests/wpt/tests/url/IdnaTestV2.window.js b/tests/wpt/tests/url/IdnaTestV2.window.js index 8873886bdab..4bfa3118ace 100644 --- a/tests/wpt/tests/url/IdnaTestV2.window.js +++ b/tests/wpt/tests/url/IdnaTestV2.window.js @@ -1,19 +1,5 @@ promise_test(() => fetch("resources/IdnaTestV2.json").then(res => res.json()).then(runTests), "Loading data…"); -// Performance impact of this seems negligible (performance.now() diff in WebKit went from 48 to 52) -// and there was a preference to let more non-ASCII hit the parser. -function encodeHostEndingCodePoints(input) { - let output = ""; - for (const codePoint of input) { - if ([":", "/", "?", "#", "\\"].includes(codePoint)) { - output += encodeURIComponent(codePoint); - } else { - output += codePoint; - } - } - return output; -} - function runTests(idnaTests) { for (const idnaTest of idnaTests) { if (typeof idnaTest === "string") { @@ -22,15 +8,12 @@ function runTests(idnaTests) { if (idnaTest.input === "") { continue // cannot test empty string input through new URL() } - // Percent-encode the input such that ? and equivalent code points do not end up counting as - // part of the URL, but are parsed through the host parser instead. - const encodedInput = encodeHostEndingCodePoints(idnaTest.input); test(() => { if (idnaTest.output === null) { - assert_throws_js(TypeError, () => new URL(`https://${encodedInput}/x`)); + assert_throws_js(TypeError, () => new URL(`https://${idnaTest.input}/x`)); } else { - const url = new URL(`https://${encodedInput}/x`); + const url = new URL(`https://${idnaTest.input}/x`); assert_equals(url.host, idnaTest.output); assert_equals(url.hostname, idnaTest.output); assert_equals(url.pathname, "/x"); diff --git a/tests/wpt/tests/url/resources/IdnaTestV2-removed.json b/tests/wpt/tests/url/resources/IdnaTestV2-removed.json new file mode 100644 index 00000000000..523dac3bfa1 --- /dev/null +++ b/tests/wpt/tests/url/resources/IdnaTestV2-removed.json @@ -0,0 +1,104 @@ +[ + "This is generated with the help from ../tools/IdnaTestV2-compare.py.", + "These tests are from an older IdnaTestV2 and thus the comment line may no longer be accurate.", + { + "comment": "P1; V6; V3 (ignored)", + "input": "-\udb40\ude56\ua867\uff0e\udb40\ude82\ud8dc\udd83\ud83c\udd09", + "output": null + }, + { + "comment": "P1; V5; V6", + "input": "\ud83c\udd04\uff0e\u1cdc\u2488\u00df", + "output": null + }, + { + "comment": "P1; V5; V6", + "input": "\ud83c\udd04\uff0e\u1cdc\u2488SS", + "output": null + }, + { + "comment": "P1; V5; V6", + "input": "\ud83c\udd04\uff0e\u1cdc\u2488ss", + "output": null + }, + { + "comment": "P1; V5; V6", + "input": "\ud83c\udd04\uff0e\u1cdc\u2488Ss", + "output": null + }, + { + "comment": "C2; P1; V6", + "input": "\u0756\u3002\u3164\u200d\u03c2", + "output": null + }, + { + "comment": "C2; P1; V6", + "input": "\u0756\u3002\u1160\u200d\u03c2", + "output": null + }, + { + "comment": "C2; P1; V6", + "input": "\u0756\u3002\u1160\u200d\u03a3", + "output": null + }, + { + "comment": "C2; P1; V6", + "input": "\u0756\u3002\u1160\u200d\u03c3", + "output": null + }, + { + "comment": "C2; P1; V6", + "input": "\u0756\u3002\u3164\u200d\u03a3", + "output": null + }, + { + "comment": "C2; P1; V6", + "input": "\u0756\u3002\u3164\u200d\u03c3", + "output": null + }, + { + "comment": "P1; V6", + "input": "\ud83c\udd07\u4f10\ufe12.\ud831\ude5a\ua8c4", + "output": null + }, + { + "comment": "P1; V5; V6", + "input": "\ud802\ude3f.\ud83c\udd06\u2014", + "output": null + }, + { + "comment": "C2; P1; V5; V6", + "input": "\u1c32\ud83c\udd08\u2f9b\u05a6\uff0e\u200d\uda7e\udd64\u07fd", + "output": null + }, + { + "comment": "C2; P1; V5; V6", + "input": "\ud83e\udc9f\ud83c\udd08\u200d\ua84e\uff61\u0f84", + "output": null + }, + { + "comment": "P1; V6", + "input": "\udaa5\udeaa\uff61\ud83c\udd02", + "output": null + }, + { + "comment": "C2; P1; V6", + "input": "\u186f\u2689\u59f6\ud83c\udd09\uff0e\u06f7\u200d\ud83c\udfaa\u200d", + "output": null + }, + { + "comment": "C1; P1; V5; V6", + "input": "\ua67d\u200c\ud87e\uddf5\ud83c\udd06\uff61\u200c\ud804\udc42\u1b01", + "output": null + }, + { + "comment": "C1; P1; V5; V6", + "input": "\ua67d\u200c\u9723\ud83c\udd06\uff61\u200c\ud804\udc42\u1b01", + "output": null + }, + { + "comment": "C1; P1; V5; V6; V3 (ignored)", + "input": "-\u1897\u200c\ud83c\udd04.\ud805\udf22", + "output": null + } +] diff --git a/tests/wpt/tests/url/resources/IdnaTestV2.json b/tests/wpt/tests/url/resources/IdnaTestV2.json index 669d4b09382..f0dcced7102 100644 --- a/tests/wpt/tests/url/resources/IdnaTestV2.json +++ b/tests/wpt/tests/url/resources/IdnaTestV2.json @@ -1,6 +1,6 @@ [ "THIS IS A GENERATED FILE. PLEASE DO NOT MODIFY DIRECTLY. See ../tools/IdnaTestV2-parser.py instead.", - "--exclude-ipv4-like: True; --exclude-std3: True; --exclude_bidi: True", + "--exclude-ipv4-like: True; --exclude-std3: True; --exclude-bidi: True", { "input": "fass.de", "output": "fass.de" @@ -166,12 +166,17 @@ "output": "xn--pkf" }, { - "comment": "A4_2 (ignored)", + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "", + "output": "" + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", "input": "\u3002", "output": "." }, { - "comment": "A4_2 (ignored)", + "comment": "A4_1 (ignored); A4_2 (ignored)", "input": ".", "output": "." }, @@ -269,6 +274,14 @@ "output": "xn--bb-eka" }, { + "input": "FA\u1e9e.de", + "output": "xn--fa-hia.de" + }, + { + "input": "FA\u1e9e.DE", + "output": "xn--fa-hia.de" + }, + { "input": "\u03b2\u03cc\u03bb\u03bf\u03c2.com", "output": "xn--nxasmm1c.com" }, @@ -437,30 +450,37 @@ "output": "xn--mgba3gch31f.com" }, { + "comment": "A4_2 (ignored)", "input": "a.b\uff0ec\u3002d\uff61", "output": "a.b.c.d." }, { + "comment": "A4_2 (ignored)", "input": "a.b.c\u3002d\u3002", "output": "a.b.c.d." }, { + "comment": "A4_2 (ignored)", "input": "A.B.C\u3002D\u3002", "output": "a.b.c.d." }, { + "comment": "A4_2 (ignored)", "input": "A.b.c\u3002D\u3002", "output": "a.b.c.d." }, { + "comment": "A4_2 (ignored)", "input": "a.b.c.d.", "output": "a.b.c.d." }, { + "comment": "A4_2 (ignored)", "input": "A.B\uff0eC\u3002D\uff61", "output": "a.b.c.d." }, { + "comment": "A4_2 (ignored)", "input": "A.b\uff0ec\u3002D\uff61", "output": "a.b.c.d." }, @@ -530,7 +550,7 @@ "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "a\u2488com", "output": null }, @@ -539,22 +559,22 @@ "output": "a1.com" }, { - "comment": "P1; V6", + "comment": "V7", "input": "A\u2488COM", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "A\u2488Com", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--acom-0w1b", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--a-ecp.ru", "output": null }, @@ -564,7 +584,7 @@ "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--a.pt", "output": null }, @@ -609,9 +629,9 @@ "output": null }, { - "comment": "V2 (ignored)", + "comment": "V4; V2 (ignored)", "input": "xn--xn--a--gua.pt", - "output": "xn--xn--a--gua.pt" + "output": null }, { "input": "\u65e5\u672c\u8a9e\u3002\uff2a\uff30", @@ -830,6 +850,35 @@ "output": "xn--bssffl" }, { + "input": "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.", + "output": "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b." + }, + { + "comment": "A4_1 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c", + "output": "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a", + "output": "123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.", + "output": "123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a." + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { "input": "\u00e41234567890123456789012345678901234567890123456789012345", "output": "xn--1234567890123456789012345678901234567890123456789012345-9te" }, @@ -850,6 +899,151 @@ "output": "xn--1234567890123456789012345678901234567890123456789012345-9te" }, { + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00e4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890a\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "input": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00e4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890a\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b." + }, + { + "comment": "A4_1 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00e4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c" + }, + { + "comment": "A4_1 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890a\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c" + }, + { + "comment": "A4_1 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901C", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c" + }, + { + "comment": "A4_1 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901C", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c" + }, + { + "comment": "A4_1 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00e41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890a\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789A", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789A", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00e41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890a\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789A.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789A.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a." + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00e41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890a\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890B", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { "comment": "V2 (ignored); V3 (ignored); A4_2 (ignored)", "input": "a.b..-q--a-.e", "output": "a.b..-q--a-.e" @@ -895,7 +1089,7 @@ "output": "a..c" }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "a.-b.", "output": "a.-b." }, @@ -915,6 +1109,11 @@ "output": "a.bc--de.f" }, { + "comment": "V4; V2 (ignored)", + "input": "xn--xn---epa", + "output": null + }, + { "comment": "A4_2 (ignored)", "input": "\u00e4.\u00ad.c", "output": "xn--4ca..c" @@ -940,27 +1139,27 @@ "output": "xn--4ca..c" }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "\u00e4.-b.", "output": "xn--4ca.-b." }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "a\u0308.-b.", "output": "xn--4ca.-b." }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "A\u0308.-B.", "output": "xn--4ca.-b." }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "\u00c4.-B.", "output": "xn--4ca.-b." }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "xn--4ca.-b.", "output": "xn--4ca.-b." }, @@ -1060,22 +1259,22 @@ "output": "xn--4ca.bc--de.f" }, { - "comment": "V5", + "comment": "V6", "input": "a.b.\u0308c.d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "A.B.\u0308C.D", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "A.b.\u0308c.d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "a.b.xn--c-bcb.d", "output": null }, @@ -1175,11 +1374,6 @@ "output": null }, { - "comment": "A4_2 (ignored)", - "input": "", - "output": "" - }, - { "comment": "C2", "input": "xn--1ug", "output": null @@ -1331,22 +1525,207 @@ "output": "..xn--skb" }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "U1 (ignored)", + "input": "$", + "output": "$" + }, + { + "comment": "U1 (ignored)", + "input": "\u2477.four", + "output": "(4).four" + }, + { + "comment": "U1 (ignored)", + "input": "(4).four", + "output": "(4).four" + }, + { + "comment": "U1 (ignored)", + "input": "\u2477.FOUR", + "output": "(4).four" + }, + { + "comment": "U1 (ignored)", + "input": "\u2477.Four", + "output": "(4).four" + }, + { + "comment": "V7; A3", + "input": "a\ud900z", + "output": null + }, + { + "comment": "V7; A3", + "input": "A\ud900Z", + "output": null + }, + { + "comment": "P4; A4_1 (ignored); A4_2 (ignored)", + "input": "xn--", + "output": null + }, + { + "comment": "P4", + "input": "xn---", + "output": null + }, + { + "comment": "P4", + "input": "xn--ASCII-", + "output": null + }, + { + "input": "ascii", + "output": "ascii" + }, + { + "comment": "P4", + "input": "xn--unicode-.org", + "output": null + }, + { + "input": "unicode.org", + "output": "unicode.org" + }, + { + "input": "\uf951\ud87e\udc68\ud87e\udc74\ud87e\udd1f\ud87e\udd5f\ud87e\uddbf", + "output": "xn--snl253bgitxhzwu2arn60c" + }, + { + "input": "\u964b\u36fc\u5f53\ud850\udfab\u7aee\u45d7", + "output": "xn--snl253bgitxhzwu2arn60c" + }, + { + "input": "xn--snl253bgitxhzwu2arn60c", + "output": "xn--snl253bgitxhzwu2arn60c" + }, + { + "input": "\u96fb\ud844\udf6a\u5f33\u43ab\u7aae\u4d57", + "output": "xn--kbo60w31ob3z6t3av9z5b" + }, + { + "input": "xn--kbo60w31ob3z6t3av9z5b", + "output": "xn--kbo60w31ob3z6t3av9z5b" + }, + { + "input": "xn--A-1ga", + "output": "xn--a-1ga" + }, + { + "input": "a\u00f6", + "output": "xn--a-1ga" + }, + { + "input": "ao\u0308", + "output": "xn--a-1ga" + }, + { + "input": "AO\u0308", + "output": "xn--a-1ga" + }, + { + "input": "A\u00d6", + "output": "xn--a-1ga" + }, + { + "input": "A\u00f6", + "output": "xn--a-1ga" + }, + { + "input": "Ao\u0308", + "output": "xn--a-1ga" + }, + { + "input": "\uff1d\u0338", + "output": "xn--1ch" + }, + { + "input": "\u2260", + "output": "xn--1ch" + }, + { + "input": "=\u0338", + "output": "xn--1ch" + }, + { + "input": "xn--1ch", + "output": "xn--1ch" + }, + { + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b." + }, + { + "comment": "A4_1 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u0308123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c" + }, + { + "comment": "A4_1 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c4123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901c" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a" + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a." + }, + { + "comment": "A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a.", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789a." + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890A\u03081234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "A4_1 (ignored); A4_2 (ignored)", + "input": "123456789012345678901234567890123456789012345678901234567890123.1234567890\u00c41234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b", + "output": "123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890b" + }, + { + "comment": "V7; V3 (ignored)", "input": "\u2495\u221d\u065f\uda0e\udd26\uff0e-\udb40\udd2f", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "14.\u221d\u065f\uda0e\udd26.-\udb40\udd2f", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "14.xn--7hb713l3v90n.-", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--7hb713lfwbi1311b.-", "output": null }, @@ -1359,92 +1738,177 @@ "output": "xn--8c9a.xn--qsb" }, { - "comment": "P1; V6", + "comment": "C2", + "input": "\u200d\u2260\u1899\u226f.\uc1a3-\u1874\u10a0", + "output": null + }, + { + "comment": "C2", + "input": "\u200d=\u0338\u1899>\u0338.\u1109\u1169\u11be-\u1874\u10a0", + "output": null + }, + { + "comment": "C2", + "input": "\u200d=\u0338\u1899>\u0338.\u1109\u1169\u11be-\u1874\u2d00", + "output": null + }, + { + "comment": "C2", + "input": "\u200d\u2260\u1899\u226f.\uc1a3-\u1874\u2d00", + "output": null + }, + { + "input": "xn--jbf911clb.xn----p9j493ivi4l", + "output": "xn--jbf911clb.xn----p9j493ivi4l" + }, + { + "input": "\u2260\u1899\u226f.\uc1a3-\u1874\u2d00", + "output": "xn--jbf911clb.xn----p9j493ivi4l" + }, + { + "input": "=\u0338\u1899>\u0338.\u1109\u1169\u11be-\u1874\u2d00", + "output": "xn--jbf911clb.xn----p9j493ivi4l" + }, + { + "input": "=\u0338\u1899>\u0338.\u1109\u1169\u11be-\u1874\u10a0", + "output": "xn--jbf911clb.xn----p9j493ivi4l" + }, + { + "input": "\u2260\u1899\u226f.\uc1a3-\u1874\u10a0", + "output": "xn--jbf911clb.xn----p9j493ivi4l" + }, + { + "comment": "C2", + "input": "xn--jbf929a90b0b.xn----p9j493ivi4l", + "output": null + }, + { + "comment": "V7", + "input": "xn--jbf911clb.xn----6zg521d196p", + "output": null + }, + { + "comment": "C2; V7", + "input": "xn--jbf929a90b0b.xn----6zg521d196p", + "output": null + }, + { + "comment": "V7", "input": "\ud97d\udf9c\uff0e\ud803\udfc7\u0fa2\u077d\u0600", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud97d\udf9c\uff0e\ud803\udfc7\u0fa1\u0fb7\u077d\u0600", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud97d\udf9c.\ud803\udfc7\u0fa1\u0fb7\u077d\u0600", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--gw68a.xn--ifb57ev2psc6027m", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud84f\udcd4\u0303.\ud805\udcc2", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--nsa95820a.xn--wz1d", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\ud9d4\udfad.\u10b2\ud804\uddc0", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\ud9d4\udfad.\u2d12\ud804\uddc0", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--bn95b.xn--9kj2034e", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug15083f.xn--9kj2034e", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--bn95b.xn--qnd6272k", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug15083f.xn--qnd6272k", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u7e71\ud805\uddbf\u200d.\uff18\ufe12", "output": null }, { - "comment": "V6", + "comment": "A4_2 (ignored)", + "input": "xn--gl0as212a.i.", + "output": "xn--gl0as212a.i." + }, + { + "comment": "A4_2 (ignored)", + "input": "\u7e71\ud805\uddbf.i.", + "output": "xn--gl0as212a.i." + }, + { + "comment": "A4_2 (ignored)", + "input": "\u7e71\ud805\uddbf.I.", + "output": "xn--gl0as212a.i." + }, + { + "comment": "A4_2 (ignored)", + "input": "xn--1ug6928ac48e.i.", + "output": "xn--1ug6928ac48e.i." + }, + { + "comment": "A4_2 (ignored)", + "input": "\u7e71\ud805\uddbf\u200d.i.", + "output": "xn--1ug6928ac48e.i." + }, + { + "comment": "A4_2 (ignored)", + "input": "\u7e71\ud805\uddbf\u200d.I.", + "output": "xn--1ug6928ac48e.i." + }, + { + "comment": "V7", "input": "xn--gl0as212a.xn--8-o89h", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--1ug6928ac48e.xn--8-o89h", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "\udb40\uddbe\uff0e\ud838\udc08", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "\udb40\uddbe.\ud838\udc08", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": ".xn--ph4h", "output": null }, @@ -1469,18 +1933,22 @@ "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--ss-59d.", "output": "xn--ss-59d." }, { + "comment": "A4_2 (ignored)", "input": "ss\u06eb.", "output": "xn--ss-59d." }, { + "comment": "A4_2 (ignored)", "input": "SS\u06eb.", "output": "xn--ss-59d." }, { + "comment": "A4_2 (ignored)", "input": "Ss\u06eb.", "output": "xn--ss-59d." }, @@ -1495,301 +1963,381 @@ "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\udb41\udc35\u200c\u2488\uff0e\udb40\udf87", "output": null }, { - "comment": "C1; P1; V6; A4_2 (ignored)", + "comment": "C1; V7; A4_2 (ignored)", "input": "\udb41\udc35\u200c1..\udb40\udf87", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "xn--1-bs31m..xn--tv36e", "output": null }, { - "comment": "C1; V6; A4_2 (ignored)", + "comment": "C1; V7; A4_2 (ignored)", "input": "xn--1-rgn37671n..xn--tv36e", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--tshz2001k.xn--tv36e", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug88o47900b.xn--tv36e", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb3c\ude23\u065f\uaab2\u00df\u3002\udaf1\udce7", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb3c\ude23\u065f\uaab2SS\u3002\udaf1\udce7", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb3c\ude23\u065f\uaab2ss\u3002\udaf1\udce7", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb3c\ude23\u065f\uaab2Ss\u3002\udaf1\udce7", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--ss-3xd2839nncy1m.xn--bb79d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--zca92z0t7n5w96j.xn--bb79d", "output": null }, { - "comment": "C1; C2; P1; V6", + "comment": "C1; C2; V7", "input": "\u0774\u200c\ud83a\udd3f\u3002\ud8b5\ude10\u425c\u200d\ud9be\udd3c", "output": null }, { - "comment": "C1; C2; P1; V6", + "comment": "C1; C2; V7", "input": "\u0774\u200c\ud83a\udd1d\u3002\ud8b5\ude10\u425c\u200d\ud9be\udd3c", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--4pb2977v.xn--z0nt555ukbnv", "output": null }, { - "comment": "C1; C2; V6", + "comment": "C1; C2; V7", "input": "xn--4pb607jjt73a.xn--1ug236ke314donv1a", "output": null }, { - "comment": "P1; V6", + "comment": "V6; A4_2 (ignored)", "input": "\u3164\u094d\u10a0\u17d0.\u180b", "output": null }, { - "comment": "P1; V6", + "comment": "V6; A4_2 (ignored)", "input": "\u1160\u094d\u10a0\u17d0.\u180b", "output": null }, { - "comment": "P1; V6", + "comment": "V6; A4_2 (ignored)", "input": "\u1160\u094d\u2d00\u17d0.\u180b", "output": null }, { - "comment": "V6", - "input": "xn--n3b742bkqf4ty.", + "comment": "V6; A4_2 (ignored)", + "input": "xn--n3b445e53p.", "output": null }, { - "comment": "V6", - "input": "xn--n3b468aoqa89r.", + "comment": "V6; A4_2 (ignored)", + "input": "\u3164\u094d\u2d00\u17d0.\u180b", "output": null }, { - "comment": "P1; V6", - "input": "\u3164\u094d\u2d00\u17d0.\u180b", + "comment": "V7; A4_2 (ignored)", + "input": "xn--n3b742bkqf4ty.", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", + "input": "xn--n3b468aoqa89r.", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", "input": "xn--n3b445e53po6d.", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--n3b468azngju2a.", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u2763\u200d\uff0e\u09cd\ud807\udc3d\u0612\ua929", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u2763\u200d.\u09cd\ud807\udc3d\u0612\ua929", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--pei.xn--0fb32q3w7q2g4d", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--1ugy10a.xn--0fb32q3w7q2g4d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u0349\u3002\ud85e\udc6b", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--nua.xn--bc6k", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; A4_2 (ignored)", "input": "\ud807\udc3f\udb40\udd66\uff0e\u1160", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; A4_2 (ignored)", "input": "\ud807\udc3f\udb40\udd66.\u1160", "output": null }, { - "comment": "V5; V6", + "comment": "V6; A4_2 (ignored)", + "input": "xn--ok3d.", + "output": null + }, + { + "comment": "V6; V7", "input": "xn--ok3d.xn--psd", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u850f\uff61\ud807\udc3a", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u850f\u3002\ud807\udc3a", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--uy1a.xn--jk3d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--8g1d12120a.xn--5l6h", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud804\udee7\ua9c02\uff61\u39c9\uda09\udd84", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud804\udee7\ua9c02\u3002\u39c9\uda09\udd84", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--2-5z4eu89y.xn--97l02706d", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\u2938\u03c2\ud8ab\udc40\uff61\uffa0", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\u2938\u03c2\ud8ab\udc40\u3002\u1160", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\u2938\u03a3\ud8ab\udc40\u3002\u1160", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\u2938\u03c3\ud8ab\udc40\u3002\u1160", "output": null }, { - "comment": "V6", - "input": "xn--4xa192qmp03d.xn--psd", + "comment": "V7; A4_2 (ignored)", + "input": "xn--4xa192qmp03d.", "output": null }, { - "comment": "V6", - "input": "xn--3xa392qmp03d.xn--psd", + "comment": "V7; A4_2 (ignored)", + "input": "xn--3xa392qmp03d.", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\u2938\u03a3\ud8ab\udc40\uff61\uffa0", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\u2938\u03c3\ud8ab\udc40\uff61\uffa0", "output": null }, { - "comment": "V6", + "comment": "V7", + "input": "xn--4xa192qmp03d.xn--psd", + "output": null + }, + { + "comment": "V7", + "input": "xn--3xa392qmp03d.xn--psd", + "output": null + }, + { + "comment": "V7", "input": "xn--4xa192qmp03d.xn--cl7c", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--3xa392qmp03d.xn--cl7c", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\u200d\udb7d\udc56\udb40\udc50\uff0e\u05bd\ud826\udfb0\ua85d\ud800\udee1", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\u200d\udb7d\udc56\udb40\udc50.\u05bd\ud826\udfb0\ua85d\ud800\udee1", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--b726ey18m.xn--ldb8734fg0qcyzzg", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u3002\udbcc\ude35\u03c2\ud8c2\udc07\u3002\ud802\udf88", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u3002\udbcc\ude35\u03a3\ud8c2\udc07\u3002\ud802\udf88", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u3002\udbcc\ude35\u03c3\ud8c2\udc07\u3002\ud802\udf88", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--4xa68573c7n64d.xn--f29c", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--3xa88573c7n64d.xn--f29c", "output": null }, { + "comment": "V7", + "input": "\u2489\udb40\ude93\u2260\uff61\u10bf\u2b23\u10a8", + "output": null + }, + { + "comment": "V7", + "input": "\u2489\udb40\ude93=\u0338\uff61\u10bf\u2b23\u10a8", + "output": null + }, + { + "comment": "V7", + "input": "2.\udb40\ude93\u2260\u3002\u10bf\u2b23\u10a8", + "output": null + }, + { + "comment": "V7", + "input": "2.\udb40\ude93=\u0338\u3002\u10bf\u2b23\u10a8", + "output": null + }, + { + "comment": "V7", + "input": "2.\udb40\ude93=\u0338\u3002\u2d1f\u2b23\u2d08", + "output": null + }, + { + "comment": "V7", + "input": "2.\udb40\ude93\u2260\u3002\u2d1f\u2b23\u2d08", + "output": null + }, + { + "comment": "V7", + "input": "2.xn--1chz4101l.xn--45iz7d6b", + "output": null + }, + { + "comment": "V7", + "input": "\u2489\udb40\ude93=\u0338\uff61\u2d1f\u2b23\u2d08", + "output": null + }, + { + "comment": "V7", + "input": "\u2489\udb40\ude93\u2260\uff61\u2d1f\u2b23\u2d08", + "output": null + }, + { + "comment": "V7", + "input": "xn--1ch07f91401d.xn--45iz7d6b", + "output": null + }, + { + "comment": "V7", + "input": "2.xn--1chz4101l.xn--gnd9b297j", + "output": null + }, + { + "comment": "V7", + "input": "xn--1ch07f91401d.xn--gnd9b297j", + "output": null + }, + { "input": "\ud83a\udd37.\ud802\udf90\ud83a\udc81\ud803\ude60\u0624", "output": "xn--ve6h.xn--jgb1694kz0b2176a" }, @@ -1810,53 +2358,60 @@ "output": "xn--ve6h.xn--jgb1694kz0b2176a" }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored); U1 (ignored)", "input": "-\udb40\ude56\ua867\uff0e\udb40\ude82\ud8dc\udd83\ud83c\udd09", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored); U1 (ignored)", + "input": "-\udb40\ude56\ua867.\udb40\ude82\ud8dc\udd838,", + "output": null + }, + { + "comment": "V7; V3 (ignored); U1 (ignored)", + "input": "xn----hg4ei0361g.xn--8,-k362evu488a", + "output": null + }, + { + "comment": "V7; V3 (ignored)", "input": "xn----hg4ei0361g.xn--207ht163h7m94c", "output": null }, { - "comment": "C1; V5", + "comment": "C1; V6", "input": "\u200c\uff61\u0354", "output": null }, { - "comment": "C1; V5", + "comment": "C1; V6", "input": "\u200c\u3002\u0354", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": ".xn--yua", "output": null }, { - "comment": "C1; V5", + "comment": "C1; V6", "input": "xn--0ug.xn--yua", "output": null }, { - "comment": "P1; V6", "input": "\ud83a\udd25\udb40\udd6e\uff0e\u1844\u10ae", - "output": null + "output": "xn--de6h.xn--37e857h" }, { - "comment": "P1; V6", "input": "\ud83a\udd25\udb40\udd6e.\u1844\u10ae", - "output": null + "output": "xn--de6h.xn--37e857h" }, { "input": "\ud83a\udd25\udb40\udd6e.\u1844\u2d0e", "output": "xn--de6h.xn--37e857h" }, { - "comment": "P1; V6", "input": "\ud83a\udd03\udb40\udd6e.\u1844\u10ae", - "output": null + "output": "xn--de6h.xn--37e857h" }, { "input": "\ud83a\udd03\udb40\udd6e.\u1844\u2d0e", @@ -1871,104 +2426,101 @@ "output": "xn--de6h.xn--37e857h" }, { - "comment": "P1; V6", "input": "\ud83a\udd03.\u1844\u10ae", - "output": null + "output": "xn--de6h.xn--37e857h" }, { "input": "\ud83a\udd03.\u1844\u2d0e", "output": "xn--de6h.xn--37e857h" }, { - "comment": "V6", - "input": "xn--de6h.xn--mnd799a", - "output": null - }, - { "input": "\ud83a\udd25\udb40\udd6e\uff0e\u1844\u2d0e", "output": "xn--de6h.xn--37e857h" }, { - "comment": "P1; V6", "input": "\ud83a\udd03\udb40\udd6e\uff0e\u1844\u10ae", - "output": null + "output": "xn--de6h.xn--37e857h" }, { "input": "\ud83a\udd03\udb40\udd6e\uff0e\u1844\u2d0e", "output": "xn--de6h.xn--37e857h" }, { - "comment": "P1; V6", - "input": "\ud83a\udd25.\u1844\u10ae", + "comment": "V7", + "input": "xn--de6h.xn--mnd799a", "output": null }, { - "comment": "P1; V5; V6", + "input": "\ud83a\udd25.\u1844\u10ae", + "output": "xn--de6h.xn--37e857h" + }, + { + "comment": "V6; V7", "input": "\u0fa4\ud986\udd2f\uff0e\ud835\udfed\u10bb", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0fa4\ud986\udd2f.1\u10bb", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0fa4\ud986\udd2f.1\u2d1b", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--0fd40533g.xn--1-tws", "output": null }, { - "comment": "V5; V6", - "input": "xn--0fd40533g.xn--1-q1g", + "comment": "V6; V7", + "input": "\u0fa4\ud986\udd2f\uff0e\ud835\udfed\u2d1b", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u0fa4\ud986\udd2f\uff0e\ud835\udfed\u2d1b", + "comment": "V6; V7", + "input": "xn--0fd40533g.xn--1-q1g", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03c2\ud9d5\udf0c\uff18.\ud83a\udf64", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03c2\ud9d5\udf0c8.\ud83a\udf64", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03a3\ud9d5\udf0c8.\ud83a\udf64", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03c3\ud9d5\udf0c8.\ud83a\udf64", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--8-zmb14974n.xn--su6h", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--8-xmb44974n.xn--su6h", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03a3\ud9d5\udf0c\uff18.\ud83a\udf64", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03c3\ud9d5\udf0c\uff18.\ud83a\udf64", "output": null }, @@ -1993,68 +2545,158 @@ "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\ub253\u6cd3\ud833\udd7d.\u09cd\u200d", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u1102\u1170\u11be\u6cd3\ud833\udd7d.\u09cd\u200d", "output": null }, { - "comment": "V5; V6", + "comment": "V6", "input": "xn--lwwp69lqs7m.xn--b7b", "output": null }, { - "comment": "V5; V6", + "comment": "V6", "input": "xn--lwwp69lqs7m.xn--b7b605i", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", + "input": "\u1b44\uff0e\u1baa-\u226e\u2260", + "output": null + }, + { + "comment": "V6", + "input": "\u1b44\uff0e\u1baa-<\u0338=\u0338", + "output": null + }, + { + "comment": "V6", + "input": "\u1b44.\u1baa-\u226e\u2260", + "output": null + }, + { + "comment": "V6", + "input": "\u1b44.\u1baa-<\u0338=\u0338", + "output": null + }, + { + "comment": "V6", + "input": "xn--1uf.xn----nmlz65aub", + "output": null + }, + { + "comment": "V6", "input": "\u1bf3\u10b1\u115f\uff0e\ud804\udd34\u2132", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u1bf3\u10b1\u115f.\ud804\udd34\u2132", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u1bf3\u2d11\u115f.\ud804\udd34\u214e", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u1bf3\u10b1\u115f.\ud804\udd34\u214e", "output": null }, { - "comment": "V5; V6", + "comment": "V6", + "input": "xn--1zf224e.xn--73g3065g", + "output": null + }, + { + "comment": "V6", + "input": "\u1bf3\u2d11\u115f\uff0e\ud804\udd34\u214e", + "output": null + }, + { + "comment": "V6", + "input": "\u1bf3\u10b1\u115f\uff0e\ud804\udd34\u214e", + "output": null + }, + { + "comment": "V6; V7", "input": "xn--pnd26a55x.xn--73g3065g", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--osd925cvyn.xn--73g3065g", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--pnd26a55x.xn--f3g7465g", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u1bf3\u2d11\u115f\uff0e\ud804\udd34\u214e", + "comment": "V7", + "input": "\u10a9\u7315\udba5\udeeb\u226e\uff0e\ufe12", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u1bf3\u10b1\u115f\uff0e\ud804\udd34\u214e", + "comment": "V7", + "input": "\u10a9\u7315\udba5\udeeb<\u0338\uff0e\ufe12", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": "\u10a9\u7315\udba5\udeeb\u226e.\u3002", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": "\u10a9\u7315\udba5\udeeb<\u0338.\u3002", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": "\u2d09\u7315\udba5\udeeb<\u0338.\u3002", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": "\u2d09\u7315\udba5\udeeb\u226e.\u3002", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": "xn--gdh892bbz0d5438s..", + "output": null + }, + { + "comment": "V7", + "input": "\u2d09\u7315\udba5\udeeb<\u0338\uff0e\ufe12", + "output": null + }, + { + "comment": "V7", + "input": "\u2d09\u7315\udba5\udeeb\u226e\uff0e\ufe12", + "output": null + }, + { + "comment": "V7", + "input": "xn--gdh892bbz0d5438s.xn--y86c", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": "xn--hnd212gz32d54x5r..", + "output": null + }, + { + "comment": "V7", + "input": "xn--hnd212gz32d54x5r.xn--y86c", "output": null }, { @@ -2088,7 +2730,7 @@ "output": null }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "xn----1fa1788k.", "output": "xn----1fa1788k." }, @@ -2108,277 +2750,340 @@ "output": null }, { - "comment": "C1; C2; P1; V5; V6", + "comment": "C1; C2; V6; V7", "input": "\ub8f1\u200d\ud880\udf68\u200c\u3002\ud836\ude16\ufe12", "output": null }, { - "comment": "C1; C2; P1; V5; V6", + "comment": "C1; C2; V6; V7", "input": "\u1105\u116e\u11b0\u200d\ud880\udf68\u200c\u3002\ud836\ude16\ufe12", "output": null }, { - "comment": "C1; C2; V5", + "comment": "C1; C2; V6; A4_2 (ignored)", "input": "\ub8f1\u200d\ud880\udf68\u200c\u3002\ud836\ude16\u3002", "output": null }, { - "comment": "C1; C2; V5", + "comment": "C1; C2; V6; A4_2 (ignored)", "input": "\u1105\u116e\u11b0\u200d\ud880\udf68\u200c\u3002\ud836\ude16\u3002", "output": null }, { - "comment": "V5", + "comment": "V6; A4_2 (ignored)", "input": "xn--ct2b0738h.xn--772h.", "output": null }, { - "comment": "C1; C2; V5", + "comment": "C1; C2; V6; A4_2 (ignored)", "input": "xn--0ugb3358ili2v.xn--772h.", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--ct2b0738h.xn--y86cl899a", "output": null }, { - "comment": "C1; C2; V5; V6", + "comment": "C1; C2; V6; V7", "input": "xn--0ugb3358ili2v.xn--y86cl899a", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7; U1 (ignored)", "input": "\ud83c\udd04\uff0e\u1cdc\u2488\u00df", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; U1 (ignored)", + "input": "3,.\u1cdc1.\u00df", + "output": null + }, + { + "comment": "V6; U1 (ignored)", + "input": "3,.\u1cdc1.SS", + "output": null + }, + { + "comment": "V6; U1 (ignored)", + "input": "3,.\u1cdc1.ss", + "output": null + }, + { + "comment": "V6; U1 (ignored)", + "input": "3,.\u1cdc1.Ss", + "output": null + }, + { + "comment": "V6; U1 (ignored)", + "input": "3,.xn--1-43l.ss", + "output": null + }, + { + "comment": "V6; U1 (ignored)", + "input": "3,.xn--1-43l.xn--zca", + "output": null + }, + { + "comment": "V6; V7; U1 (ignored)", "input": "\ud83c\udd04\uff0e\u1cdc\u2488SS", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7; U1 (ignored)", "input": "\ud83c\udd04\uff0e\u1cdc\u2488ss", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7; U1 (ignored)", "input": "\ud83c\udd04\uff0e\u1cdc\u2488Ss", "output": null }, { - "comment": "V5; V6", - "input": "xn--x07h.xn--ss-k1r094b", + "comment": "V6; V7; U1 (ignored)", + "input": "3,.xn--ss-k1r094b", "output": null }, { - "comment": "V5; V6", - "input": "xn--x07h.xn--zca344lmif", + "comment": "V6; V7; U1 (ignored)", + "input": "3,.xn--zca344lmif", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", - "input": "\u1bf3.-\u900b\ud98e\uddad\udb25\ude6e", + "comment": "V6; V7", + "input": "xn--x07h.xn--ss-k1r094b", "output": null }, { - "comment": "V5; V6; V3 (ignored)", - "input": "xn--1zf.xn----483d46987byr50b", + "comment": "V6; V7", + "input": "xn--x07h.xn--zca344lmif", + "output": null + }, + { + "comment": "C2; V6", + "input": "\u1dfd\u103a\u094d\uff0e\u2260\u200d\u31db", "output": null }, { - "comment": "C2; P1; V6", - "input": "\u0756\u3002\u3164\u200d\u03c2", + "comment": "C2; V6", + "input": "\u103a\u094d\u1dfd\uff0e\u2260\u200d\u31db", "output": null }, { - "comment": "C2; P1; V6", - "input": "\u0756\u3002\u1160\u200d\u03c2", + "comment": "C2; V6", + "input": "\u103a\u094d\u1dfd\uff0e=\u0338\u200d\u31db", "output": null }, { - "comment": "C2; P1; V6", - "input": "\u0756\u3002\u1160\u200d\u03a3", + "comment": "C2; V6", + "input": "\u103a\u094d\u1dfd.\u2260\u200d\u31db", "output": null }, { - "comment": "C2; P1; V6", - "input": "\u0756\u3002\u1160\u200d\u03c3", + "comment": "C2; V6", + "input": "\u103a\u094d\u1dfd.=\u0338\u200d\u31db", "output": null }, { "comment": "V6", - "input": "xn--9ob.xn--4xa380e", + "input": "xn--n3b956a9zm.xn--1ch912d", "output": null }, { "comment": "C2; V6", - "input": "xn--9ob.xn--4xa380ebol", + "input": "xn--n3b956a9zm.xn--1ug63gz5w", "output": null }, { - "comment": "C2; V6", - "input": "xn--9ob.xn--3xa580ebol", + "comment": "V6; V7; V3 (ignored)", + "input": "\u1bf3.-\u900b\ud98e\uddad\udb25\ude6e", "output": null }, { - "comment": "C2; P1; V6", - "input": "\u0756\u3002\u3164\u200d\u03a3", + "comment": "V6; V7; V3 (ignored)", + "input": "xn--1zf.xn----483d46987byr50b", "output": null }, { - "comment": "C2; P1; V6", - "input": "\u0756\u3002\u3164\u200d\u03c3", + "input": "xn--9ob.xn--4xa", + "output": "xn--9ob.xn--4xa" + }, + { + "input": "\u0756.\u03c3", + "output": "xn--9ob.xn--4xa" + }, + { + "input": "\u0756.\u03a3", + "output": "xn--9ob.xn--4xa" + }, + { + "comment": "V7", + "input": "xn--9ob.xn--4xa380e", "output": null }, { - "comment": "V6", + "comment": "C2; V7", + "input": "xn--9ob.xn--4xa380ebol", + "output": null + }, + { + "comment": "C2; V7", + "input": "xn--9ob.xn--3xa580ebol", + "output": null + }, + { + "comment": "V7", "input": "xn--9ob.xn--4xa574u", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--9ob.xn--4xa795lq2l", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--9ob.xn--3xa995lq2l", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u1846\u10a3\uff61\udb3a\udca7\u0315\u200d\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u1846\u10a3\u3002\udb3a\udca7\u0315\u200d\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u1846\u2d03\u3002\udb3a\udca7\u0315\u200d\u200d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--57e237h.xn--5sa98523p", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--57e237h.xn--5sa649la993427a", "output": null }, { - "comment": "V6", - "input": "xn--bnd320b.xn--5sa98523p", + "comment": "C2; V7", + "input": "\u1846\u2d03\uff61\udb3a\udca7\u0315\u200d\u200d", "output": null }, { - "comment": "C2; V6", - "input": "xn--bnd320b.xn--5sa649la993427a", + "comment": "V7", + "input": "xn--bnd320b.xn--5sa98523p", "output": null }, { - "comment": "C2; P1; V6", - "input": "\u1846\u2d03\uff61\udb3a\udca7\u0315\u200d\u200d", + "comment": "C2; V7", + "input": "xn--bnd320b.xn--5sa649la993427a", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud838\udc28\uff61\u1b44\uda45\udee8\ud838\udf87", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud838\udc28\u3002\u1b44\uda45\udee8\ud838\udf87", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--mi4h.xn--1uf6843smg20c", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u189b\udb60\udd5f\u00df.\u1327", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u189b\udb60\udd5fSS.\u1327", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u189b\udb60\udd5fss.\u1327", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u189b\udb60\udd5fSs.\u1327", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--ss-7dp66033t.xn--p5d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--zca562jc642x.xn--p5d", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u2b92\u200c.\ud909\ude97\u200c", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--b9i.xn--5p9y", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ugx66b.xn--0ugz2871c", "output": null }, { - "comment": "P1; V6", - "input": "\u00df\uff61\ud800\udef3\u10ac\u0fb8", + "comment": "V6; V7", + "input": "\u226f\ud805\udf2b\udb42\udf47.\u1734\ud909\udfa4\ud804\udf6c\u18a7", "output": null }, { - "comment": "P1; V6", - "input": "\u00df\u3002\ud800\udef3\u10ac\u0fb8", + "comment": "V6; V7", + "input": ">\u0338\ud805\udf2b\udb42\udf47.\u1734\ud909\udfa4\ud804\udf6c\u18a7", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--hdhx157g68o0g.xn--c0e65eu616c34o7a", "output": null }, { + "input": "\u00df\uff61\ud800\udef3\u10ac\u0fb8", + "output": "xn--zca.xn--lgd921mvv0m" + }, + { + "input": "\u00df\u3002\ud800\udef3\u10ac\u0fb8", + "output": "xn--zca.xn--lgd921mvv0m" + }, + { "input": "\u00df\u3002\ud800\udef3\u2d0c\u0fb8", "output": "xn--zca.xn--lgd921mvv0m" }, { - "comment": "P1; V6", "input": "SS\u3002\ud800\udef3\u10ac\u0fb8", - "output": null + "output": "ss.xn--lgd921mvv0m" }, { "input": "ss\u3002\ud800\udef3\u2d0c\u0fb8", "output": "ss.xn--lgd921mvv0m" }, { - "comment": "P1; V6", "input": "Ss\u3002\ud800\udef3\u10ac\u0fb8", - "output": null - }, - { - "comment": "V6", - "input": "ss.xn--lgd10cu829c", - "output": null + "output": "ss.xn--lgd921mvv0m" }, { "input": "ss.xn--lgd921mvv0m", @@ -2389,14 +3094,12 @@ "output": "ss.xn--lgd921mvv0m" }, { - "comment": "P1; V6", "input": "SS.\ud800\udef3\u10ac\u0fb8", - "output": null + "output": "ss.xn--lgd921mvv0m" }, { - "comment": "P1; V6", "input": "Ss.\ud800\udef3\u10ac\u0fb8", - "output": null + "output": "ss.xn--lgd921mvv0m" }, { "input": "xn--zca.xn--lgd921mvv0m", @@ -2407,335 +3110,498 @@ "output": "xn--zca.xn--lgd921mvv0m" }, { - "comment": "V6", - "input": "xn--zca.xn--lgd10cu829c", - "output": null - }, - { "input": "\u00df\uff61\ud800\udef3\u2d0c\u0fb8", "output": "xn--zca.xn--lgd921mvv0m" }, { - "comment": "P1; V6", "input": "SS\uff61\ud800\udef3\u10ac\u0fb8", - "output": null + "output": "ss.xn--lgd921mvv0m" }, { "input": "ss\uff61\ud800\udef3\u2d0c\u0fb8", "output": "ss.xn--lgd921mvv0m" }, { - "comment": "P1; V6", "input": "Ss\uff61\ud800\udef3\u10ac\u0fb8", + "output": "ss.xn--lgd921mvv0m" + }, + { + "comment": "V7", + "input": "ss.xn--lgd10cu829c", + "output": null + }, + { + "comment": "V7", + "input": "xn--zca.xn--lgd10cu829c", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1a5a\ud82e\udd9d\u0c4d\u3002\ud829\udf6c\ud835\udff5", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1a5a\ud82e\udd9d\u0c4d\u3002\ud829\udf6c9", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--lqc703ebm93a.xn--9-000p", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\u1856\uff61\u031f\ud91d\udee8\u0b82-", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\u1856\u3002\u031f\ud91d\udee8\u0b82-", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn--m8e.xn----mdb555dkk71m", "output": null }, { - "comment": "P1; V6", + "comment": "V6; V7", + "input": "\u0596\u10ab\uff0e\ud835\udff3\u226f\ufe12\ufe0a", + "output": null + }, + { + "comment": "V6; V7", + "input": "\u0596\u10ab\uff0e\ud835\udff3>\u0338\ufe12\ufe0a", + "output": null + }, + { + "comment": "V6; A4_2 (ignored)", + "input": "\u0596\u10ab.7\u226f\u3002\ufe0a", + "output": null + }, + { + "comment": "V6; A4_2 (ignored)", + "input": "\u0596\u10ab.7>\u0338\u3002\ufe0a", + "output": null + }, + { + "comment": "V6; A4_2 (ignored)", + "input": "\u0596\u2d0b.7>\u0338\u3002\ufe0a", + "output": null + }, + { + "comment": "V6; A4_2 (ignored)", + "input": "\u0596\u2d0b.7\u226f\u3002\ufe0a", + "output": null + }, + { + "comment": "V6; A4_2 (ignored)", + "input": "xn--hcb613r.xn--7-pgo.", + "output": null + }, + { + "comment": "V6; V7", + "input": "\u0596\u2d0b\uff0e\ud835\udff3>\u0338\ufe12\ufe0a", + "output": null + }, + { + "comment": "V6; V7", + "input": "\u0596\u2d0b\uff0e\ud835\udff3\u226f\ufe12\ufe0a", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--hcb613r.xn--7-pgoy530h", + "output": null + }, + { + "comment": "V6; V7; A4_2 (ignored)", + "input": "xn--hcb887c.xn--7-pgo.", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--hcb887c.xn--7-pgoy530h", + "output": null + }, + { + "comment": "V7; U1 (ignored)", "input": "\ud83c\udd07\u4f10\ufe12.\ud831\ude5a\ua8c4", "output": null }, { - "comment": "V6", + "comment": "V7; U1 (ignored); A4_2 (ignored)", + "input": "6,\u4f10\u3002.\ud831\ude5a\ua8c4", + "output": null + }, + { + "comment": "V7; U1 (ignored); A4_2 (ignored)", + "input": "xn--6,-7i3c..xn--0f9ao925c", + "output": null + }, + { + "comment": "V7; U1 (ignored)", + "input": "xn--6,-7i3cj157d.xn--0f9ao925c", + "output": null + }, + { + "comment": "V7", "input": "xn--woqs083bel0g.xn--0f9ao925c", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\udb40\udda0\uff0e\ud99d\udc34\udaf1\udfc8", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\udb40\udda0.\ud99d\udc34\udaf1\udfc8", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--rx21bhv12i", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "-.\u1886\udb47\udca3-", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "-.xn----pbkx6497q", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udafd\udcb0\uff0e-\ud835\udffb\u00df", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udafd\udcb0.-5\u00df", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udafd\udcb0.-5SS", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udafd\udcb0.-5ss", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--t960e.-5ss", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--t960e.xn---5-hia", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udafd\udcb0\uff0e-\ud835\udffbSS", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udafd\udcb0\uff0e-\ud835\udffbss", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udafd\udcb0\uff0e-\ud835\udffbSs", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udafd\udcb0.-5Ss", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d\ud802\ude3f.\ud83e\udd12\u10c5\uda06\udfb6", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d\ud802\ude3f.\ud83e\udd12\u2d25\uda06\udfb6", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--0s9c.xn--tljz038l0gz4b", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--1ug9533g.xn--tljz038l0gz4b", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--0s9c.xn--9nd3211w0gz4b", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--1ug9533g.xn--9nd3211w0gz4b", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud894\udec5\u3002\u00df\ud873\udd69\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud894\udec5\u3002SS\ud873\udd69\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud894\udec5\u3002ss\ud873\udd69\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud894\udec5\u3002Ss\ud873\udd69\u200d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--ey1p.xn--ss-eq36b", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--ey1p.xn--ss-n1tx0508a", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--ey1p.xn--zca870nz438b", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\uff61\ud805\uddbf\u1abb\u03c2\u2260", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\uff61\ud805\uddbf\u1abb\u03c2=\u0338", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\u3002\ud805\uddbf\u1abb\u03c2\u2260", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\u3002\ud805\uddbf\u1abb\u03c2=\u0338", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\u3002\ud805\uddbf\u1abb\u03a3=\u0338", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\u3002\ud805\uddbf\u1abb\u03a3\u2260", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\u3002\ud805\uddbf\u1abb\u03c3\u2260", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\u3002\ud805\uddbf\u1abb\u03c3=\u0338", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--zb9h5968x.xn--4xa378i1mfjw7y", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\uff61\ud805\uddbf\u1abb\u03a3=\u0338", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\uff61\ud805\uddbf\u1abb\u03a3\u2260", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\uff61\ud805\uddbf\u1abb\u03c3\u2260", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\udb40\udd6f\ud9df\udf6d\u200c\ud83d\udf2d\uff61\ud805\uddbf\u1abb\u03c3=\u0338", + "output": null + }, + { + "comment": "C2; V7", "input": "\u248b\uff61\u2488\u200d\uda8f\udd22", "output": null }, { - "comment": "C2; P1; V6; A4_2 (ignored)", + "comment": "C2; V7; A4_2 (ignored)", "input": "4.\u30021.\u200d\uda8f\udd22", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "4..1.xn--sf51d", "output": null }, { - "comment": "C2; V6; A4_2 (ignored)", + "comment": "C2; V7; A4_2 (ignored)", "input": "4..1.xn--1ug64613i", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--wsh.xn--tsh07994h", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--wsh.xn--1ug58o74922a", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10b3\ud805\udf2b\u200d\uda1e\udf53\uff0e\u06a7\ud807\udc36", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10b3\ud805\udf2b\u200d\uda1e\udf53.\u06a7\ud807\udc36", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2d13\ud805\udf2b\u200d\uda1e\udf53.\u06a7\ud807\udc36", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--blj6306ey091d.xn--9jb4223l", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--1ugy52cym7p7xu5e.xn--9jb4223l", "output": null }, { - "comment": "V6", + "comment": "V7", + "input": "\u2d13\ud805\udf2b\u200d\uda1e\udf53\uff0e\u06a7\ud807\udc36", + "output": null + }, + { + "comment": "V7", "input": "xn--rnd8945ky009c.xn--9jb4223l", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--rnd479ep20q7x12e.xn--9jb4223l", "output": null }, { - "comment": "P1; V6", - "input": "\u2d13\ud805\udf2b\u200d\uda1e\udf53\uff0e\u06a7\ud807\udc36", + "comment": "V6; U1 (ignored)", + "input": "\ud802\ude3f.\ud83c\udd06\u2014", "output": null }, { - "comment": "P1; V5; V6", - "input": "\ud802\ude3f.\ud83c\udd06\u2014", + "comment": "V6; U1 (ignored)", + "input": "\ud802\ude3f.5,\u2014", "output": null }, { - "comment": "V5; V6", + "comment": "V6; U1 (ignored)", + "input": "xn--0s9c.xn--5,-81t", + "output": null + }, + { + "comment": "V6; V7", "input": "xn--0s9c.xn--8ug8324p", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\uda10\udeb1\ud8c6\uddae\u06f8\u3002\udb43\udfad-", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--lmb18944c0g2z.xn----2k81m", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud83d\udf85\udb43\udce1\udb30\udf59.\ud989\uddb7", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--ie9hi1349bqdlb.xn--oj69a", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\u20e7\ud97e\udc4e-\uda6e\udcdd.4\u10a4\u200c", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\u20e7\ud97e\udc4e-\uda6e\udcdd.4\u2d04\u200c", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn----9snu5320fi76w.xn--4-ivs", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn----9snu5320fi76w.xn--4-sgn589c", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn----9snu5320fi76w.xn--4-f0g", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn----9snu5320fi76w.xn--4-f0g649i", "output": null }, @@ -2796,47 +3662,127 @@ "output": "xn--hwe.xn--ss-ci1ub261a" }, { - "comment": "P1; V5; V6", + "comment": "V6", + "input": "\ud805\udc44\u226f\uff61\ud805\udf24", + "output": null + }, + { + "comment": "V6", + "input": "\ud805\udc44>\u0338\uff61\ud805\udf24", + "output": null + }, + { + "comment": "V6", + "input": "\ud805\udc44\u226f\u3002\ud805\udf24", + "output": null + }, + { + "comment": "V6", + "input": "\ud805\udc44>\u0338\u3002\ud805\udf24", + "output": null + }, + { + "comment": "V6", + "input": "xn--hdh5636g.xn--ci2d", + "output": null + }, + { + "comment": "C2", + "input": "\u10ab\u226e\ud887\udc86\u3002\u200d\u07a7\ud800\udee3", + "output": null + }, + { + "comment": "C2", + "input": "\u10ab<\u0338\ud887\udc86\u3002\u200d\u07a7\ud800\udee3", + "output": null + }, + { + "comment": "C2", + "input": "\u2d0b<\u0338\ud887\udc86\u3002\u200d\u07a7\ud800\udee3", + "output": null + }, + { + "comment": "C2", + "input": "\u2d0b\u226e\ud887\udc86\u3002\u200d\u07a7\ud800\udee3", + "output": null + }, + { + "comment": "V6", + "input": "xn--gdhz03bxt42d.xn--lrb6479j", + "output": null + }, + { + "comment": "C2", + "input": "xn--gdhz03bxt42d.xn--lrb506jqr4n", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--jnd802gsm17c.xn--lrb6479j", + "output": null + }, + { + "comment": "C2; V7", + "input": "xn--jnd802gsm17c.xn--lrb506jqr4n", + "output": null + }, + { + "comment": "V6; V7", + "input": "\u17d2.\ud9db\udf52\u226f", + "output": null + }, + { + "comment": "V6; V7", + "input": "\u17d2.\ud9db\udf52>\u0338", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--u4e.xn--hdhx0084f", + "output": null + }, + { + "comment": "V6; V7", "input": "\ud8fc\udc47\u1734\uff0e\ud802\ude3a\u00c9\u2b13\ud804\udd34", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud8fc\udc47\u1734\uff0e\ud802\ude3aE\u0301\u2b13\ud804\udd34", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud8fc\udc47\u1734.\ud802\ude3a\u00c9\u2b13\ud804\udd34", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud8fc\udc47\u1734.\ud802\ude3aE\u0301\u2b13\ud804\udd34", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud8fc\udc47\u1734.\ud802\ude3ae\u0301\u2b13\ud804\udd34", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud8fc\udc47\u1734.\ud802\ude3a\u00e9\u2b13\ud804\udd34", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--c0e34564d.xn--9ca207st53lg3f", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud8fc\udc47\u1734\uff0e\ud802\ude3ae\u0301\u2b13\ud804\udd34", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud8fc\udc47\u1734\uff0e\ud802\ude3a\u00e9\u2b13\ud804\udd34", "output": null }, @@ -2846,97 +3792,122 @@ "output": "xn--09e4694e..xn--ye6h" }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u10c3\uff0e\u0653\u18a4", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u10c3.\u0653\u18a4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u2d23.\u0653\u18a4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--rlj.xn--vhb294g", "output": null }, { - "comment": "V5; V6", - "input": "xn--7nd.xn--vhb294g", + "comment": "V6", + "input": "\u2d23\uff0e\u0653\u18a4", "output": null }, { - "comment": "V5", - "input": "\u2d23\uff0e\u0653\u18a4", + "comment": "V6; V7", + "input": "xn--7nd.xn--vhb294g", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb40\udd08\u0813\uff0e\uc2c9\ud9d0\uddbb\u10c4\ud9ca\udc50", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb40\udd08\u0813\uff0e\u1109\u1174\u11b0\ud9d0\uddbb\u10c4\ud9ca\udc50", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb40\udd08\u0813.\uc2c9\ud9d0\uddbb\u10c4\ud9ca\udc50", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb40\udd08\u0813.\u1109\u1174\u11b0\ud9d0\uddbb\u10c4\ud9ca\udc50", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb40\udd08\u0813.\u1109\u1174\u11b0\ud9d0\uddbb\u2d24\ud9ca\udc50", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb40\udd08\u0813.\uc2c9\ud9d0\uddbb\u2d24\ud9ca\udc50", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--oub.xn--sljz109bpe25dviva", "output": null }, { - "comment": "V6", + "comment": "V7", + "input": "\udb40\udd08\u0813\uff0e\u1109\u1174\u11b0\ud9d0\uddbb\u2d24\ud9ca\udc50", + "output": null + }, + { + "comment": "V7", + "input": "\udb40\udd08\u0813\uff0e\uc2c9\ud9d0\uddbb\u2d24\ud9ca\udc50", + "output": null + }, + { + "comment": "V7", "input": "xn--oub.xn--8nd9522gpe69cviva", "output": null }, { - "comment": "P1; V6", - "input": "\udb40\udd08\u0813\uff0e\u1109\u1174\u11b0\ud9d0\uddbb\u2d24\ud9ca\udc50", + "comment": "V6", + "input": "\uaa2c\ud807\udcab\u226e\uff0e\u2902", "output": null }, { - "comment": "P1; V6", - "input": "\udb40\udd08\u0813\uff0e\uc2c9\ud9d0\uddbb\u2d24\ud9ca\udc50", + "comment": "V6", + "input": "\uaa2c\ud807\udcab<\u0338\uff0e\u2902", + "output": null + }, + { + "comment": "V6", + "input": "\uaa2c\ud807\udcab\u226e.\u2902", + "output": null + }, + { + "comment": "V6", + "input": "\uaa2c\ud807\udcab<\u0338.\u2902", + "output": null + }, + { + "comment": "V6", + "input": "xn--gdh1854cn19c.xn--kqi", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\ud804\udc45\u3002-", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn--210d.-", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "\ua866\u1851\u200d\u2488\u3002\ud800\udee3-", "output": null }, @@ -2956,22 +3927,22 @@ "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--h8e863drj7h.xn----381i", "output": null }, { - "comment": "C2; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "xn--h8e470bl0d838o.xn----381i", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "\u2488\u4c39\u200d-\u3002\uc6c8", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "\u2488\u4c39\u200d-\u3002\u110b\u116e\u11bf", "output": null }, @@ -2996,332 +3967,487 @@ "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn----dcp160o.xn--kp5b", "output": null }, { - "comment": "C2; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "xn----tgnx5rjr6c.xn--kp5b", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u3066\u3002\u200c\udb43\udcfd\u07f3", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--m9j.xn--rtb10784p", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--m9j.xn--rtb154j9l73w", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03c2\uff61\ua9c0\u06e7", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03c2\u3002\ua9c0\u06e7", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03a3\u3002\ua9c0\u06e7", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03c3\u3002\ua9c0\u06e7", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--4xa.xn--3lb1944f", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--3xa.xn--3lb1944f", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03a3\uff61\ua9c0\u06e7", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03c3\uff61\ua9c0\u06e7", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0bcd\udb56\udec5\ud9f0\ude51.\u10a2\u10b5", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0bcd\udb56\udec5\ud9f0\ude51.\u2d02\u2d15", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0bcd\udb56\udec5\ud9f0\ude51.\u10a2\u2d15", "output": null }, { - "comment": "V5; V6", - "input": "xn--xmc83135idcxza.xn--9md086l", + "comment": "V6; V7", + "input": "xn--xmc83135idcxza.xn--tkjwb", "output": null }, { - "comment": "V5; V6", - "input": "xn--xmc83135idcxza.xn--tkjwb", + "comment": "V6; V7", + "input": "xn--xmc83135idcxza.xn--9md086l", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--xmc83135idcxza.xn--9md2b", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7; U1 (ignored)", "input": "\u1c32\ud83c\udd08\u2f9b\u05a6\uff0e\u200d\uda7e\udd64\u07fd", "output": null }, { - "comment": "V5; V6", + "comment": "C2; V6; V7; U1 (ignored)", + "input": "\u1c327,\u8d70\u05a6.\u200d\uda7e\udd64\u07fd", + "output": null + }, + { + "comment": "V6; V7; U1 (ignored)", + "input": "xn--7,-bid991urn3k.xn--1tb13454l", + "output": null + }, + { + "comment": "C2; V6; V7; U1 (ignored)", + "input": "xn--7,-bid991urn3k.xn--1tb334j1197q", + "output": null + }, + { + "comment": "V6; V7", "input": "xn--xcb756i493fwi5o.xn--1tb13454l", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--xcb756i493fwi5o.xn--1tb334j1197q", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1897\uff61\u04c0\ud934\udd3b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1897\u3002\u04c0\ud934\udd3b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1897\u3002\u04cf\ud934\udd3b", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--hbf.xn--s5a83117e", "output": null }, { - "comment": "V6", - "input": "xn--hbf.xn--d5a86117e", + "comment": "V7", + "input": "\u1897\uff61\u04cf\ud934\udd3b", "output": null }, { - "comment": "P1; V6", - "input": "\u1897\uff61\u04cf\ud934\udd3b", + "comment": "V7", + "input": "xn--hbf.xn--d5a86117e", "output": null }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "-\ud800\udef7\ud81b\udf91\u3002\udb40\uddac", "output": "xn----991iq40y." }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "xn----991iq40y.", "output": "xn----991iq40y." }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\ud807\udc98\udb40\udd12\ud80d\udc61\uff61\ud835\udfea\u10bc", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\ud807\udc98\udb40\udd12\ud80d\udc61\u30028\u10bc", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\ud807\udc98\udb40\udd12\ud80d\udc61\u30028\u2d1c", "output": null }, { - "comment": "V5; V6", + "comment": "V6", "input": "xn--7m3d291b.xn--8-vws", "output": null }, { - "comment": "V5; V6", - "input": "xn--7m3d291b.xn--8-s1g", + "comment": "V6", + "input": "\ud807\udc98\udb40\udd12\ud80d\udc61\uff61\ud835\udfea\u2d1c", "output": null }, { - "comment": "P1; V5; V6", - "input": "\ud807\udc98\udb40\udd12\ud80d\udc61\uff61\ud835\udfea\u2d1c", + "comment": "V6; V7", + "input": "xn--7m3d291b.xn--8-s1g", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1bab\uff61\ud83c\udc89\udb40\udc70", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1bab\u3002\ud83c\udc89\udb40\udc70", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--zxf.xn--fx7ho0250c", "output": null }, { - "comment": "C1; P1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "\udb71\udeb6\udba0\uded6\uda1a\ude70-\u3002\u200c", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored); A4_2 (ignored)", "input": "xn----7i12hu122k9ire.", "output": null }, { - "comment": "C1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "xn----7i12hu122k9ire.xn--0ug", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ufe12\uff0e\ufe2f\ud805\udc42", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ufe12\uff0e\ud805\udc42\ufe2f", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "\u3002.\ud805\udc42\ufe2f", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "..xn--s96cu30b", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--y86c.xn--s96cu30b", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\ua92c\u3002\u200d", "output": null }, { - "comment": "V5", + "comment": "V6; A4_2 (ignored)", "input": "xn--zi9a.", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--zi9a.xn--1ug", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\udb58\ude04\u3002-", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--xm38e.-", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V7", + "input": "\u22e0\ud800\udeee\uff0e\uda98\ude2e\u0f18\u00df\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\u227c\u0338\ud800\udeee\uff0e\uda98\ude2e\u0f18\u00df>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\u22e0\ud800\udeee.\uda98\ude2e\u0f18\u00df\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\u227c\u0338\ud800\udeee.\uda98\ude2e\u0f18\u00df>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\u227c\u0338\ud800\udeee.\uda98\ude2e\u0f18SS>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\u22e0\ud800\udeee.\uda98\ude2e\u0f18SS\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\u22e0\ud800\udeee.\uda98\ude2e\u0f18ss\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\u227c\u0338\ud800\udeee.\uda98\ude2e\u0f18ss>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\u227c\u0338\ud800\udeee.\uda98\ude2e\u0f18Ss>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\u22e0\ud800\udeee.\uda98\ude2e\u0f18Ss\u226f", + "output": null + }, + { + "comment": "V7", + "input": "xn--pgh4639f.xn--ss-ifj426nle504a", + "output": null + }, + { + "comment": "V7", + "input": "xn--pgh4639f.xn--zca593eo6oc013y", + "output": null + }, + { + "comment": "V7", + "input": "\u227c\u0338\ud800\udeee\uff0e\uda98\ude2e\u0f18SS>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\u22e0\ud800\udeee\uff0e\uda98\ude2e\u0f18SS\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\u22e0\ud800\udeee\uff0e\uda98\ude2e\u0f18ss\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\u227c\u0338\ud800\udeee\uff0e\uda98\ude2e\u0f18ss>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\u227c\u0338\ud800\udeee\uff0e\uda98\ude2e\u0f18Ss>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\u22e0\ud800\udeee\uff0e\uda98\ude2e\u0f18Ss\u226f", + "output": null + }, + { + "comment": "V6; V7", "input": "\u0330\uff0e\udb81\udf31\u8680", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0330.\udb81\udf31\u8680", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--xta.xn--e91aw9417e", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; U1 (ignored)", "input": "\ud83e\udc9f\ud83c\udd08\u200d\ua84e\uff61\u0f84", "output": null }, { - "comment": "V5; V6", + "comment": "C2; V6; U1 (ignored)", + "input": "\ud83e\udc9f7,\u200d\ua84e\u3002\u0f84", + "output": null + }, + { + "comment": "V6; U1 (ignored)", + "input": "xn--7,-gh9hg322i.xn--3ed", + "output": null + }, + { + "comment": "C2; V6; U1 (ignored)", + "input": "xn--7,-n1t0654eqo3o.xn--3ed", + "output": null + }, + { + "comment": "V6; V7", "input": "xn--nc9aq743ds0e.xn--3ed", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--1ug4874cfd0kbmg.xn--3ed", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ua854\u3002\u1039\u1887", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--tc9a.xn--9jd663b", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6", + "input": "\u20eb\u226e.\ud836\ude16", + "output": null + }, + { + "comment": "V6", + "input": "\u20eb<\u0338.\ud836\ude16", + "output": null + }, + { + "comment": "V6", + "input": "xn--e1g71d.xn--772h", + "output": null + }, + { + "comment": "C1", + "input": "\u200c.\u226f", + "output": null + }, + { + "comment": "C1", + "input": "\u200c.>\u0338", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": ".xn--hdh", + "output": ".xn--hdh" + }, + { + "comment": "C1", + "input": "xn--0ug.xn--hdh", + "output": null + }, + { + "comment": "V6; V7; V3 (ignored)", "input": "\ud880\udd67\ud94e\ude60-\uff0e\uabed-\u609c", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\ud880\udd67\ud94e\ude60-.\uabed-\u609c", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn----7m53aj640l.xn----8f4br83t", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "\u1849\ud899\udce7\u2b1e\u189c.-\u200d\ud83a\udcd1\u202e", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--87e0ol04cdl39e.xn----qinu247r", "output": null }, { - "comment": "C2; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "xn--87e0ol04cdl39e.xn----ugn5e3763s", "output": null }, @@ -3353,14 +4479,12 @@ "output": "-.xn----ptf" }, { - "comment": "P1; V6", "input": "\u10ba\ud800\udef8\udb40\udd04\u3002\ud835\udfdd\ud7f6\u103a", - "output": null + "output": "xn--ilj2659d.xn--5-dug9054m" }, { - "comment": "P1; V6", "input": "\u10ba\ud800\udef8\udb40\udd04\u30025\ud7f6\u103a", - "output": null + "output": "xn--ilj2659d.xn--5-dug9054m" }, { "input": "\u2d1a\ud800\udef8\udb40\udd04\u30025\ud7f6\u103a", @@ -3375,50 +4499,61 @@ "output": "xn--ilj2659d.xn--5-dug9054m" }, { - "comment": "P1; V6", "input": "\u10ba\ud800\udef8.5\ud7f6\u103a", - "output": null - }, - { - "comment": "V6", - "input": "xn--ynd2415j.xn--5-dug9054m", - "output": null + "output": "xn--ilj2659d.xn--5-dug9054m" }, { "input": "\u2d1a\ud800\udef8\udb40\udd04\u3002\ud835\udfdd\ud7f6\u103a", "output": "xn--ilj2659d.xn--5-dug9054m" }, { - "comment": "C2; P1; V5; V6", + "comment": "V7", + "input": "xn--ynd2415j.xn--5-dug9054m", + "output": null + }, + { + "comment": "C2; V6; U1 (ignored)", "input": "\u200d-\u1839\ufe6a.\u1de1\u1922", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; U1 (ignored)", "input": "\u200d-\u1839%.\u1de1\u1922", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V3 (ignored); U1 (ignored)", "input": "xn---%-u4o.xn--gff52t", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; U1 (ignored)", "input": "xn---%-u4oy48b.xn--gff52t", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn----c6jx047j.xn--gff52t", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn----c6j614b1z4v.xn--gff52t", "output": null }, { + "input": "\u2260.\u183f", + "output": "xn--1ch.xn--y7e" + }, + { + "input": "=\u0338.\u183f", + "output": "xn--1ch.xn--y7e" + }, + { + "input": "xn--1ch.xn--y7e", + "output": "xn--1ch.xn--y7e" + }, + { "input": "\u0723\u05a3\uff61\u332a", "output": "xn--ucb18e.xn--eck4c5a" }, @@ -3435,17 +4570,17 @@ "output": "xn--ucb18e.xn--eck4c5a" }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud84e\ude6b\uff0e\ud9f1\udc72", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud84e\ude6b.\ud9f1\udc72", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--td3j.xn--4628b", "output": null }, @@ -3458,242 +4593,492 @@ "output": "xn--skb" }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\u0c4d\ud836\ude3e\u05a9\ud835\udfed\u3002-\ud805\udf28", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\u0c4d\ud836\ude3e\u05a91\u3002-\ud805\udf28", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn--1-rfc312cdp45c.xn----nq0j", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\uda4f\udfc8\u3002\ub64f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\uda4f\udfc8\u3002\u1104\u116b\u11ae", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--ph26c.xn--281b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud916\ude1a\udb40\udd0c\udb07\udf40\u1840.\u08b6", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--z7e98100evc01b.xn--czb", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d\uff61\ud8d4\udc5b", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d\u3002\ud8d4\udc5b", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--6x4u", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--1ug.xn--6x4u", "output": null }, { - "comment": "C1; V5", - "input": "\ud805\uddbf\ud836\ude14.\u185f\ud805\uddbf\u1b42\u200c", + "comment": "C1; V7", + "input": "\ufff9\u200c\uff61\u66f3\u2f91\ud800\udef0\u226f", "output": null }, { - "comment": "V5", - "input": "xn--461dw464a.xn--v8e29loy65a", + "comment": "C1; V7", + "input": "\ufff9\u200c\uff61\u66f3\u2f91\ud800\udef0>\u0338", "output": null }, { - "comment": "C1; V5", - "input": "xn--461dw464a.xn--v8e29ldzfo952a", + "comment": "C1; V7", + "input": "\ufff9\u200c\u3002\u66f3\u897e\ud800\udef0\u226f", + "output": null + }, + { + "comment": "C1; V7", + "input": "\ufff9\u200c\u3002\u66f3\u897e\ud800\udef0>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "xn--vn7c.xn--hdh501y8wvfs5h", + "output": null + }, + { + "comment": "C1; V7", + "input": "xn--0ug2139f.xn--hdh501y8wvfs5h", + "output": null + }, + { + "comment": "V7", + "input": "\u226f\u2488\u3002\u00df", + "output": null + }, + { + "comment": "V7", + "input": ">\u0338\u2488\u3002\u00df", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": "\u226f1.\u3002\u00df", + "output": "xn--1-ogo..xn--zca" + }, + { + "comment": "A4_2 (ignored)", + "input": ">\u03381.\u3002\u00df", + "output": "xn--1-ogo..xn--zca" + }, + { + "comment": "A4_2 (ignored)", + "input": ">\u03381.\u3002SS", + "output": "xn--1-ogo..ss" + }, + { + "comment": "A4_2 (ignored)", + "input": "\u226f1.\u3002SS", + "output": "xn--1-ogo..ss" + }, + { + "comment": "A4_2 (ignored)", + "input": "\u226f1.\u3002ss", + "output": "xn--1-ogo..ss" + }, + { + "comment": "A4_2 (ignored)", + "input": ">\u03381.\u3002ss", + "output": "xn--1-ogo..ss" + }, + { + "comment": "A4_2 (ignored)", + "input": ">\u03381.\u3002Ss", + "output": "xn--1-ogo..ss" + }, + { + "comment": "A4_2 (ignored)", + "input": "\u226f1.\u3002Ss", + "output": "xn--1-ogo..ss" + }, + { + "comment": "A4_2 (ignored)", + "input": "xn--1-ogo..ss", + "output": "xn--1-ogo..ss" + }, + { + "comment": "A4_2 (ignored)", + "input": "xn--1-ogo..xn--zca", + "output": "xn--1-ogo..xn--zca" + }, + { + "comment": "V7", + "input": ">\u0338\u2488\u3002SS", + "output": null + }, + { + "comment": "V7", + "input": "\u226f\u2488\u3002SS", + "output": null + }, + { + "comment": "V7", + "input": "\u226f\u2488\u3002ss", + "output": null + }, + { + "comment": "V7", + "input": ">\u0338\u2488\u3002ss", + "output": null + }, + { + "comment": "V7", + "input": ">\u0338\u2488\u3002Ss", + "output": null + }, + { + "comment": "V7", + "input": "\u226f\u2488\u3002Ss", + "output": null + }, + { + "comment": "V7", + "input": "xn--hdh84f.ss", + "output": null + }, + { + "comment": "V7", + "input": "xn--hdh84f.xn--zca", "output": null }, { - "comment": "C1; P1; V6", - "input": "\ud02c-?\ud99b\udcd2.\u200c\u0ac5\udb67\ude24\u06f4", + "comment": "C1", + "input": "\u200c\uff61\u2260", "output": null }, { - "comment": "C1; P1; V6", - "input": "\u110f\u1170\u11bb-?\ud99b\udcd2.\u200c\u0ac5\udb67\ude24\u06f4", + "comment": "C1", + "input": "\u200c\uff61=\u0338", "output": null }, { - "comment": "P1; V5; V6", - "input": "xn---?-6g4k75207c.xn--hmb76q74166b", + "comment": "C1", + "input": "\u200c\u3002\u2260", "output": null }, { - "comment": "C1; P1; V6", - "input": "xn---?-6g4k75207c.xn--hmb76q48y18505a", + "comment": "C1", + "input": "\u200c\u3002=\u0338", "output": null }, { - "comment": "P1; V5; V6", - "input": "\ud02c-?\ud99b\udcd2.xn--hmb76q74166b", + "comment": "A4_2 (ignored)", + "input": ".xn--1ch", + "output": ".xn--1ch" + }, + { + "comment": "C1", + "input": "xn--0ug.xn--1ch", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u110f\u1170\u11bb-?\ud99b\udcd2.xn--hmb76q74166b", + "comment": "C1; V6", + "input": "\ud805\uddbf\ud836\ude14.\u185f\ud805\uddbf\u1b42\u200c", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u110f\u1170\u11bb-?\ud99b\udcd2.XN--HMB76Q74166B", + "comment": "V6", + "input": "xn--461dw464a.xn--v8e29loy65a", "output": null }, { - "comment": "P1; V5; V6", - "input": "\ud02c-?\ud99b\udcd2.XN--HMB76Q74166B", + "comment": "C1; V6", + "input": "xn--461dw464a.xn--v8e29ldzfo952a", "output": null }, { - "comment": "P1; V5; V6", - "input": "\ud02c-?\ud99b\udcd2.Xn--Hmb76q74166b", + "comment": "C2; V6; V7; V3 (ignored)", + "input": "\uda12\udcf3\u200d\uda05\udf71.\ud81a\udf34\u2183\u2260-", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u110f\u1170\u11bb-?\ud99b\udcd2.Xn--Hmb76q74166b", + "comment": "C2; V6; V7; V3 (ignored)", + "input": "\uda12\udcf3\u200d\uda05\udf71.\ud81a\udf34\u2183=\u0338-", "output": null }, { - "comment": "C1; P1; V6", - "input": "\ud02c-?\ud99b\udcd2.xn--hmb76q48y18505a", + "comment": "C2; V6; V7; V3 (ignored)", + "input": "\uda12\udcf3\u200d\uda05\udf71.\ud81a\udf34\u2184=\u0338-", "output": null }, { - "comment": "C1; P1; V6", - "input": "\u110f\u1170\u11bb-?\ud99b\udcd2.xn--hmb76q48y18505a", + "comment": "C2; V6; V7; V3 (ignored)", + "input": "\uda12\udcf3\u200d\uda05\udf71.\ud81a\udf34\u2184\u2260-", "output": null }, { - "comment": "C1; P1; V6", - "input": "\u110f\u1170\u11bb-?\ud99b\udcd2.XN--HMB76Q48Y18505A", + "comment": "V6; V7; V3 (ignored)", + "input": "xn--6j00chy9a.xn----81n51bt713h", "output": null }, { - "comment": "C1; P1; V6", - "input": "\ud02c-?\ud99b\udcd2.XN--HMB76Q48Y18505A", + "comment": "C2; V6; V7; V3 (ignored)", + "input": "xn--1ug15151gkb5a.xn----81n51bt713h", "output": null }, { - "comment": "C1; P1; V6", - "input": "\ud02c-?\ud99b\udcd2.Xn--Hmb76q48y18505a", + "comment": "V6; V7; V3 (ignored)", + "input": "xn--6j00chy9a.xn----61n81bt713h", "output": null }, { - "comment": "C1; P1; V6", - "input": "\u110f\u1170\u11bb-?\ud99b\udcd2.Xn--Hmb76q48y18505a", + "comment": "C2; V6; V7; V3 (ignored)", + "input": "xn--1ug15151gkb5a.xn----61n81bt713h", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u252e\udb40\uddd0\uff0e\u0c00\u0c4d\u1734\u200d", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u252e\udb40\uddd0.\u0c00\u0c4d\u1734\u200d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--kxh.xn--eoc8m432a", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--1ug04r.xn--eoc8m432a40i", "output": null }, { - "comment": "P1; V6", + "comment": "V7; U1 (ignored)", "input": "\udaa5\udeaa\uff61\ud83c\udd02", "output": null }, { - "comment": "V6", + "comment": "V7; U1 (ignored)", + "input": "\udaa5\udeaa\u30021,", + "output": null + }, + { + "comment": "V7; U1 (ignored)", + "input": "xn--n433d.1,", + "output": null + }, + { + "comment": "V7", "input": "xn--n433d.xn--v07h", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud804\udf68\u520d.\ud83d\udee6", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--rbry728b.xn--y88h", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\udb40\udf0f3\uff61\u1bf1\ud835\udfd2", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\udb40\udf0f3\u3002\u1bf14", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--3-ib31m.xn--4-pql", "output": null }, { - "comment": "V5", + "comment": "V7", + "input": "\ua87d\u226f\uff0e\udaaf\udc80\uda0b\udcc4", + "output": null + }, + { + "comment": "V7", + "input": "\ua87d>\u0338\uff0e\udaaf\udc80\uda0b\udcc4", + "output": null + }, + { + "comment": "V7", + "input": "\ua87d\u226f.\udaaf\udc80\uda0b\udcc4", + "output": null + }, + { + "comment": "V7", + "input": "\ua87d>\u0338.\udaaf\udc80\uda0b\udcc4", + "output": null + }, + { + "comment": "V7", + "input": "xn--hdh8193c.xn--5z40cp629b", + "output": null + }, + { + "comment": "C2; V7", + "input": "\udb43\udcdb\uff0e\u200d\u492b\u2260\u10be", + "output": null + }, + { + "comment": "C2; V7", + "input": "\udb43\udcdb\uff0e\u200d\u492b=\u0338\u10be", + "output": null + }, + { + "comment": "C2; V7", + "input": "\udb43\udcdb.\u200d\u492b\u2260\u10be", + "output": null + }, + { + "comment": "C2; V7", + "input": "\udb43\udcdb.\u200d\u492b=\u0338\u10be", + "output": null + }, + { + "comment": "C2; V7", + "input": "\udb43\udcdb.\u200d\u492b=\u0338\u2d1e", + "output": null + }, + { + "comment": "C2; V7", + "input": "\udb43\udcdb.\u200d\u492b\u2260\u2d1e", + "output": null + }, + { + "comment": "V7", + "input": "xn--1t56e.xn--1ch153bqvw", + "output": null + }, + { + "comment": "C2; V7", + "input": "xn--1t56e.xn--1ug73gzzpwi3a", + "output": null + }, + { + "comment": "C2; V7", + "input": "\udb43\udcdb\uff0e\u200d\u492b=\u0338\u2d1e", + "output": null + }, + { + "comment": "C2; V7", + "input": "\udb43\udcdb\uff0e\u200d\u492b\u2260\u2d1e", + "output": null + }, + { + "comment": "V7", + "input": "xn--1t56e.xn--2nd141ghl2a", + "output": null + }, + { + "comment": "C2; V7", + "input": "xn--1t56e.xn--2nd159e9vb743e", + "output": null + }, + { + "comment": "V6", + "input": "3.1.xn--110d.j", + "output": null + }, + { + "comment": "V7", + "input": "xn--tshd3512p.j", + "output": null + }, + { + "comment": "V6", "input": "\u034a\uff0e\ud802\ude0e", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u034a.\ud802\ude0e", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--oua.xn--mr9c", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "\ua846\u3002\u2183\u0fb5\ub1ae-", + "comment": "V6", + "input": "\ud6c9\u226e\uff61\u0e34", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "\ua846\u3002\u2183\u0fb5\u1102\u116a\u11c1-", + "comment": "V6", + "input": "\u1112\u116e\u11ac<\u0338\uff61\u0e34", + "output": null + }, + { + "comment": "V6", + "input": "\ud6c9\u226e\u3002\u0e34", + "output": null + }, + { + "comment": "V6", + "input": "\u1112\u116e\u11ac<\u0338\u3002\u0e34", + "output": null + }, + { + "comment": "V6", + "input": "xn--gdh2512e.xn--i4c", "output": null }, { "comment": "V3 (ignored)", + "input": "\ua846\u3002\u2183\u0fb5\ub1ae-", + "output": "xn--fc9a.xn----qmg097k469k" + }, + { + "comment": "V3 (ignored)", + "input": "\ua846\u3002\u2183\u0fb5\u1102\u116a\u11c1-", + "output": "xn--fc9a.xn----qmg097k469k" + }, + { + "comment": "V3 (ignored)", "input": "\ua846\u3002\u2184\u0fb5\u1102\u116a\u11c1-", "output": "xn--fc9a.xn----qmg097k469k" }, @@ -3708,27 +5093,57 @@ "output": "xn--fc9a.xn----qmg097k469k" }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--fc9a.xn----qmg787k869k", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "V7", + "input": "\u226e\ud834\udd76\uff0e\ud987\udc81\uaaec\u2e48\udb82\udd6d", + "output": null + }, + { + "comment": "V7", + "input": "<\u0338\ud834\udd76\uff0e\ud987\udc81\uaaec\u2e48\udb82\udd6d", + "output": null + }, + { + "comment": "V7", + "input": "\u226e\ud834\udd76.\ud987\udc81\uaaec\u2e48\udb82\udd6d", + "output": null + }, + { + "comment": "V7", + "input": "<\u0338\ud834\udd76.\ud987\udc81\uaaec\u2e48\udb82\udd6d", + "output": null + }, + { + "comment": "V7", + "input": "xn--gdh.xn--4tjx101bsg00ds9pyc", + "output": null + }, + { + "comment": "V7", + "input": "xn--gdh0880o.xn--4tjx101bsg00ds9pyc", + "output": null + }, + { + "comment": "C2; V6; V7", "input": "\ud805\udc42\uff61\u200d\udb55\udf80\ud83d\udf95\uda54\udc54", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\ud805\udc42\u3002\u200d\udb55\udf80\ud83d\udf95\uda54\udc54", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--8v1d.xn--ye9h41035a2qqs", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--8v1d.xn--1ug1386plvx1cd8vya", "output": null }, @@ -3801,37 +5216,37 @@ "output": "xn--6dc.xn--tot" }, { - "comment": "C1; P1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "-\u200c\u2499\ud802\udee5\uff61\ud836\ude35", "output": null }, { - "comment": "C1; V5; V3 (ignored)", + "comment": "C1; V6; V3 (ignored)", "input": "-\u200c18.\ud802\udee5\u3002\ud836\ude35", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "-18.xn--rx9c.xn--382h", "output": null }, { - "comment": "C1; V5; V3 (ignored)", + "comment": "C1; V6; V3 (ignored)", "input": "xn---18-9m0a.xn--rx9c.xn--382h", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn----ddps939g.xn--382h", "output": null }, { - "comment": "C1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "xn----sgn18r3191a.xn--382h", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ufe05\ufe12\u3002\ud858\udc3e\u1ce0", "output": null }, @@ -3846,7 +5261,7 @@ "output": "..xn--t6f5138v" }, { - "comment": "V6", + "comment": "V7", "input": "xn--y86c.xn--t6f5138v", "output": null }, @@ -3859,82 +5274,214 @@ "output": "xn--t6f5138v" }, { - "comment": "P1; V6", + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f\uff0e-\u00df\u200c\u2260", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f\uff0e-\u00df\u200c=\u0338", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f.-\u00df\u200c\u2260", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f.-\u00df\u200c=\u0338", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f.-SS\u200c=\u0338", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f.-SS\u200c\u2260", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f.-ss\u200c\u2260", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f.-ss\u200c=\u0338", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f.-Ss\u200c=\u0338", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f.-Ss\u200c\u2260", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "xn--u836e.xn---ss-gl2a", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "xn--u836e.xn---ss-cn0at5l", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "xn--u836e.xn----qfa750ve7b", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f\uff0e-SS\u200c=\u0338", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f\uff0e-SS\u200c\u2260", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f\uff0e-ss\u200c\u2260", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f\uff0e-ss\u200c=\u0338", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f\uff0e-Ss\u200c=\u0338", + "output": null + }, + { + "comment": "C1; V7; V3 (ignored)", + "input": "\udb41\udd4f\uff0e-Ss\u200c\u2260", + "output": null + }, + { + "comment": "C1", + "input": "\u1859\u200c\uff61\u226f\ud800\udef2\u2260", + "output": null + }, + { + "comment": "C1", + "input": "\u1859\u200c\uff61>\u0338\ud800\udef2=\u0338", + "output": null + }, + { + "comment": "C1", + "input": "\u1859\u200c\u3002\u226f\ud800\udef2\u2260", + "output": null + }, + { + "comment": "C1", + "input": "\u1859\u200c\u3002>\u0338\ud800\udef2=\u0338", + "output": null + }, + { + "input": "xn--p8e.xn--1ch3a7084l", + "output": "xn--p8e.xn--1ch3a7084l" + }, + { + "input": "\u1859.\u226f\ud800\udef2\u2260", + "output": "xn--p8e.xn--1ch3a7084l" + }, + { + "input": "\u1859.>\u0338\ud800\udef2=\u0338", + "output": "xn--p8e.xn--1ch3a7084l" + }, + { + "comment": "C1", + "input": "xn--p8e650b.xn--1ch3a7084l", + "output": null + }, + { + "comment": "V7", "input": "\uda7b\udd5b\u0613.\u10b5", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\uda7b\udd5b\u0613.\u2d15", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--1fb94204l.xn--dlj", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--1fb94204l.xn--tnd", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\udb40\udd37\uff61\uda09\udc41", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\udb40\udd37\u3002\uda09\udc41", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--w720c", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug.xn--w720c", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u2488\u0dd6\u7105.\udb1e\udc59\u200d\ua85f", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "1.\u0dd6\u7105.\udb1e\udc59\u200d\ua85f", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "1.xn--t1c6981c.xn--4c9a21133d", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "1.xn--t1c6981c.xn--1ugz184c9lw7i", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--t1c337io97c.xn--4c9a21133d", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--t1c337io97c.xn--1ugz184c9lw7i", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud804\uddc0\u258d.\u205e\u1830", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--9zh3057f.xn--j7e103b", "output": null }, @@ -3954,27 +5501,127 @@ "output": null }, { - "comment": "V5", + "comment": "C1; C2", + "input": "\u2132\u17d2\u200d\uff61\u2260\u200d\u200c", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u2132\u17d2\u200d\uff61=\u0338\u200d\u200c", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u2132\u17d2\u200d\u3002\u2260\u200d\u200c", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u2132\u17d2\u200d\u3002=\u0338\u200d\u200c", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u214e\u17d2\u200d\u3002=\u0338\u200d\u200c", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u214e\u17d2\u200d\u3002\u2260\u200d\u200c", + "output": null + }, + { + "input": "xn--u4e969b.xn--1ch", + "output": "xn--u4e969b.xn--1ch" + }, + { + "input": "\u214e\u17d2.\u2260", + "output": "xn--u4e969b.xn--1ch" + }, + { + "input": "\u214e\u17d2.=\u0338", + "output": "xn--u4e969b.xn--1ch" + }, + { + "input": "\u2132\u17d2.=\u0338", + "output": "xn--u4e969b.xn--1ch" + }, + { + "input": "\u2132\u17d2.\u2260", + "output": "xn--u4e969b.xn--1ch" + }, + { + "comment": "C1; C2", + "input": "xn--u4e823bq1a.xn--0ugb89o", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u214e\u17d2\u200d\uff61=\u0338\u200d\u200c", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u214e\u17d2\u200d\uff61\u2260\u200d\u200c", + "output": null + }, + { + "comment": "V7", + "input": "xn--u4e319b.xn--1ch", + "output": null + }, + { + "comment": "C1; C2; V7", + "input": "xn--u4e823bcza.xn--0ugb89o", + "output": null + }, + { + "comment": "V7", + "input": "\ud9a9\udd2f\u0fa8\uff0e\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\ud9a9\udd2f\u0fa8\uff0e>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\ud9a9\udd2f\u0fa8.\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\ud9a9\udd2f\u0fa8.>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "xn--4fd57150h.xn--hdh", + "output": null + }, + { + "comment": "V6", "input": "\ud802\ude3f\udb40\udd8c\u9e2e\ud805\udeb6.\u03c2", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud802\ude3f\udb40\udd8c\u9e2e\ud805\udeb6.\u03a3", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud802\ude3f\udb40\udd8c\u9e2e\ud805\udeb6.\u03c3", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--l76a726rt2h.xn--4xa", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--l76a726rt2h.xn--3xa", "output": null }, @@ -4024,227 +5671,242 @@ "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u1734-\u0ce2\uff0e\udb40\udd29\u10a4", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u1734-\u0ce2.\udb40\udd29\u10a4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u1734-\u0ce2.\udb40\udd29\u2d04", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn----ggf830f.xn--vkj", "output": null }, { - "comment": "V5; V6", - "input": "xn----ggf830f.xn--cnd", + "comment": "V6", + "input": "\u1734-\u0ce2\uff0e\udb40\udd29\u2d04", "output": null }, { - "comment": "V5", - "input": "\u1734-\u0ce2\uff0e\udb40\udd29\u2d04", + "comment": "V6; V7", + "input": "xn----ggf830f.xn--cnd", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\u200d\u3002\ud838\udc18\u2488\ua84d\u64c9", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u3002\ud838\udc181.\ua84d\u64c9", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": ".xn--1-1p4r.xn--s7uv61m", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--1ug.xn--1-1p4r.xn--s7uv61m", "output": null }, { - "comment": "V5; V6; A4_2 (ignored)", + "comment": "V6; V7; A4_2 (ignored)", "input": ".xn--tsh026uql4bew9p", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--1ug.xn--tsh026uql4bew9p", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2ad0\uff61\u10c0-\udacd\udc22", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2ad0\u3002\u10c0-\udacd\udc22", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2ad0\u3002\u2d20-\udacd\udc22", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--r3i.xn----2wst7439i", "output": null }, { - "comment": "V6", - "input": "xn--r3i.xn----z1g58579u", + "comment": "V7", + "input": "\u2ad0\uff61\u2d20-\udacd\udc22", "output": null }, { - "comment": "P1; V6", - "input": "\u2ad0\uff61\u2d20-\udacd\udc22", + "comment": "V7", + "input": "xn--r3i.xn----z1g58579u", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud805\udc42\u25ca\uff0e\u299f\u2220", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud805\udc42\u25ca.\u299f\u2220", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--01h3338f.xn--79g270a", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud5c1\udb21\udd99\u0e3a\udb28\udf5a\u3002\u06ba\ud835\udfdc", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1112\u1164\u11bc\udb21\udd99\u0e3a\udb28\udf5a\u3002\u06ba\ud835\udfdc", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud5c1\udb21\udd99\u0e3a\udb28\udf5a\u3002\u06ba4", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1112\u1164\u11bc\udb21\udd99\u0e3a\udb28\udf5a\u3002\u06ba4", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--o4c1723h8g85gt4ya.xn--4-dvc", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ua953.\u033d\ud804\udcbd\u998b", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--3j9a.xn--bua0708eqzrd", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\udae2\udedd\uda69\udef8\u200d\uff61\u4716", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\udae2\udedd\uda69\udef8\u200d\u3002\u4716", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--g138cxw05a.xn--k0o", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--1ug30527h9mxi.xn--k0o", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; U1 (ignored)", "input": "\u186f\u2689\u59f6\ud83c\udd09\uff0e\u06f7\u200d\ud83c\udfaa\u200d", "output": null }, { - "comment": "V6", + "comment": "C2; U1 (ignored)", + "input": "\u186f\u2689\u59f68,.\u06f7\u200d\ud83c\udfaa\u200d", + "output": null + }, + { + "comment": "U1 (ignored)", + "input": "xn--8,-g9oy26fzu4d.xn--kmb6733w", + "output": "xn--8,-g9oy26fzu4d.xn--kmb6733w" + }, + { + "comment": "C2; U1 (ignored)", + "input": "xn--8,-g9oy26fzu4d.xn--kmb859ja94998b", + "output": null + }, + { + "comment": "V7", "input": "xn--c9e433epi4b3j20a.xn--kmb6733w", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--c9e433epi4b3j20a.xn--kmb859ja94998b", "output": null }, { - "comment": "C1; P1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "\u135f\u1848\u200c\uff0e\ufe12-\ud81b\udf90-", "output": null }, { - "comment": "C1; V5; V3 (ignored); A4_2 (ignored)", + "comment": "C1; V6; V3 (ignored); A4_2 (ignored)", "input": "\u135f\u1848\u200c.\u3002-\ud81b\udf90-", "output": null }, { - "comment": "V5; V3 (ignored); A4_2 (ignored)", + "comment": "V6; V3 (ignored); A4_2 (ignored)", "input": "xn--b7d82w..xn-----pe4u", "output": null }, { - "comment": "C1; V5; V3 (ignored); A4_2 (ignored)", + "comment": "C1; V6; V3 (ignored); A4_2 (ignored)", "input": "xn--b7d82wo4h..xn-----pe4u", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn--b7d82w.xn-----c82nz547a", "output": null }, { - "comment": "C1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "xn--b7d82wo4h.xn-----c82nz547a", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\ud836\ude5c\u3002-\u0b4d\u10ab", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\ud836\ude5c\u3002-\u0b4d\u2d0b", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn--792h.xn----bse820x", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn--792h.xn----bse632b", "output": null }, @@ -4259,10 +5921,12 @@ "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--9-mfs8024b.", "output": "xn--9-mfs8024b." }, { + "comment": "A4_2 (ignored)", "input": "9\u9681\u2bee.", "output": "xn--9-mfs8024b." }, @@ -4272,16 +5936,66 @@ "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6", "input": "\u1bac\u10ac\u200c\u0325\u3002\ud835\udff8", "output": null }, { - "comment": "C1; V5", + "comment": "V6", + "input": "xn--mta176jjjm.c", + "output": null + }, + { + "comment": "C1; V6", + "input": "xn--mta176j97cl2q.c", + "output": null + }, + { + "comment": "C1; V6", "input": "\u1bac\u2d0c\u200c\u0325\u3002\ud835\udff8", "output": null }, { + "comment": "V6; V7", + "input": "xn--mta930emri.c", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "xn--mta930emribme.c", + "output": null + }, + { + "comment": "V6; V7", + "input": "\udb40\udd01\u035f\u2fb6\uff61\u2087\ufe12\ub207\u226e", + "output": null + }, + { + "comment": "V6; V7", + "input": "\udb40\udd01\u035f\u2fb6\uff61\u2087\ufe12\u1102\u116e\u11aa<\u0338", + "output": null + }, + { + "comment": "V6", + "input": "\udb40\udd01\u035f\u98db\u30027\u3002\ub207\u226e", + "output": null + }, + { + "comment": "V6", + "input": "\udb40\udd01\u035f\u98db\u30027\u3002\u1102\u116e\u11aa<\u0338", + "output": null + }, + { + "comment": "V6", + "input": "xn--9ua0567e.7.xn--gdh6767c", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--9ua0567e.xn--7-ngou006d1ttc", + "output": null + }, + { "input": "xn--2ib43l.xn--te6h", "output": "xn--2ib43l.xn--te6h" }, @@ -4294,56 +6008,92 @@ "output": "xn--2ib43l.xn--te6h" }, { - "comment": "C1; P1; V6", + "comment": "C1; V6", "input": "\u200c\u3002\uffa0\u0f84\u0f96", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V6", "input": "\u200c\u3002\u1160\u0f84\u0f96", "output": null }, { "comment": "V6; A4_2 (ignored)", - "input": ".xn--3ed0b20h", + "input": ".xn--3ed0b", "output": null }, { "comment": "C1; V6", + "input": "xn--0ug.xn--3ed0b", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": ".xn--3ed0b20h", + "output": null + }, + { + "comment": "C1; V7", "input": "xn--0ug.xn--3ed0b20h", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--3ed0by082k", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug.xn--3ed0by082k", "output": null }, { - "comment": "P1; V6", - "input": "\ua9d0\u04c0\u1baa\u08f6\uff0e\ub235", + "comment": "C2; V7", + "input": "\u226f\ud9f5\ude05\uff0e\u200d\ud800\udd7c\uda88\udddb", "output": null }, { - "comment": "P1; V6", - "input": "\ua9d0\u04c0\u1baa\u08f6\uff0e\u1102\u116f\u11bc", + "comment": "C2; V7", + "input": ">\u0338\ud9f5\ude05\uff0e\u200d\ud800\udd7c\uda88\udddb", "output": null }, { - "comment": "P1; V6", - "input": "\ua9d0\u04c0\u1baa\u08f6.\ub235", + "comment": "C2; V7", + "input": "\u226f\ud9f5\ude05.\u200d\ud800\udd7c\uda88\udddb", "output": null }, { - "comment": "P1; V6", - "input": "\ua9d0\u04c0\u1baa\u08f6.\u1102\u116f\u11bc", + "comment": "C2; V7", + "input": ">\u0338\ud9f5\ude05.\u200d\ud800\udd7c\uda88\udddb", + "output": null + }, + { + "comment": "V7", + "input": "xn--hdh84488f.xn--xy7cw2886b", "output": null }, { + "comment": "C2; V7", + "input": "xn--hdh84488f.xn--1ug8099fbjp4e", + "output": null + }, + { + "input": "\ua9d0\u04c0\u1baa\u08f6\uff0e\ub235", + "output": "xn--s5a04sn4u297k.xn--2e1b" + }, + { + "input": "\ua9d0\u04c0\u1baa\u08f6\uff0e\u1102\u116f\u11bc", + "output": "xn--s5a04sn4u297k.xn--2e1b" + }, + { + "input": "\ua9d0\u04c0\u1baa\u08f6.\ub235", + "output": "xn--s5a04sn4u297k.xn--2e1b" + }, + { + "input": "\ua9d0\u04c0\u1baa\u08f6.\u1102\u116f\u11bc", + "output": "xn--s5a04sn4u297k.xn--2e1b" + }, + { "input": "\ua9d0\u04cf\u1baa\u08f6.\u1102\u116f\u11bc", "output": "xn--s5a04sn4u297k.xn--2e1b" }, @@ -4356,11 +6106,6 @@ "output": "xn--s5a04sn4u297k.xn--2e1b" }, { - "comment": "V6", - "input": "xn--d5a07sn4u297k.xn--2e1b", - "output": null - }, - { "input": "\ua9d0\u04cf\u1baa\u08f6\uff0e\u1102\u116f\u11bc", "output": "xn--s5a04sn4u297k.xn--2e1b" }, @@ -4369,95 +6114,162 @@ "output": "xn--s5a04sn4u297k.xn--2e1b" }, { - "comment": "P1; V5; V6", + "comment": "V7", + "input": "xn--d5a07sn4u297k.xn--2e1b", + "output": null + }, + { + "comment": "V6; V7", "input": "\ua8ea\uff61\ud818\udd3f\ud804\uddbe\udb40\uddd7", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ua8ea\u3002\ud818\udd3f\ud804\uddbe\udb40\uddd7", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--3g9a.xn--ud1dz07k", "output": null }, { + "comment": "V7", + "input": "\udadd\udcd3\ud805\udeb3\u3002\ud903\uddff\u226f\u2f87", + "output": null + }, + { + "comment": "V7", + "input": "\udadd\udcd3\ud805\udeb3\u3002\ud903\uddff>\u0338\u2f87", + "output": null + }, + { + "comment": "V7", + "input": "\udadd\udcd3\ud805\udeb3\u3002\ud903\uddff\u226f\u821b", + "output": null + }, + { + "comment": "V7", + "input": "\udadd\udcd3\ud805\udeb3\u3002\ud903\uddff>\u0338\u821b", + "output": null + }, + { + "comment": "V7", + "input": "xn--3e2d79770c.xn--hdh0088abyy1c", + "output": null + }, + { + "comment": "A4_2 (ignored)", "input": "xn--9hb7344k.", "output": "xn--9hb7344k." }, { + "comment": "A4_2 (ignored)", "input": "\ud802\udec7\u0661.", "output": "xn--9hb7344k." }, { - "comment": "P1; V5; V6", + "comment": "C1; V7", + "input": "\ud944\udd48\u782a\u226f\u1891\uff61\u226f\ud836\ude5a\uda0f\udd14\u200c", + "output": null + }, + { + "comment": "C1; V7", + "input": "\ud944\udd48\u782a>\u0338\u1891\uff61>\u0338\ud836\ude5a\uda0f\udd14\u200c", + "output": null + }, + { + "comment": "C1; V7", + "input": "\ud944\udd48\u782a\u226f\u1891\u3002\u226f\ud836\ude5a\uda0f\udd14\u200c", + "output": null + }, + { + "comment": "C1; V7", + "input": "\ud944\udd48\u782a>\u0338\u1891\u3002>\u0338\ud836\ude5a\uda0f\udd14\u200c", + "output": null + }, + { + "comment": "V7", + "input": "xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b", + "output": null + }, + { + "comment": "C1; V7", + "input": "xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c", + "output": null + }, + { + "comment": "V6", "input": "\u10c5.\ud804\udd33\u32b8", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u10c5.\ud804\udd3343", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u2d25.\ud804\udd3343", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--tlj.xn--43-274o", "output": null }, { - "comment": "V5; V6", - "input": "xn--9nd.xn--43-274o", + "comment": "V6", + "input": "\u2d25.\ud804\udd33\u32b8", "output": null }, { - "comment": "V5", - "input": "\u2d25.\ud804\udd33\u32b8", + "comment": "V6; V7", + "input": "xn--9nd.xn--43-274o", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91e\udea8\udb40\udd09\uffa0\u0fb7.\ud9a1\udfb0\ua953", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91e\udea8\udb40\udd09\u1160\u0fb7.\ud9a1\udfb0\ua953", "output": null }, { - "comment": "V6", + "comment": "V7", + "input": "xn--kgd72212e.xn--3j9au7544a", + "output": null + }, + { + "comment": "V7", "input": "xn--kgd36f9z57y.xn--3j9au7544a", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--kgd7493jee34a.xn--3j9au7544a", "output": null }, { - "comment": "C1; V5", + "comment": "C1; V6", "input": "\u0618.\u06f3\u200c\ua953", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--6fb.xn--gmb0524f", "output": null }, { - "comment": "C1; V5", + "comment": "C1; V6", "input": "xn--6fb.xn--gmb469jjf1h", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u184c\uff0e\ufe12\u1891", "output": null }, @@ -4472,41 +6284,181 @@ "output": "xn--c8e..xn--bbf" }, { - "comment": "V6", + "comment": "V7", "input": "xn--c8e.xn--bbf9168i", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud83b\uddcf\u3002\u1822\uda0d\ude06", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--hd7h.xn--46e66060j", "output": null }, { - "comment": "C2; P1; V6", + "comment": "V7", + "input": "\ud9f0\uded4\udb40\udd8e\udb40\udd97\ud807\udc95\u3002\u226e", + "output": null + }, + { + "comment": "V7", + "input": "\ud9f0\uded4\udb40\udd8e\udb40\udd97\ud807\udc95\u3002<\u0338", + "output": null + }, + { + "comment": "V7", + "input": "xn--4m3dv4354a.xn--gdh", + "output": null + }, + { + "comment": "V6; A4_2 (ignored)", + "input": "\udb40\udda6.\u08e3\u6680\u2260", + "output": null + }, + { + "comment": "V6; A4_2 (ignored)", + "input": "\udb40\udda6.\u08e3\u6680=\u0338", + "output": null + }, + { + "comment": "V6; A4_2 (ignored)", + "input": ".xn--m0b461k3g2c", + "output": null + }, + { + "comment": "C2; V7", "input": "\u40b9\udbb9\udd85\ud800\udee6\uff0e\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u40b9\udbb9\udd85\ud800\udee6.\u200d", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--0on3543c5981i.", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--0on3543c5981i.xn--1ug", "output": null }, { + "comment": "V7", + "input": "\ufe12\uff61\u10a3\u226f", + "output": null + }, + { + "comment": "V7", + "input": "\ufe12\uff61\u10a3>\u0338", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": "\u3002\u3002\u10a3\u226f", + "output": "..xn--hdh782b" + }, + { + "comment": "A4_2 (ignored)", + "input": "\u3002\u3002\u10a3>\u0338", + "output": "..xn--hdh782b" + }, + { + "comment": "A4_2 (ignored)", + "input": "\u3002\u3002\u2d03>\u0338", + "output": "..xn--hdh782b" + }, + { + "comment": "A4_2 (ignored)", + "input": "\u3002\u3002\u2d03\u226f", + "output": "..xn--hdh782b" + }, + { + "comment": "A4_2 (ignored)", + "input": "..xn--hdh782b", + "output": "..xn--hdh782b" + }, + { + "comment": "V7", + "input": "\ufe12\uff61\u2d03>\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\ufe12\uff61\u2d03\u226f", + "output": null + }, + { + "comment": "V7", + "input": "xn--y86c.xn--hdh782b", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": "..xn--bnd622g", + "output": null + }, + { + "comment": "V7", + "input": "xn--y86c.xn--bnd622g", + "output": null + }, + { + "comment": "V7", + "input": "\u7b83\u10c1-\udb40\udc5d\uff61\u2260-\ud83e\udd16", + "output": null + }, + { + "comment": "V7", + "input": "\u7b83\u10c1-\udb40\udc5d\uff61=\u0338-\ud83e\udd16", + "output": null + }, + { + "comment": "V7", + "input": "\u7b83\u10c1-\udb40\udc5d\u3002\u2260-\ud83e\udd16", + "output": null + }, + { + "comment": "V7", + "input": "\u7b83\u10c1-\udb40\udc5d\u3002=\u0338-\ud83e\udd16", + "output": null + }, + { + "comment": "V7", + "input": "\u7b83\u2d21-\udb40\udc5d\u3002=\u0338-\ud83e\udd16", + "output": null + }, + { + "comment": "V7", + "input": "\u7b83\u2d21-\udb40\udc5d\u3002\u2260-\ud83e\udd16", + "output": null + }, + { + "comment": "V7", + "input": "xn----4wsr321ay823p.xn----tfot873s", + "output": null + }, + { + "comment": "V7", + "input": "\u7b83\u2d21-\udb40\udc5d\uff61=\u0338-\ud83e\udd16", + "output": null + }, + { + "comment": "V7", + "input": "\u7b83\u2d21-\udb40\udc5d\uff61\u2260-\ud83e\udd16", + "output": null + }, + { + "comment": "V7", + "input": "xn----11g3013fy8x5m.xn----tfot873s", + "output": null + }, + { "input": "\u07e5.\u06b5", "output": "xn--dtb.xn--okb" }, @@ -4532,87 +6484,108 @@ "output": "xn--3e6h" }, { - "comment": "C1; V5; V3 (ignored)", + "comment": "C1; V6; V3 (ignored)", "input": "\u103a\u200d\u200c\u3002-\u200c", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn--bkd.-", "output": null }, { - "comment": "C1; V5; V3 (ignored)", + "comment": "C1; V6; V3 (ignored)", "input": "xn--bkd412fca.xn----sgn", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ufe12\uff61\u1b44\u1849", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "\u3002\u3002\u1b44\u1849", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "..xn--87e93m", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--y86c.xn--87e93m", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "-\u1bab\ufe12\u200d.\ud90b\udd88\ud957\ude53", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "-\u1bab\u3002\u200d.\ud90b\udd88\ud957\ude53", "output": null }, { - "comment": "V6; V3 (ignored); A4_2 (ignored)", + "comment": "V7; V3 (ignored); A4_2 (ignored)", "input": "xn----qml..xn--x50zy803a", "output": null }, { - "comment": "C2; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "xn----qml.xn--1ug.xn--x50zy803a", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn----qml1407i.xn--x50zy803a", "output": null }, { - "comment": "C2; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "xn----qmlv7tw180a.xn--x50zy803a", "output": null }, { - "comment": "P1; V6", - "input": "\u06b9\uff0e\u1873\u115f", + "comment": "V7", + "input": "\udb42\uddae.\u226f\ud838\udc06", "output": null }, { - "comment": "P1; V6", - "input": "\u06b9.\u1873\u115f", + "comment": "V7", + "input": "\udb42\uddae.>\u0338\ud838\udc06", "output": null }, { - "comment": "V6", + "comment": "V7", + "input": "xn--t546e.xn--hdh5166o", + "output": null + }, + { + "input": "\u06b9\uff0e\u1873\u115f", + "output": "xn--skb.xn--g9e" + }, + { + "input": "\u06b9.\u1873\u115f", + "output": "xn--skb.xn--g9e" + }, + { + "input": "xn--skb.xn--g9e", + "output": "xn--skb.xn--g9e" + }, + { + "input": "\u06b9.\u1873", + "output": "xn--skb.xn--g9e" + }, + { + "comment": "V7", "input": "xn--skb.xn--osd737a", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u3a1b\ud823\udc4e.\ufe12\ud835\udfd5\u0d01", "output": null }, @@ -4627,17 +6600,17 @@ "output": "xn--mbm8237g..xn--7-7hf" }, { - "comment": "V6", + "comment": "V7", "input": "xn--mbm8237g.xn--7-7hf1526p", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1", "input": "\u00df\u200c\uaaf6\u18a5\uff0e\u22b6\u10c1\u10b6", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1", "input": "\u00df\u200c\uaaf6\u18a5.\u22b6\u10c1\u10b6", "output": null }, @@ -4647,7 +6620,7 @@ "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1", "input": "SS\u200c\uaaf6\u18a5.\u22b6\u10c1\u10b6", "output": null }, @@ -4657,130 +6630,128 @@ "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1", "input": "Ss\u200c\uaaf6\u18a5.\u22b6\u10c1\u2d16", "output": null }, { - "comment": "V6", - "input": "xn--ss-4epx629f.xn--5nd703gyrh", - "output": null + "input": "xn--ss-4epx629f.xn--ifh802b6a", + "output": "xn--ss-4epx629f.xn--ifh802b6a" }, { - "comment": "C1; V6", - "input": "xn--ss-4ep585bkm5p.xn--5nd703gyrh", - "output": null + "input": "ss\uaaf6\u18a5.\u22b6\u2d21\u2d16", + "output": "xn--ss-4epx629f.xn--ifh802b6a" }, { - "input": "xn--ss-4epx629f.xn--ifh802b6a", + "input": "SS\uaaf6\u18a5.\u22b6\u10c1\u10b6", "output": "xn--ss-4epx629f.xn--ifh802b6a" }, { - "input": "ss\uaaf6\u18a5.\u22b6\u2d21\u2d16", + "input": "Ss\uaaf6\u18a5.\u22b6\u10c1\u2d16", "output": "xn--ss-4epx629f.xn--ifh802b6a" }, { - "comment": "P1; V6", - "input": "SS\uaaf6\u18a5.\u22b6\u10c1\u10b6", + "comment": "C1", + "input": "xn--ss-4ep585bkm5p.xn--ifh802b6a", "output": null }, { - "comment": "P1; V6", - "input": "Ss\uaaf6\u18a5.\u22b6\u10c1\u2d16", + "comment": "C1", + "input": "xn--zca682johfi89m.xn--ifh802b6a", "output": null }, { - "comment": "V6", - "input": "xn--ss-4epx629f.xn--undv409k", + "comment": "C1", + "input": "\u00df\u200c\uaaf6\u18a5\uff0e\u22b6\u2d21\u2d16", "output": null }, { "comment": "C1", - "input": "xn--ss-4ep585bkm5p.xn--ifh802b6a", + "input": "SS\u200c\uaaf6\u18a5\uff0e\u22b6\u10c1\u10b6", "output": null }, { - "comment": "C1; V6", - "input": "xn--ss-4ep585bkm5p.xn--undv409k", + "comment": "C1", + "input": "ss\u200c\uaaf6\u18a5\uff0e\u22b6\u2d21\u2d16", "output": null }, { "comment": "C1", - "input": "xn--zca682johfi89m.xn--ifh802b6a", + "input": "Ss\u200c\uaaf6\u18a5\uff0e\u22b6\u10c1\u2d16", "output": null }, { - "comment": "C1; V6", - "input": "xn--zca682johfi89m.xn--undv409k", + "comment": "V7", + "input": "xn--ss-4epx629f.xn--5nd703gyrh", "output": null }, { - "comment": "C1", - "input": "\u00df\u200c\uaaf6\u18a5\uff0e\u22b6\u2d21\u2d16", + "comment": "C1; V7", + "input": "xn--ss-4ep585bkm5p.xn--5nd703gyrh", "output": null }, { - "comment": "C1; P1; V6", - "input": "SS\u200c\uaaf6\u18a5\uff0e\u22b6\u10c1\u10b6", + "comment": "V7", + "input": "xn--ss-4epx629f.xn--undv409k", "output": null }, { - "comment": "C1", - "input": "ss\u200c\uaaf6\u18a5\uff0e\u22b6\u2d21\u2d16", + "comment": "C1; V7", + "input": "xn--ss-4ep585bkm5p.xn--undv409k", "output": null }, { - "comment": "C1; P1; V6", - "input": "Ss\u200c\uaaf6\u18a5\uff0e\u22b6\u10c1\u2d16", + "comment": "C1; V7", + "input": "xn--zca682johfi89m.xn--undv409k", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d\u3002\u03c2\udb40\udc49", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d\u3002\u03a3\udb40\udc49", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d\u3002\u03c3\udb40\udc49", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--4xa24344p", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--1ug.xn--4xa24344p", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--1ug.xn--3xa44344p", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\u2492\uda61\ude19\uda8f\udce0\ud805\udcc0.-\udb3a\udc4a", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "11.\uda61\ude19\uda8f\udce0\ud805\udcc0.-\udb3a\udc4a", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "11.xn--uz1d59632bxujd.xn----x310m", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--3shy698frsu9dt1me.xn----x310m", "output": null }, @@ -4795,7 +6766,7 @@ "output": null }, { - "comment": "V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "-.", "output": "-." }, @@ -4805,22 +6776,22 @@ "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u126c\uda12\udc3c\ud8c5\uddf6\uff61\ud802\ude2c\ud835\udfe0", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u126c\uda12\udc3c\ud8c5\uddf6\u3002\ud802\ude2c8", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--d0d41273c887z.xn--8-ob5i", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V3 (ignored)", "input": "\u03c2\u200d-.\u10c3\ud859\udfd9", "output": null }, @@ -4830,7 +6801,7 @@ "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V3 (ignored)", "input": "\u03a3\u200d-.\u10c3\ud859\udfd9", "output": null }, @@ -4850,172 +6821,200 @@ "output": null }, { - "comment": "V6; V3 (ignored)", - "input": "xn----zmb.xn--7nd64871a", + "comment": "C2; V3 (ignored)", + "input": "xn----xmb348s.xn--rlj2573p", "output": null }, { - "comment": "C2; V6; V3 (ignored)", - "input": "xn----zmb048s.xn--7nd64871a", + "comment": "V7; V3 (ignored)", + "input": "xn----zmb.xn--7nd64871a", "output": null }, { - "comment": "C2; V3 (ignored)", - "input": "xn----xmb348s.xn--rlj2573p", + "comment": "C2; V7; V3 (ignored)", + "input": "xn----zmb048s.xn--7nd64871a", "output": null }, { - "comment": "C2; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "xn----xmb348s.xn--7nd64871a", "output": null }, { - "comment": "P1; V6", + "input": "\u2260\u3002\ud83d\udfb3\ud835\udff2", + "output": "xn--1ch.xn--6-dl4s" + }, + { + "input": "=\u0338\u3002\ud83d\udfb3\ud835\udff2", + "output": "xn--1ch.xn--6-dl4s" + }, + { + "input": "\u2260\u3002\ud83d\udfb36", + "output": "xn--1ch.xn--6-dl4s" + }, + { + "input": "=\u0338\u3002\ud83d\udfb36", + "output": "xn--1ch.xn--6-dl4s" + }, + { + "input": "xn--1ch.xn--6-dl4s", + "output": "xn--1ch.xn--6-dl4s" + }, + { + "input": "\u2260.\ud83d\udfb36", + "output": "xn--1ch.xn--6-dl4s" + }, + { + "input": "=\u0338.\ud83d\udfb36", + "output": "xn--1ch.xn--6-dl4s" + }, + { + "comment": "V7", "input": "\udad6\udf3d.\u8814", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--g747d.xn--xl2a", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u08e6\u200d\uff0e\ubf3d", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u08e6\u200d\uff0e\u1108\u1168\u11c0", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u08e6\u200d.\ubf3d", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u08e6\u200d.\u1108\u1168\u11c0", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--p0b.xn--e43b", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--p0b869i.xn--e43b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud8f6\ude3d\uff0e\ud8ef\ude15", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud8f6\ude3d.\ud8ef\ude15", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--pr3x.xn--rv7w", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud802\udfc0\ud803\ude09\ud83a\uddcf\u3002\ud949\udea7\u2084\u10ab\ud8cb\ude6b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud802\udfc0\ud803\ude09\ud83a\uddcf\u3002\ud949\udea74\u10ab\ud8cb\ude6b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud802\udfc0\ud803\ude09\ud83a\uddcf\u3002\ud949\udea74\u2d0b\ud8cb\ude6b", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--039c42bq865a.xn--4-wvs27840bnrzm", "output": null }, { - "comment": "V6", - "input": "xn--039c42bq865a.xn--4-t0g49302fnrzm", + "comment": "V7", + "input": "\ud802\udfc0\ud803\ude09\ud83a\uddcf\u3002\ud949\udea7\u2084\u2d0b\ud8cb\ude6b", "output": null }, { - "comment": "P1; V6", - "input": "\ud802\udfc0\ud803\ude09\ud83a\uddcf\u3002\ud949\udea7\u2084\u2d0b\ud8cb\ude6b", + "comment": "V7", + "input": "xn--039c42bq865a.xn--4-t0g49302fnrzm", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud835\udfd3\u3002\u06d7", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "5\u3002\u06d7", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "5.xn--nlb", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\udaab\ude29.\u2f95", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\udaab\ude29.\u8c37", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--i183d.xn--6g3a", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug26167i.xn--6g3a", "output": null }, { - "comment": "C1; C2; P1; V6; V3 (ignored)", + "comment": "C1; C2; V7; V3 (ignored)", "input": "\ufe12\udafb\udc07\u200d.-\u073c\u200c", "output": null }, { - "comment": "C1; C2; P1; V6; V3 (ignored); A4_2 (ignored)", + "comment": "C1; C2; V7; V3 (ignored); A4_2 (ignored)", "input": "\u3002\udafb\udc07\u200d.-\u073c\u200c", "output": null }, { - "comment": "V6; V3 (ignored); A4_2 (ignored)", + "comment": "V7; V3 (ignored); A4_2 (ignored)", "input": ".xn--hh50e.xn----t2c", "output": null }, { - "comment": "C1; C2; V6; V3 (ignored); A4_2 (ignored)", + "comment": "C1; C2; V7; V3 (ignored); A4_2 (ignored)", "input": ".xn--1ug05310k.xn----t2c071q", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--y86c71305c.xn----t2c", "output": null }, { - "comment": "C1; C2; V6; V3 (ignored)", + "comment": "C1; C2; V7; V3 (ignored)", "input": "xn--1ug1658ftw26f.xn----t2c071q", "output": null }, @@ -5025,140 +7024,191 @@ "output": null }, { - "comment": "C1; P1; V6", + "comment": "C2", + "input": "\u200d.j", + "output": null + }, + { + "comment": "C2", + "input": "\u200d.J", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": ".j", + "output": ".j" + }, + { + "comment": "C2", + "input": "xn--1ug.j", + "output": null + }, + { + "input": "j", + "output": "j" + }, + { + "comment": "C1; V7", "input": "\u10ad\ud8be\udccd\ua868\u05ae\u3002\u10be\u200c\u200c", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u2d0d\ud8be\udccd\ua868\u05ae\u3002\u2d1e\u200c\u200c", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--5cb172r175fug38a.xn--mlj", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--5cb172r175fug38a.xn--0uga051h", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--5cb347co96jug15a.xn--2nd", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--5cb347co96jug15a.xn--2nd059ea", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud800\udef0\u3002\udb05\udcf1", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--k97c.xn--q031e", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u08df\u10ab\ud89b\udff8\uade4\uff0e\uda40\udd7c\ud835\udfe2\ud72a\u0ae3", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u08df\u10ab\ud89b\udff8\u1100\u1172\u11af\uff0e\uda40\udd7c\ud835\udfe2\u1112\u1171\u11b9\u0ae3", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u08df\u10ab\ud89b\udff8\uade4.\uda40\udd7c0\ud72a\u0ae3", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u08df\u10ab\ud89b\udff8\u1100\u1172\u11af.\uda40\udd7c0\u1112\u1171\u11b9\u0ae3", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u08df\u2d0b\ud89b\udff8\u1100\u1172\u11af.\uda40\udd7c0\u1112\u1171\u11b9\u0ae3", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u08df\u2d0b\ud89b\udff8\uade4.\uda40\udd7c0\ud72a\u0ae3", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f", "output": null }, { - "comment": "V5; V6", - "input": "xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f", + "comment": "V6; V7", + "input": "\u08df\u2d0b\ud89b\udff8\u1100\u1172\u11af\uff0e\uda40\udd7c\ud835\udfe2\u1112\u1171\u11b9\u0ae3", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u08df\u2d0b\ud89b\udff8\u1100\u1172\u11af\uff0e\uda40\udd7c\ud835\udfe2\u1112\u1171\u11b9\u0ae3", + "comment": "V6; V7", + "input": "\u08df\u2d0b\ud89b\udff8\uade4\uff0e\uda40\udd7c\ud835\udfe2\ud72a\u0ae3", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u08df\u2d0b\ud89b\udff8\uade4\uff0e\uda40\udd7c\ud835\udfe2\ud72a\u0ae3", + "comment": "V6; V7", + "input": "xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u0784\uff0e\ud83a\udc5d\u0601", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u0784.\ud83a\udc5d\u0601", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--lqb.xn--jfb1808v", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u0acd\u2083.8\ua8c4\u200d\ud83c\udce4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u0acd3.8\ua8c4\u200d\ud83c\udce4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--3-yke.xn--8-sl4et308f", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--3-yke.xn--8-ugnv982dbkwm", "output": null }, { + "comment": "V7", + "input": "\ua855\u2260\u105e\udb7b\udff1\uff61\ud803\udd67\udb40\udd2b\uffa0", + "output": null + }, + { + "comment": "V7", + "input": "\ua855=\u0338\u105e\udb7b\udff1\uff61\ud803\udd67\udb40\udd2b\uffa0", + "output": null + }, + { + "comment": "V7", + "input": "\ua855\u2260\u105e\udb7b\udff1\u3002\ud803\udd67\udb40\udd2b\u1160", + "output": null + }, + { + "comment": "V7", + "input": "\ua855=\u0338\u105e\udb7b\udff1\u3002\ud803\udd67\udb40\udd2b\u1160", + "output": null + }, + { + "comment": "V7", + "input": "xn--cld333gn31h0158l.xn--3g0d", + "output": null + }, + { "comment": "C1", "input": "\u9c4a\u3002\u200c", "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--rt6a.", "output": "xn--rt6a." }, { + "comment": "A4_2 (ignored)", "input": "\u9c4a.", "output": "xn--rt6a." }, @@ -5168,14 +7218,17 @@ "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--4-0bd15808a.", "output": "xn--4-0bd15808a." }, { + "comment": "A4_2 (ignored)", "input": "\ud83a\udd3a\u07cc4.", "output": "xn--4-0bd15808a." }, { + "comment": "A4_2 (ignored)", "input": "\ud83a\udd18\u07cc4.", "output": "xn--4-0bd15808a." }, @@ -5195,36 +7248,108 @@ "output": "-.xn--xco" }, { - "comment": "C1; C2; P1; V6", + "comment": "C1; C2; V7", "input": "\u200c\ud908\udce0\uff0e\u200d", "output": null }, { - "comment": "C1; C2; P1; V6", + "comment": "C1; C2; V7", "input": "\u200c\ud908\udce0.\u200d", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--dj8y.", "output": null }, { - "comment": "C1; C2; V6", + "comment": "C1; C2; V7", "input": "xn--0ugz7551c.xn--1ug", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud804\uddc0.\udb42\ude31", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--wd1d.xn--k946e", "output": null }, { + "input": "\u2f86\uff0e\ua848\uff15\u226f\u00df", + "output": "xn--tc1a.xn--5-qfa988w745i" + }, + { + "input": "\u2f86\uff0e\ua848\uff15>\u0338\u00df", + "output": "xn--tc1a.xn--5-qfa988w745i" + }, + { + "input": "\u820c.\ua8485\u226f\u00df", + "output": "xn--tc1a.xn--5-qfa988w745i" + }, + { + "input": "\u820c.\ua8485>\u0338\u00df", + "output": "xn--tc1a.xn--5-qfa988w745i" + }, + { + "input": "\u820c.\ua8485>\u0338SS", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u820c.\ua8485\u226fSS", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u820c.\ua8485\u226fss", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u820c.\ua8485>\u0338ss", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u820c.\ua8485>\u0338Ss", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u820c.\ua8485\u226fSs", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "xn--tc1a.xn--5ss-3m2a5009e", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "xn--tc1a.xn--5-qfa988w745i", + "output": "xn--tc1a.xn--5-qfa988w745i" + }, + { + "input": "\u2f86\uff0e\ua848\uff15>\u0338SS", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u2f86\uff0e\ua848\uff15\u226fSS", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u2f86\uff0e\ua848\uff15\u226fss", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u2f86\uff0e\ua848\uff15>\u0338ss", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u2f86\uff0e\ua848\uff15>\u0338Ss", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { + "input": "\u2f86\uff0e\ua848\uff15\u226fSs", + "output": "xn--tc1a.xn--5ss-3m2a5009e" + }, + { "input": "\ud83a\udd2a.\u03c2", "output": "xn--ie6h.xn--3xa" }, @@ -5257,12 +7382,12 @@ "output": "xn--ie6h.xn--4xa" }, { - "comment": "C1; P1; V6", + "comment": "C1", "input": "\u200c\u10ba\uff61\u03c2", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1", "input": "\u200c\u10ba\u3002\u03c2", "output": null }, @@ -5272,7 +7397,7 @@ "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1", "input": "\u200c\u10ba\u3002\u03a3", "output": null }, @@ -5290,37 +7415,24 @@ "output": "xn--ilj.xn--4xa" }, { - "comment": "P1; V6", "input": "\u10ba.\u03a3", - "output": null + "output": "xn--ilj.xn--4xa" }, { "input": "\u2d1a.\u03c2", "output": "xn--ilj.xn--3xa" }, { - "comment": "P1; V6", "input": "\u10ba.\u03c2", - "output": null - }, - { - "comment": "V6", - "input": "xn--ynd.xn--4xa", - "output": null - }, - { - "comment": "V6", - "input": "xn--ynd.xn--3xa", - "output": null + "output": "xn--ilj.xn--3xa" }, { "input": "xn--ilj.xn--3xa", "output": "xn--ilj.xn--3xa" }, { - "comment": "P1; V6", "input": "\u10ba.\u03c3", - "output": null + "output": "xn--ilj.xn--4xa" }, { "comment": "C1", @@ -5328,33 +7440,43 @@ "output": null }, { - "comment": "C1; V6", - "input": "xn--ynd759e.xn--4xa", + "comment": "C1", + "input": "xn--0ug262c.xn--3xa", "output": null }, { "comment": "C1", - "input": "xn--0ug262c.xn--3xa", + "input": "\u200c\u2d1a\uff61\u03c2", "output": null }, { - "comment": "C1; V6", - "input": "xn--ynd759e.xn--3xa", + "comment": "C1", + "input": "\u200c\u10ba\uff61\u03a3", "output": null }, { "comment": "C1", - "input": "\u200c\u2d1a\uff61\u03c2", + "input": "\u200c\u2d1a\uff61\u03c3", "output": null }, { - "comment": "C1; P1; V6", - "input": "\u200c\u10ba\uff61\u03a3", + "comment": "V7", + "input": "xn--ynd.xn--4xa", "output": null }, { - "comment": "C1", - "input": "\u200c\u2d1a\uff61\u03c3", + "comment": "V7", + "input": "xn--ynd.xn--3xa", + "output": null + }, + { + "comment": "C1; V7", + "input": "xn--ynd759e.xn--4xa", + "output": null + }, + { + "comment": "C1; V7", + "input": "xn--ynd759e.xn--3xa", "output": null }, { @@ -5373,7 +7495,7 @@ "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--6g3a.xn--0sa8175flwa", "output": null }, @@ -5395,117 +7517,117 @@ "output": "xn--34w.xn--x7e" }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\uda72\ude29\u10b3\u2753\uff61\ud804\udd28", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\uda72\ude29\u10b3\u2753\u3002\ud804\udd28", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\uda72\ude29\u2d13\u2753\u3002\ud804\udd28", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--8di78qvw32y.xn--k80d", "output": null }, { - "comment": "V5; V6", - "input": "xn--rnd896i0j14q.xn--k80d", + "comment": "V6; V7", + "input": "\uda72\ude29\u2d13\u2753\uff61\ud804\udd28", "output": null }, { - "comment": "P1; V5; V6", - "input": "\uda72\ude29\u2d13\u2753\uff61\ud804\udd28", + "comment": "V6; V7", + "input": "xn--rnd896i0j14q.xn--k80d", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u17ff\uff61\ud83a\udf33", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u17ff\u3002\ud83a\udf33", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--45e.xn--et6h", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u0652\u200d\uff61\u0ccd\ud805\udeb3", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u0652\u200d\u3002\u0ccd\ud805\udeb3", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--uhb.xn--8tc4527k", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--uhb882k.xn--8tc4527k", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u00df\ud880\udc3b\ud8da\udf17\uff61\ud836\ude68\ud83d\udd6e\u00df", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u00df\ud880\udc3b\ud8da\udf17\u3002\ud836\ude68\ud83d\udd6e\u00df", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "SS\ud880\udc3b\ud8da\udf17\u3002\ud836\ude68\ud83d\udd6eSS", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "ss\ud880\udc3b\ud8da\udf17\u3002\ud836\ude68\ud83d\udd6ess", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "Ss\ud880\udc3b\ud8da\udf17\u3002\ud836\ude68\ud83d\udd6eSs", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--ss-jl59biy67d.xn--ss-4d11aw87d", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--zca20040bgrkh.xn--zca3653v86qa", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "SS\ud880\udc3b\ud8da\udf17\uff61\ud836\ude68\ud83d\udd6eSS", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "ss\ud880\udc3b\ud8da\udf17\uff61\ud836\ude68\ud83d\udd6ess", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "Ss\ud880\udc3b\ud8da\udf17\uff61\ud836\ude68\ud83d\udd6eSs", "output": null }, @@ -5520,52 +7642,52 @@ "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\udb41\udc58\uff0e\udb40\udd2e", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\udb41\udc58.\udb40\udd2e", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--s136e.", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ua9b7\udb37\udd59\uba79\u3002\u249b\udb42\ude07", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ua9b7\udb37\udd59\u1106\u1167\u11b0\u3002\u249b\udb42\ude07", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ua9b7\udb37\udd59\uba79\u300220.\udb42\ude07", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ua9b7\udb37\udd59\u1106\u1167\u11b0\u300220.\udb42\ude07", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--ym9av13acp85w.20.xn--d846e", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--ym9av13acp85w.xn--dth22121k", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\uff61\ufe12", "output": null }, @@ -5585,12 +7707,12 @@ "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--y86c", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug.xn--y86c", "output": null }, @@ -5650,36 +7772,106 @@ "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\udb27\udd9c\u1898\u3002\u1a7f\u2ea2", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--ibf35138o.xn--fpfz94g", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\uda1c\udda7\ud835\udfef\u3002\u2488\u1a76\ud835\udfda\uda41\ude0c", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\uda1c\udda73\u30021.\u1a762\uda41\ude0c", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--3-rj42h.1.xn--2-13k96240l", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--3-rj42h.xn--2-13k746cq465x", "output": null }, { + "comment": "C2; V7", + "input": "\u200d\u2085\u2488\u3002\u226f\ud835\udff4\u200d", + "output": null + }, + { + "comment": "C2; V7", + "input": "\u200d\u2085\u2488\u3002>\u0338\ud835\udff4\u200d", + "output": null + }, + { + "comment": "C2; A4_2 (ignored)", + "input": "\u200d51.\u3002\u226f8\u200d", + "output": null + }, + { + "comment": "C2; A4_2 (ignored)", + "input": "\u200d51.\u3002>\u03388\u200d", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": "51..xn--8-ogo", + "output": "51..xn--8-ogo" + }, + { + "comment": "C2; A4_2 (ignored)", + "input": "xn--51-l1t..xn--8-ugn00i", + "output": null + }, + { + "comment": "V7", + "input": "xn--5-ecp.xn--8-ogo", + "output": null + }, + { + "comment": "C2; V7", + "input": "xn--5-tgnz5r.xn--8-ugn00i", + "output": null + }, + { + "comment": "V7", + "input": "\ud8bb\uddc2\u0a42\u10aa\ud8c8\udc9f.\u226e", + "output": null + }, + { + "comment": "V7", + "input": "\ud8bb\uddc2\u0a42\u10aa\ud8c8\udc9f.<\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\ud8bb\uddc2\u0a42\u2d0a\ud8c8\udc9f.<\u0338", + "output": null + }, + { + "comment": "V7", + "input": "\ud8bb\uddc2\u0a42\u2d0a\ud8c8\udc9f.\u226e", + "output": null + }, + { + "comment": "V7", + "input": "xn--nbc229o4y27dgskb.xn--gdh", + "output": null + }, + { + "comment": "V7", + "input": "xn--nbc493aro75ggskb.xn--gdh", + "output": null + }, + { "input": "\ua860\uff0e\u06f2", "output": "xn--5c9a.xn--fmb" }, @@ -5692,37 +7884,52 @@ "output": "xn--5c9a.xn--fmb" }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; U1 (ignored)", "input": "\ua67d\u200c\ud87e\uddf5\ud83c\udd06\uff61\u200c\ud804\udc42\u1b01", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; U1 (ignored)", "input": "\ua67d\u200c\u9723\ud83c\udd06\uff61\u200c\ud804\udc42\u1b01", "output": null }, { - "comment": "V5; V6", + "comment": "C1; V6; U1 (ignored)", + "input": "\ua67d\u200c\u97235,\u3002\u200c\ud804\udc42\u1b01", + "output": null + }, + { + "comment": "V6; U1 (ignored)", + "input": "xn--5,-op8g373c.xn--4sf0725i", + "output": null + }, + { + "comment": "C1; V6; U1 (ignored)", + "input": "xn--5,-i1tz135dnbqa.xn--4sf36u6u4w", + "output": null + }, + { + "comment": "V6; V7", "input": "xn--2q5a751a653w.xn--4sf0725i", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn--0ug4208b2vjuk63a.xn--4sf36u6u4w", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u514e\uff61\u183c\udb43\udd1c\ud805\udeb6\ud807\udc3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u514e\u3002\u183c\udb43\udd1c\ud805\udeb6\ud807\udc3f", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--b5q.xn--v7e6041kqqd4m251b", "output": null }, @@ -5737,408 +7944,540 @@ "output": null }, { + "input": "1.2h", + "output": "1.2h" + }, + { "comment": "C2", "input": "1.xn--27-l1tb", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\u1868-\uff61\udb43\udecb\ud835\udff7", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\u1868-\u3002\udb43\udecb1", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn----z8j.xn--1-5671m", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u10bc\ud9e3\udded\u0f80\u2f87\u3002\u10af\u2640\u200c\u200c", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u10bc\ud9e3\udded\u0f80\u821b\u3002\u10af\u2640\u200c\u200c", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u2d1c\ud9e3\udded\u0f80\u821b\u3002\u2d0f\u2640\u200c\u200c", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--zed372mdj2do3v4h.xn--e5h11w", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--zed372mdj2do3v4h.xn--0uga678bgyh", "output": null }, { - "comment": "V6", - "input": "xn--zed54dz10wo343g.xn--nnd651i", + "comment": "C1; V7", + "input": "\u2d1c\ud9e3\udded\u0f80\u2f87\u3002\u2d0f\u2640\u200c\u200c", "output": null }, { - "comment": "C1; V6", - "input": "xn--zed54dz10wo343g.xn--nnd089ea464d", + "comment": "V7", + "input": "xn--zed54dz10wo343g.xn--nnd651i", "output": null }, { - "comment": "C1; P1; V6", - "input": "\u2d1c\ud9e3\udded\u0f80\u2f87\u3002\u2d0f\u2640\u200c\u200c", + "comment": "C1; V7", + "input": "xn--zed54dz10wo343g.xn--nnd089ea464d", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\ud804\udc46\ud835\udff0.\u200d", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\ud804\udc464.\u200d", "output": null }, { - "comment": "V5", + "comment": "V6; A4_2 (ignored)", "input": "xn--4-xu7i.", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--4-xu7i.xn--1ug", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud97b\udd18\u10be\u7640\uff61\ud805\ude3f\u200d\u200c\ubdbc", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud97b\udd18\u10be\u7640\uff61\ud805\ude3f\u200d\u200c\u1107\u1170\u11ab", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud97b\udd18\u10be\u7640\u3002\ud805\ude3f\u200d\u200c\ubdbc", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud97b\udd18\u10be\u7640\u3002\ud805\ude3f\u200d\u200c\u1107\u1170\u11ab", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud97b\udd18\u2d1e\u7640\u3002\ud805\ude3f\u200d\u200c\u1107\u1170\u11ab", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud97b\udd18\u2d1e\u7640\u3002\ud805\ude3f\u200d\u200c\ubdbc", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--mlju35u7qx2f.xn--et3bn23n", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn--mlju35u7qx2f.xn--0ugb6122js83c", "output": null }, { - "comment": "V5; V6", + "comment": "C1; V6; V7", + "input": "\ud97b\udd18\u2d1e\u7640\uff61\ud805\ude3f\u200d\u200c\u1107\u1170\u11ab", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "\ud97b\udd18\u2d1e\u7640\uff61\ud805\ude3f\u200d\u200c\ubdbc", + "output": null + }, + { + "comment": "V6; V7", "input": "xn--2nd6803c7q37d.xn--et3bn23n", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn--2nd6803c7q37d.xn--0ugb6122js83c", "output": null }, { - "comment": "C1; P1; V5; V6", - "input": "\ud97b\udd18\u2d1e\u7640\uff61\ud805\ude3f\u200d\u200c\u1107\u1170\u11ab", + "comment": "V7", + "input": "\u1843\ud835\udfe7\u226f\u1823\uff0e\u6c01\ud960\udff1\ua06b", "output": null }, { - "comment": "C1; P1; V5; V6", - "input": "\ud97b\udd18\u2d1e\u7640\uff61\ud805\ude3f\u200d\u200c\ubdbc", + "comment": "V7", + "input": "\u1843\ud835\udfe7>\u0338\u1823\uff0e\u6c01\ud960\udff1\ua06b", + "output": null + }, + { + "comment": "V7", + "input": "\u18435\u226f\u1823.\u6c01\ud960\udff1\ua06b", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7", + "input": "\u18435>\u0338\u1823.\u6c01\ud960\udff1\ua06b", + "output": null + }, + { + "comment": "V7", + "input": "xn--5-24jyf768b.xn--lqw213ime95g", + "output": null + }, + { + "comment": "V7; V3 (ignored)", "input": "-\ud804\ude36\u248f\uff0e\u248e\ud881\udee2\udb40\udfad", "output": null }, { - "comment": "P1; V6; V3 (ignored); A4_2 (ignored)", + "comment": "V7; V3 (ignored); A4_2 (ignored)", "input": "-\ud804\ude368..7.\ud881\udee2\udb40\udfad", "output": null }, { - "comment": "V6; V3 (ignored); A4_2 (ignored)", + "comment": "V7; V3 (ignored); A4_2 (ignored)", "input": "xn---8-bv5o..7.xn--c35nf1622b", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn----scp6252h.xn--zshy411yzpx2d", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C1; C2", + "input": "\u200c\u10a1\u755d\u200d\uff0e\u226e", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u200c\u10a1\u755d\u200d\uff0e<\u0338", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u200c\u10a1\u755d\u200d.\u226e", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u200c\u10a1\u755d\u200d.<\u0338", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u200c\u2d01\u755d\u200d.<\u0338", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u200c\u2d01\u755d\u200d.\u226e", + "output": null + }, + { + "input": "xn--skjy82u.xn--gdh", + "output": "xn--skjy82u.xn--gdh" + }, + { + "input": "\u2d01\u755d.\u226e", + "output": "xn--skjy82u.xn--gdh" + }, + { + "input": "\u2d01\u755d.<\u0338", + "output": "xn--skjy82u.xn--gdh" + }, + { + "input": "\u10a1\u755d.<\u0338", + "output": "xn--skjy82u.xn--gdh" + }, + { + "input": "\u10a1\u755d.\u226e", + "output": "xn--skjy82u.xn--gdh" + }, + { + "comment": "C1; C2", + "input": "xn--0ugc160hb36e.xn--gdh", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u200c\u2d01\u755d\u200d\uff0e<\u0338", + "output": null + }, + { + "comment": "C1; C2", + "input": "\u200c\u2d01\u755d\u200d\uff0e\u226e", + "output": null + }, + { + "comment": "V7", + "input": "xn--8md0962c.xn--gdh", + "output": null + }, + { + "comment": "C1; C2; V7", + "input": "xn--8md700fea3748f.xn--gdh", + "output": null + }, + { + "comment": "C2; V6; V7", "input": "\u0ecb\u200d\uff0e\u9381\udb43\udc11", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\u0ecb\u200d.\u9381\udb43\udc11", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--t8c.xn--iz4a43209d", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--t8c059f.xn--iz4a43209d", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\ud9e5\udef4.-\u1862\u0592\ud836\ude20", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn--ep37b.xn----hec165lho83b", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\ud8bc\udc2b\uff0e\u1baa\u03c2\u10a6\u200d", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\ud8bc\udc2b.\u1baa\u03c2\u10a6\u200d", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\ud8bc\udc2b.\u1baa\u03c2\u2d06\u200d", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\ud8bc\udc2b.\u1baa\u03a3\u10a6\u200d", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\ud8bc\udc2b.\u1baa\u03c3\u2d06\u200d", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\ud8bc\udc2b.\u1baa\u03a3\u2d06\u200d", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--nu4s.xn--4xa153j7im", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--nu4s.xn--4xa153jk8cs1q", "output": null }, { - "comment": "V5; V6", - "input": "xn--nu4s.xn--4xa217dxri", + "comment": "C2; V6; V7", + "input": "xn--nu4s.xn--3xa353jk8cs1q", "output": null }, { - "comment": "C2; V5; V6", - "input": "xn--nu4s.xn--4xa217dxriome", + "comment": "C2; V6; V7", + "input": "\ud8bc\udc2b\uff0e\u1baa\u03c2\u2d06\u200d", "output": null }, { - "comment": "C2; V5; V6", - "input": "xn--nu4s.xn--3xa353jk8cs1q", + "comment": "C2; V6; V7", + "input": "\ud8bc\udc2b\uff0e\u1baa\u03a3\u10a6\u200d", "output": null }, { - "comment": "C2; V5; V6", - "input": "xn--nu4s.xn--3xa417dxriome", + "comment": "C2; V6; V7", + "input": "\ud8bc\udc2b\uff0e\u1baa\u03c3\u2d06\u200d", "output": null }, { - "comment": "C2; P1; V5; V6", - "input": "\ud8bc\udc2b\uff0e\u1baa\u03c2\u2d06\u200d", + "comment": "C2; V6; V7", + "input": "\ud8bc\udc2b\uff0e\u1baa\u03a3\u2d06\u200d", "output": null }, { - "comment": "C2; P1; V5; V6", - "input": "\ud8bc\udc2b\uff0e\u1baa\u03a3\u10a6\u200d", + "comment": "V6; V7", + "input": "xn--nu4s.xn--4xa217dxri", "output": null }, { - "comment": "C2; P1; V5; V6", - "input": "\ud8bc\udc2b\uff0e\u1baa\u03c3\u2d06\u200d", + "comment": "C2; V6; V7", + "input": "xn--nu4s.xn--4xa217dxriome", "output": null }, { - "comment": "C2; P1; V5; V6", - "input": "\ud8bc\udc2b\uff0e\u1baa\u03a3\u2d06\u200d", + "comment": "C2; V6; V7", + "input": "xn--nu4s.xn--3xa417dxriome", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\u2488\u200c\uaaec\ufe12\uff0e\u0acd", "output": null }, { - "comment": "C1; V5; A4_2 (ignored)", + "comment": "C1; V6; A4_2 (ignored)", "input": "1.\u200c\uaaec\u3002.\u0acd", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "1.xn--sv9a..xn--mfc", "output": null }, { - "comment": "C1; V5; A4_2 (ignored)", + "comment": "C1; V6; A4_2 (ignored)", "input": "1.xn--0ug7185c..xn--mfc", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--tsh0720cse8b.xn--mfc", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn--0ug78o720myr1c.xn--mfc", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\u00df\u200d.\u1bf2\ud8d3\udfbc", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "SS\u200d.\u1bf2\ud8d3\udfbc", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "ss\u200d.\u1bf2\ud8d3\udfbc", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "Ss\u200d.\u1bf2\ud8d3\udfbc", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "ss.xn--0zf22107b", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--ss-n1t.xn--0zf22107b", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn--zca870n.xn--0zf22107b", "output": null }, { - "comment": "P1; V6", - "input": "\ud83d\udd7c\uff0e\uffa0", + "comment": "V6", + "input": "\ud805\udcc2\u200c\u226e.\u226e", "output": null }, { - "comment": "P1; V6", - "input": "\ud83d\udd7c.\u1160", + "comment": "V6", + "input": "\ud805\udcc2\u200c<\u0338.<\u0338", "output": null }, { "comment": "V6", - "input": "xn--my8h.xn--psd", + "input": "xn--gdhz656g.xn--gdh", "output": null }, { "comment": "V6", + "input": "xn--0ugy6glz29a.xn--gdh", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": "\ud83d\udd7c\uff0e\uffa0", + "output": "xn--my8h." + }, + { + "comment": "A4_2 (ignored)", + "input": "\ud83d\udd7c.\u1160", + "output": "xn--my8h." + }, + { + "comment": "A4_2 (ignored)", + "input": "xn--my8h.", + "output": "xn--my8h." + }, + { + "comment": "A4_2 (ignored)", + "input": "\ud83d\udd7c.", + "output": "xn--my8h." + }, + { + "comment": "V7", + "input": "xn--my8h.xn--psd", + "output": null + }, + { + "comment": "V7", "input": "xn--my8h.xn--cl7c", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u7215\uda8d\ude51\uff0e\ud835\udff0\u6c17", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u7215\uda8d\ude51.4\u6c17", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--1zxq3199c.xn--4-678b", "output": null }, { - "comment": "P1; V6; V2 (ignored); V3 (ignored)", + "comment": "V7; V2 (ignored); V3 (ignored)", "input": "\udb39\udf43\u3002\uda04\udd83\ud8e6\udc97--", "output": null }, { - "comment": "V6; V2 (ignored); V3 (ignored)", + "comment": "V7; V2 (ignored); V3 (ignored)", "input": "xn--2y75e.xn-----1l15eer88n", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u8530\u3002\udb40\udc79\u08dd-\ud804\ude35", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--sz1a.xn----mrd9984r3dl0i", "output": null }, { - "comment": "P1; V6", "input": "\u03c2\u10c5\u3002\u075a", - "output": null + "output": "xn--3xa403s.xn--epb" }, { "input": "\u03c2\u2d25\u3002\u075a", "output": "xn--3xa403s.xn--epb" }, { - "comment": "P1; V6", "input": "\u03a3\u10c5\u3002\u075a", - "output": null + "output": "xn--4xa203s.xn--epb" }, { "input": "\u03c3\u2d25\u3002\u075a", @@ -6157,20 +8496,14 @@ "output": "xn--4xa203s.xn--epb" }, { - "comment": "P1; V6", "input": "\u03a3\u10c5.\u075a", - "output": null + "output": "xn--4xa203s.xn--epb" }, { "input": "\u03a3\u2d25.\u075a", "output": "xn--4xa203s.xn--epb" }, { - "comment": "V6", - "input": "xn--4xa477d.xn--epb", - "output": null - }, - { "input": "xn--3xa403s.xn--epb", "output": "xn--3xa403s.xn--epb" }, @@ -6179,7 +8512,12 @@ "output": "xn--3xa403s.xn--epb" }, { - "comment": "V6", + "comment": "V7", + "input": "xn--4xa477d.xn--epb", + "output": null + }, + { + "comment": "V7", "input": "xn--3xa677d.xn--epb", "output": null }, @@ -6204,11 +8542,6 @@ "output": "xn--vkb.xn--08e172a" }, { - "comment": "V6", - "input": "xn--pt9c.xn--hnd666l", - "output": null - }, - { "input": "xn--pt9c.xn--0kjya", "output": "xn--pt9c.xn--0kjya" }, @@ -6217,176 +8550,269 @@ "output": "xn--pt9c.xn--0kjya" }, { - "comment": "P1; V6", "input": "\ud802\ude57.\u10a9\u10b5", - "output": null + "output": "xn--pt9c.xn--0kjya" }, { - "comment": "P1; V6", "input": "\ud802\ude57.\u10a9\u2d15", + "output": "xn--pt9c.xn--0kjya" + }, + { + "comment": "V7", + "input": "xn--pt9c.xn--hnd666l", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--pt9c.xn--hndy", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\u200c\u200c\u3124\uff0e\u032e\udb16\ude11\u09c2", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\u200c\u200c\u3124.\u032e\udb16\ude11\u09c2", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--1fk.xn--vta284a9o563a", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn--0uga242k.xn--vta284a9o563a", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10b4\ud836\ude28\u2083\udb40\udc66\uff0e\ud835\udff3\ud804\udcb9\u0b82", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10b4\ud836\ude283\udb40\udc66.7\ud804\udcb9\u0b82", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2d14\ud836\ude283\udb40\udc66.7\ud804\udcb9\u0b82", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--3-ews6985n35s3g.xn--7-cve6271r", "output": null }, { - "comment": "V6", - "input": "xn--3-b1g83426a35t0g.xn--7-cve6271r", + "comment": "V7", + "input": "\u2d14\ud836\ude28\u2083\udb40\udc66\uff0e\ud835\udff3\ud804\udcb9\u0b82", "output": null }, { - "comment": "P1; V6", - "input": "\u2d14\ud836\ude28\u2083\udb40\udc66\uff0e\ud835\udff3\ud804\udcb9\u0b82", + "comment": "V7", + "input": "xn--3-b1g83426a35t0g.xn--7-cve6271r", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u43c8\u200c\u3002\u200c\u2488\ud986\udc95", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u43c8\u200c\u3002\u200c1.\ud986\udc95", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--eco.1.xn--ms39a", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug491l.xn--1-rgn.xn--ms39a", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--eco.xn--tsh21126d", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug491l.xn--0ug88oot66q", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\uff11\uaaf6\u00df\ud807\udca5\uff61\u1dd8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "1\uaaf6\u00df\ud807\udca5\u3002\u1dd8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "1\uaaf6SS\ud807\udca5\u3002\u1dd8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "1\uaaf6ss\ud807\udca5\u3002\u1dd8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--1ss-ir6ln166b.xn--weg", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--1-qfa2471kdb0d.xn--weg", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\uff11\uaaf6SS\ud807\udca5\uff61\u1dd8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\uff11\uaaf6ss\ud807\udca5\uff61\u1dd8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "1\uaaf6Ss\ud807\udca5\u3002\u1dd8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\uff11\uaaf6Ss\ud807\udca5\uff61\u1dd8", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--3j78f.xn--mkb20b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud88a\udd31\u249b\u2fb3\uff0e\ua866\u2488", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\ud88a\udd3120.\u97f3.\ua8661.", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--20-9802c.xn--0w5a.xn--1-eg4e.", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--dth6033bzbvx.xn--tsh9439b", "output": null }, { + "input": "\u10b5\u3002\u06f0\u226e\u00df\u0745", + "output": "xn--dlj.xn--zca912alh227g" + }, + { + "input": "\u10b5\u3002\u06f0<\u0338\u00df\u0745", + "output": "xn--dlj.xn--zca912alh227g" + }, + { + "input": "\u2d15\u3002\u06f0<\u0338\u00df\u0745", + "output": "xn--dlj.xn--zca912alh227g" + }, + { + "input": "\u2d15\u3002\u06f0\u226e\u00df\u0745", + "output": "xn--dlj.xn--zca912alh227g" + }, + { + "input": "\u10b5\u3002\u06f0\u226eSS\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u10b5\u3002\u06f0<\u0338SS\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u2d15\u3002\u06f0<\u0338ss\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u2d15\u3002\u06f0\u226ess\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u10b5\u3002\u06f0\u226eSs\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u10b5\u3002\u06f0<\u0338Ss\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "xn--dlj.xn--ss-jbe65aw27i", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u2d15.\u06f0\u226ess\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u2d15.\u06f0<\u0338ss\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u10b5.\u06f0<\u0338SS\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u10b5.\u06f0\u226eSS\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u10b5.\u06f0\u226eSs\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "\u10b5.\u06f0<\u0338Ss\u0745", + "output": "xn--dlj.xn--ss-jbe65aw27i" + }, + { + "input": "xn--dlj.xn--zca912alh227g", + "output": "xn--dlj.xn--zca912alh227g" + }, + { + "input": "\u2d15.\u06f0\u226e\u00df\u0745", + "output": "xn--dlj.xn--zca912alh227g" + }, + { + "input": "\u2d15.\u06f0<\u0338\u00df\u0745", + "output": "xn--dlj.xn--zca912alh227g" + }, + { + "comment": "V7", + "input": "xn--tnd.xn--ss-jbe65aw27i", + "output": null + }, + { + "comment": "V7", + "input": "xn--tnd.xn--zca912alh227g", + "output": null + }, + { "input": "xn--ge6h.xn--oc9a", "output": "xn--ge6h.xn--oc9a" }, @@ -6399,7 +8825,57 @@ "output": "xn--ge6h.xn--oc9a" }, { - "comment": "C1; P1; V6; V3 (ignored)", + "comment": "V7", + "input": "\u2132\udb40\udd7a\ud937\udd52\u3002\u226f\u2f91", + "output": null + }, + { + "comment": "V7", + "input": "\u2132\udb40\udd7a\ud937\udd52\u3002>\u0338\u2f91", + "output": null + }, + { + "comment": "V7", + "input": "\u2132\udb40\udd7a\ud937\udd52\u3002\u226f\u897e", + "output": null + }, + { + "comment": "V7", + "input": "\u2132\udb40\udd7a\ud937\udd52\u3002>\u0338\u897e", + "output": null + }, + { + "comment": "V7", + "input": "\u214e\udb40\udd7a\ud937\udd52\u3002>\u0338\u897e", + "output": null + }, + { + "comment": "V7", + "input": "\u214e\udb40\udd7a\ud937\udd52\u3002\u226f\u897e", + "output": null + }, + { + "comment": "V7", + "input": "xn--73g39298c.xn--hdhz171b", + "output": null + }, + { + "comment": "V7", + "input": "\u214e\udb40\udd7a\ud937\udd52\u3002>\u0338\u2f91", + "output": null + }, + { + "comment": "V7", + "input": "\u214e\udb40\udd7a\ud937\udd52\u3002\u226f\u2f91", + "output": null + }, + { + "comment": "V7", + "input": "xn--f3g73398c.xn--hdhz171b", + "output": null + }, + { + "comment": "C1; V3 (ignored)", "input": "\u200c.\u00df\u10a9-", "output": null }, @@ -6409,7 +8885,7 @@ "output": null }, { - "comment": "C1; P1; V6; V3 (ignored)", + "comment": "C1; V3 (ignored)", "input": "\u200c.SS\u10a9-", "output": null }, @@ -6434,22 +8910,22 @@ "output": null }, { - "comment": "V6; V3 (ignored); A4_2 (ignored)", - "input": ".xn--ss--4rn", + "comment": "C1; V3 (ignored)", + "input": "xn--0ug.xn----pfa2305a", "output": null }, { - "comment": "C1; V6; V3 (ignored)", - "input": "xn--0ug.xn--ss--4rn", + "comment": "V7; V3 (ignored); A4_2 (ignored)", + "input": ".xn--ss--4rn", "output": null }, { - "comment": "C1; V3 (ignored)", - "input": "xn--0ug.xn----pfa2305a", + "comment": "C1; V7; V3 (ignored)", + "input": "xn--0ug.xn--ss--4rn", "output": null }, { - "comment": "C1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "xn--0ug.xn----pfa042j", "output": null }, @@ -6494,162 +8970,182 @@ "output": "xn----4-p16k.ss" }, { - "comment": "C2; P1; V6", - "input": "\udacf\udc99\udb40\uded8\uff61?-\u200d", + "comment": "V7; V3 (ignored)", + "input": "\udb42\udea2-\u3002\uda2c\udc8f\u226e\ud805\udf2b", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "\udb42\udea2-\u3002\uda2c\udc8f<\u0338\ud805\udf2b", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "xn----bh61m.xn--gdhz157g0em1d", + "output": null + }, + { + "comment": "C1; C2; V7", + "input": "\u200c\udb40\ude79\u200d\u3002\ud9f3\udfe7\u226e\u10a9", + "output": null + }, + { + "comment": "C1; C2; V7", + "input": "\u200c\udb40\ude79\u200d\u3002\ud9f3\udfe7<\u0338\u10a9", "output": null }, { - "comment": "C2; P1; V6", - "input": "\udacf\udc99\udb40\uded8\u3002?-\u200d", + "comment": "C1; C2; V7", + "input": "\u200c\udb40\ude79\u200d\u3002\ud9f3\udfe7<\u0338\u2d09", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "xn--ct86d8w51a.?-", + "comment": "C1; C2; V7", + "input": "\u200c\udb40\ude79\u200d\u3002\ud9f3\udfe7\u226e\u2d09", "output": null }, { - "comment": "C2; P1; V6", - "input": "xn--ct86d8w51a.xn--?--n1t", + "comment": "V7", + "input": "xn--3n36e.xn--gdh992byu01p", "output": null }, { - "comment": "C2; P1; V6", - "input": "xn--ct86d8w51a.?-\u200d", + "comment": "C1; C2; V7", + "input": "xn--0ugc90904y.xn--gdh992byu01p", "output": null }, { - "comment": "C2; P1; V6", - "input": "XN--CT86D8W51A.?-\u200d", + "comment": "V7", + "input": "xn--3n36e.xn--hnd112gpz83n", "output": null }, { - "comment": "C2; P1; V6", - "input": "Xn--Ct86d8w51a.?-\u200d", + "comment": "C1; C2; V7", + "input": "xn--0ugc90904y.xn--hnd112gpz83n", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\ud836\ude9e\u10b0\uff61\ucaa1", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\ud836\ude9e\u10b0\uff61\u110d\u1168\u11a8", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\ud836\ude9e\u10b0\u3002\ucaa1", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\ud836\ude9e\u10b0\u3002\u110d\u1168\u11a8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud836\ude9e\u2d10\u3002\u110d\u1168\u11a8", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud836\ude9e\u2d10\u3002\ucaa1", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--7kj1858k.xn--pi6b", "output": null }, { - "comment": "V5; V6", - "input": "xn--ond3755u.xn--pi6b", + "comment": "V6", + "input": "\ud836\ude9e\u2d10\uff61\u110d\u1168\u11a8", "output": null }, { - "comment": "V5", - "input": "\ud836\ude9e\u2d10\uff61\u110d\u1168\u11a8", + "comment": "V6", + "input": "\ud836\ude9e\u2d10\uff61\ucaa1", "output": null }, { - "comment": "V5", - "input": "\ud836\ude9e\u2d10\uff61\ucaa1", + "comment": "V6; V7", + "input": "xn--ond3755u.xn--pi6b", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u1845\uff10\u200c\uff61\u23a2\udb52\ude04", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u18450\u200c\u3002\u23a2\udb52\ude04", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--0-z6j.xn--8lh28773l", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0-z6jy93b.xn--8lh28773l", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud88a\udf9a\uff19\ua369\u17d3\uff0e\u200d\u00df", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud88a\udf9a9\ua369\u17d3.\u200d\u00df", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud88a\udf9a9\ua369\u17d3.\u200dSS", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud88a\udf9a9\ua369\u17d3.\u200dss", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--9-i0j5967eg3qz.ss", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--9-i0j5967eg3qz.xn--ss-l1t", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--9-i0j5967eg3qz.xn--zca770n", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud88a\udf9a\uff19\ua369\u17d3\uff0e\u200dSS", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud88a\udf9a\uff19\ua369\u17d3\uff0e\u200dss", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud88a\udf9a9\ua369\u17d3.\u200dSs", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\ud88a\udf9a\uff19\ua369\u17d3\uff0e\u200dSs", "output": null }, @@ -6662,12 +9158,42 @@ "output": "xn--ju8a625r.xn--hpb0073k" }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", + "input": "\u2490\u226f-\u3002\ufe12\uda65\udc63-\ud939\udee0", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "\u2490>\u0338-\u3002\ufe12\uda65\udc63-\ud939\udee0", + "output": null + }, + { + "comment": "V7; V3 (ignored); A4_2 (ignored)", + "input": "9.\u226f-\u3002\u3002\uda65\udc63-\ud939\udee0", + "output": null + }, + { + "comment": "V7; V3 (ignored); A4_2 (ignored)", + "input": "9.>\u0338-\u3002\u3002\uda65\udc63-\ud939\udee0", + "output": null + }, + { + "comment": "V7; V3 (ignored); A4_2 (ignored)", + "input": "9.xn----ogo..xn----xj54d1s69k", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "xn----ogot9g.xn----n89hl0522az9u2a", + "output": null + }, + { + "comment": "C2; V3 (ignored)", "input": "\u10af\udb40\udd4b-\uff0e\u200d\u10a9", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V3 (ignored)", "input": "\u10af\udb40\udd4b-.\u200d\u10a9", "output": null }, @@ -6687,207 +9213,212 @@ "output": null }, { - "comment": "V6; V3 (ignored)", - "input": "xn----00g.xn--hnd", + "comment": "C2; V3 (ignored)", + "input": "\u2d0f\udb40\udd4b-\uff0e\u200d\u2d09", "output": null }, { - "comment": "C2; V6; V3 (ignored)", - "input": "xn----00g.xn--hnd399e", + "comment": "V7; V3 (ignored)", + "input": "xn----00g.xn--hnd", "output": null }, { - "comment": "C2; V3 (ignored)", - "input": "\u2d0f\udb40\udd4b-\uff0e\u200d\u2d09", + "comment": "C2; V7; V3 (ignored)", + "input": "xn----00g.xn--hnd399e", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\u1714\u3002\udb40\udda3-\ud804\udeea", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn--fze.xn----ly8i", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\uabe8-\uff0e\uda60\udfdc\u05bd\u00df", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\uabe8-.\uda60\udfdc\u05bd\u00df", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\uabe8-.\uda60\udfdc\u05bdSS", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\uabe8-.\uda60\udfdc\u05bdss", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\uabe8-.\uda60\udfdc\u05bdSs", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn----pw5e.xn--ss-7jd10716y", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn----pw5e.xn--zca50wfv060a", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\uabe8-\uff0e\uda60\udfdc\u05bdSS", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\uabe8-\uff0e\uda60\udfdc\u05bdss", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\uabe8-\uff0e\uda60\udfdc\u05bdSs", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud835\udfe5\u266e\ud805\udf2b\u08ed\uff0e\u17d2\ud805\udf2b8\udb40\udd8f", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "3\u266e\ud805\udf2b\u08ed.\u17d2\ud805\udf2b8\udb40\udd8f", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--3-ksd277tlo7s.xn--8-f0jx021l", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "-\uff61\uda14\udf00\u200d\u2761", "output": null }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "-\u3002\uda14\udf00\u200d\u2761", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "-.xn--nei54421f", "output": null }, { - "comment": "C2; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "-.xn--1ug800aq795s", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ud835\udfd3\u2631\ud835\udfd0\uda57\udc35\uff61\ud836\udeae\ud902\udc73", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "5\u26312\uda57\udc35\u3002\ud836\udeae\ud902\udc73", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--52-dwx47758j.xn--kd3hk431k", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "-.-\u251c\uda1a\udda3", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "-.xn----ukp70432h", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03c2\uff0e\ufdc1\ud83d\udf9b\u2488", "output": null }, { + "comment": "A4_2 (ignored)", "input": "\u03c2.\u0641\u0645\u064a\ud83d\udf9b1.", "output": "xn--3xa.xn--1-gocmu97674d." }, { + "comment": "A4_2 (ignored)", "input": "\u03a3.\u0641\u0645\u064a\ud83d\udf9b1.", "output": "xn--4xa.xn--1-gocmu97674d." }, { + "comment": "A4_2 (ignored)", "input": "\u03c3.\u0641\u0645\u064a\ud83d\udf9b1.", "output": "xn--4xa.xn--1-gocmu97674d." }, { + "comment": "A4_2 (ignored)", "input": "xn--4xa.xn--1-gocmu97674d.", "output": "xn--4xa.xn--1-gocmu97674d." }, { + "comment": "A4_2 (ignored)", "input": "xn--3xa.xn--1-gocmu97674d.", "output": "xn--3xa.xn--1-gocmu97674d." }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03a3\uff0e\ufdc1\ud83d\udf9b\u2488", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u03c3\uff0e\ufdc1\ud83d\udf9b\u2488", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--4xa.xn--dhbip2802atb20c", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--3xa.xn--dhbip2802atb20c", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "9\udb40\udde5\uff0e\udb6b\udd34\u1893", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "9\udb40\udde5.\udb6b\udd34\u1893", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "9.xn--dbf91222q", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\ufe12\u10b6\u0366\uff0e\u200c", "output": null }, { - "comment": "C1; P1; V6; A4_2 (ignored)", + "comment": "C1; A4_2 (ignored)", "input": "\u3002\u10b6\u0366.\u200c", "output": null }, @@ -6907,55 +9438,57 @@ "output": null }, { - "comment": "V6; A4_2 (ignored)", - "input": ".xn--hva929d.", + "comment": "C1; V7", + "input": "\ufe12\u2d16\u0366\uff0e\u200c", "output": null }, { - "comment": "C1; V6; A4_2 (ignored)", - "input": ".xn--hva929d.xn--0ug", + "comment": "V7; A4_2 (ignored)", + "input": "xn--hva754sy94k.", "output": null }, { - "comment": "C1; P1; V6", - "input": "\ufe12\u2d16\u0366\uff0e\u200c", + "comment": "C1; V7", + "input": "xn--hva754sy94k.xn--0ug", "output": null }, { - "comment": "V6", - "input": "xn--hva754sy94k.", + "comment": "V7; A4_2 (ignored)", + "input": ".xn--hva929d.", "output": null }, { - "comment": "C1; V6", - "input": "xn--hva754sy94k.xn--0ug", + "comment": "C1; V7; A4_2 (ignored)", + "input": ".xn--hva929d.xn--0ug", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--hva929dl29p.", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--hva929dl29p.xn--0ug", "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--hva754s.", "output": "xn--hva754s." }, { + "comment": "A4_2 (ignored)", "input": "\u2d16\u0366.", "output": "xn--hva754s." }, { - "comment": "P1; V6", + "comment": "A4_2 (ignored)", "input": "\u10b6\u0366.", - "output": null + "output": "xn--hva754s." }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--hva929d.", "output": null }, @@ -6968,138 +9501,137 @@ "output": "xn--hzb.xn--ukj4430l" }, { - "comment": "P1; V6", "input": "\u08bb.\u10a3\ud838\udc12", - "output": null + "output": "xn--hzb.xn--ukj4430l" }, { - "comment": "V6", + "comment": "V7", "input": "xn--hzb.xn--bnd2938u", "output": null }, { - "comment": "C1; C2; P1; V6", + "comment": "C1; C2; V7", "input": "\u200d\u200c\u3002\uff12\u4af7\udb42\uddf7", "output": null }, { - "comment": "C1; C2; P1; V6", + "comment": "C1; C2; V7", "input": "\u200d\u200c\u30022\u4af7\udb42\uddf7", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--2-me5ay1273i", "output": null }, { - "comment": "C1; C2; V6", + "comment": "C1; C2; V7", "input": "xn--0ugb.xn--2-me5ay1273i", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "-\ud838\udc24\udb32\udc10\u3002\ud9e2\udf16", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn----rq4re4997d.xn--l707b", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\udb8d\udec2\ufe12\u200c\u37c0\uff0e\u0624\u2488", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\udb8d\udec2\ufe12\u200c\u37c0\uff0e\u0648\u0654\u2488", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--z272f.xn--etl.xn--1-smc.", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--etlt457ccrq7h.xn--jgb476m", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug754gxl4ldlt0k.xn--jgb476m", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u07fc\ud803\ude06.\ud80d\udd8f\ufe12\ud8ea\ude29\u10b0", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u07fc\ud803\ude06.\ud80d\udd8f\u3002\ud8ea\ude29\u10b0", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u07fc\ud803\ude06.\ud80d\udd8f\u3002\ud8ea\ude29\u2d10", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--0tb8725k.xn--tu8d.xn--7kj73887a", "output": null }, { - "comment": "V6", - "input": "xn--0tb8725k.xn--tu8d.xn--ond97931d", + "comment": "V7", + "input": "\u07fc\ud803\ude06.\ud80d\udd8f\ufe12\ud8ea\ude29\u2d10", "output": null }, { - "comment": "P1; V6", - "input": "\u07fc\ud803\ude06.\ud80d\udd8f\ufe12\ud8ea\ude29\u2d10", + "comment": "V7", + "input": "xn--0tb8725k.xn--7kj9008dt18a7py9c", "output": null }, { - "comment": "V6", - "input": "xn--0tb8725k.xn--7kj9008dt18a7py9c", + "comment": "V7", + "input": "xn--0tb8725k.xn--tu8d.xn--ond97931d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--0tb8725k.xn--ond3562jt18a7py9c", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u10c5\u26ad\udb41\uddab\u22c3\uff61\ud804\udf3c", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u10c5\u26ad\udb41\uddab\u22c3\u3002\ud804\udf3c", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u2d25\u26ad\udb41\uddab\u22c3\u3002\ud804\udf3c", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--vfh16m67gx1162b.xn--ro1d", "output": null }, { - "comment": "V5; V6", - "input": "xn--9nd623g4zc5z060c.xn--ro1d", + "comment": "V6; V7", + "input": "\u2d25\u26ad\udb41\uddab\u22c3\uff61\ud804\udf3c", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u2d25\u26ad\udb41\uddab\u22c3\uff61\ud804\udf3c", + "comment": "V6; V7", + "input": "xn--9nd623g4zc5z060c.xn--ro1d", "output": null }, { @@ -7113,7 +9645,32 @@ "output": "xn----o9p.xn--rc9a" }, { - "comment": "C2; P1; V6", + "comment": "V7; V3 (ignored)", + "input": "\ud8c8\ude26\u5e37\uff61\u226f\u843a\u1dc8-", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "\ud8c8\ude26\u5e37\uff61>\u0338\u843a\u1dc8-", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "\ud8c8\ude26\u5e37\u3002\u226f\u843a\u1dc8-", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "\ud8c8\ude26\u5e37\u3002>\u0338\u843a\u1dc8-", + "output": null + }, + { + "comment": "V7; V3 (ignored)", + "input": "xn--qutw175s.xn----mimu6tf67j", + "output": null + }, + { + "comment": "C2", "input": "\u200d\u650c\uabed\u3002\u1896-\u10b8", "output": null }, @@ -7131,32 +9688,31 @@ "output": "xn--p9ut19m.xn----mck373i" }, { - "comment": "P1; V6", "input": "\u650c\uabed.\u1896-\u10b8", - "output": null + "output": "xn--p9ut19m.xn----mck373i" }, { - "comment": "V6", - "input": "xn--p9ut19m.xn----k1g451d", + "comment": "C2", + "input": "xn--1ug592ykp6b.xn----mck373i", "output": null }, { - "comment": "C2", - "input": "xn--1ug592ykp6b.xn----mck373i", + "comment": "V7", + "input": "xn--p9ut19m.xn----k1g451d", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--1ug592ykp6b.xn----k1g451d", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\ua5a8\uff0e\u2497\uff13\ud212\u06f3", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\ua5a8\uff0e\u2497\uff13\u1110\u116d\u11a9\u06f3", "output": null }, @@ -7188,12 +9744,12 @@ "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--9r8a.xn--3-nyc678tu07m", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug2473c.xn--3-nyc678tu07m", "output": null }, @@ -7208,10 +9764,12 @@ "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--1-5bt6845n.", "output": "xn--1-5bt6845n." }, { + "comment": "A4_2 (ignored)", "input": "1\ud836\ude19\u2e16.", "output": "xn--1-5bt6845n." }, @@ -7221,231 +9779,306 @@ "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "F\udb40\udd5f\uff61\ud9fd\uddc5\u265a", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "F\udb40\udd5f\u3002\ud9fd\uddc5\u265a", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "f\udb40\udd5f\u3002\ud9fd\uddc5\u265a", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "f.xn--45hz6953f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "f\udb40\udd5f\uff61\ud9fd\uddc5\u265a", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0b4d\ud804\udd34\u1de9\u3002\ud835\udfee\u10b8\ud838\udc28\ud8ce\udd47", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0b4d\ud804\udd34\u1de9\u30022\u10b8\ud838\udc28\ud8ce\udd47", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u0b4d\ud804\udd34\u1de9\u30022\u2d18\ud838\udc28\ud8ce\udd47", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--9ic246gs21p.xn--2-nws2918ndrjr", "output": null }, { - "comment": "V5; V6", - "input": "xn--9ic246gs21p.xn--2-k1g43076adrwq", + "comment": "V6; V7", + "input": "\u0b4d\ud804\udd34\u1de9\u3002\ud835\udfee\u2d18\ud838\udc28\ud8ce\udd47", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u0b4d\ud804\udd34\u1de9\u3002\ud835\udfee\u2d18\ud838\udc28\ud8ce\udd47", + "comment": "V6; V7", + "input": "xn--9ic246gs21p.xn--2-k1g43076adrwq", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\uda0e\udc2d\u200c\u200c\u2488\u3002\u52c9\ud804\udc45", "output": null }, { - "comment": "C1; P1; V6; A4_2 (ignored)", + "comment": "C1; V7; A4_2 (ignored)", "input": "\uda0e\udc2d\u200c\u200c1.\u3002\u52c9\ud804\udc45", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "xn--1-yi00h..xn--4grs325b", "output": null }, { - "comment": "C1; V6; A4_2 (ignored)", + "comment": "C1; V7; A4_2 (ignored)", "input": "xn--1-rgna61159u..xn--4grs325b", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--tsh11906f.xn--4grs325b", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0uga855aez302a.xn--4grs325b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1843.\u73bf\ud96c\ude1c\udb15\udf90", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--27e.xn--7cy81125a0yq4a", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "C1; V7", + "input": "\u200c\u200c\uff61\u2488\u226f\ud835\udff5", + "output": null + }, + { + "comment": "C1; V7", + "input": "\u200c\u200c\uff61\u2488>\u0338\ud835\udff5", + "output": null + }, + { + "comment": "C1", + "input": "\u200c\u200c\u30021.\u226f9", + "output": null + }, + { + "comment": "C1", + "input": "\u200c\u200c\u30021.>\u03389", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": ".1.xn--9-ogo", + "output": ".1.xn--9-ogo" + }, + { + "comment": "C1", + "input": "xn--0uga.1.xn--9-ogo", + "output": null + }, + { + "comment": "V7; A4_2 (ignored)", + "input": ".xn--9-ogo37g", + "output": null + }, + { + "comment": "C1; V7", + "input": "xn--0uga.xn--9-ogo37g", + "output": null + }, + { + "comment": "V6; V3 (ignored)", "input": "\u20da\uff0e\ud805\ude3f-", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\u20da.\ud805\ude3f-", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn--w0g.xn----bd0j", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\u1082-\u200d\ua8ea\uff0e\ua84a\u200d\ud9b3\ude33", "output": null }, { - "comment": "C2; P1; V5; V6", + "comment": "C2; V6; V7", "input": "\u1082-\u200d\ua8ea.\ua84a\u200d\ud9b3\ude33", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn----gyg3618i.xn--jc9ao4185a", "output": null }, { - "comment": "C2; V5; V6", + "comment": "C2; V6; V7", "input": "xn----gyg250jio7k.xn--1ug8774cri56d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud804\ude35\u5eca.\ud802\udc0d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--xytw701b.xn--yc9c", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10be\ud899\udec0\ud82d\uddfb\uff0e\u1897\ub9ab", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10be\ud899\udec0\ud82d\uddfb\uff0e\u1897\u1105\u1174\u11c2", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10be\ud899\udec0\ud82d\uddfb.\u1897\ub9ab", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10be\ud899\udec0\ud82d\uddfb.\u1897\u1105\u1174\u11c2", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2d1e\ud899\udec0\ud82d\uddfb.\u1897\u1105\u1174\u11c2", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2d1e\ud899\udec0\ud82d\uddfb.\u1897\ub9ab", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--mlj0486jgl2j.xn--hbf6853f", "output": null }, { - "comment": "V6", - "input": "xn--2nd8876sgl2j.xn--hbf6853f", + "comment": "V7", + "input": "\u2d1e\ud899\udec0\ud82d\uddfb\uff0e\u1897\u1105\u1174\u11c2", "output": null }, { - "comment": "P1; V6", - "input": "\u2d1e\ud899\udec0\ud82d\uddfb\uff0e\u1897\u1105\u1174\u11c2", + "comment": "V7", + "input": "\u2d1e\ud899\udec0\ud82d\uddfb\uff0e\u1897\ub9ab", "output": null }, { - "comment": "P1; V6", - "input": "\u2d1e\ud899\udec0\ud82d\uddfb\uff0e\u1897\ub9ab", + "comment": "V7", + "input": "xn--2nd8876sgl2j.xn--hbf6853f", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u00df\u200d\u103a\uff61\u2488", "output": null }, { - "comment": "C2; P1; V6", + "comment": "A4_2 (ignored)", + "input": "xn--ss-f4j.b.", + "output": "xn--ss-f4j.b." + }, + { + "comment": "A4_2 (ignored)", + "input": "ss\u103a.b.", + "output": "xn--ss-f4j.b." + }, + { + "comment": "A4_2 (ignored)", + "input": "SS\u103a.B.", + "output": "xn--ss-f4j.b." + }, + { + "comment": "A4_2 (ignored)", + "input": "Ss\u103a.b.", + "output": "xn--ss-f4j.b." + }, + { + "comment": "C2; A4_2 (ignored)", + "input": "xn--ss-f4j585j.b.", + "output": null + }, + { + "comment": "C2; A4_2 (ignored)", + "input": "xn--zca679eh2l.b.", + "output": null + }, + { + "comment": "C2; V7", "input": "SS\u200d\u103a\uff61\u2488", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "ss\u200d\u103a\uff61\u2488", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "Ss\u200d\u103a\uff61\u2488", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--ss-f4j.xn--tsh", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--ss-f4j585j.xn--tsh", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--zca679eh2l.xn--tsh", "output": null }, { + "comment": "A4_2 (ignored)", + "input": "SS\u103a.b.", + "output": "xn--ss-f4j.b." + }, + { "input": "\u06cc\ud802\ude3f\uff0e\u00df\u0f84\ud804\udf6c", "output": "xn--clb2593k.xn--zca216edt0r" }, @@ -7486,157 +10119,295 @@ "output": "xn--clb2593k.xn--ss-toj6092t" }, { - "comment": "V5; V3 (ignored)", + "comment": "C1; A4_2 (ignored)", + "input": "\ud835\udfe0\u226e\u200c\uff61\udb40\udd71\u17b4", + "output": null + }, + { + "comment": "C1; A4_2 (ignored)", + "input": "\ud835\udfe0<\u0338\u200c\uff61\udb40\udd71\u17b4", + "output": null + }, + { + "comment": "C1; A4_2 (ignored)", + "input": "8\u226e\u200c\u3002\udb40\udd71\u17b4", + "output": null + }, + { + "comment": "C1; A4_2 (ignored)", + "input": "8<\u0338\u200c\u3002\udb40\udd71\u17b4", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": "xn--8-ngo.", + "output": "xn--8-ngo." + }, + { + "comment": "A4_2 (ignored)", + "input": "8\u226e.", + "output": "xn--8-ngo." + }, + { + "comment": "A4_2 (ignored)", + "input": "8<\u0338.", + "output": "xn--8-ngo." + }, + { + "comment": "C1; A4_2 (ignored)", + "input": "xn--8-sgn10i.", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--8-ngo.xn--z3e", + "output": null + }, + { + "comment": "C1; V6; V7", + "input": "xn--8-sgn10i.xn--z3e", + "output": null + }, + { + "comment": "V7", + "input": "\u1895\u226f\ufe12\ud8d0\udcaf\uff0e\u10a0", + "output": null + }, + { + "comment": "V7", + "input": "\u1895>\u0338\ufe12\ud8d0\udcaf\uff0e\u10a0", + "output": null + }, + { + "comment": "V7", + "input": "\u1895\u226f\u3002\ud8d0\udcaf.\u10a0", + "output": null + }, + { + "comment": "V7", + "input": "\u1895>\u0338\u3002\ud8d0\udcaf.\u10a0", + "output": null + }, + { + "comment": "V7", + "input": "\u1895>\u0338\u3002\ud8d0\udcaf.\u2d00", + "output": null + }, + { + "comment": "V7", + "input": "\u1895\u226f\u3002\ud8d0\udcaf.\u2d00", + "output": null + }, + { + "comment": "V7", + "input": "xn--fbf851c.xn--ko1u.xn--rkj", + "output": null + }, + { + "comment": "V7", + "input": "\u1895>\u0338\ufe12\ud8d0\udcaf\uff0e\u2d00", + "output": null + }, + { + "comment": "V7", + "input": "\u1895\u226f\ufe12\ud8d0\udcaf\uff0e\u2d00", + "output": null + }, + { + "comment": "V7", + "input": "xn--fbf851cq98poxw1a.xn--rkj", + "output": null + }, + { + "comment": "V7", + "input": "xn--fbf851c.xn--ko1u.xn--7md", + "output": null + }, + { + "comment": "V7", + "input": "xn--fbf851cq98poxw1a.xn--7md", + "output": null + }, + { + "comment": "V6; V3 (ignored)", "input": "\u0f9f\uff0e-\u082a", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\u0f9f.-\u082a", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn--vfd.xn----fhd", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1d6c\udb40\udda0\uff0e\ud552\u2492\u2488\udbe0\udd26", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1d6c\udb40\udda0\uff0e\u1111\u1175\u11bd\u2492\u2488\udbe0\udd26", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1d6c\udb40\udda0.\ud55211.1.\udbe0\udd26", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1d6c\udb40\udda0.\u1111\u1175\u11bd11.1.\udbe0\udd26", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--tbg.xn--11-5o7k.1.xn--k469f", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--tbg.xn--tsht7586kyts9l", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2488\u270c\uda3e\udf1f\uff0e\ud835\udfe1\ud943\udc63", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "1.\u270c\uda3e\udf1f.9\ud943\udc63", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "1.xn--7bi44996f.xn--9-o706d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--tsh24g49550b.xn--9-o706d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03c2\uff0e\ua9c0\ua8c4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03c2.\ua9c0\ua8c4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03a3.\ua9c0\ua8c4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03c3.\ua9c0\ua8c4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--4xa.xn--0f9ars", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--3xa.xn--0f9ars", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03a3\uff0e\ua9c0\ua8c4", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\u03c3\uff0e\ua9c0\ua8c4", "output": null }, { - "comment": "P1; V6", + "input": "\u7f9a\uff61\u226f", + "output": "xn--xt0a.xn--hdh" + }, + { + "input": "\u7f9a\uff61>\u0338", + "output": "xn--xt0a.xn--hdh" + }, + { + "input": "\u7f9a\u3002\u226f", + "output": "xn--xt0a.xn--hdh" + }, + { + "input": "\u7f9a\u3002>\u0338", + "output": "xn--xt0a.xn--hdh" + }, + { + "input": "xn--xt0a.xn--hdh", + "output": "xn--xt0a.xn--hdh" + }, + { + "input": "\u7f9a.\u226f", + "output": "xn--xt0a.xn--hdh" + }, + { + "input": "\u7f9a.>\u0338", + "output": "xn--xt0a.xn--hdh" + }, + { + "comment": "V7", "input": "\u2786\ud99e\uddd5\u1ed7\u2488\uff0e\uda06\udf12\ud945\ude2e\u085b\ud835\udfeb", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2786\ud99e\uddd5o\u0302\u0303\u2488\uff0e\uda06\udf12\ud945\ude2e\u085b\ud835\udfeb", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u2786\ud99e\uddd5\u1ed71..\uda06\udf12\ud945\ude2e\u085b9", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u2786\ud99e\uddd5o\u0302\u03031..\uda06\udf12\ud945\ude2e\u085b9", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u2786\ud99e\uddd5O\u0302\u03031..\uda06\udf12\ud945\ude2e\u085b9", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u2786\ud99e\uddd5\u1ed61..\uda06\udf12\ud945\ude2e\u085b9", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "xn--1-3xm292b6044r..xn--9-6jd87310jtcqs", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2786\ud99e\uddd5O\u0302\u0303\u2488\uff0e\uda06\udf12\ud945\ude2e\u085b\ud835\udfeb", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2786\ud99e\uddd5\u1ed6\u2488\uff0e\uda06\udf12\ud945\ude2e\u085b\ud835\udfeb", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs", "output": null }, @@ -7658,143 +10429,143 @@ "output": "xn--ye6h" }, { - "comment": "C1; P1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "\u073c\u200c-\u3002\ud80d\udc3e\u00df", "output": null }, { - "comment": "C1; P1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "\u073c\u200c-\u3002\ud80d\udc3eSS", "output": null }, { - "comment": "C1; P1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "\u073c\u200c-\u3002\ud80d\udc3ess", "output": null }, { - "comment": "C1; P1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "\u073c\u200c-\u3002\ud80d\udc3eSs", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn----s2c.xn--ss-066q", "output": null }, { - "comment": "C1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "xn----s2c071q.xn--ss-066q", "output": null }, { - "comment": "C1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "xn----s2c071q.xn--zca7848m", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "-\uda9d\udf6c\u135e\ud805\udf27.\u1deb-\ufe12", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored); A4_2 (ignored)", "input": "-\uda9d\udf6c\u135e\ud805\udf27.\u1deb-\u3002", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored); A4_2 (ignored)", "input": "xn----b5h1837n2ok9f.xn----mkm.", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn----b5h1837n2ok9f.xn----mkmw278h", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ufe12.\uda2a\udc21\u1a59", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u3002.\uda2a\udc21\u1a59", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "..xn--cof61594i", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--y86c.xn--cof61594i", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "\ud807\udc3a.-\uda05\udfcf", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn--jk3d.xn----iz68g", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb43\udee9\uff0e\u8d4f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb43\udee9.\u8d4f", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--2856e.xn--6o3a", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u10ad\uff0e\ud8f4\udde6\u200c", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u10ad.\ud8f4\udde6\u200c", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u2d0d.\ud8f4\udde6\u200c", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--4kj.xn--p01x", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--4kj.xn--0ug56448b", "output": null }, { - "comment": "V6", - "input": "xn--lnd.xn--p01x", + "comment": "C1; V7", + "input": "\u2d0d\uff0e\ud8f4\udde6\u200c", "output": null }, { - "comment": "C1; V6", - "input": "xn--lnd.xn--0ug56448b", + "comment": "V7", + "input": "xn--lnd.xn--p01x", "output": null }, { - "comment": "C1; P1; V6", - "input": "\u2d0d\uff0e\ud8f4\udde6\u200c", + "comment": "C1; V7", + "input": "xn--lnd.xn--0ug56448b", "output": null }, { @@ -7814,7 +10585,7 @@ "output": "3.xn--6vz" }, { - "comment": "C2; P1; V6; V3 (ignored)", + "comment": "C2; V3 (ignored)", "input": "-\u200d.\u10be\ud800\udef7", "output": null }, @@ -7834,222 +10605,262 @@ "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "-.xn--2nd2315j", "output": null }, { - "comment": "C2; V6; V3 (ignored)", + "comment": "C2; V7; V3 (ignored)", "input": "xn----ugn.xn--2nd2315j", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03c2\u00df\u0731\uff0e\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03c2\u00df\u0731.\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03a3SS\u0731.\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03c3ss\u0731.\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03a3ss\u0731.\u0bcd", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--ss-ubc826a.xn--xmc", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--ss-ubc826ab34b.xn--xmc", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03a3\u00df\u0731.\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03c3\u00df\u0731.\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--zca39lk1di19a.xn--xmc", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--zca19ln1di19a.xn--xmc", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03a3SS\u0731\uff0e\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03c3ss\u0731\uff0e\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03a3ss\u0731\uff0e\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03a3\u00df\u0731\uff0e\u0bcd", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u200d\u03c3\u00df\u0731\uff0e\u0bcd", "output": null }, { - "comment": "P1; V6", + "comment": "C2", + "input": "\u2260\uff0e\u200d", + "output": null + }, + { + "comment": "C2", + "input": "=\u0338\uff0e\u200d", + "output": null + }, + { + "comment": "C2", + "input": "\u2260.\u200d", + "output": null + }, + { + "comment": "C2", + "input": "=\u0338.\u200d", + "output": null + }, + { + "comment": "A4_2 (ignored)", + "input": "xn--1ch.", + "output": "xn--1ch." + }, + { + "comment": "A4_2 (ignored)", + "input": "\u2260.", + "output": "xn--1ch." + }, + { + "comment": "A4_2 (ignored)", + "input": "=\u0338.", + "output": "xn--1ch." + }, + { + "comment": "C2", + "input": "xn--1ch.xn--1ug", + "output": null + }, + { + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03c2\uff0e\u03c2\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03c2.\u03c2\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03a3.\u03a3\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03c3.\u03c2\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03c3.\u03c3\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03a3.\u03c3\ud802\ude3f", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--4xa502av8297a.xn--4xa6055k", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03a3.\u03c2\ud802\ude3f", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--4xa502av8297a.xn--3xa8055k", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--3xa702av8297a.xn--3xa8055k", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03a3\uff0e\u03a3\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03c3\uff0e\u03c2\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03c3\uff0e\u03c3\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03a3\uff0e\u03c3\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb5c\udef5\u09cd\u03a3\uff0e\u03c2\ud802\ude3f", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud94e\udd12\uff61\ub967", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud94e\udd12\uff61\u1105\u1172\u11b6", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud94e\udd12\u3002\ub967", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud94e\udd12\u3002\u1105\u1172\u11b6", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--s264a.xn--pw2b", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1846\ud805\udcdd\uff0e\ud83b\udd46", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u1846\ud805\udcdd.\ud83b\udd46", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--57e0440k.xn--k86h", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udbef\udfe6\uff61\u183d", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udbef\udfe6\u3002\u183d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--j890g.xn--w7e", "output": null }, @@ -8064,7 +10875,7 @@ "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--b6s0078f.xn--0ic", "output": null }, @@ -8074,52 +10885,52 @@ "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c.\ud93d\udee4", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--q823a", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug.xn--q823a", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udaa9\uded5\u10a3\u4805\uff0e\ud803\ude11", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udaa9\uded5\u10a3\u4805.\ud803\ude11", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udaa9\uded5\u2d03\u4805.\ud803\ude11", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--ukju77frl47r.xn--yl0d", "output": null }, { - "comment": "V6", - "input": "xn--bnd074zr557n.xn--yl0d", + "comment": "V7", + "input": "\udaa9\uded5\u2d03\u4805\uff0e\ud803\ude11", "output": null }, { - "comment": "P1; V6", - "input": "\udaa9\uded5\u2d03\u4805\uff0e\ud803\ude11", + "comment": "V7", + "input": "xn--bnd074zr557n.xn--yl0d", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "-\uff61\ufe12", "output": null }, @@ -8134,7 +10945,7 @@ "output": "-.." }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "-.xn--y86c", "output": null }, @@ -8229,51 +11040,101 @@ "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d\uff0e\udbc3\ude28", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u200d.\udbc3\ude28", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--h327f", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--1ug.xn--h327f", "output": null }, { - "comment": "V6", + "comment": "V7", + "input": "\ud94e\udf7b\ud8f2\udd41\uff61\u2260\ud835\udff2", + "output": null + }, + { + "comment": "V7", + "input": "\ud94e\udf7b\ud8f2\udd41\uff61=\u0338\ud835\udff2", + "output": null + }, + { + "comment": "V7", + "input": "\ud94e\udf7b\ud8f2\udd41\u3002\u22606", + "output": null + }, + { + "comment": "V7", + "input": "\ud94e\udf7b\ud8f2\udd41\u3002=\u03386", + "output": null + }, + { + "comment": "V7", + "input": "xn--h79w4z99a.xn--6-tfo", + "output": null + }, + { + "comment": "V7", "input": "xn--98e.xn--om9c", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\uaaf6\u188f\u0e3a\uff12.\ud800\udee2\u0745\u0f9f\ufe12", "output": null }, { - "comment": "V5", + "comment": "V6; A4_2 (ignored)", "input": "\uaaf6\u188f\u0e3a2.\ud800\udee2\u0745\u0f9f\u3002", "output": null }, { - "comment": "V5", + "comment": "V6; A4_2 (ignored)", "input": "xn--2-2zf840fk16m.xn--sob093b2m7s.", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--2-2zf840fk16m.xn--sob093bj62sz9d", "output": null }, { + "comment": "V7", + "input": "\udad7\udd27\uff61\u2260-\udb41\ude44\u2f9b", + "output": null + }, + { + "comment": "V7", + "input": "\udad7\udd27\uff61=\u0338-\udb41\ude44\u2f9b", + "output": null + }, + { + "comment": "V7", + "input": "\udad7\udd27\u3002\u2260-\udb41\ude44\u8d70", + "output": null + }, + { + "comment": "V7", + "input": "\udad7\udd27\u3002=\u0338-\udb41\ude44\u8d70", + "output": null + }, + { + "comment": "V7", + "input": "xn--gm57d.xn----tfo4949b3664m", + "output": null + }, + { "input": "\ud835\udfce\u3002\u752f", "output": "0.xn--qny" }, @@ -8290,17 +11151,17 @@ "output": "0.xn--qny" }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "-\u2f86\uff0e\uaaf6", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "-\u820c.\uaaf6", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn----ef8c.xn--2v9a", "output": null }, @@ -8320,6 +11181,31 @@ "output": "-.xn--ibf" }, { + "input": "\ud83c\udcb4\u10ab.\u226e", + "output": "xn--2kj7565l.xn--gdh" + }, + { + "input": "\ud83c\udcb4\u10ab.<\u0338", + "output": "xn--2kj7565l.xn--gdh" + }, + { + "input": "\ud83c\udcb4\u2d0b.<\u0338", + "output": "xn--2kj7565l.xn--gdh" + }, + { + "input": "\ud83c\udcb4\u2d0b.\u226e", + "output": "xn--2kj7565l.xn--gdh" + }, + { + "input": "xn--2kj7565l.xn--gdh", + "output": "xn--2kj7565l.xn--gdh" + }, + { + "comment": "V7", + "input": "xn--jnd1986v.xn--gdh", + "output": null + }, + { "comment": "C1", "input": "\u74bc\ud836\ude2d\uff61\u200c\udb40\udddf", "output": null @@ -8330,10 +11216,12 @@ "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--gky8837e.", "output": "xn--gky8837e." }, { + "comment": "A4_2 (ignored)", "input": "\u74bc\ud836\ude2d.", "output": "xn--gky8837e." }, @@ -8365,97 +11253,117 @@ "output": "xn--157b.xn--gnb" }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u10b7\uff0e\u05c2\ud804\udd34\ua9b7\ud920\udce8", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u10b7\uff0e\ud804\udd34\u05c2\ua9b7\ud920\udce8", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u10b7.\ud804\udd34\u05c2\ua9b7\ud920\udce8", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u2d17.\ud804\udd34\u05c2\ua9b7\ud920\udce8", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--flj.xn--qdb0605f14ycrms3c", "output": null }, { - "comment": "V5; V6", - "input": "xn--vnd.xn--qdb0605f14ycrms3c", + "comment": "V6; V7", + "input": "\u2d17\uff0e\ud804\udd34\u05c2\ua9b7\ud920\udce8", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u2d17\uff0e\ud804\udd34\u05c2\ua9b7\ud920\udce8", + "comment": "V6; V7", + "input": "\u2d17\uff0e\u05c2\ud804\udd34\ua9b7\ud920\udce8", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u2d17\uff0e\u05c2\ud804\udd34\ua9b7\ud920\udce8", + "comment": "V6; V7", + "input": "xn--vnd.xn--qdb0605f14ycrms3c", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u2488\u916b\ufe12\u3002\u08d6", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "1.\u916b\u3002\u3002\u08d6", "output": null }, { - "comment": "V5; A4_2 (ignored)", + "comment": "V6; A4_2 (ignored)", "input": "1.xn--8j4a..xn--8zb", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--tsh4490bfe8c.xn--8zb", "output": null }, { - "comment": "V6", - "input": "xn--co6h.xn--1-h1g429s", + "comment": "C1; V6", + "input": "\u2de3\u200c\u226e\u1a6b.\u200c\u0e3a", + "output": null + }, + { + "comment": "C1; V6", + "input": "\u2de3\u200c<\u0338\u1a6b.\u200c\u0e3a", "output": null }, { "comment": "V6", + "input": "xn--uof548an0j.xn--o4c", + "output": null + }, + { + "comment": "C1; V6", + "input": "xn--uof63xk4bf3s.xn--o4c732g", + "output": null + }, + { + "comment": "V7", "input": "xn--co6h.xn--1-kwssa", "output": null }, { - "comment": "V6", + "comment": "V7", + "input": "xn--co6h.xn--1-h1g429s", + "output": null + }, + { + "comment": "V7", "input": "xn--co6h.xn--1-h1gs", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\ua806\u3002\ud8ad\ude8f\u0fb0\u2495", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7; A4_2 (ignored)", "input": "\ua806\u3002\ud8ad\ude8f\u0fb014.", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7; A4_2 (ignored)", "input": "xn--l98a.xn--14-jsj57880f.", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--l98a.xn--dgd218hhp28d", "output": null }, @@ -8483,22 +11391,104 @@ "output": null }, { - "comment": "C1; P1; V6", + "input": "\u226e\ud835\udfd5\uff0e\u8b16\u00df\u226f", + "output": "xn--7-mgo.xn--zca892oly5e" + }, + { + "input": "<\u0338\ud835\udfd5\uff0e\u8b16\u00df>\u0338", + "output": "xn--7-mgo.xn--zca892oly5e" + }, + { + "input": "\u226e7.\u8b16\u00df\u226f", + "output": "xn--7-mgo.xn--zca892oly5e" + }, + { + "input": "<\u03387.\u8b16\u00df>\u0338", + "output": "xn--7-mgo.xn--zca892oly5e" + }, + { + "input": "<\u03387.\u8b16SS>\u0338", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "\u226e7.\u8b16SS\u226f", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "\u226e7.\u8b16ss\u226f", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "<\u03387.\u8b16ss>\u0338", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "<\u03387.\u8b16Ss>\u0338", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "\u226e7.\u8b16Ss\u226f", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "xn--7-mgo.xn--ss-xjvv174c", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "xn--7-mgo.xn--zca892oly5e", + "output": "xn--7-mgo.xn--zca892oly5e" + }, + { + "input": "<\u0338\ud835\udfd5\uff0e\u8b16SS>\u0338", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "\u226e\ud835\udfd5\uff0e\u8b16SS\u226f", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "\u226e\ud835\udfd5\uff0e\u8b16ss\u226f", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "<\u0338\ud835\udfd5\uff0e\u8b16ss>\u0338", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "<\u0338\ud835\udfd5\uff0e\u8b16Ss>\u0338", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "input": "\u226e\ud835\udfd5\uff0e\u8b16Ss\u226f", + "output": "xn--7-mgo.xn--ss-xjvv174c" + }, + { + "comment": "C1; V7", "input": "\ud975\udf0e\u2488\uff61\u200c\ud835\udfe4", "output": null }, { - "comment": "C1; P1; V6; A4_2 (ignored)", + "comment": "C1; V7; A4_2 (ignored)", "input": "\ud975\udf0e1.\u3002\u200c2", "output": null }, { - "comment": "C1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", + "input": "xn--1-ex54e..c", + "output": null + }, + { + "comment": "C1; V7; A4_2 (ignored)", "input": "xn--1-ex54e..xn--2-rgn", "output": null }, { - "comment": "C1; V6", + "comment": "V7", + "input": "xn--tsh94183d.c", + "output": null + }, + { + "comment": "C1; V7", "input": "xn--tsh94183d.xn--2-rgn", "output": null }, @@ -8574,7 +11564,7 @@ "output": "xn--ss-bh7o" }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\ufe12\u200c\u30f6\u44a9.\ua86a", "output": null }, @@ -8594,12 +11584,12 @@ "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--qekw60dns9k.xn--gd9a", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug287dj0or48o.xn--gd9a", "output": null }, @@ -8612,52 +11602,62 @@ "output": "xn--qekw60d.xn--gd9a" }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\u2488\ud852\udf8d.\udb49\udccb\u1a60", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c1.\ud852\udf8d.\udb49\udccb\u1a60", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "1.xn--4x6j.xn--jof45148n", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--1-rgn.xn--4x6j.xn--jof45148n", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--tshw462r.xn--jof45148n", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ug88o7471d.xn--jof45148n", "output": null }, { - "comment": "P1; V6", + "comment": "V7; A4_2 (ignored)", "input": "\ud834\udd75\uff61\ud835\udfeb\ud838\udc08\u4b3a\u2488", "output": null }, { - "comment": "P1; V6", + "comment": "A4_2 (ignored)", "input": "\ud834\udd75\u30029\ud838\udc08\u4b3a1.", + "output": ".xn--91-030c1650n." + }, + { + "comment": "A4_2 (ignored)", + "input": ".xn--91-030c1650n.", + "output": ".xn--91-030c1650n." + }, + { + "comment": "V7; A4_2 (ignored)", + "input": ".xn--9-ecp936non25a", "output": null }, { - "comment": "V6", + "comment": "V7; A4_2 (ignored)", "input": "xn--3f1h.xn--91-030c1650n.", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--3f1h.xn--9-ecp936non25a", "output": null }, @@ -8674,447 +11674,477 @@ "output": "xn--8c1a.xn--2ib8jn539l" }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "-\udb40\udd710\uff61\u17cf\u1dfd\ud187\uc2ed", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "-\udb40\udd710\uff61\u17cf\u1dfd\u1110\u1168\u11aa\u1109\u1175\u11b8", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "-\udb40\udd710\u3002\u17cf\u1dfd\ud187\uc2ed", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "-\udb40\udd710\u3002\u17cf\u1dfd\u1110\u1168\u11aa\u1109\u1175\u11b8", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "-0.xn--r4e872ah77nghm", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u115f\u10bf\u10b5\u10e0\uff61\u0b4d", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u115f\u10bf\u10b5\u10e0\u3002\u0b4d", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u115f\u2d1f\u2d15\u10e0\u3002\u0b4d", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u115f\u10bf\u10b5\u1ca0\u3002\u0b4d", "output": null }, { - "comment": "V5; V6", - "input": "xn--tndt4hvw.xn--9ic", + "comment": "V6", + "input": "xn--1od555l3a.xn--9ic", "output": null }, { - "comment": "V5; V6", - "input": "xn--1od7wz74eeb.xn--9ic", + "comment": "V6", + "input": "\u115f\u2d1f\u2d15\u10e0\uff61\u0b4d", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u115f\u2d1f\u2d15\u10e0\uff61\u0b4d", + "comment": "V6", + "input": "\u115f\u10bf\u10b5\u1ca0\uff61\u0b4d", "output": null }, { - "comment": "P1; V5; V6", - "input": "\u115f\u10bf\u10b5\u1ca0\uff61\u0b4d", + "comment": "V6; V7", + "input": "xn--tndt4hvw.xn--9ic", + "output": null + }, + { + "comment": "V6; V7", + "input": "xn--1od7wz74eeb.xn--9ic", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u115f\u10bf\u2d15\u10e0\u3002\u0b4d", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--3nd0etsm92g.xn--9ic", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6", "input": "\u115f\u10bf\u2d15\u10e0\uff61\u0b4d", "output": null }, { - "comment": "V6", + "comment": "V7", + "input": "xn--l96h.xn--o8e4044k", + "output": null + }, + { + "comment": "V7", "input": "xn--l96h.xn--03e93aq365d", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\ud835\udfdb\ud834\uddaa\ua8c4\uff61\ua8ea-", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\ud835\udfdb\ua8c4\ud834\uddaa\uff61\ua8ea-", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "3\ua8c4\ud834\uddaa\u3002\ua8ea-", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn--3-sl4eu679e.xn----xn4e", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1139\uff61\u0eca\uda42\udfe4\udb40\udd1e", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1139\u3002\u0eca\uda42\udfe4\udb40\udd1e", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--lrd.xn--s8c05302k", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10a6\udaae\udca9\uff0e\udb40\udda1\ufe09\ud83a\udd0d", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u10a6\udaae\udca9.\udb40\udda1\ufe09\ud83a\udd0d", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2d06\udaae\udca9.\udb40\udda1\ufe09\ud83a\udd2f", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--xkjw3965g.xn--ne6h", "output": null }, { - "comment": "V6", - "input": "xn--end82983m.xn--ne6h", + "comment": "V7", + "input": "\u2d06\udaae\udca9\uff0e\udb40\udda1\ufe09\ud83a\udd2f", "output": null }, { - "comment": "P1; V6", - "input": "\u2d06\udaae\udca9\uff0e\udb40\udda1\ufe09\ud83a\udd2f", + "comment": "V7", + "input": "xn--end82983m.xn--ne6h", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2d06\udaae\udca9.\udb40\udda1\ufe09\ud83a\udd0d", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\u2d06\udaae\udca9\uff0e\udb40\udda1\ufe09\ud83a\udd0d", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91d\udee8.\ud9d5\udfe2\ud835\udfe8\ua8c4", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91d\udee8.\ud9d5\udfe26\ua8c4", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--mi60a.xn--6-sl4es8023c", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud800\udef8\udb79\ude0b\u10c2.\u10a1", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud800\udef8\udb79\ude0b\u2d22.\u2d01", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud800\udef8\udb79\ude0b\u10c2.\u2d01", "output": null }, { - "comment": "V6", - "input": "xn--6nd5215jr2u0h.xn--skj", + "comment": "V7", + "input": "xn--qlj1559dr224h.xn--skj", "output": null }, { - "comment": "V6", - "input": "xn--qlj1559dr224h.xn--skj", + "comment": "V7", + "input": "xn--6nd5215jr2u0h.xn--skj", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--6nd5215jr2u0h.xn--8md", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91d\udc7f\ua806\u2084\uda65\udf86\uff61\ud88a\ude67\udb41\udcb9\u03c2", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91d\udc7f\ua8064\uda65\udf86\u3002\ud88a\ude67\udb41\udcb9\u03c2", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91d\udc7f\ua8064\uda65\udf86\u3002\ud88a\ude67\udb41\udcb9\u03a3", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91d\udc7f\ua8064\uda65\udf86\u3002\ud88a\ude67\udb41\udcb9\u03c3", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91d\udc7f\ua806\u2084\uda65\udf86\uff61\ud88a\ude67\udb41\udcb9\u03a3", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud91d\udc7f\ua806\u2084\uda65\udf86\uff61\ud88a\ude67\udb41\udcb9\u03c3", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud8ba\udcac\u3002\u0729\u3002\ucbd95", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\ud8ba\udcac\u3002\u0729\u3002\u110d\u1173\u11ac5", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--t92s.xn--znb.xn--5-y88f", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u17ca.\u200d\ud835\udfee\ud804\udc3f", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "\u17ca.\u200d2\ud804\udc3f", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--m4e.xn--2-ku7i", "output": null }, { - "comment": "C2; V5", + "comment": "C2; V6", "input": "xn--m4e.xn--2-tgnv469h", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\uaaf6\u3002\u5b36\u00df\u847d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\uaaf6\u3002\u5b36SS\u847d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\uaaf6\u3002\u5b36ss\u847d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\uaaf6\u3002\u5b36Ss\u847d", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--2v9a.xn--ss-q40dp97m", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--2v9a.xn--zca7637b14za", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u03c2\ud805\udc3d\ud896\udc88\ud805\udf2b\uff61\ud83a\udf29\u200c\ud802\udec4", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u03c2\ud805\udc3d\ud896\udc88\ud805\udf2b\u3002\ud83a\udf29\u200c\ud802\udec4", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u03a3\ud805\udc3d\ud896\udc88\ud805\udf2b\u3002\ud83a\udf29\u200c\ud802\udec4", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u03c3\ud805\udc3d\ud896\udc88\ud805\udf2b\u3002\ud83a\udf29\u200c\ud802\udec4", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--4xa2260lk3b8z15g.xn--tw9ct349a", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u03a3\ud805\udc3d\ud896\udc88\ud805\udf2b\uff61\ud83a\udf29\u200c\ud802\udec4", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u03c3\ud805\udc3d\ud896\udc88\ud805\udf2b\uff61\ud83a\udf29\u200c\ud802\udec4", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u2ea2\ud9df\ude85\ud835\udfe4\uff61\u200d\ud83d\udeb7", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u2ea2\ud9df\ude852\u3002\u200d\ud83d\udeb7", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--2-4jtr4282f.xn--m78h", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--2-4jtr4282f.xn--1ugz946p", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud836\ude25\u3002\u2adf\ud804\ude3e", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--n82h.xn--63iw010f", "output": null }, { - "comment": "C1; P1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V3 (ignored); U1 (ignored)", "input": "-\u1897\u200c\ud83c\udd04.\ud805\udf22", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "C1; V6; V3 (ignored); U1 (ignored)", + "input": "-\u1897\u200c3,.\ud805\udf22", + "output": null + }, + { + "comment": "V6; V3 (ignored); U1 (ignored)", + "input": "xn---3,-3eu.xn--9h2d", + "output": null + }, + { + "comment": "C1; V6; V3 (ignored); U1 (ignored)", + "input": "xn---3,-3eu051c.xn--9h2d", + "output": null + }, + { + "comment": "V6; V7; V3 (ignored)", "input": "xn----pck1820x.xn--9h2d", "output": null }, { - "comment": "C1; V5; V6; V3 (ignored)", + "comment": "C1; V6; V7; V3 (ignored)", "input": "xn----pck312bx563c.xn--9h2d", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "\u17b4.\ucb87-", - "output": null + "output": ".xn----938f" }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", "input": "\u17b4.\u110d\u1170\u11ae-", - "output": null + "output": ".xn----938f" }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V3 (ignored); A4_2 (ignored)", + "input": ".xn----938f", + "output": ".xn----938f" + }, + { + "comment": "V6; V7; V3 (ignored)", "input": "xn--z3e.xn----938f", "output": null }, { - "comment": "C1; P1; V6", + "comment": "C1; V7", "input": "\u200c\ud805\udcc2\u3002\u2488-\udbc2\ude9b", "output": null }, { - "comment": "C1; P1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "\u200c\ud805\udcc2\u30021.-\udbc2\ude9b", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn--wz1d.1.xn----rg03o", "output": null }, { - "comment": "C1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "xn--0ugy057g.1.xn----rg03o", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--wz1d.xn----dcp29674o", "output": null }, { - "comment": "C1; V6", + "comment": "C1; V7", "input": "xn--0ugy057g.xn----dcp29674o", "output": null }, @@ -9132,67 +12162,67 @@ "output": "xn--hcb32bni" }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\u0f94\ua84b-\uff0e-\ud81a\udf34", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "\u0f94\ua84b-.-\ud81a\udf34", "output": null }, { - "comment": "V5; V3 (ignored)", + "comment": "V6; V3 (ignored)", "input": "xn----ukg9938i.xn----4u5m", "output": null }, { - "comment": "C1; P1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "\ud9bd\udcb3-\u22e2\u200c\uff0e\u6807-", "output": null }, { - "comment": "C1; P1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "\ud9bd\udcb3-\u2291\u0338\u200c\uff0e\u6807-", "output": null }, { - "comment": "C1; P1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "\ud9bd\udcb3-\u22e2\u200c.\u6807-", "output": null }, { - "comment": "C1; P1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "\ud9bd\udcb3-\u2291\u0338\u200c.\u6807-", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn----9mo67451g.xn----qj7b", "output": null }, { - "comment": "C1; V6; V3 (ignored)", + "comment": "C1; V7; V3 (ignored)", "input": "xn----sgn90kn5663a.xn----qj7b", "output": null }, { - "comment": "P1; V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "-\ud914\ude74.\u06e0\u189a-", "output": null }, { - "comment": "V5; V6; V3 (ignored)", + "comment": "V6; V7; V3 (ignored)", "input": "xn----qi38c.xn----jxc827k", "output": null }, { - "comment": "P1; V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": "\u3002\u0635\u0649\u0e37\u0644\u0627\u3002\u5c93\u1bf2\udb43\udf83\u1842", "output": null }, { - "comment": "V6; A4_2 (ignored)", + "comment": "V7; A4_2 (ignored)", "input": ".xn--mgb1a7bt462h.xn--17e10qe61f9r71s", "output": null }, @@ -9212,62 +12242,92 @@ "output": "xn--59e.xn----5jd" }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1039-\ud82a\udfad\ud83d\udfa2\uff0e\u00df", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1039-\ud82a\udfad\ud83d\udfa2.\u00df", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1039-\ud82a\udfad\ud83d\udfa2.SS", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1039-\ud82a\udfad\ud83d\udfa2.ss", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1039-\ud82a\udfad\ud83d\udfa2.Ss", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn----9tg11172akr8b.ss", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn----9tg11172akr8b.xn--zca", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1039-\ud82a\udfad\ud83d\udfa2\uff0eSS", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1039-\ud82a\udfad\ud83d\udfa2\uff0ess", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\u1039-\ud82a\udfad\ud83d\udfa2\uff0eSs", "output": null }, { - "comment": "P1; V5; V6", + "comment": "C1; C2; V6; V7", + "input": "\u0d4d-\u200d\u200c\uff61\ud955\udfa7\u2085\u2260", + "output": null + }, + { + "comment": "C1; C2; V6; V7", + "input": "\u0d4d-\u200d\u200c\uff61\ud955\udfa7\u2085=\u0338", + "output": null + }, + { + "comment": "C1; C2; V6; V7", + "input": "\u0d4d-\u200d\u200c\u3002\ud955\udfa75\u2260", + "output": null + }, + { + "comment": "C1; C2; V6; V7", + "input": "\u0d4d-\u200d\u200c\u3002\ud955\udfa75=\u0338", + "output": null + }, + { + "comment": "V6; V7; V3 (ignored)", + "input": "xn----jmf.xn--5-ufo50192e", + "output": null + }, + { + "comment": "C1; C2; V6; V7", + "input": "xn----jmf215lda.xn--5-ufo50192e", + "output": null + }, + { + "comment": "V6; V7", "input": "\u9523\u3002\u0a4d\udb41\ude3b\udb41\ude86", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--gc5a.xn--ybc83044ppga", "output": null }, @@ -9280,32 +12340,24 @@ "output": "xn--8gb2338k.xn--lhb0154f" }, { - "comment": "P1; V6", "input": "\u10c1\u10b16\u0318\u3002\u00df\u1b03", - "output": null + "output": "xn--6-8cb7433a2ba.xn--zca894k" }, { "input": "\u2d21\u2d116\u0318\u3002\u00df\u1b03", "output": "xn--6-8cb7433a2ba.xn--zca894k" }, { - "comment": "P1; V6", "input": "\u10c1\u10b16\u0318\u3002SS\u1b03", - "output": null + "output": "xn--6-8cb7433a2ba.xn--ss-2vq" }, { "input": "\u2d21\u2d116\u0318\u3002ss\u1b03", "output": "xn--6-8cb7433a2ba.xn--ss-2vq" }, { - "comment": "P1; V6", "input": "\u10c1\u2d116\u0318\u3002Ss\u1b03", - "output": null - }, - { - "comment": "V6", - "input": "xn--6-8cb306hms1a.xn--ss-2vq", - "output": null + "output": "xn--6-8cb7433a2ba.xn--ss-2vq" }, { "input": "xn--6-8cb7433a2ba.xn--ss-2vq", @@ -9316,19 +12368,12 @@ "output": "xn--6-8cb7433a2ba.xn--ss-2vq" }, { - "comment": "P1; V6", "input": "\u10c1\u10b16\u0318.SS\u1b03", - "output": null + "output": "xn--6-8cb7433a2ba.xn--ss-2vq" }, { - "comment": "P1; V6", "input": "\u10c1\u2d116\u0318.Ss\u1b03", - "output": null - }, - { - "comment": "V6", - "input": "xn--6-8cb555h2b.xn--ss-2vq", - "output": null + "output": "xn--6-8cb7433a2ba.xn--ss-2vq" }, { "input": "xn--6-8cb7433a2ba.xn--zca894k", @@ -9339,77 +12384,117 @@ "output": "xn--6-8cb7433a2ba.xn--zca894k" }, { - "comment": "V6", + "comment": "V7", + "input": "xn--6-8cb306hms1a.xn--ss-2vq", + "output": null + }, + { + "comment": "V7", + "input": "xn--6-8cb555h2b.xn--ss-2vq", + "output": null + }, + { + "comment": "V7", "input": "xn--6-8cb555h2b.xn--zca894k", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V7", + "input": "\ud9ee\udc50\uff61\u226f\ud804\udeea", + "output": null + }, + { + "comment": "V7", + "input": "\ud9ee\udc50\uff61>\u0338\ud804\udeea", + "output": null + }, + { + "comment": "V7", + "input": "\ud9ee\udc50\u3002\u226f\ud804\udeea", + "output": null + }, + { + "comment": "V7", + "input": "\ud9ee\udc50\u3002>\u0338\ud804\udeea", + "output": null + }, + { + "comment": "V7", + "input": "xn--eo08b.xn--hdh3385g", + "output": null + }, + { + "comment": "V6; V7; A4_2 (ignored)", "input": "\udb40\udd0f\ud81a\udf34\udb43\udcbd\uff61\uffa0", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7; A4_2 (ignored)", "input": "\udb40\udd0f\ud81a\udf34\udb43\udcbd\u3002\u1160", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7; A4_2 (ignored)", + "input": "xn--619ep9154c.", + "output": null + }, + { + "comment": "V6; V7", "input": "xn--619ep9154c.xn--psd", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--619ep9154c.xn--cl7c", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb42\udf54.\ud800\udef1\u2082", "output": null }, { - "comment": "P1; V6", + "comment": "V7", "input": "\udb42\udf54.\ud800\udef12", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--vi56e.xn--2-w91i", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u2dbf.\u00df\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u2dbf.SS\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u2dbf.ss\u200d", "output": null }, { - "comment": "C2; P1; V6", + "comment": "C2; V7", "input": "\u2dbf.Ss\u200d", "output": null }, { - "comment": "V6", + "comment": "V7", "input": "xn--7pj.ss", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--7pj.xn--ss-n1t", "output": null }, { - "comment": "C2; V6", + "comment": "C2; V7", "input": "xn--7pj.xn--zca870n", "output": null }, @@ -9419,10 +12504,12 @@ "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--7zv.", "output": "xn--7zv." }, { + "comment": "A4_2 (ignored)", "input": "\u6889.", "output": "xn--7zv." }, @@ -9444,26 +12531,46 @@ "output": "xn--iwb.ss" }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "\u40da\u87e5-\u3002-\ud9b5\udc98\u2488", "output": null }, { - "comment": "P1; V6; V3 (ignored)", + "comment": "V7; V3 (ignored); A4_2 (ignored)", "input": "\u40da\u87e5-\u3002-\ud9b5\udc981.", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored); A4_2 (ignored)", "input": "xn----n50a258u.xn---1-up07j.", "output": null }, { - "comment": "V6; V3 (ignored)", + "comment": "V7; V3 (ignored)", "input": "xn----n50a258u.xn----ecp33805f", "output": null }, { + "comment": "C2; V7", + "input": "\u1894\u2260\udbec\ude42.\u200d\ud800\udee2", + "output": null + }, + { + "comment": "C2; V7", + "input": "\u1894=\u0338\udbec\ude42.\u200d\ud800\udee2", + "output": null + }, + { + "comment": "V7", + "input": "xn--ebf031cf7196a.xn--587c", + "output": null + }, + { + "comment": "C2; V7", + "input": "xn--ebf031cf7196a.xn--1ug9540g", + "output": null + }, + { "comment": "V3 (ignored)", "input": "-\uff61\u2e90", "output": "-.xn--6vj" @@ -9479,220 +12586,162 @@ "output": "-.xn--6vj" }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\udb43\udc29\ud807\udcac\uff0e\u065c", "output": null }, { - "comment": "P1; V5; V6", + "comment": "V6; V7", "input": "\udb43\udc29\ud807\udcac.\u065c", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--sn3d59267c.xn--4hb", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud800\udf7a.\ud928\uddc3\u200c", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--ie8c.xn--2g51a", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn--ie8c.xn--0ug03366c", "output": null }, { - "comment": "C2; P1; V6", - "input": "\u200d\u200d\u8954\u3002\u10bc5\ua86e\ud995\udf4f", - "output": null - }, - { - "comment": "C2; P1; V6", - "input": "\u200d\u200d\u8954\u3002\u2d1c5\ua86e\ud995\udf4f", - "output": null - }, - { - "comment": "V6", - "input": "xn--2u2a.xn--5-uws5848bpf44e", - "output": null - }, - { - "comment": "C2; V6", - "input": "xn--1uga7691f.xn--5-uws5848bpf44e", - "output": null - }, - { - "comment": "V6", - "input": "xn--2u2a.xn--5-r1g7167ipfw8d", - "output": null - }, - { - "comment": "C2; V6", - "input": "xn--1uga7691f.xn--5-r1g7167ipfw8d", - "output": null - }, - { - "input": "xn--ix9c26l.xn--q0s", - "output": "xn--ix9c26l.xn--q0s" - }, - { - "input": "\ud802\udedc\ud804\udf3c.\u5a40", - "output": "xn--ix9c26l.xn--q0s" - }, - { - "comment": "P1; V6; V3 (ignored)", - "input": "\ud835\udfd6\u00df\uff0e\udb40\udd10-?\u10af", + "comment": "C2; V7; V3 (ignored)", + "input": "\u200d\u226e\uff0e\udb41\udfea\ud8a6\udecf-", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8\u00df.\udb40\udd10-?\u10af", + "comment": "C2; V7; V3 (ignored)", + "input": "\u200d<\u0338\uff0e\udb41\udfea\ud8a6\udecf-", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8\u00df.\udb40\udd10-?\u2d0f", + "comment": "C2; V7; V3 (ignored)", + "input": "\u200d\u226e.\udb41\udfea\ud8a6\udecf-", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8SS.\udb40\udd10-?\u10af", + "comment": "C2; V7; V3 (ignored)", + "input": "\u200d<\u0338.\udb41\udfea\ud8a6\udecf-", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8ss.\udb40\udd10-?\u2d0f", + "comment": "V7; V3 (ignored)", + "input": "xn--gdh.xn----cr99a1w710b", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8ss.\udb40\udd10-?\u10af", + "comment": "C2; V7; V3 (ignored)", + "input": "xn--1ug95g.xn----cr99a1w710b", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8ss.xn---?-gfk", - "output": null - }, - { - "comment": "P1; V6; V3 (ignored)", - "input": "8ss.xn---?-261a", + "comment": "C2; V7", + "input": "\u200d\u200d\u8954\u3002\u10bc5\ua86e\ud995\udf4f", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "xn--8-qfa.xn---?-261a", + "comment": "C2; V7", + "input": "\u200d\u200d\u8954\u3002\u2d1c5\ua86e\ud995\udf4f", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "xn--8-qfa.xn---?-gfk", + "comment": "V7", + "input": "xn--2u2a.xn--5-uws5848bpf44e", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "\ud835\udfd6\u00df\uff0e\udb40\udd10-?\u2d0f", + "comment": "C2; V7", + "input": "xn--1uga7691f.xn--5-uws5848bpf44e", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "\ud835\udfd6SS\uff0e\udb40\udd10-?\u10af", + "comment": "V7", + "input": "xn--2u2a.xn--5-r1g7167ipfw8d", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "\ud835\udfd6ss\uff0e\udb40\udd10-?\u2d0f", + "comment": "C2; V7", + "input": "xn--1uga7691f.xn--5-r1g7167ipfw8d", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "\ud835\udfd6ss\uff0e\udb40\udd10-?\u10af", - "output": null + "input": "xn--ix9c26l.xn--q0s", + "output": "xn--ix9c26l.xn--q0s" }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8ss.-?\u10af", - "output": null + "input": "\ud802\udedc\ud804\udf3c.\u5a40", + "output": "xn--ix9c26l.xn--q0s" }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8ss.-?\u2d0f", + "comment": "C2; V6; V7", + "input": "\ua9b9\u200d\ud077\ud8af\udda1\uff61\u2082", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8SS.-?\u10af", + "comment": "C2; V6; V7", + "input": "\ua9b9\u200d\u110f\u1173\u11b2\ud8af\udda1\uff61\u2082", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "xn--8-qfa.-?\u2d0f", + "comment": "V6; V7", + "input": "xn--0m9as84e2e21c.c", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "XN--8-QFA.-?\u10af", + "comment": "C2; V6; V7", + "input": "xn--1ug1435cfkyaoi04d.c", "output": null }, { - "comment": "P1; V6; V3 (ignored)", - "input": "Xn--8-Qfa.-?\u10af", - "output": null + "input": "\ud802\udec0\uff0e\u0689\ud804\udf00", + "output": "xn--pw9c.xn--fjb8658k" }, { - "comment": "P1; V6; V3 (ignored)", - "input": "xn--8-qfa.-?\u10af", - "output": null + "input": "\ud802\udec0.\u0689\ud804\udf00", + "output": "xn--pw9c.xn--fjb8658k" }, { - "comment": "P1; V6; V3 (ignored)", - "input": "\ud835\udfd6Ss\uff0e\udb40\udd10-?\u10af", - "output": null + "input": "xn--pw9c.xn--fjb8658k", + "output": "xn--pw9c.xn--fjb8658k" }, { - "comment": "P1; V6; V3 (ignored)", - "input": "8Ss.\udb40\udd10-?\u10af", + "comment": "V6", + "input": "\u2260\u81a3\u3002\u0f83", "output": null }, { - "comment": "C2; P1; V5; V6", - "input": "\ua9b9\u200d\ud077\ud8af\udda1\uff61\u2082", + "comment": "V6", + "input": "=\u0338\u81a3\u3002\u0f83", "output": null }, { - "comment": "C2; P1; V5; V6", - "input": "\ua9b9\u200d\u110f\u1173\u11b2\ud8af\udda1\uff61\u2082", + "comment": "V6", + "input": "xn--1chy468a.xn--2ed", "output": null }, { - "input": "\ud802\udec0\uff0e\u0689\ud804\udf00", - "output": "xn--pw9c.xn--fjb8658k" - }, - { - "input": "\ud802\udec0.\u0689\ud804\udf00", - "output": "xn--pw9c.xn--fjb8658k" - }, - { - "input": "xn--pw9c.xn--fjb8658k", - "output": "xn--pw9c.xn--fjb8658k" - }, - { "comment": "C2", "input": "\ud800\udef7\u3002\u200d", "output": null }, { + "comment": "A4_2 (ignored)", "input": "xn--r97c.", "output": "xn--r97c." }, { + "comment": "A4_2 (ignored)", "input": "\ud800\udef7.", "output": "xn--r97c." }, @@ -9702,53 +12751,53 @@ "output": null }, { - "comment": "V5", + "comment": "V6", "input": "\ud807\udc33\ud804\ude2f\u3002\u296a", "output": null }, { - "comment": "V5", + "comment": "V6", "input": "xn--2g1d14o.xn--jti", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud804\udd80\u4074\ud952\udde3\uff0e\u10b5\ud835\udfdc\u200c\u0348", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud804\udd80\u4074\ud952\udde3.\u10b54\u200c\u0348", "output": null }, { - "comment": "C1; P1; V5; V6", + "comment": "C1; V6; V7", "input": "\ud804\udd80\u4074\ud952\udde3.\u2d154\u200c\u0348", "output": null }, { - "comment": "V5; V6", + "comment": "V6; V7", "input": "xn--1mnx647cg3x1b.xn--4-zfb5123a", "output": null }, { - "comment": "C1; V5; V6", + "comment": "C1; V6; V7", "input": "xn--1mnx647cg3x1b.xn--4-zfb502tlsl", "output": null }, { - "comment": "V5; V6", - "input": "xn--1mnx647cg3x1b.xn--4-zfb324h", + "comment": "C1; V6; V7", + "input": "\ud804\udd80\u4074\ud952\udde3\uff0e\u2d15\ud835\udfdc\u200c\u0348", "output": null }, { - "comment": "C1; V5; V6", - "input": "xn--1mnx647cg3x1b.xn--4-zfb324h32o", + "comment": "V6; V7", + "input": "xn--1mnx647cg3x1b.xn--4-zfb324h", "output": null }, { - "comment": "C1; P1; V5; V6", - "input": "\ud804\udd80\u4074\ud952\udde3\uff0e\u2d15\ud835\udfdc\u200c\u0348", + "comment": "C1; V6; V7", + "input": "xn--1mnx647cg3x1b.xn--4-zfb324h32o", "output": null } ] diff --git a/tests/wpt/tests/url/resources/setters_tests.json b/tests/wpt/tests/url/resources/setters_tests.json index 3850606d660..efd548b6c88 100644 --- a/tests/wpt/tests/url/resources/setters_tests.json +++ b/tests/wpt/tests/url/resources/setters_tests.json @@ -1921,8 +1921,8 @@ "href": "a:/", "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", "expected": { - "href": "a:/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9", - "pathname": "/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9" + "href": "a:/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]%5E_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9", + "pathname": "/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]%5E_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9" } }, { diff --git a/tests/wpt/tests/url/resources/toascii.json b/tests/wpt/tests/url/resources/toascii.json index 6445db80e3c..02291962ebc 100644 --- a/tests/wpt/tests/url/resources/toascii.json +++ b/tests/wpt/tests/url/resources/toascii.json @@ -259,7 +259,7 @@ }, { "input": "look\u180Eout.net", - "output": null + "output": "lookout.net" }, { "input": "look\u2060out.net", @@ -291,7 +291,7 @@ }, { "input": "look\u206Bout.net", - "output": null + "output": "lookout.net" }, { "input": "look\uDB40\uDC01out.net", @@ -319,16 +319,15 @@ }, { "input": "\u04C0.com", - "output": null + "output": "xn--s5a.com" }, { - "comment": "This is U+2F868 (which is mapped to U+36FC starting with Unicode 16.0)", "input": "\uD87E\uDC68.com", "output": "xn--snl.com" }, { "input": "\u2183.com", - "output": null + "output": "xn--r5g.com" }, { "input": "look\u034Fout.net", diff --git a/tests/wpt/tests/url/resources/urltestdata.json b/tests/wpt/tests/url/resources/urltestdata.json index 7669217c470..214ed0852aa 100644 --- a/tests/wpt/tests/url/resources/urltestdata.json +++ b/tests/wpt/tests/url/resources/urltestdata.json @@ -8508,6 +8508,21 @@ "username": "" }, { + "input": "non-special:cannot-be-a-base-url-!\"$%&'()*+,-.;<=>@[\\]^_`{|}~@/", + "base": null, + "hash": "", + "host": "", + "hostname": "", + "href": "non-special:cannot-be-a-base-url-!\"$%&'()*+,-.;<=>@[\\]^_`{|}~@/", + "origin": "null", + "password": "", + "pathname": "cannot-be-a-base-url-!\"$%&'()*+,-.;<=>@[\\]^_`{|}~@/", + "port": "", + "protocol": "non-special:", + "search": "", + "username": "" + }, + { "input": "https://www.example.com/path{\u007Fpath.html?query'\u007F=query#fragment<\u007Ffragment", "base": null, "hash": "#fragment%3C%7Ffragment", @@ -8634,10 +8649,10 @@ "hash": "", "host": "host", "hostname": "host", - "href": "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~", + "href": "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]%5E_%60%7B|%7D~", "origin": "null", "password": "", - "pathname": "/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~", + "pathname": "/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]%5E_%60%7B|%7D~", "port":"", "protocol": "foo:", "search": "", @@ -8649,10 +8664,10 @@ "hash": "", "host": "host", "hostname": "host", - "href": "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~", + "href": "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B|%7D~", "origin": "wss://host", "password": "", - "pathname": "/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~", + "pathname": "/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B|%7D~", "port":"", "protocol": "wss:", "search": "", diff --git a/tests/wpt/tests/url/tools/IdnaTestV2-compare.py b/tests/wpt/tests/url/tools/IdnaTestV2-compare.py new file mode 100644 index 00000000000..a76ad1ada87 --- /dev/null +++ b/tests/wpt/tests/url/tools/IdnaTestV2-compare.py @@ -0,0 +1,73 @@ +# This script can be used to compare IdnaTestV2.json across revisions, with some manual labor. It is +# used primarily for review and to add to IdnaTestV2-removed.json, to ensure we never lose a test. +# (IdnaTestV2.json is the output of IdnaTestV2-parser.py.) + +import argparse +import json + +def compute_differences(): + data_old = None + data_new = None + with open("IdnaTestV2-old.json", "r") as file_handle: + data_old = json.load(file_handle) + + with open("IdnaTestV2-new.json", "r") as file_handle: + data_new = json.load(file_handle) + + added_tests = [] + changed_tests = [] + removed_tests = [] + + for old_test in data_old: + if isinstance(old_test, str): + continue + found = None + for new_test in data_new: + if isinstance(new_test, str): + continue + if old_test["input"] == new_test["input"]: + found = new_test + break + + if not found: + # We now exclude ? as it's a forbidden domain code point. This check can be removed in the future. + if "?" not in old_test["input"]: + removed_tests.append(old_test) + # For changed tests we only care about parsing no longer succeeding. + elif old_test["output"] != found["output"] and old_test["output"]: + changed_tests.append({ "input": old_test["input"], "output_old": old_test["output"], "output_new": found["output"] }) + + for new_test in data_new: + if isinstance(new_test, str): + continue + found = False + for old_test in data_old: + if isinstance(old_test, str): + continue + if new_test["input"] == old_test["input"]: + found = True + break + if not found: + added_tests.append(new_test) + + return { "added": added_tests, "changed": changed_tests, "removed": removed_tests } + +def main(): + parser = argparse.ArgumentParser(epilog="Thanks for caring about IDNA!") + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument("--differences", action="store_true", help="Output the differences") + group.add_argument("--removed", action="store_true", help="Output the removed tests only") + args = parser.parse_args() + + differences = compute_differences() + + output = None + + if args.differences: + output = differences + elif args.removed: + output = differences["removed"] + + print(json.dumps(output, sort_keys=True, allow_nan=False, indent=2, separators=(',', ': '))) + +main() diff --git a/tests/wpt/tests/url/tools/IdnaTestV2-parser.py b/tests/wpt/tests/url/tools/IdnaTestV2-parser.py index e4154f0ee85..26ce31113c0 100644 --- a/tests/wpt/tests/url/tools/IdnaTestV2-parser.py +++ b/tests/wpt/tests/url/tools/IdnaTestV2-parser.py @@ -21,12 +21,21 @@ def get_IdnaTestV2_lines(): IdnaTestV2 = os.path.join(os.path.dirname(__file__), "IdnaTestV2.txt") if not os.path.exists(IdnaTestV2): # Download IdnaTestV2.txt if it doesn't exist yet - open(IdnaTestV2, "w").write(requests.get("https://unicode.org/Public/idna/latest/IdnaTestV2.txt").text) - return open(IdnaTestV2, "r").readlines() + open(IdnaTestV2, "w", encoding="utf-8").write(requests.get("https://unicode.org/Public/idna/latest/IdnaTestV2.txt").text) + return open(IdnaTestV2, "r", encoding="utf-8").readlines() def remove_escapes(input): return json.loads("\"" + input + "\"") +def get_column_value(input, default = ""): + if input == "": + return default + # "" means an empty string + if input == "\"\"": + return "" + # Remove escapes (doesn't handle \x{XXXX} but those do not appear in the source) + return remove_escapes(input) + def ends_in_a_number(input): # This method is not robust. It uses https://www.unicode.org/reports/tr46/#Notation but there # are likely other ways to end up with a dot, e.g., through decomposition or percent-decoding. @@ -50,7 +59,7 @@ def contains_bidi_status(statuses): def parse(lines, exclude_ipv4_like, exclude_std3, exclude_bidi): # Main quest. output = ["THIS IS A GENERATED FILE. PLEASE DO NOT MODIFY DIRECTLY. See ../tools/IdnaTestV2-parser.py instead."] - output.append(f"--exclude-ipv4-like: {exclude_ipv4_like}; --exclude-std3: {exclude_std3}; --exclude_bidi: {exclude_bidi}") + output.append(f"--exclude-ipv4-like: {exclude_ipv4_like}; --exclude-std3: {exclude_std3}; --exclude-bidi: {exclude_bidi}") # Side quest. unique_statuses = [] @@ -63,9 +72,6 @@ def parse(lines, exclude_ipv4_like, exclude_std3, exclude_bidi): if line.startswith("#") or line == "": continue - # Remove escapes (doesn't handle \x{XXXX} but those do not appear in the source) - line = remove_escapes(line) - # Normalize columns # # Since we are only interested in ToASCII and enforce Transitional_Processing=false we care @@ -79,10 +85,8 @@ def parse(lines, exclude_ipv4_like, exclude_std3, exclude_bidi): columns = [column.strip() for column in line.split(";")] # Column 1 (source) and Column 2 (toUnicode; if empty, Column 1 (source)) - source = columns[0] - to_unicode = columns[1] - if to_unicode == "": - to_unicode = source + source = get_column_value(columns[0]) + to_unicode = get_column_value(columns[1], source) # Immediately exclude IPv4-like tests when desired. While we could force all their # expectations to be failure instead, it's not clear we need that many additional tests that @@ -92,13 +96,11 @@ def parse(lines, exclude_ipv4_like, exclude_std3, exclude_bidi): continue if exclude_std3: - if re.search(r"\u2260|\u226E|\u226F|\<|\>|\$|,", to_unicode): + if re.search(r"\<|\>|\:|\/|\?|\#|\\", to_unicode): continue # Column 4 (toAsciiN; if empty, use Column 2 (toUnicode)) - to_ascii = columns[3] - if to_ascii == "": - to_ascii = to_unicode + to_ascii = get_column_value(columns[3], to_unicode) # Column 5 (toAsciiNStatus; if empty, use Column 3 (toUnicodeStatus)) temp_statuses = columns[4] @@ -147,7 +149,7 @@ def parse(lines, exclude_ipv4_like, exclude_std3, exclude_bidi): return { "tests": output, "unique_statuses": unique_statuses } def to_json(data): - handle = open(os.path.join(os.path.dirname(__file__), "../resources/IdnaTestV2.json"), "w") + handle = open(os.path.join(os.path.dirname(__file__), "../resources/IdnaTestV2.json"), "w", encoding="utf-8") handle.write(json.dumps(data, sort_keys=True, allow_nan=False, indent=2, separators=(',', ': '))) handle.write("\n") handle.close() diff --git a/tests/wpt/tests/urlpattern/resources/urlpatterntestdata.json b/tests/wpt/tests/urlpattern/resources/urlpatterntestdata.json index 1d2ba25ff7d..3d5ddce1eab 100644 --- a/tests/wpt/tests/urlpattern/resources/urlpatterntestdata.json +++ b/tests/wpt/tests/urlpattern/resources/urlpatterntestdata.json @@ -1202,6 +1202,14 @@ { "pattern": [{ "protocol": "http", "port": "80 " }], "inputs": [{ "protocol": "http", "port": "80" }], + "exactly_empty_components": ["port"], + "expected_match": { + "protocol": { "input": "http", "groups": {} } + } + }, + { + "pattern": [{ "protocol": "http", "port": "100000" }], + "inputs": [{ "protocol": "http", "port": "100000" }], "expected_obj": "error" }, { @@ -2424,7 +2432,11 @@ }, { "pattern": [{ "hostname": "bad#hostname" }], - "expected_obj": "error" + "inputs": [{ "hostname": "bad" }], + "exactly_empty_components": ["port"], + "expected_match": { + "hostname": { "input": "bad", "groups": {} } + } }, { "pattern": [{ "hostname": "bad%hostname" }], @@ -2432,7 +2444,10 @@ }, { "pattern": [{ "hostname": "bad/hostname" }], - "expected_obj": "error" + "inputs": [{ "hostname": "bad" }], + "expected_match": { + "hostname": { "input": "bad", "groups": {} } + } }, { "pattern": [{ "hostname": "bad\\:hostname" }], @@ -2464,7 +2479,8 @@ }, { "pattern": [{ "hostname": "bad\\\\hostname" }], - "expected_obj": "error" + "inputs": [{ "hostname": "badhostname" }], + "expected_match": null }, { "pattern": [{ "hostname": "bad^hostname" }], @@ -2476,15 +2492,24 @@ }, { "pattern": [{ "hostname": "bad\nhostname" }], - "expected_obj": "error" + "inputs": [{ "hostname": "badhostname" }], + "expected_match": { + "hostname": { "input": "badhostname", "groups": {} } + } }, { "pattern": [{ "hostname": "bad\rhostname" }], - "expected_obj": "error" + "inputs": [{ "hostname": "badhostname" }], + "expected_match": { + "hostname": { "input": "badhostname", "groups": {} } + } }, { "pattern": [{ "hostname": "bad\thostname" }], - "expected_obj": "error" + "inputs": [{ "hostname": "badhostname" }], + "expected_match": { + "hostname": { "input": "badhostname", "groups": {} } + } }, { "pattern": [{}], diff --git a/tests/wpt/tests/wai-aria/scripts/aria-utils.js b/tests/wpt/tests/wai-aria/scripts/aria-utils.js index ec53464c18f..5ed73b06e45 100644 --- a/tests/wpt/tests/wai-aria/scripts/aria-utils.js +++ b/tests/wpt/tests/wai-aria/scripts/aria-utils.js @@ -45,6 +45,9 @@ const AriaUtils = { } for (const el of els) { let role = el.getAttribute("data-expectedrole"); + if (!role) { + throw `Element should have attribute \'data-expectedrole\'. Element: ${el.outerHTML}`; + } let testName = el.getAttribute("data-testname") || role; // data-testname optional if role is unique per test file if (typeof roleTestNamePrefix !== "undefined") { testName = roleTestNamePrefix + testName; @@ -137,6 +140,9 @@ const AriaUtils = { } for (const el of els) { let label = el.getAttribute("data-expectedlabel"); + if (!label) { + throw `Element should have attribute \'data-expectedlabel\'. Element: ${el.outerHTML}`; + } let testName = el.getAttribute("data-testname") || label; // data-testname optional if label is unique per test file if (typeof labelTestNamePrefix !== "undefined") { testName = labelTestNamePrefix + testName; diff --git a/tests/wpt/tests/web-animations/crashtests/effectively-infinite-timing-parameters.html b/tests/wpt/tests/web-animations/crashtests/effectively-infinite-timing-parameters.html new file mode 100644 index 00000000000..2b02147f04e --- /dev/null +++ b/tests/wpt/tests/web-animations/crashtests/effectively-infinite-timing-parameters.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html class='test-wait'> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Starting an animation with an effectively infinite timing parameters + </title> +</head> +<!-- crbug.com/400741639 --> +<body> + <div id="target">test</div> +</body> +<script> + async function raf(n) { + return new Promise(resolve => { + const tick = () => { + if (--n) { + requestAnimationFrame(tick); + } else { + resolve(); + } + } + requestAnimationFrame(tick); + }); + }; + + window.onload = async () => { + const target = document.getElementById('target'); + const anim = target.animate([ + {"transform": "scale(2)"}, + {"transform": "none"} + ], { + duration: 95903184853313357582278077554606, + iterationStart: 3.165661661777848e+19, + }); + await anim.ready; + await raf(5); + document.documentElement.classList.remove('test-wait'); + }; +</script> +</html> diff --git a/tests/wpt/tests/web-animations/interfaces/AnimationTrigger/constructor.html b/tests/wpt/tests/web-animations/interfaces/AnimationTrigger/constructor.html index e7b632fd90f..3429c5b1877 100644 --- a/tests/wpt/tests/web-animations/interfaces/AnimationTrigger/constructor.html +++ b/tests/wpt/tests/web-animations/interfaces/AnimationTrigger/constructor.html @@ -80,60 +80,4 @@ assert_equals(trigger.exitRangeEnd, "cover 90%", "exitRangeEnd is supplied value"); }, "All values supplied (view timeline)."); - - test(t => { - const trigger = new AnimationTrigger(); - assert_equals(trigger.type, "once", "default type is once."); - trigger.type = "alternate"; - assert_equals(trigger.type, "alternate", "valid type change is honored."); - trigger.type = "etanretla"; - assert_equals(trigger.type, "alternate", "invalid type change is ignored."); - }, "Set AnimationTrigger.type."); - - test(t => { - const trigger = new AnimationTrigger(); - assert_equals(trigger.timeline, document.timeline, - "default timeline is document.timeline."); - const scroll_timeline = new ScrollTimeline(); - trigger.timeline = scroll_timeline; - assert_equals(trigger.timeline, scroll_timeline, - "valid timeline change is honored."); - assert_throws_js(TypeError, () => { - trigger.timeline = document.createElement("div"); - }); - assert_equals(trigger.timeline, scroll_timeline, - "invalid timeline change is ignored."); - }, "Set AnimationTrigger.timeline."); - - test(t => { - const trigger = new AnimationTrigger(); - assert_equals(trigger.rangeStart, "normal", - "default rangeStart is normal."); - const rangeOffset = { rangeName: "entry", offset: CSS.percent("20") }; - // Valid values - trigger.rangeStart = rangeOffset; - assert_true(typeof(trigger.rangeStart) == "object", - "trigger.rangeStart is an object"); - assert_equals(trigger.rangeStart.rangeName, rangeOffset.rangeName, - "valid rangeStart (TimelineRange.rangeName) change is honored."); - assert_equals(trigger.rangeStart.offset, rangeOffset.offset, - "valid rangeStart (TimelineRange.offset) change is honored."); - trigger.rangeStart = "contain 10%"; - assert_equals(trigger.rangeStart, "contain 10%", - "valid rangeStart (string) change is honored."); - - // Invalid values - let func = () => { - trigger.rangeStart = "totally not a valid rangeStart"; - } - assert_throws_js(TypeError, func); - func = () => { - trigger.rangeStart = { rangeName: 'invalid' }; - } - assert_throws_js(TypeError, func); - func = () => { - trigger.rangeStart = { offset: 'invalid' }; - } - assert_throws_js(TypeError, func); - }, "Set AnimationTrigger.rangeStart."); </script> diff --git a/tests/wpt/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-playoutstats.html b/tests/wpt/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-playoutstats.html new file mode 100644 index 00000000000..ef0468122ce --- /dev/null +++ b/tests/wpt/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-playoutstats.html @@ -0,0 +1,140 @@ +<!DOCTYPE html> +<html> + <head> + <title>Testing AudioContext.playoutStats attribute</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + + <body> + <script> + function should_be_in_range(value, min, max) { + assert_greater_than_equal(value, min); + assert_less_than_equal(value, max); + } + + promise_test(async (t) => { + let context = new AudioContext(); + assert_not_equals(context.playoutStats, null); + + // Initially, the stats should all be 0. + let stats = context.playoutStats; + assert_equals(stats.totalFramesDuration, 0); + assert_equals(stats.fallbackFramesDuration, 0); + assert_equals(stats.fallbackFramesEvents, 0); + assert_equals(stats.minimumLatency, 0); + assert_equals(stats.maximumLatency, 0); + assert_equals(stats.averageLatency, 0); + + // Asynchronously wait for 1.5 seconds. We will then check that the + // stats reflect that the context has been playing for at least 1 + // second. The extra 0.5 seconds is to avoid flakiness. + // Note that awaiting moves us to a new task in the execution cycle, + // which allows the stats to change. + await new Promise((r) => step_timeout(r, 1500)); + assert_greater_than(stats.totalFramesDuration, 1000); + should_be_in_range( + stats.fallbackFramesDuration, + 0, + stats.totalFramesDuration + ); + assert_greater_than_equal(stats.fallbackFramesEvents, 0); + assert_greater_than_equal(stats.minimumLatency, 0); + assert_greater_than_equal(stats.maximumLatency, 0); + should_be_in_range( + stats.averageLatency, + stats.minimumLatency, + stats.maximumLatency + ); + }, "Test that the stats increase during playout"); + + promise_test(async (t) => { + let context = new AudioContext(); + + // Wait a while so that we get stats that aren't all zeroes. + await new Promise((r) => step_timeout(r, 1500)); + let stats = context.playoutStats; + assert_greater_than(stats.totalFramesDuration, 1000); + + // Check that the stats from the toJSON object match the PlayoutStats + // object. + let json = stats.toJSON(); + assert_equals(json.totalFramesDuration, stats.totalFramesDuration); + assert_equals( + json.fallbackFramesDuration, + stats.fallbackFramesDuration + ); + assert_equals(json.fallbackFramesEvents, stats.fallbackFramesEvents); + assert_equals(json.minimumLatency, stats.minimumLatency); + assert_equals(json.maximumLatency, stats.maximumLatency); + assert_equals(json.averageLatency, stats.averageLatency); + }, "Test that toJSON reflects the current stats"); + + promise_test(async (t) => { + let context = new AudioContext(); + + // Wait a while so that we get stats that aren't all zeroes. + await new Promise((r) => step_timeout(r, 1500)); + let stats = context.playoutStats; + assert_greater_than(stats.totalFramesDuration, 1000); + + // Average latency should be between minimum and maximum. + let beforeReset = stats.toJSON(); + should_be_in_range( + beforeReset.averageLatency, + beforeReset.minimumLatency, + beforeReset.maximumLatency + ); + + // After a reset, the minimum, maximum and average latencies should be + // the same. + stats.resetLatency(); + let afterReset = stats.toJSON(); + assert_equals(afterReset.minimumLatency, afterReset.averageLatency); + assert_equals(afterReset.maximumLatency, afterReset.averageLatency); + }, "Test PlayoutStats.resetLatency()"); + + promise_test(async (t) => { + // Tests that the API adheres to run to completion semantics, as + // defined here: https://w3ctag.github.io/design-principles/#js-rtc + let context = new AudioContext(); + + // Wait a while so that we get stats that aren't all zeroes. + await new Promise((r) => step_timeout(r, 1500)); + let stats = context.playoutStats; + assert_greater_than(stats.totalFramesDuration, 1000); + let beforeWait = stats.toJSON(); + + // Synchronously wait 500 ms. + const start = performance.now(); + while (performance.now() - start < 500); + + // We are still in the same execution cycle, so the stats shouldn't + // have changed. + assert_equals( + stats.totalFramesDuration, + beforeWait.totalFramesDuration + ); + assert_equals( + stats.fallbackFramesDuration, + beforeWait.fallbackFramesDuration + ); + assert_equals( + stats.fallbackFramesEvents, + beforeWait.fallbackFramesEvents + ); + assert_equals(stats.minimumLatency, beforeWait.minimumLatency); + assert_equals(stats.maximumLatency, beforeWait.maximumLatency); + assert_equals(stats.averageLatency, beforeWait.averageLatency); + + // Move to the next execution cycle. Since it was 500 ms since the + // stats were last updated, they have now increased. + await Promise.resolve(); + assert_greater_than( + stats.totalFramesDuration, + beforeWait.totalFramesDuration + ); + }, "Test that stats are unchanged within the same execution cycle."); + </script> + </body> +</html> diff --git a/tests/wpt/tests/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-messageport.https.html b/tests/wpt/tests/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-messageport.https.html index 546bd1d0d0e..cf203a1473a 100644 --- a/tests/wpt/tests/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-messageport.https.html +++ b/tests/wpt/tests/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-messageport.https.html @@ -16,6 +16,19 @@ let filePath = 'processors/port-processor.js'; + // AudioWorket to global communication. + audit.define( + 'Test postMessage from AudioWorklet to AudioWorkletGlobalScope', + (task, should) => { + context.audioWorklet.port.onmessage = (event) => { + should(event.data, + 'The response from AudioWorkletGlobalscope') + .beEqualTo('hello world'); + task.done(); + }; + context.audioWorklet.port.postMessage("hello world"); + }); + // Creates an AudioWorkletNode and sets an EventHandler on MessagePort // object. The associated PortProcessor will post a message upon its // construction. Test if the message is received correctly. diff --git a/tests/wpt/tests/webaudio/the-audio-api/the-audioworklet-interface/processors/port-processor.js b/tests/wpt/tests/webaudio/the-audio-api/the-audioworklet-interface/processors/port-processor.js index 8def5a61d7e..c3fa52faf85 100644 --- a/tests/wpt/tests/webaudio/the-audio-api/the-audioworklet-interface/processors/port-processor.js +++ b/tests/wpt/tests/webaudio/the-audio-api/the-audioworklet-interface/processors/port-processor.js @@ -32,3 +32,5 @@ class PortProcessor extends AudioWorkletProcessor { } registerProcessor('port-processor', PortProcessor); + +port.onmessage = (event) => port.postMessage(event.data); diff --git a/tests/wpt/tests/webdriver/tests/bidi/web_extension/__init__.py b/tests/wpt/tests/webdriver/tests/bidi/web_extension/__init__.py index e69de29bb2d..0f229bd3f99 100644 --- a/tests/wpt/tests/webdriver/tests/bidi/web_extension/__init__.py +++ b/tests/wpt/tests/webdriver/tests/bidi/web_extension/__init__.py @@ -0,0 +1,8 @@ +from .. import any_string + + +def assert_extension_id(extension_id, extension_data): + if extension_data["id"] is None: + any_string(extension_id) + else: + assert extension_id == extension_data["id"] diff --git a/tests/wpt/tests/webdriver/tests/bidi/web_extension/conftest.py b/tests/wpt/tests/webdriver/tests/bidi/web_extension/conftest.py index c68da8696e2..e59af399b07 100644 --- a/tests/wpt/tests/webdriver/tests/bidi/web_extension/conftest.py +++ b/tests/wpt/tests/webdriver/tests/bidi/web_extension/conftest.py @@ -13,9 +13,9 @@ EXTENSION_DATA = { "chrome": { "id": None, "path": get_extension_path("chrome/unpacked/"), - "archivePath": None, + "archivePath": get_extension_path("chrome/packed.crx"), "archivePathInvalid": get_extension_path("chrome/invalid"), - "base64": None, + "base64": get_base64_for_extension_file("chrome/packed.crx"), } } diff --git a/tests/wpt/tests/webdriver/tests/bidi/web_extension/install/install.py b/tests/wpt/tests/webdriver/tests/bidi/web_extension/install/install.py index a6f54dfe10b..a801928452d 100644 --- a/tests/wpt/tests/webdriver/tests/bidi/web_extension/install/install.py +++ b/tests/wpt/tests/webdriver/tests/bidi/web_extension/install/install.py @@ -1,5 +1,7 @@ import pytest +from .. import assert_extension_id + @pytest.mark.asyncio async def test_install_from_base64(bidi_session, extension_data): @@ -10,7 +12,7 @@ async def test_install_from_base64(bidi_session, extension_data): } ) try: - assert web_extension == extension_data["id"] + assert_extension_id(web_extension, extension_data) finally: # Clean up the extension. await bidi_session.web_extension.uninstall(extension=web_extension) @@ -25,7 +27,7 @@ async def test_install_from_path(bidi_session, extension_data): } ) try: - assert web_extension == extension_data["id"] + assert_extension_id(web_extension, extension_data) finally: # Clean up the extension. await bidi_session.web_extension.uninstall(extension=web_extension) @@ -40,7 +42,7 @@ async def test_install_from_archive_path(bidi_session, extension_data): } ) try: - assert web_extension == extension_data["id"] + assert_extension_id(web_extension, extension_data) finally: # Clean up the extension. await bidi_session.web_extension.uninstall(extension=web_extension) diff --git a/tests/wpt/tests/webdriver/tests/support/asserts.py b/tests/wpt/tests/webdriver/tests/support/asserts.py index 1c626a735d5..0aa0d97db30 100644 --- a/tests/wpt/tests/webdriver/tests/support/asserts.py +++ b/tests/wpt/tests/webdriver/tests/support/asserts.py @@ -1,5 +1,3 @@ -import imghdr -import json from base64 import decodebytes from webdriver import NoSuchAlertException, WebDriverException, WebElement @@ -235,6 +233,5 @@ def assert_png(screenshot): image = decodebytes(screenshot.encode()) else: image = screenshot - mime_type = imghdr.what("", image) - assert mime_type == "png", "Expected image to be PNG, but it was {}".format(mime_type) + assert image.startswith(b'\211PNG\r\n\032\n'), "Expected image to be PNG" return image diff --git a/tests/wpt/tests/webdriver/tests/support/webextensions/chrome/packed.crx b/tests/wpt/tests/webdriver/tests/support/webextensions/chrome/packed.crx Binary files differnew file mode 100644 index 00000000000..618c307bfba --- /dev/null +++ b/tests/wpt/tests/webdriver/tests/support/webextensions/chrome/packed.crx diff --git a/tests/wpt/tests/webnn/conformance_tests/byob_readtensor.https.any.js b/tests/wpt/tests/webnn/conformance_tests/byob_readtensor.https.any.js index 97bd666fa2c..5cbadb3c611 100644 --- a/tests/wpt/tests/webnn/conformance_tests/byob_readtensor.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/byob_readtensor.https.any.js @@ -1,5 +1,5 @@ // META: title=test WebNN API tensor operations -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu @@ -94,22 +94,24 @@ promise_test(async () => { assert_array_equals(new Uint32Array(arrayBuffer), testContents); }, `readTensor() with an ArrayBuffer`); -promise_test(async () => { - const sharedArrayBuffer = new SharedArrayBuffer(testContents.byteLength); +if ('SharedArrayBuffer' in globalThis) { + promise_test(async () => { + const sharedArrayBuffer = new SharedArrayBuffer(testContents.byteLength); - await mlContext.readTensor(mlTensor, sharedArrayBuffer); + await mlContext.readTensor(mlTensor, sharedArrayBuffer); - assert_array_equals(new Uint32Array(sharedArrayBuffer), testContents); -}, `readTensor() with a SharedArrayBuffer`); + assert_array_equals(new Uint32Array(sharedArrayBuffer), testContents); + }, `readTensor() with a SharedArrayBuffer`); -promise_test(async () => { - const sharedArrayBuffer = new SharedArrayBuffer(testContents.byteLength); - const typedArray = new Uint32Array(sharedArrayBuffer); + promise_test(async () => { + const sharedArrayBuffer = new SharedArrayBuffer(testContents.byteLength); + const typedArray = new Uint32Array(sharedArrayBuffer); - await mlContext.readTensor(mlTensor, typedArray); + await mlContext.readTensor(mlTensor, typedArray); - assert_array_equals(typedArray, testContents); -}, `readTensor() with a typeArray from a SharedArrayBuffer`); + assert_array_equals(typedArray, testContents); + }, `readTensor() with a typeArray from a SharedArrayBuffer`); +} promise_test(async () => { // Create a slightly larger ArrayBuffer and set up the TypedArray at an diff --git a/tests/wpt/tests/webnn/conformance_tests/identity.https.any.js b/tests/wpt/tests/webnn/conformance_tests/identity.https.any.js index 05fee94f71d..214d16e3964 100644 --- a/tests/wpt/tests/webnn/conformance_tests/identity.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/identity.https.any.js @@ -1,5 +1,5 @@ // META: title=test WebNN API element-wise identity operation -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/conformance_tests/inputs-are-not-modified.https.any.js b/tests/wpt/tests/webnn/conformance_tests/inputs-are-not-modified.https.any.js index 730941fbd8b..0ea7a08c87b 100644 --- a/tests/wpt/tests/webnn/conformance_tests/inputs-are-not-modified.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/inputs-are-not-modified.https.any.js @@ -1,5 +1,5 @@ // META: title=test that input tensors are not modified during a call to dispatch() -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/conformance_tests/parallel-dispatch.https.any.js b/tests/wpt/tests/webnn/conformance_tests/parallel-dispatch.https.any.js index 4051645771f..6ad4cd93d65 100644 --- a/tests/wpt/tests/webnn/conformance_tests/parallel-dispatch.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/parallel-dispatch.https.any.js @@ -1,5 +1,5 @@ // META: title=test parallel WebNN API dispatch calls -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/conformance_tests/scalars.https.any.js b/tests/wpt/tests/webnn/conformance_tests/scalars.https.any.js index 7cb3ceeff7f..095d96c519e 100644 --- a/tests/wpt/tests/webnn/conformance_tests/scalars.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/scalars.https.any.js @@ -1,5 +1,5 @@ // META: title=test that scalar values work as expected -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/conformance_tests/shared_arraybuffer_constant.https.any.js b/tests/wpt/tests/webnn/conformance_tests/shared_arraybuffer_constant.https.any.js index 8bf7212feaf..8f0d5e2eda3 100644 --- a/tests/wpt/tests/webnn/conformance_tests/shared_arraybuffer_constant.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/shared_arraybuffer_constant.https.any.js @@ -1,5 +1,5 @@ // META: title=test WebNN API constant with shared array buffer -// META: global=window,dedicatedworker +// META: global=window,dedicatedworker,serviceworker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/conformance_tests/subgraph.https.any.js b/tests/wpt/tests/webnn/conformance_tests/subgraph.https.any.js index ed35637b43c..9b21d6e4f94 100644 --- a/tests/wpt/tests/webnn/conformance_tests/subgraph.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/subgraph.https.any.js @@ -1,5 +1,5 @@ // META: title=test WebNN API subgraph with multiple operations -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/conformance_tests/tensor.https.any.js b/tests/wpt/tests/webnn/conformance_tests/tensor.https.any.js index 0906ae96ba2..1a46c35b320 100644 --- a/tests/wpt/tests/webnn/conformance_tests/tensor.https.any.js +++ b/tests/wpt/tests/webnn/conformance_tests/tensor.https.any.js @@ -1,5 +1,5 @@ // META: title=test WebNN API tensor operations -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu @@ -175,44 +175,46 @@ const testWriteTensor = (testName) => { } }); - promise_test(async () => { - const tensorDescriptor = { - dataType: 'int32', - shape: [4], - readable: true, - writable: true, - }; - const tensorByteLength = sizeOfDescriptor(tensorDescriptor); - - // Required to use SharedArrayBuffer. - assert_true( - self.crossOriginIsolated, - 'The page is served with COOP and COEP, it should be cross-origin-isolated.'); - - let arrayBuffer = new ArrayBuffer(tensorByteLength); - let arrayBufferView = new Int32Array(arrayBuffer); - arrayBufferView.fill(7); - - let sharedArrayBuffer = new SharedArrayBuffer(tensorByteLength); - let sharedArrayBufferView = new Int32Array(sharedArrayBuffer); - sharedArrayBufferView.fill(7); - - const tensors = await Promise.all([ - mlContext.createTensor(tensorDescriptor), - mlContext.createTensor(tensorDescriptor), - mlContext.createTensor(tensorDescriptor), - mlContext.createTensor(tensorDescriptor) - ]); - - mlContext.writeTensor(tensors[0], arrayBuffer); - mlContext.writeTensor(tensors[2], arrayBufferView); - mlContext.writeTensor(tensors[1], sharedArrayBuffer); - mlContext.writeTensor(tensors[3], sharedArrayBufferView); - - await Promise.all(tensors.map(async (tensor) => { - assert_tensor_data_equals(mlContext, tensor, arrayBufferView); - })); - }, `${testName} / write with different kinds of buffers`); + if ('SharedArrayBuffer' in globalThis) { + promise_test(async () => { + const tensorDescriptor = { + dataType: 'int32', + shape: [4], + readable: true, + writable: true, + }; + const tensorByteLength = sizeOfDescriptor(tensorDescriptor); + + // Required to use SharedArrayBuffer. + assert_true( + self.crossOriginIsolated, + 'The page is served with COOP and COEP, it should be cross-origin-isolated.'); + + let arrayBuffer = new ArrayBuffer(tensorByteLength); + let arrayBufferView = new Int32Array(arrayBuffer); + arrayBufferView.fill(7); + + let sharedArrayBuffer = new SharedArrayBuffer(tensorByteLength); + let sharedArrayBufferView = new Int32Array(sharedArrayBuffer); + sharedArrayBufferView.fill(7); + + const tensors = await Promise.all([ + mlContext.createTensor(tensorDescriptor), + mlContext.createTensor(tensorDescriptor), + mlContext.createTensor(tensorDescriptor), + mlContext.createTensor(tensorDescriptor) + ]); + + mlContext.writeTensor(tensors[0], arrayBuffer); + mlContext.writeTensor(tensors[2], arrayBufferView); + mlContext.writeTensor(tensors[1], sharedArrayBuffer); + mlContext.writeTensor(tensors[3], sharedArrayBufferView); + + await Promise.all(tensors.map(async (tensor) => { + assert_tensor_data_equals(mlContext, tensor, arrayBufferView); + })); + }, `${testName} / write with different kinds of buffers`); + } promise_test(async () => { const tensorDescriptor = { diff --git a/tests/wpt/tests/webnn/helper-validation.window.js b/tests/wpt/tests/webnn/helper-validation.window.js new file mode 100644 index 00000000000..f5b147b5ad7 --- /dev/null +++ b/tests/wpt/tests/webnn/helper-validation.window.js @@ -0,0 +1,222 @@ +// META: title=Validate WebNN test helpers +// META: script=resources/utils.js + +// This doesn't validate the WebNN API itself, it just verifies behavior of +// non-trivial helper functions. + +'use strict'; + +// Largest integer uniquely representable as a float32. +const MAX_FLOAT32_INTEGER = 2 ** 24; + +test(t => { + const dataType = 'float32'; + [[0.0, 0.0, 0n], + [0.0, 1e-46, 0n], + [0.0, 1e-36, 61482021n], + [1.0, 1.0, 0n], + [1.0, -1.0, 2130706432n], + [1.0, 2.0, 8388608n], + [1.000001, 1.000002, 9n], + [1.0000001, 1.0000002, 1n], + [-1.000001, 1.000002, 2130706457n], + [-1.0000001, 1.0000002, 2130706435n], + [0.0, 1.401298464324817e-45, 1n], + [99.28312683105469, 39.03501892089844, 11169050n], + [MAX_FLOAT32_INTEGER - 1, MAX_FLOAT32_INTEGER, 1n], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + assert_equals( + ulpDistance(-a, -b, dataType), expected, + `ULP distance between ${- a} and ${- b} (negated)`); + }); +}, 'ULP Distance - float32'); + +// TODO: Add test cases for 'float16' data type. + +test(t => { + const dataType = 'int64'; + [[0n, 0n, 0n], + [1n, 0n, 1n], + [1n, 2n, 1n], + [10n, 11n, 1n], + [10n, 20n, 10n], + [100000001n, 100000002n, 1n], + [0x7FFFFFFFFFFFFFFEn, 0x7FFFFFFFFFFFFFFFn, 1n], + [-0x7FFFFFFFFFFFFFFFn, 0x7FFFFFFFFFFFFFFFn, 0xFFFFFFFFFFFFFFFEn], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + assert_equals( + ulpDistance(-a, -b, dataType), expected, + `ULP distance between ${- a} and ${- b} (negated)`); + }); + assert_equals( + ulpDistance(-0x8000000000000000n, 0x7FFFFFFFFFFFFFFFn, dataType), + 0xFFFFFFFFFFFFFFFFn, 'ULP distance between min and max int64'); +}, 'ULP Distance - int64'); + +test(t => { + const dataType = 'uint64'; + [[0n, 0n, 0n], + [1n, 0n, 1n], + [1n, 2n, 1n], + [10n, 11n, 1n], + [10n, 20n, 10n], + [100000001n, 100000002, 1n], + [0xFFFFFFFFFFFFFFFEn, 0xFFFFFFFFFFFFFFFFn, 1n], + [0n, 0xFFFFFFFFFFFFFFFFn, 0xFFFFFFFFFFFFFFFFn], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + }); +}, 'ULP Distance - uint64'); + +test(t => { + const dataType = 'int32'; + [[0, 0, 0], + [1, 0, 1], + [1, 2, 1], + [10, 11, 1], + [10, 20, 10], + [100000001, 100000002, 1], + [0x7FFFFFFE, 0x7FFFFFFF, 1], + [-0x7FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFE], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + assert_equals( + ulpDistance(-a, -b, dataType), expected, + `ULP distance between ${- a} and ${- b} (negated)`); + }); + assert_equals( + ulpDistance(-0x80000000, 0x7FFFFFFF, dataType), 0xFFFFFFFF, + 'ULP distance between min and max int32'); +}, 'ULP Distance - int32'); + +test(t => { + const dataType = 'uint32'; + [[0, 0, 0], + [1, 0, 1], + [1, 2, 1], + [10, 11, 1], + [10, 20, 10], + [100000001, 100000002, 1], + [0xFFFFFFFE, 0xFFFFFFFF, 1], + [0, 0xFFFFFFFF, 0xFFFFFFFF], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + }); +}, 'ULP Distance - uint32'); + +test(t => { + const dataType = 'int8'; + [[0, 0, 0], + [1, 0, 1], + [1, 2, 1], + [10, 11, 1], + [10, 20, 10], + [101, 102, 1], + [0x7E, 0x7F, 1], + [-0x7F, 0x7F, 0xFE], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + assert_equals( + ulpDistance(-a, -b, dataType), expected, + `ULP distance between ${- a} and ${- b} (negated)`); + }); + assert_equals( + ulpDistance(-0x80, 0x7F, dataType), 0xFF, + 'ULP distance between min and max int8'); +}, 'ULP Distance - int8'); + +test(t => { + const dataType = 'uint8'; + [[0, 0, 0], + [1, 0, 1], + [1, 2, 1], + [10, 11, 1], + [10, 20, 10], + [101, 102, 1], + [0xFE, 0xFF, 1], + [0, 0xFF, 0xFF], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + }); +}, 'ULP Distance - uint8'); + +test(t => { + const dataType = 'int4'; + [[0, 0, 0], + [1, 0, 1], + [1, 2, 1], + [10, 11, 1], + [1, 10, 9], + [6, 7, 1], + [-7, 7, 14], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + assert_equals( + ulpDistance(-a, -b, dataType), expected, + `ULP distance between ${- a} and ${- b} (negated)`); + }); + assert_equals( + ulpDistance(-0x8, 0x7, dataType), 0xF, + 'ULP distance between min and max int4'); +}, 'ULP Distance - int4'); + +test(t => { + const dataType = 'uint4'; + [[0, 0, 0], + [1, 0, 1], + [1, 2, 1], + [10, 11, 1], + [1, 10, 9], + [0xE, 0xF, 1], + [0, 0xF, 0xF], + ].forEach(([a, b, expected]) => { + assert_equals( + ulpDistance(a, b, dataType), expected, + `ULP distance between ${a} and ${b}`); + assert_equals( + ulpDistance(b, a, dataType), expected, + `ULP distance between ${b} and ${a} (commutative)`); + }); +}, 'ULP Distance - uint4'); diff --git a/tests/wpt/tests/webnn/idlharness.https.any.js b/tests/wpt/tests/webnn/idlharness.https.any.js index 905744ffea6..feb9d09f1a8 100644 --- a/tests/wpt/tests/webnn/idlharness.https.any.js +++ b/tests/wpt/tests/webnn/idlharness.https.any.js @@ -1,4 +1,4 @@ -// META: global=window,dedicatedworker +// META: global=window,worker // META: script=/resources/WebIDLParser.js // META: script=/resources/idlharness.js // META: script=./resources/utils.js diff --git a/tests/wpt/tests/webnn/resources/utils.js b/tests/wpt/tests/webnn/resources/utils.js index 496e7d5180c..7cecf29061f 100644 --- a/tests/wpt/tests/webnn/resources/utils.js +++ b/tests/wpt/tests/webnn/resources/utils.js @@ -249,23 +249,22 @@ const sizeOfShape = (array) => { /** * Get bitwise of the given value. * @param {Number} value - * @param {String} dataType - A data type string, like "float32", "float16", - * more types, please see: - * https://www.w3.org/TR/webnn/#enumdef-mloperanddatatype - * @return {Number} A 64-bit signed integer. + * @param {String} dataType - A data type string; currently only "float32" is + * supported by this function. + * @return {BigInt} A 64-bit signed integer. */ const getBitwise = (value, dataType) => { const buffer = new ArrayBuffer(8); const int64Array = new BigInt64Array(buffer); - int64Array[0] = value < 0 ? ~BigInt(0) : BigInt(0); let typedArray; if (dataType === "float32") { typedArray = new Float32Array(buffer); } else { throw new AssertionError(`Data type ${dataType} is not supported`); } - typedArray[0] = value; - return int64Array[0]; + typedArray[0] = Math.abs(value); + const int64 = int64Array[0]; + return (value < 0) ? -int64 : int64; }; /** @@ -295,29 +294,7 @@ const assert_array_approx_equals_ulp = (actual, expected, nulp, dataType, descri if (actual[i] === expected[i]) { continue; } else { - // measure the ULP distance - if (dataType === 'float32') { - actualBitwise = getBitwise(actual[i], dataType); - expectedBitwise = getBitwise(expected[i], dataType); - } else if (dataType === 'float16') { - actualBitwise = actual[i]; - // convert expected data of Float16 to Uint16 - expectedBitwise = toHalf(expected[i]); - } else if (dataType === 'int64') { - actualBitwise = actual[i]; - expectedBitwise = BigInt(expected[i]); - } else if (dataType === 'uint64') { - actualBitwise = actual[i]; - expectedBitwise = BigUint64Array(expected[i]); - } else if ( - dataType === 'int8' || dataType === 'uint8' || dataType === 'int32' || - dataType === 'uint32' || dataType === 'int4' || - dataType === 'uint4') { - actualBitwise = actual[i]; - expectedBitwise = expected[i]; - } - distance = actualBitwise - expectedBitwise; - distance = distance >= 0 ? distance : -distance; + distance = ulpDistance(actual[i], expected[i], dataType); // if true, invoke assert_true() in failure case // if false, it's expected, not invoke assert_true() in success case to @@ -335,6 +312,40 @@ const assert_array_approx_equals_ulp = (actual, expected, nulp, dataType, descri }; /** + * Compute the ULP distance between ``a`` and ``b`` for the given ``dataType``. + * + * @param {(Number|BigInt)} a - First value. + * @param {(Number|BigInt)} b - Second value. + * @param {String} dataType - A data type string, value: "float32", + * more types, please see: + * https://www.w3.org/TR/webnn/#enumdef-mloperanddatatype + */ +const ulpDistance = (a, b, dataType) => { + let aBitwise, bBitwise; + // measure the ULP distance + if (dataType === 'float32') { + aBitwise = getBitwise(a, dataType); + bBitwise = getBitwise(b, dataType); + } else if (dataType === 'float16') { + aBitwise = a; + // convert b data of Float16 to Uint16 + bBitwise = toHalf(b); + } else if (dataType === 'int64' || dataType === 'uint64') { + aBitwise = BigInt(a); + bBitwise = BigInt(b); + } else if ( + dataType === 'int8' || dataType === 'uint8' || dataType === 'int32' || + dataType === 'uint32' || dataType === 'int4' || dataType === 'uint4') { + aBitwise = a; + bBitwise = b; + } else { + throw new AssertionError(`Data type ${dataType} is not supported`); + } + const distance = aBitwise - bBitwise; + return distance >= 0 ? distance : -distance; +}; + +/** * This function converts a Float16 stored as the bits of a Uint16 into a * JavaScript Number. * @param {Number} uint16 - a Float16 stored as the bits of a Uint16 diff --git a/tests/wpt/tests/webnn/validation_tests/build-more-than-once.https.any.js b/tests/wpt/tests/webnn/validation_tests/build-more-than-once.https.any.js index 3d648c9b019..405a9acf27f 100644 --- a/tests/wpt/tests/webnn/validation_tests/build-more-than-once.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/build-more-than-once.https.any.js @@ -1,5 +1,5 @@ // META: title=ensure MLMLGraphBuilder may build at most one MLGraph -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/validation_tests/constant-changed-buffer.https.any.js b/tests/wpt/tests/webnn/validation_tests/constant-changed-buffer.https.any.js index b3c8e56046a..d5a827aae75 100644 --- a/tests/wpt/tests/webnn/validation_tests/constant-changed-buffer.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/constant-changed-buffer.https.any.js @@ -1,5 +1,5 @@ // META: title=ensure MLGraphBuilder.constant() handles buffers which change -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/validation_tests/constant.https.any.js b/tests/wpt/tests/webnn/validation_tests/constant.https.any.js index 31a7a676a6b..f9e34ea94ec 100644 --- a/tests/wpt/tests/webnn/validation_tests/constant.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/constant.https.any.js @@ -1,5 +1,5 @@ // META: title=validation tests for WebNN API constant interface -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu @@ -32,7 +32,62 @@ const tests = [ // one by given dimensions } }, - // TODO (crbug.com/329702838): Test building a constant with float16 data type + { + name: '[constant] Test building a constant with float16 data type', + descriptor: {dataType: 'float16', shape: [2, 3]}, + buffer: {type: Float16Array, byteLength: 6 * 2}, + output: {dataType: 'float16', shape: [2, 3]} + }, + { + name: + '[constant] Throw if byte length of float16 buffer doesn\'t match the given dimensions', + descriptor: {dataType: 'float16', shape: [2, 3]}, + buffer: { + type: Float16Array, + byteLength: 6 * 2 - 2 // The buffer's byte length is less than the + // one by given dimensions + } + }, + { + name: + '[constant] Throw if using Float32Array buffer for float16 operand data type', + descriptor: {dataType: 'float16', shape: [2, 3]}, + buffer: { + type: Float32Array, + byteLength: 6 * 4, + }, + viewTestOnly: true + }, + { + name: + '[constant] Throw if using Int16Array buffer for float16 operand data type', + descriptor: {dataType: 'float16', shape: [2, 3]}, + buffer: { + type: Int16Array, + byteLength: 6 * 2, + }, + viewTestOnly: true + }, + + // TODO(crbug.com/399459942): remove below two Uint16Array buffer tests for + // float16 data type when implementation removes it. + { + name: + '[constant] Test building a constant with float16 data type using Uint16Array buffer', + descriptor: {dataType: 'float16', shape: [2, 3]}, + buffer: {type: Uint16Array, byteLength: 6 * 2}, + output: {dataType: 'float16', shape: [2, 3]} + }, + { + name: + '[constant] Throw if byte length of float16 buffer (using Uint16Array buffer) doesn\'t match the given dimensions', + descriptor: {dataType: 'float16', shape: [2, 3]}, + buffer: { + type: Uint16Array, + byteLength: 6 * 2 - 2 // The buffer's byte length is less than the + // one by given dimensions + } + }, { name: '[constant] Test building a constant with int32 data type', descriptor: {dataType: 'int32', shape: [2, 3]}, @@ -116,10 +171,16 @@ const tests = [ }, { name: - '[constant] Throw if buffer view\'s type doesn\'t match the operand data type', + '[constant] Throw if using Int32Array buffer for float32 operand data type', descriptor: {dataType: 'float32', shape: [2, 3]}, buffer: {type: Int32Array, byteLength: 6 * 4}, viewTestOnly: true + }, + { + name: + '[constant] Throw if the operand data type isn\'t of type MLOperandDataType', + descriptor: {dataType: 'int16', shape: [2, 3]}, + buffer: {type: Int16Array, byteLength: 6 * 2} } ]; @@ -128,8 +189,6 @@ tests.forEach( const builder = new MLGraphBuilder(context); const buffer = new ArrayBuffer(test.buffer.byteLength); const bufferView = new test.buffer.type(buffer); - const sharedBuffer = new SharedArrayBuffer(test.buffer.byteLength); - const sharedBufferView = new test.buffer.type(sharedBuffer); if (test.viewTestOnly === undefined || test.viewTestOnly === false) { // Test building constant from ArrayBuffer. @@ -141,15 +200,19 @@ tests.forEach( assert_throws_js( TypeError, () => builder.constant(test.descriptor, buffer)); } - // Test building constant from SharedArrayBuffer. - if (test.output) { - const constantOperand = - builder.constant(test.descriptor, sharedBuffer); - assert_equals(constantOperand.dataType, test.output.dataType); - assert_array_equals(constantOperand.shape, test.output.shape); - } else { - assert_throws_js( - TypeError, () => builder.constant(test.descriptor, sharedBuffer)); + if ('SharedArrayBuffer' in globalThis) { + // Test building constant from SharedArrayBuffer. + const sharedBuffer = new SharedArrayBuffer(test.buffer.byteLength); + if (test.output) { + const constantOperand = + builder.constant(test.descriptor, sharedBuffer); + assert_equals(constantOperand.dataType, test.output.dataType); + assert_array_equals(constantOperand.shape, test.output.shape); + } else { + assert_throws_js( + TypeError, + () => builder.constant(test.descriptor, sharedBuffer)); + } } } @@ -162,15 +225,19 @@ tests.forEach( assert_throws_js( TypeError, () => builder.constant(test.descriptor, bufferView)); } - // Test building constant from shared ArrayBufferView. - if (test.output) { - const constantOperand = - builder.constant(test.descriptor, sharedBufferView); - assert_equals(constantOperand.dataType, test.output.dataType); - assert_array_equals(constantOperand.shape, test.output.shape); - } else { - assert_throws_js( - TypeError, - () => builder.constant(test.descriptor, sharedBufferView)); + if ('SharedArrayBuffer' in globalThis) { + // Test building constant from shared ArrayBufferView. + const sharedBuffer = new SharedArrayBuffer(test.buffer.byteLength); + const sharedBufferView = new test.buffer.type(sharedBuffer); + if (test.output) { + const constantOperand = + builder.constant(test.descriptor, sharedBufferView); + assert_equals(constantOperand.dataType, test.output.dataType); + assert_array_equals(constantOperand.shape, test.output.shape); + } else { + assert_throws_js( + TypeError, + () => builder.constant(test.descriptor, sharedBufferView)); + } } }, test.name)); diff --git a/tests/wpt/tests/webnn/validation_tests/createContext.https.any.js b/tests/wpt/tests/webnn/validation_tests/createContext.https.any.js index 0357c88335f..314f7e3e3c6 100644 --- a/tests/wpt/tests/webnn/validation_tests/createContext.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/createContext.https.any.js @@ -1,5 +1,5 @@ // META: title=validation tests for WebNN API createContext() -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/validation_tests/destroyContext.https.any.js b/tests/wpt/tests/webnn/validation_tests/destroyContext.https.any.js index ba11362564d..03ce62e6996 100644 --- a/tests/wpt/tests/webnn/validation_tests/destroyContext.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/destroyContext.https.any.js @@ -1,6 +1,6 @@ // META: timeout=long // META: title=validation tests for WebNN API MLContext::destroy() -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/validation_tests/destroyGraph.https.any.js b/tests/wpt/tests/webnn/validation_tests/destroyGraph.https.any.js index b77b2ad4e6e..472ffce8c13 100644 --- a/tests/wpt/tests/webnn/validation_tests/destroyGraph.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/destroyGraph.https.any.js @@ -1,6 +1,6 @@ // META: timeout=long // META: title=validation tests for WebNN API MLContext::destroy() -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/validation_tests/input.https.any.js b/tests/wpt/tests/webnn/validation_tests/input.https.any.js index 54f50b146cb..ed30548f9bd 100644 --- a/tests/wpt/tests/webnn/validation_tests/input.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/input.https.any.js @@ -1,5 +1,5 @@ // META: title=validation tests for WebNN API input interface -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/validation_tests/invalid-rank.https.any.js b/tests/wpt/tests/webnn/validation_tests/invalid-rank.https.any.js index 93dfa105c6b..c1f96f99cc0 100644 --- a/tests/wpt/tests/webnn/validation_tests/invalid-rank.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/invalid-rank.https.any.js @@ -1,5 +1,5 @@ // META: title=ensure an MLOperand cannot be created with an invalid rank -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/validation_tests/pooling-and-reduction-keep-dims.https.any.js b/tests/wpt/tests/webnn/validation_tests/pooling-and-reduction-keep-dims.https.any.js index f2264e468d4..da7afc9bce9 100644 --- a/tests/wpt/tests/webnn/validation_tests/pooling-and-reduction-keep-dims.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/pooling-and-reduction-keep-dims.https.any.js @@ -1,5 +1,5 @@ // META: title=validation tests for pooling and reduction operators keep dimensions -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webnn/validation_tests/unprintableNames.https.any.js b/tests/wpt/tests/webnn/validation_tests/unprintableNames.https.any.js index b954f361c0e..c3847d68e3e 100644 --- a/tests/wpt/tests/webnn/validation_tests/unprintableNames.https.any.js +++ b/tests/wpt/tests/webnn/validation_tests/unprintableNames.https.any.js @@ -1,5 +1,5 @@ // META: title=test graph inputs/outputs with unprintable names -// META: global=window,dedicatedworker +// META: global=window,worker // META: variant=?cpu // META: variant=?gpu // META: variant=?npu diff --git a/tests/wpt/tests/webrtc-encoded-transform/tentative/RTCEncodedFrame-timestamps.html b/tests/wpt/tests/webrtc-encoded-transform/tentative/RTCEncodedFrame-timestamps.html index 0ae67a3592c..d5b2a956805 100644 --- a/tests/wpt/tests/webrtc-encoded-transform/tentative/RTCEncodedFrame-timestamps.html +++ b/tests/wpt/tests/webrtc-encoded-transform/tentative/RTCEncodedFrame-timestamps.html @@ -117,4 +117,44 @@ promise_test(async t => { return workerPromise; }, 'captureTime and senderCaptureTimeOffset not present in audio receiver if extension not used'); +promise_test(async t => { + const worker = new Worker(`data:text/javascript,(${doWorkExpectingCaptureTimestamps.toString()})()`); + const workerPromise = new Promise((resolve, reject) => { + worker.onmessage = t.step_func(message => { + if (message.data == "OK") { + resolve(); + } else { + reject(message.data); + } + }); + }); + + await initiateCall( + t, /*streamOptions=*/{audio: false, video: true}, + /*enableAbsCaptureTime=*/true, worker, /*enableSenderTransform=*/false, + /*enableReceiverTransform=*/true); + + return workerPromise; +}, 'captureTime and senderCaptureTimeOffset present in video receiver if extension is used'); + +promise_test(async t => { + const worker = new Worker(`data:text/javascript,(${doWorkExpectingNoCaptureTimestamps.toString()})()`); + const workerPromise = new Promise((resolve, reject) => { + worker.onmessage = t.step_func(message => { + if (message.data == "OK") { + resolve(); + } else { + reject(message.data); + } + }); + }); + + await initiateCall( + t, /*streamOptions=*/{audio: false, video: true}, + /*enableAbsCaptureTime=*/false, worker, /*enableSenderTransform=*/false, + /*enableReceiverTransform=*/true); + + return workerPromise; +}, 'captureTime and senderCaptureTimeOffset not present in video receiver if extension not used'); + </script> diff --git a/tests/wpt/tests/webrtc-stats/getStats-remote-candidate-address.html b/tests/wpt/tests/webrtc-stats/getStats-remote-candidate-address.html index d30f2252bf2..add679044c7 100644 --- a/tests/wpt/tests/webrtc-stats/getStats-remote-candidate-address.html +++ b/tests/wpt/tests/webrtc-stats/getStats-remote-candidate-address.html @@ -5,8 +5,6 @@ <script src="/resources/testharnessreport.js"></script> <script src="../webrtc/RTCPeerConnection-helper.js"></script> <script> - 'use strict'; - promise_test(async (test) => { const localPc = new RTCPeerConnection(); test.add_cleanup(() => localPc.close()); @@ -39,7 +37,6 @@ promise_test(async (test) => { assert_equals(remoteCandidateStats.address, null, "address should be null"); }, "Do not expose in stats remote addresses that are not known to be already exposed to JS"); - promise_test(async (test) => { const localPc = new RTCPeerConnection(); test.add_cleanup(() => localPc.close()); diff --git a/tests/wpt/tests/webrtc-stats/getStats-remote-candidate-ufrag.html b/tests/wpt/tests/webrtc-stats/getStats-remote-candidate-ufrag.html new file mode 100644 index 00000000000..df3ddb2bfd2 --- /dev/null +++ b/tests/wpt/tests/webrtc-stats/getStats-remote-candidate-ufrag.html @@ -0,0 +1,37 @@ +<!doctype html> +<meta charset=utf-8> +<title>Exposure of remote candidate ufrag on stats</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../webrtc/RTCPeerConnection-helper.js"></script> +<script> +promise_test(async (test) => { + const localPc = new RTCPeerConnection(); + test.add_cleanup(() => localPc.close()); + const remotePc = new RTCPeerConnection(); + test.add_cleanup(() => remotePc.close()); + + const localDataChannel = localPc.createDataChannel('test'); + localPc.addEventListener('icecandidate', event => { + remotePc.addIceCandidate(event.candidate); + }); + await localPc.setLocalDescription(); + await remotePc.setRemoteDescription(localPc.localDescription); + const answer = await remotePc.createAnswer(); + await remotePc.setLocalDescription(answer); + + await waitForIceStateChange(remotePc, ['connected', 'completed']); + + const remoteCandidateStats = [...(await localPc.getStats()).values()].find(({type}) => type === 'remote-candidate'); + assert_equals(remoteCandidateStats.candidateType, 'prflx', 'candidateType should be `prflx`'); + assert_equals(remoteCandidateStats.usernameFragment, undefined, 'usernameFragment should be undefined'); + + await localPc.setRemoteDescription(answer); + await new Promise(r => test.step_timeout(r, 100)); + + const remoteCandidateStats2 = [...(await localPc.getStats()).values()].find(({type}) => type === 'remote-candidate'); + // candidateType is still prflx since the candidate was not signaled. + assert_equals(remoteCandidateStats.candidateType, 'prflx', 'candidateType should be `prflx`'); + assert_not_equals(remoteCandidateStats2.usernameFragment, undefined, 'usernameFragment should not be undefined after signaling'); +}, 'Do not expose in stats remote ufrags that are not known via signaling'); +</script> diff --git a/tests/wpt/tests/webrtc/RTCPeerConnection-addIceCandidate.html b/tests/wpt/tests/webrtc/RTCPeerConnection-addIceCandidate.html index d8e24d608ba..618ef7e33c6 100644 --- a/tests/wpt/tests/webrtc/RTCPeerConnection-addIceCandidate.html +++ b/tests/wpt/tests/webrtc/RTCPeerConnection-addIceCandidate.html @@ -138,6 +138,19 @@ a=rtcp-rsize })); }, 'Add ICE candidate before setting remote description should reject with InvalidStateError'); + promise_test(t => { + const pc = new RTCPeerConnection(); + pc.setRemoteDescription(sessionDesc); + pc.close(); + return promise_rejects_dom(t, 'InvalidStateError', + pc.addIceCandidate({ + candidate: candidateStr1, + sdpMid: sdpMid1, + sdpMLineIndex: sdpMLineIndex1, + usernameFragment: usernameFragment1 + })); + }, 'addIceCandidate after close should reject with InvalidStateError'); + /* Success cases */ diff --git a/tests/wpt/tests/webrtc/RTCPeerConnection-getStats.https.html b/tests/wpt/tests/webrtc/RTCPeerConnection-getStats.https.html index 85ce8bc9f55..dceca74d4f1 100644 --- a/tests/wpt/tests/webrtc/RTCPeerConnection-getStats.https.html +++ b/tests/wpt/tests/webrtc/RTCPeerConnection-getStats.https.html @@ -271,4 +271,10 @@ maximumTimeElapsedBetweenGetStatsCallsMs); }, `RTCStats.timestamp increases with time passing`); + promise_test(async t => { + const pc1 = new RTCPeerConnection(); + pc1.close(); + await pc1.getStats(); + }, 'getStats succeeds on a closed peerconnection'); + </script> diff --git a/tests/wpt/tests/webrtc/RTCPeerConnection-mandatory-getStats.https.html b/tests/wpt/tests/webrtc/RTCPeerConnection-mandatory-getStats.https.html index ba04a454691..9229f3be4c7 100644 --- a/tests/wpt/tests/webrtc/RTCPeerConnection-mandatory-getStats.https.html +++ b/tests/wpt/tests/webrtc/RTCPeerConnection-mandatory-getStats.https.html @@ -115,7 +115,8 @@ const mandatory = { "port", "protocol", "candidateType", - "url", + /* url requires a STUN or TURN server so is not testable. */ + // "url", ], RTCCertificateStats: [ "fingerprint", diff --git a/tests/wpt/tests/webrtc/RTCRtpReceiver-video-anyCodec.html b/tests/wpt/tests/webrtc/RTCRtpReceiver-video-anyCodec.html new file mode 100644 index 00000000000..4a32ce98854 --- /dev/null +++ b/tests/wpt/tests/webrtc/RTCRtpReceiver-video-anyCodec.html @@ -0,0 +1,101 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Tests that RTCRtpReceiver is prepared to receive any negotiated video codec</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/webrtc/RTCPeerConnection-helper.js"></script> +<script src="/webrtc/third_party/sdp/sdp.js"></script> +<body> +<script> +'use strict' + + function filterOnlySecondaryCodec(description) { + const sections = SDPUtils.splitSections(description.sdp); + const dtls = SDPUtils.getDtlsParameters(sections[1], sections[0]); + const ice = SDPUtils.getIceParameters(sections[1], sections[0]); + const rtpParameters = SDPUtils.parseRtpParameters(sections[1]); + const setupValue = SDPUtils.matchPrefix(description.sdp, 'a=setup:')[0].substring(8); + const mline = SDPUtils.parseMLine(sections[1]); + + // Of all the codecs in the description, filter out one that has multiple + // payload types, and use only one of those payload types that is not the + // preferred codec. + // + // Ideally this would test all PTs through RTCRtpSender.setParameters, but + // Firefox does not at this time support RTCRtpEncodingParameters.codec: + // https://bugzilla.mozilla.org/show_bug.cgi?id=1894137 + const codecs = {}; + for (const codec of rtpParameters.codecs) { + if (["RED", "RTX", "ULPFEC"].includes(codec.name.toUpperCase())) { + continue; + } + codecs[codec.name] ??= []; + codecs[codec.name].push(codec); + } + + const multipleCodecs = []; + for (const name of Object.keys(codecs)) { + if (codecs[name].length > 1) { + multipleCodecs.push(codecs[name]); + } + } + + assert_implements_optional(multipleCodecs.length > 0, 'No codec with multiple payload types'); + + const multiplePtsCodecs = multipleCodecs[0]; + const nonPreferredCodec = multiplePtsCodecs[1]; + rtpParameters.codecs = [nonPreferredCodec]; + + return SDPUtils.writeSessionBoilerplate() + + SDPUtils.writeDtlsParameters(dtls, setupValue) + + SDPUtils.writeIceParameters(ice) + + SDPUtils.writeRtpDescription(mline.kind, rtpParameters); + } + + promise_test(async t => { + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + const pc2 = new RTCPeerConnection(); + t.add_cleanup(() => pc2.close()); + pc1.onicecandidate = ({candidate}) => pc2.addIceCandidate(candidate); + pc2.onicecandidate = ({candidate}) => pc1.addIceCandidate(candidate); + + const [track] = (await getNoiseStream({video: true})).getTracks(); + t.add_cleanup(() => track.stop()); + pc1.addTrack(track); + + await pc1.setLocalDescription(); + await pc2.setRemoteDescription(pc1.localDescription); + await pc2.setLocalDescription(); + + const nonPreferredAnswer = {type: 'answer', sdp: filterOnlySecondaryCodec(pc2.localDescription)}; + await pc1.setRemoteDescription(nonPreferredAnswer); + + // Verify that the right payloadType is sent, *and* received. + const start = performance.now(); + const timeoutThreshold = start + 5000; + while (true) { + const stats = [...(await pc1.getStats()).values()].find(({type}) => type === 'outbound-rtp'); + if (stats?.framesSent > 0) { + break; + } + if (performance.now() > timeoutThreshold) { + assert_unreached("Timed out waiting for sent frames"); + } + await new Promise(r => t.step_timeout(r, 100)); + } + + while (true) { + const stats = [...(await pc2.getStats()).values()].find(({type}) => type === 'inbound-rtp'); + if (stats?.framesReceived > 0) { + break; + } + if (performance.now() > timeoutThreshold) { + assert_unreached("Timed out waiting for received frames"); + } + await new Promise(r => t.step_timeout(r, 100)); + } + }, 'An RTCRtpReceiver is prepared to receive any negotiated codec.'); + +</script> +</body> diff --git a/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/portrait-ref.tentative.html b/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/portrait-ref.tentative.html new file mode 100644 index 00000000000..0cdce1ddab6 --- /dev/null +++ b/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/portrait-ref.tentative.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<title>Reference for WebVTT rendering, portrait video</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<style> +html { overflow:hidden } +body { margin:0 } +.video { + display: inline-block; + width: 180px; + height: 320px; + position: relative; + /* Tentative: https://github.com/w3c/webvtt/issues/529 proposes to make + this 9px as based on 5vmin insteaed of 16px if it was based on 5vh. */ + font-size: 9px; +} +.cue { + position: absolute; + bottom: 0; + left: 0; + right: 0; + text-align: center +} +.cue > span { + font-family: Ahem, sans-serif; + background: rgba(0,0,0,0.8); + color: green; +} +</style> +<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div> diff --git a/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/portrait.tentative.html b/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/portrait.tentative.html new file mode 100644 index 00000000000..dfa07630f9e --- /dev/null +++ b/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/portrait.tentative.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<title>WebVTT rendering, portrait videos</title> +<link rel="match" href="portrait-ref.tentative.html"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<style> +html { overflow:hidden } +body { margin:0 } +::cue { + font-family: Ahem, sans-serif; + color: green +} +</style> +<script src="/common/reftest-wait.js"></script> +<video width="180" height="320" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();"> + <source src="/media/white.webm" type="video/webm"> + <source src="/media/white.mp4" type="video/mp4"> + <track src="support/test.vtt"> + <script> + document.getElementsByTagName('track')[0].track.mode = 'showing'; + </script> +</video> +</html> diff --git a/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/fontsize_smaller_than_container-ref.tentative.html b/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/fontsize_smaller_than_container-ref.tentative.html new file mode 100644 index 00000000000..c17f6e89610 --- /dev/null +++ b/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/fontsize_smaller_than_container-ref.tentative.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<title>Reference for WebVTT rendering, ::cue, smaller font-size than container</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<style> +html { overflow:hidden } +body { margin:0 } +.video { + display: inline-block; + width: 320px; + height: 320px; + position: relative; + /* Tentative: https://github.com/w3c/webvtt/issues/530 proposes to make + this 0. It is 9px for now for practical reasons, as as change affects + all other tests. */ + font-size: 9px; +} +.cue { + position: absolute; + bottom: 0; + left: 0; + right: 0; + text-align: center; +} +.cueText { + font-family: Ahem, sans-serif; + background: rgba(0,0,0,0.8); + color: green; + font-size: 4px; +} +</style> +<div class="video"> + <span class="cue"> + <div><span class="cueText">This is another test subtitle</span></div> + <div><span class="cueText">This is a test subtitle</span></div> + </span> +</div> diff --git a/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/fontsize_smaller_than_container.tentative.html b/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/fontsize_smaller_than_container.tentative.html new file mode 100644 index 00000000000..bfc7e14ba14 --- /dev/null +++ b/tests/wpt/tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/fontsize_smaller_than_container.tentative.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<title>WebVTT rendering, ::cue, smaller font-size than container</title> +<link rel="match" href="fontsize_smaller_than_container-ref.tentative.html"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<style> +html { overflow:hidden } +body { margin:0 } +::cue { + font-family: Ahem, sans-serif; + color: green; + font-size: 4px; +} +</style> +<script src="/common/reftest-wait.js"></script> +<video width="320" height="320" autoplay onplaying="this.onplaying = null; this.pause(); this.currentTime = 2;" onseeked="this.onseeked = null; takeScreenshot();"> + <source src="/media/white.webm" type="video/webm"> + <source src="/media/white.mp4" type="video/mp4"> + <track src="../../support/2_cues_overlapping_completely_move_up.vtt"> + <script> + document.getElementsByTagName('track')[0].track.mode = 'showing'; + </script> +</video> +</html> |