aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2018-04-03 03:54:22 -0400
committerGitHub <noreply@github.com>2018-04-03 03:54:22 -0400
commit20db733f8efa8effdfd128e98fcc7b1310fb533a (patch)
treeece74924e4ecb3f9d27b72a874bbbda4f20edd48
parent0a3ffc0c6045eb6983273010d91a35267d8ec3fa (diff)
parent04276c4e1fcf360f02da9b7ded5b0632af1ea807 (diff)
downloadservo-20db733f8efa8effdfd128e98fcc7b1310fb533a.tar.gz
servo-20db733f8efa8effdfd128e98fcc7b1310fb533a.zip
Auto merge of #20510 - servo-wpt-sync:wpt_update_02-04-2018, r=jdm
Sync WPT with upstream (02-04-2018) Automated downstream sync of changes from upstream as of 02-04-2018. [no-wpt-sync] <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20510) <!-- Reviewable:end -->
-rw-r--r--tests/wpt/metadata/MANIFEST.json736
-rw-r--r--tests/wpt/metadata/css/css-values/vh_not_refreshing_on_chrome.html.ini2
-rw-r--r--tests/wpt/metadata/fetch/corb/img-mime-types-coverage.tentative.sub.html.ini4
-rw-r--r--tests/wpt/metadata/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html.ini5
-rw-r--r--tests/wpt/metadata/fetch/nosniff/image.html.ini4
-rw-r--r--tests/wpt/metadata/html/dom/dynamic-markup-insertion/opening-the-input-stream/010.html.ini4
-rw-r--r--tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/context/context-release-with-workers.html.ini5
-rw-r--r--tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/ogles/GL/atan/atan_001_to_008.html.ini5
-rw-r--r--tests/wpt/web-platform-tests/README.md2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/README.md26
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/observation.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html12
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/ordering.tentative.https.html8
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js1114
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/cookie-test-helpers.js (renamed from tests/wpt/web-platform-tests/cookie-store/resources/testharness-helpers.js)220
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/delete_cookies.js44
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/document_cookie.js43
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/expiration.js89
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/get_set_get_all.js74
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/http_cookie_and_set_cookie_headers.js112
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/no_name_and_no_value.js45
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/no_name_equals_in_value.js46
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/no_name_multiple_values.js38
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/one_simple_origin_cookie.js57
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/ordering.js41
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/secure_cookies.js46
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/secure_cookies.tentative.html8
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/secure_cookies.tentative.https.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-001.html95
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-002.html95
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-001.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-002.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-001.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-002.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-001.html95
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-002.html95
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-001.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-002.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-001.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-002.html96
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html3
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-registry/upgrade.html13
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children.html24
-rw-r--r--tests/wpt/web-platform-tests/fetch/corb/img-mime-types-coverage.tentative.sub.html75
-rw-r--r--tests/wpt/web-platform-tests/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html24
-rw-r--r--tests/wpt/web-platform-tests/fetch/nosniff/image.html14
-rw-r--r--tests/wpt/web-platform-tests/fetch/nosniff/resources/image.py8
-rw-r--r--tests/wpt/web-platform-tests/images/green-96x96.svg3
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-xhr-sync-on-worker.https.html41
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-sync-on-worker-worker.js41
94 files changed, 2580 insertions, 2208 deletions
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index a64769ab73b..fc18aa9789c 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -214114,7 +214114,7 @@
{}
]
],
- "cookie-store/resources/cookie-store-tests.js": [
+ "cookie-store/resources/cookie-test-helpers.js": [
[
{}
]
@@ -214124,7 +214124,57 @@
{}
]
],
- "cookie-store/resources/testharness-helpers.js": [
+ "cookie-store/resources/delete_cookies.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/document_cookie.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/expiration.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/get_set_get_all.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/http_cookie_and_set_cookie_headers.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/no_name_and_no_value.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/no_name_equals_in_value.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/no_name_multiple_values.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/one_simple_origin_cookie.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/ordering.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/resources/secure_cookies.js": [
[
{}
]
@@ -285429,6 +285479,11 @@
{}
]
],
+ "images/green-96x96.svg": [
+ [
+ {}
+ ]
+ ],
"images/green.png": [
[
{}
@@ -292664,6 +292719,11 @@
{}
]
],
+ "service-workers/service-worker/resources/fetch-request-xhr-sync-on-worker-worker.js": [
+ [
+ {}
+ ]
+ ],
"service-workers/service-worker/resources/fetch-request-xhr-sync-worker.js": [
[
{}
@@ -311250,100 +311310,28 @@
{}
]
],
- "cookie-store/cookie_store_tests.tentative.html": [
- [
- "/cookie-store/cookie_store_tests.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/cookie_store_tests.tentative.https.html": [
- [
- "/cookie-store/cookie_store_tests.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/cookie_store_tests_static.tentative.html": [
- [
- "/cookie-store/cookie_store_tests_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/cookie_store_tests_static.tentative.https.html": [
- [
- "/cookie-store/cookie_store_tests_static.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
"cookie-store/delete_cookies.tentative.html": [
[
"/cookie-store/delete_cookies.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/delete_cookies.tentative.https.html": [
[
"/cookie-store/delete_cookies.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/delete_cookies_static.tentative.html": [
- [
- "/cookie-store/delete_cookies_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/delete_cookies_static.tentative.https.html": [
- [
- "/cookie-store/delete_cookies_static.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/document_cookie.tentative.html": [
[
"/cookie-store/document_cookie.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/document_cookie.tentative.https.html": [
[
"/cookie-store/document_cookie.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/document_cookie_static.tentative.html": [
- [
- "/cookie-store/document_cookie_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/document_cookie_static.tentative.https.html": [
- [
- "/cookie-store/document_cookie_static.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/document_getAll_multiple.tentative.html": [
@@ -311355,81 +311343,37 @@
"cookie-store/expiration.tentative.html": [
[
"/cookie-store/expiration.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/expiration.tentative.https.html": [
[
"/cookie-store/expiration.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/expiration_static.tentative.html": [
- [
- "/cookie-store/expiration_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/expiration_static.tentative.https.html": [
- [
- "/cookie-store/expiration_static.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/get_set_get_all.tentative.html": [
[
"/cookie-store/get_set_get_all.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/get_set_get_all.tentative.https.html": [
[
"/cookie-store/get_set_get_all.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/get_set_get_all_static.tentative.html": [
- [
- "/cookie-store/get_set_get_all_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/get_set_get_all_static.tentative.https.html": [
- [
- "/cookie-store/get_set_get_all_static.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/http_cookie_and_set_cookie_headers.tentative.html": [
[
"/cookie-store/http_cookie_and_set_cookie_headers.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html": [
[
"/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/idlharness.tentative.html": [
@@ -311444,196 +311388,70 @@
{}
]
],
- "cookie-store/meta_http_equiv_set_cookie.tentative.html": [
- [
- "/cookie-store/meta_http_equiv_set_cookie.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/meta_http_equiv_set_cookie.tentative.https.html": [
- [
- "/cookie-store/meta_http_equiv_set_cookie.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/meta_http_equiv_set_cookie_static.tentative.html": [
- [
- "/cookie-store/meta_http_equiv_set_cookie_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html": [
- [
- "/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
"cookie-store/no_name_and_no_value.tentative.html": [
[
"/cookie-store/no_name_and_no_value.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/no_name_and_no_value.tentative.https.html": [
[
"/cookie-store/no_name_and_no_value.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/no_name_and_no_value_static.tentative.html": [
- [
- "/cookie-store/no_name_and_no_value_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/no_name_and_no_value_static.tentative.https.html": [
- [
- "/cookie-store/no_name_and_no_value_static.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/no_name_equals_in_value.tentative.html": [
[
"/cookie-store/no_name_equals_in_value.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/no_name_equals_in_value.tentative.https.html": [
[
"/cookie-store/no_name_equals_in_value.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/no_name_equals_in_value_static.tentative.html": [
- [
- "/cookie-store/no_name_equals_in_value_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/no_name_equals_in_value_static.tentative.https.html": [
- [
- "/cookie-store/no_name_equals_in_value_static.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/no_name_multiple_values.tentative.html": [
[
"/cookie-store/no_name_multiple_values.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/no_name_multiple_values.tentative.https.html": [
[
"/cookie-store/no_name_multiple_values.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/no_name_multiple_values_static.tentative.html": [
- [
- "/cookie-store/no_name_multiple_values_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/no_name_multiple_values_static.tentative.https.html": [
- [
- "/cookie-store/no_name_multiple_values_static.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/observation.tentative.html": [
- [
- "/cookie-store/observation.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/observation.tentative.https.html": [
- [
- "/cookie-store/observation.tentative.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/observation_static.tentative.html": [
- [
- "/cookie-store/observation_static.tentative.html",
- {
- "timeout": "long"
- }
- ]
- ],
- "cookie-store/observation_static.tentative.https.html": [
- [
- "/cookie-store/observation_static.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/one_simple_origin_cookie.tentative.html": [
[
"/cookie-store/one_simple_origin_cookie.tentative.html",
- {
- "timeout": "long"
- }
+ {}
]
],
"cookie-store/one_simple_origin_cookie.tentative.https.html": [
[
"/cookie-store/one_simple_origin_cookie.tentative.https.html",
- {
- "timeout": "long"
- }
+ {}
]
],
- "cookie-store/one_simple_origin_cookie_static.tentative.html": [
+ "cookie-store/ordering.tentative.https.html": [
[
- "/cookie-store/one_simple_origin_cookie_static.tentative.html",
- {
- "timeout": "long"
- }
+ "/cookie-store/ordering.tentative.https.html",
+ {}
]
],
- "cookie-store/one_simple_origin_cookie_static.tentative.https.html": [
+ "cookie-store/secure_cookies.tentative.html": [
[
- "/cookie-store/one_simple_origin_cookie_static.tentative.https.html",
- {
- "timeout": "long"
- }
+ "/cookie-store/secure_cookies.tentative.html",
+ {}
+ ]
+ ],
+ "cookie-store/secure_cookies.tentative.https.html": [
+ [
+ "/cookie-store/secure_cookies.tentative.https.html",
+ {}
]
],
"cookie-store/serviceworker_cookieStore_arguments.tentative.https.html": [
@@ -314276,6 +314094,78 @@
{}
]
],
+ "css/css-grid/grid-items/grid-items-percentage-margins-001.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-margins-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-002.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-margins-002.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-001.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-002.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-002.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-001.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-002.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-002.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-001.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-paddings-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-002.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-paddings-002.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-001.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-002.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-002.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-001.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-002.html": [
+ [
+ "/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-002.html",
+ {}
+ ]
+ ],
"css/css-grid/grid-items/grid-minimum-size-grid-items-021.html": [
[
"/css/css-grid/grid-items/grid-minimum-size-grid-items-021.html",
@@ -326298,6 +326188,18 @@
{}
]
],
+ "fetch/corb/img-mime-types-coverage.tentative.sub.html": [
+ [
+ "/fetch/corb/img-mime-types-coverage.tentative.sub.html",
+ {}
+ ]
+ ],
+ "fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html": [
+ [
+ "/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html",
+ {}
+ ]
+ ],
"fetch/corb/script-html-correctly-labeled.tentative.sub.html": [
[
"/fetch/corb/script-html-correctly-labeled.tentative.sub.html",
@@ -361346,6 +361248,12 @@
{}
]
],
+ "service-workers/service-worker/fetch-request-xhr-sync-on-worker.https.html": [
+ [
+ "/service-workers/service-worker/fetch-request-xhr-sync-on-worker.https.html",
+ {}
+ ]
+ ],
"service-workers/service-worker/fetch-request-xhr-sync.https.html": [
[
"/service-workers/service-worker/fetch-request-xhr-sync.https.html",
@@ -392160,7 +392068,7 @@
"support"
],
"./README.md": [
- "23780fdf7eea63c82965c8d5d4d847c0b9752c7e",
+ "4efe0e6f320c51a8e67d04b52f14c0b0ef167432",
"support"
],
"./check_stability.ini": [
@@ -423184,7 +423092,7 @@
"support"
],
"cookie-store/README.md": [
- "f2c101203c2a2d82a4191164943e79734530d124",
+ "40595162d15dec7e315ef16f94646045596d7b1c",
"support"
],
"cookie-store/cookieStore_delete_arguments.tentative.window.js": [
@@ -423247,52 +423155,20 @@
"d1cfe7619cc915b17dbf4d358363b16ec8ba9666",
"testharness"
],
- "cookie-store/cookie_store_tests.tentative.html": [
- "245e7096ba810ae0c2311a801845ce0355f1ff75",
- "testharness"
- ],
- "cookie-store/cookie_store_tests.tentative.https.html": [
- "80e5f99d4e0b66f2d610c1f2826cb4553d532676",
- "testharness"
- ],
- "cookie-store/cookie_store_tests_static.tentative.html": [
- "4c02698eec209e52ba2203f9e0a82d84a029ee0f",
- "testharness"
- ],
- "cookie-store/cookie_store_tests_static.tentative.https.html": [
- "3ab3e4103cc30105fbab3db789891309d0e76428",
- "testharness"
- ],
"cookie-store/delete_cookies.tentative.html": [
- "0ca53252ef4ee4609613775229d3365ad1ffeafc",
+ "9ad9854eb07172eab8103a4131baf0817a926e16",
"testharness"
],
"cookie-store/delete_cookies.tentative.https.html": [
- "5c5323abea15eb3649fa9b8ccc5075964bcf157b",
- "testharness"
- ],
- "cookie-store/delete_cookies_static.tentative.html": [
- "c2869a65f9ca8834e8b3e463ace14e651bafd4aa",
- "testharness"
- ],
- "cookie-store/delete_cookies_static.tentative.https.html": [
- "77f4da0946bbe53224a33014dd17216fdd20a07d",
+ "69d05ab73a4692a08aa33ac20aa43cd1f6bb4e52",
"testharness"
],
"cookie-store/document_cookie.tentative.html": [
- "6664e739c03c46c164cfc5dbfdb786123417e5a8",
+ "23916c5325b2c98875eac4ab7291622b44974daf",
"testharness"
],
"cookie-store/document_cookie.tentative.https.html": [
- "a51cc13bdb5b92a535fee3fec1b130e3b27cbcba",
- "testharness"
- ],
- "cookie-store/document_cookie_static.tentative.html": [
- "1ea750d2ba36d4f90e2c586f3ead9d80d8b353ac",
- "testharness"
- ],
- "cookie-store/document_cookie_static.tentative.https.html": [
- "fbd6d1a628df1b8afa6941f2279697ff0a2677a8",
+ "447ba96e7bb23a0def44817e584891097bb81998",
"testharness"
],
"cookie-store/document_getAll_multiple.tentative.html": [
@@ -423300,43 +423176,27 @@
"testharness"
],
"cookie-store/expiration.tentative.html": [
- "9bfb18862c9b9f6ace5f97ceb4f9d1da15eed64d",
+ "a4e8764c12e39068a4008ad0f12c982540565dbf",
"testharness"
],
"cookie-store/expiration.tentative.https.html": [
- "8f1aaa4a1b0ebf0c99f6d92f1e70e02d9a23c249",
- "testharness"
- ],
- "cookie-store/expiration_static.tentative.html": [
- "7a308f48f5c51ddf4df04069259f7d3feff4cc8e",
- "testharness"
- ],
- "cookie-store/expiration_static.tentative.https.html": [
- "d708add276da0fc58b6b628f05bacaa2965795ca",
+ "fff43dd4b66455e493c06d2a1e98333e8e9b2437",
"testharness"
],
"cookie-store/get_set_get_all.tentative.html": [
- "dc66cbf2b2a939179cae29aaeb39cb44eb488e2a",
+ "89c72f73d511ab3510653baebb7c77aab6441f35",
"testharness"
],
"cookie-store/get_set_get_all.tentative.https.html": [
- "8359d66bc5de963f57596033d29eca513f30ef79",
- "testharness"
- ],
- "cookie-store/get_set_get_all_static.tentative.html": [
- "17f09f2aa4f41bdfc7e0541309ea36b6af232380",
- "testharness"
- ],
- "cookie-store/get_set_get_all_static.tentative.https.html": [
- "d8f03ba31699bfad79e4d4870208fa3ad94c261a",
+ "e2164c6e423724be2f91d47c0fa4931944ebff4f",
"testharness"
],
"cookie-store/http_cookie_and_set_cookie_headers.tentative.html": [
- "42c03466979c5e6d94803d5e69b6c07a595e9728",
+ "7fb04dc519bafed5f35493f65664b51e23131a1d",
"testharness"
],
"cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html": [
- "11c763dd1b7b3a1bff14b9f65538fb33ca97b81b",
+ "2ccfc03ad6fedb063e2cd3ff9726b8d482ab5cf0",
"testharness"
],
"cookie-store/idlharness.tentative.html": [
@@ -423351,114 +423211,102 @@
"0c8a1302ab1839cab71c87db2bda1ca6abcb6a23",
"testharness"
],
- "cookie-store/meta_http_equiv_set_cookie.tentative.html": [
- "6b7dc5aaa1f3c765c45886017163b70520e5f367",
- "testharness"
- ],
- "cookie-store/meta_http_equiv_set_cookie.tentative.https.html": [
- "c1d942ff3fb24b77fd659f9e60bd385bbbfe2279",
- "testharness"
- ],
- "cookie-store/meta_http_equiv_set_cookie_static.tentative.html": [
- "991dae7d02c9c1f03842bd9f43fdc21bfbf9f261",
- "testharness"
- ],
- "cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html": [
- "36d0c3672f44335eb6a0a294b55cf61b9efecd03",
- "testharness"
- ],
"cookie-store/no_name_and_no_value.tentative.html": [
- "634ceaac54e40d7227772abb097f029ce901876b",
+ "da68f9d93ef6f0f91da4827240e32a1e93a8df73",
"testharness"
],
"cookie-store/no_name_and_no_value.tentative.https.html": [
- "c943068f523d6345abfeec24135438fc88fad8de",
- "testharness"
- ],
- "cookie-store/no_name_and_no_value_static.tentative.html": [
- "073a939169dafa7685c02ebdd51653d8f5c49df5",
- "testharness"
- ],
- "cookie-store/no_name_and_no_value_static.tentative.https.html": [
- "a67b186ef0d5393c0bcf8dab8870a76384e14bcf",
+ "61cfa6f1e5ee1e9165dcc16e32486660a1da9c42",
"testharness"
],
"cookie-store/no_name_equals_in_value.tentative.html": [
- "22273b9be0e44dc35a59b701733265d8f538aeb1",
+ "07d5e9462c4395002f23aa4aaf25ae795f9f2452",
"testharness"
],
"cookie-store/no_name_equals_in_value.tentative.https.html": [
- "351b8ac618717bb7a8205cee65678a72a7df7450",
- "testharness"
- ],
- "cookie-store/no_name_equals_in_value_static.tentative.html": [
- "84f03808a8c20ed1809c682982719c5fab1d6b34",
- "testharness"
- ],
- "cookie-store/no_name_equals_in_value_static.tentative.https.html": [
- "cb98e1c8c370e1415dd51cec75be7c4f1c933a18",
+ "61e7a3cc1f5b197d924c76098b66979d00444012",
"testharness"
],
"cookie-store/no_name_multiple_values.tentative.html": [
- "864d3955cf9a92ec4bddf00b19fdb471c691e3cd",
+ "edab422cf19fcdb906e20dcba9dc4a90dde41415",
"testharness"
],
"cookie-store/no_name_multiple_values.tentative.https.html": [
- "e4671297e2474c38e73cd76268f7cdd53eb46b28",
+ "aa3ed15714a1ed2b7cac4ba2fc7998d9792b7339",
"testharness"
],
- "cookie-store/no_name_multiple_values_static.tentative.html": [
- "2bb6d547e7ac220a1c36172dfd2c59e36b49c520",
+ "cookie-store/one_simple_origin_cookie.tentative.html": [
+ "1ba5278aa3725c8e27bb486388b5456045f735a0",
"testharness"
],
- "cookie-store/no_name_multiple_values_static.tentative.https.html": [
- "e10639064527c376420fb51cc5ef5137069dec7b",
+ "cookie-store/one_simple_origin_cookie.tentative.https.html": [
+ "e86d324bf8a771b7f7deb6c4e2e64da088baef69",
"testharness"
],
- "cookie-store/observation.tentative.html": [
- "e0029a6a2cbe1e696cc3afeae9c30b245218d672",
+ "cookie-store/ordering.tentative.https.html": [
+ "e40eb0cdca00826731e9242682105b76baea9a03",
"testharness"
],
- "cookie-store/observation.tentative.https.html": [
- "954a81b8bac1fae57b8074ca3f15210806622bfb",
- "testharness"
+ "cookie-store/resources/cookie-test-helpers.js": [
+ "09f5e60fc4b96a0cdb51b69a1c622c3898ad5568",
+ "support"
],
- "cookie-store/observation_static.tentative.html": [
- "8f6c1a6cc4e671162c6aa7d26d829dc9866d69bd",
- "testharness"
+ "cookie-store/resources/cookie_helper.py": [
+ "4b95a4012e36cacceb6737f751e99634bd7326b9",
+ "support"
],
- "cookie-store/observation_static.tentative.https.html": [
- "007ec0bb007aa3b2d6855e9364ea0d8e269999a2",
- "testharness"
+ "cookie-store/resources/delete_cookies.js": [
+ "f698e4dcc887b7e6d231fa0e8aa2aba58c3bda73",
+ "support"
],
- "cookie-store/one_simple_origin_cookie.tentative.html": [
- "f96fb6627746fd1e586d959249b28886ea8ba504",
- "testharness"
+ "cookie-store/resources/document_cookie.js": [
+ "b34ad56a2afd7f52c52dd0777b15eac2d77c4856",
+ "support"
],
- "cookie-store/one_simple_origin_cookie.tentative.https.html": [
- "b31ea6c06f2e5ecaabdaa3e28efef0e012a65cb4",
- "testharness"
+ "cookie-store/resources/expiration.js": [
+ "483b923b03a0a0787b73118fd3f3b9f5d269f5ae",
+ "support"
],
- "cookie-store/one_simple_origin_cookie_static.tentative.html": [
- "d9064910e2771a2ea5337f5470299c71d831b62a",
- "testharness"
+ "cookie-store/resources/get_set_get_all.js": [
+ "235f22721a73a617d0b14068c8e639e93232526a",
+ "support"
],
- "cookie-store/one_simple_origin_cookie_static.tentative.https.html": [
- "15449e84b8a2854243b0efabca7e893d1ab427dd",
- "testharness"
+ "cookie-store/resources/http_cookie_and_set_cookie_headers.js": [
+ "12e0d0f889bbc298e47c2450b20df0fe86ffb566",
+ "support"
],
- "cookie-store/resources/cookie-store-tests.js": [
- "5f314a536820d78418a558e588af478154e33369",
+ "cookie-store/resources/no_name_and_no_value.js": [
+ "907b6f8568f43f6f41fcaa3ec6876a512bcf6fec",
"support"
],
- "cookie-store/resources/cookie_helper.py": [
- "4b95a4012e36cacceb6737f751e99634bd7326b9",
+ "cookie-store/resources/no_name_equals_in_value.js": [
+ "37b510261b203717fccaf6917c38ea3d0f24151f",
+ "support"
+ ],
+ "cookie-store/resources/no_name_multiple_values.js": [
+ "028a1c2e9b82299eef5f383886f2a1cb008c65ee",
"support"
],
- "cookie-store/resources/testharness-helpers.js": [
- "b7bc4516ad4ac7ae1bb572191c0c3932c29eb863",
+ "cookie-store/resources/one_simple_origin_cookie.js": [
+ "c5a3cc58200f8c160e50a0ca03a5d763dd96c635",
"support"
],
+ "cookie-store/resources/ordering.js": [
+ "822567b7eb113c809379dff5b62a2e24c9e9e171",
+ "support"
+ ],
+ "cookie-store/resources/secure_cookies.js": [
+ "c4ddb9a024d0fc0d370891e587ed8aba54c5709e",
+ "support"
+ ],
+ "cookie-store/secure_cookies.tentative.html": [
+ "0d0b2324cbf5439491ea9f8fddd4ef7ca4b8eed6",
+ "testharness"
+ ],
+ "cookie-store/secure_cookies.tentative.https.html": [
+ "bcfbbd7ae2e9ae85deefbf284f6cf76901975a93",
+ "testharness"
+ ],
"cookie-store/serviceworker_cookieStore_arguments.js": [
"a90956237d63fd51556f2d9e50967522870816d4",
"support"
@@ -502219,6 +502067,54 @@
"3d9ee014d1341bae70de86de585658f7432f76ef",
"testharness"
],
+ "css/css-grid/grid-items/grid-items-percentage-margins-001.html": [
+ "dac1d8c4fb5a35f7758e700fc0733a6aa88bbfd9",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-002.html": [
+ "c676792bc50636a5ceba31f870cb23e3ac48ae0d",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-001.html": [
+ "ef99c3e1f89409f0ad73defba818bd532eab840e",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-002.html": [
+ "7bca7e112e006468d4329c267a0517b0f6e6f16f",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-001.html": [
+ "128e954475484a57546231e8ee80bb1ffe414838",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-002.html": [
+ "84c9b8d9f9ca3ab51f666a9b112f4622fb399e89",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-001.html": [
+ "8e46d9ce055a64d94f0136022295079f867e3210",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-002.html": [
+ "3115e10181a67224cd178dd242b55976d7ef77a2",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-001.html": [
+ "9100d95c22d9865d69594418b4845364b2644a4f",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-002.html": [
+ "8ad00d5b2d6e635633d664fa74ad3792d09cfb08",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-001.html": [
+ "fd59a40079b6b70c4cab6abcf8d6d4146fb452a1",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-002.html": [
+ "10f3a7444d59c1bfa6cbc85551603150b57cee30",
+ "testharness"
+ ],
"css/css-grid/grid-items/grid-items-sizing-alignment-001-ref.html": [
"33080559b7f451958ea4785075bf6c8e4d8902eb",
"support"
@@ -534180,7 +534076,7 @@
"testharness"
],
"css/cssom/style-sheet-interfaces-001.html": [
- "3fbe87bc1e363bf59a84c5fbdd8b2450909c6ca1",
+ "1614c9a0e4973672b18caf46ad56e6cf188285b5",
"testharness"
],
"css/cssom/style-sheet-interfaces-002.html": [
@@ -546060,7 +545956,7 @@
"testharness"
],
"custom-elements/custom-element-registry/upgrade.html": [
- "a5c2ced54f7031d02009c9853a7ee4e883151cb3",
+ "1f82577bf6aab4ba72b3e3f017a091ad29680da7",
"testharness"
],
"custom-elements/disconnected-callbacks.html": [
@@ -546100,7 +545996,7 @@
"testharness"
],
"custom-elements/parser/parser-sets-attributes-and-children.html": [
- "8049449173e4082b2f4ccadfe552abadadc0834a",
+ "89d8b4861a76f744687479f26086d9de4f72aac3",
"testharness"
],
"custom-elements/parser/parser-uses-constructed-element.html": [
@@ -552223,6 +552119,10 @@
"699a8b2c8bb1f089f3ef1827bf8cfe1873849bf8",
"reftest"
],
+ "fetch/corb/img-mime-types-coverage.tentative.sub.html": [
+ "ccceb2eab638a0e7c88c6e3eed45c51148e0f406",
+ "testharness"
+ ],
"fetch/corb/img-png-mislabeled-as-html-nosniff.tentative.sub-expected.html": [
"1980633a4167993d90636be2ebba2aa8d72299b7",
"support"
@@ -552239,6 +552139,10 @@
"a7775fb534d38a5d5b5827a27f0c16e1268f4d0b",
"reftest"
],
+ "fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html": [
+ "e3d5ad8b15d2b206fc49090ec9a1d1bb3fa13242",
+ "testharness"
+ ],
"fetch/corb/resources/css-mislabeled-as-html-nosniff.css": [
"7d3f1614c6d0170f67442ee60fe2aab6099bedc1",
"support"
@@ -552416,7 +552320,7 @@
"testharness"
],
"fetch/nosniff/image.html": [
- "2b31b5f05d843c55640943e68224cb36a1670a5e",
+ "568ae12edabc343cddbef7cb41acde20955fc8bb",
"testharness"
],
"fetch/nosniff/importscripts.html": [
@@ -552436,7 +552340,7 @@
"support"
],
"fetch/nosniff/resources/image.py": [
- "015a20158bb41f02a1fa30214060f522f32f6249",
+ "82bd978c186e3b468d5e3a15623718484fec926e",
"support"
],
"fetch/nosniff/resources/js.py": [
@@ -572967,6 +572871,10 @@
"5c43c80281b17b20173a2c7aceb873d8ad60d5d2",
"support"
],
+ "images/green-96x96.svg": [
+ "b41390669cc5a9a03700ab429ee9f54977575e87",
+ "support"
+ ],
"images/green.png": [
"ef91d21307a12b2cfaf33a90dffe16aa1cba42c9",
"support"
@@ -593787,6 +593695,10 @@
"d21ef5a4263e26cd3053a89171e2597424eaad82",
"testharness"
],
+ "service-workers/service-worker/fetch-request-xhr-sync-on-worker.https.html": [
+ "aca28d4ad02c803873bea5fc922b8e4d427ccc4b",
+ "testharness"
+ ],
"service-workers/service-worker/fetch-request-xhr-sync.https.html": [
"4aaa0b1995643f4e18c47d1947476a1a67fe997d",
"testharness"
@@ -594595,6 +594507,10 @@
"a168a0326207e734f0229d49cce12af9a37e81ec",
"support"
],
+ "service-workers/service-worker/resources/fetch-request-xhr-sync-on-worker-worker.js": [
+ "0b7167334e08425c399bb7fa189cf7c55e480633",
+ "support"
+ ],
"service-workers/service-worker/resources/fetch-request-xhr-sync-worker.js": [
"fe1386a87464c16d62e23eb102b25891960e7209",
"support"
diff --git a/tests/wpt/metadata/css/css-values/vh_not_refreshing_on_chrome.html.ini b/tests/wpt/metadata/css/css-values/vh_not_refreshing_on_chrome.html.ini
new file mode 100644
index 00000000000..26435e28b09
--- /dev/null
+++ b/tests/wpt/metadata/css/css-values/vh_not_refreshing_on_chrome.html.ini
@@ -0,0 +1,2 @@
+[vh_not_refreshing_on_chrome.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/fetch/corb/img-mime-types-coverage.tentative.sub.html.ini b/tests/wpt/metadata/fetch/corb/img-mime-types-coverage.tentative.sub.html.ini
new file mode 100644
index 00000000000..18a49345106
--- /dev/null
+++ b/tests/wpt/metadata/fetch/corb/img-mime-types-coverage.tentative.sub.html.ini
@@ -0,0 +1,4 @@
+[img-mime-types-coverage.tentative.sub.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html.ini b/tests/wpt/metadata/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html.ini
new file mode 100644
index 00000000000..cc589928c91
--- /dev/null
+++ b/tests/wpt/metadata/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html.ini
@@ -0,0 +1,5 @@
+[preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html]
+ expected: TIMEOUT
+ [Untitled]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/fetch/nosniff/image.html.ini b/tests/wpt/metadata/fetch/nosniff/image.html.ini
new file mode 100644
index 00000000000..cc78bfd6ac1
--- /dev/null
+++ b/tests/wpt/metadata/fetch/nosniff/image.html.ini
@@ -0,0 +1,4 @@
+[image.html]
+ [URL query: image/svg+xml]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/dom/dynamic-markup-insertion/opening-the-input-stream/010.html.ini b/tests/wpt/metadata/html/dom/dynamic-markup-insertion/opening-the-input-stream/010.html.ini
new file mode 100644
index 00000000000..33164945eb6
--- /dev/null
+++ b/tests/wpt/metadata/html/dom/dynamic-markup-insertion/opening-the-input-stream/010.html.ini
@@ -0,0 +1,4 @@
+[010.html]
+ [Salvagability of document.opened document]
+ expected: FAIL
+
diff --git a/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/context/context-release-with-workers.html.ini b/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/context/context-release-with-workers.html.ini
new file mode 100644
index 00000000000..7aab2f5f662
--- /dev/null
+++ b/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/context/context-release-with-workers.html.ini
@@ -0,0 +1,5 @@
+[context-release-with-workers.html]
+ expected: TIMEOUT
+ [Overall test]
+ expected: NOTRUN
+
diff --git a/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/ogles/GL/atan/atan_001_to_008.html.ini b/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/ogles/GL/atan/atan_001_to_008.html.ini
new file mode 100644
index 00000000000..7e17f982259
--- /dev/null
+++ b/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/ogles/GL/atan/atan_001_to_008.html.ini
@@ -0,0 +1,5 @@
+[atan_001_to_008.html]
+ expected: TIMEOUT
+ [Overall test]
+ expected: NOTRUN
+
diff --git a/tests/wpt/web-platform-tests/README.md b/tests/wpt/web-platform-tests/README.md
index fe02609bbf0..cc2870b78d2 100644
--- a/tests/wpt/web-platform-tests/README.md
+++ b/tests/wpt/web-platform-tests/README.md
@@ -423,7 +423,7 @@ is [archived][ircarchive].
[contributing]: https://github.com/w3c/web-platform-tests/blob/master/CONTRIBUTING.md
[ircw3org]: https://www.w3.org/wiki/IRC
-[ircarchive]: http://logs.glob.uno/?c=w3%23testing
+[ircarchive]: https://w3.logbot.info/testing
[mailarchive]: https://lists.w3.org/Archives/Public/public-test-infra/
Documentation
diff --git a/tests/wpt/web-platform-tests/cookie-store/README.md b/tests/wpt/web-platform-tests/cookie-store/README.md
index 4ba55f7f946..c406dcc774e 100644
--- a/tests/wpt/web-platform-tests/cookie-store/README.md
+++ b/tests/wpt/web-platform-tests/cookie-store/README.md
@@ -1,2 +1,28 @@
This directory contains tests for the
[Async Cookies API](https://github.com/WICG/cookie-store).
+
+## Note on cookie naming conventions
+
+A simple origin cookie is a cookie named with the `__Host-` prefix
+which is always secure-flagged, always implicit-domain, always
+`/`-scoped, and hence always unambiguous in the cookie jar serialization
+and origin-scoped. It can be treated as a simple key/value pair.
+
+`"LEGACY"` in a cookie name here means it is an old-style unprefixed
+cookie name, so you can't tell e.g. whether it is Secure-flagged or
+`/`-pathed just by looking at it, and its flags, domain and path may
+vary even in a single cookie jar serialization leading to apparent
+duplicate entries, ambiguities, and complexity (i.e. it cannot be
+treated as a simple key/value pair.)
+
+Cookie names used in the tests are intended to be
+realistic. Traditional session cookie names are typically
+all-upper-case for broad framework compatibility. The more modern
+`"__Host-"` prefix has only one allowed casing. An expected upgrade
+path from traditional "legacy" cookie names to simple origin cookie
+names is simply to prefix the traditional name with the `"__Host-"`
+prefix.
+
+Many of the used cookie names are non-ASCII to ensure
+straightforward internationalization is possible at every API surface.
+These work in many modern browsers, though not yet all of them.
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html
deleted file mode 100644
index 39962c750ae..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Basic tests for cookieStore</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite();
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html
deleted file mode 100644
index 3bf592e7fce..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Basic tests for cookieStore (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite();
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html
deleted file mode 100644
index 6f0a3c9ecd5..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Basic tests for cookieStore (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite();
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html
deleted file mode 100644
index 08784f87ffe..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Basic tests for cookieStore (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite();
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html b/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html
index 786885ab3c5..9fa0ee4ff13 100644
--- a/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: delete cookies</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testDeleteCookies'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/delete_cookies.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html
index accb4d20d5e..192f79be599 100644
--- a/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: delete cookies (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testDeleteCookies'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/delete_cookies.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html
deleted file mode 100644
index 0ceb517f399..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: delete cookies (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testDeleteCookies'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html
deleted file mode 100644
index a022c28e9c7..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: delete cookies (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testDeleteCookies'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html b/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html
index 743f4efb40d..f5528d2d96c 100644
--- a/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: document.cookie</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testDocumentCookie'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/document_cookie.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html
index e19b841d0cf..63ddd9f63bc 100644
--- a/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: document.cookie (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testDocumentCookie'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/document_cookie.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html
deleted file mode 100644
index 8f671ddb34c..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: document.cookie (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testDocumentCookie'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html
deleted file mode 100644
index 065af2a0363..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: document.cookie (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testDocumentCookie'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html b/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html
index 47a628d0633..d7164a94718 100644
--- a/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: expiration</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testExpiration'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/expiration.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html
index e4db1a6cbea..638b0477e5a 100644
--- a/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: expiration (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testExpiration'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/expiration.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html
deleted file mode 100644
index f9c601887d7..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: expiration (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testExpiration'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html
deleted file mode 100644
index b6887686f46..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: expiration (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testExpiration'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html
index 2574ade51b0..a88d032bcac 100644
--- a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: get, set, getAll</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testGetSetGetAll'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/get_set_get_all.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html
index 5a52fdd401c..1769b166ecb 100644
--- a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: get, set, getAll (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testGetSetGetAll'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/get_set_get_all.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html
deleted file mode 100644
index 08921794983..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: get, set, getAll (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testGetSetGetAll'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html
deleted file mode 100644
index 6e44c0d4ccb..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: get, set, getAll (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testGetSetGetAll'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html b/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html
index 8784885d2a2..4370350a948 100644
--- a/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: HTTP Cookie and Set-Cookie headers</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testHttpCookieAndSetCookieHeaders'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/http_cookie_and_set_cookie_headers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html
index 9b057790d71..0c3d8b12d46 100644
--- a/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: HTTP Cookie and Set-Cookie headers (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testHttpCookieAndSetCookieHeaders'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/http_cookie_and_set_cookie_headers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html
deleted file mode 100644
index 978aa8b3bbd..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: <title>Async Cookies: document.cookie</title>lt;Meta Http-Equiv="Set-Cookie" ... <title>Async Cookies: document.cookie</title>gt;</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testMetaHttpEquivSetCookie'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html
deleted file mode 100644
index 38192b1147f..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: <title>Async Cookies: document.cookie</title>lt;Meta Http-Equiv="Set-Cookie" ... <title>Async Cookies: document.cookie</title>gt; (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testMetaHttpEquivSetCookie'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html
deleted file mode 100644
index a7063e68a4d..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: <title>Async Cookies: document.cookie</title>lt;Meta Http-Equiv="Set-Cookie" ... <title>Async Cookies: document.cookie</title>gt; (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testMetaHttpEquivSetCookie'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html
deleted file mode 100644
index 830b92710fe..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: <title>Async Cookies: document.cookie</title>lt;Meta Http-Equiv="Set-Cookie" ... <title>Async Cookies: document.cookie</title>gt; (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testMetaHttpEquivSetCookie'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html
index 25bbb82054f..79923b5ae8c 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: Test No Name and No Value</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameAndNoValue'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/no_name_and_no_value.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html
index 3f2554424f3..0f15dafa7ab 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: Test No Name and No Value (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameAndNoValue'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/no_name_and_no_value.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html
deleted file mode 100644
index d4a66b0ed50..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test No Name and No Value (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameAndNoValue'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html
deleted file mode 100644
index 46e0bf93cf6..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test No Name and No Value (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameAndNoValue'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html
index 849af3c1627..17597038c08 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, '=' in Value</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameEqualsInValue'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/no_name_equals_in_value.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html
index d352768426f..de774550fe9 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, '=' in Value (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameEqualsInValue'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/no_name_equals_in_value.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html
deleted file mode 100644
index 02fd5f71113..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test No Name, '=' in Value (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameEqualsInValue'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html
deleted file mode 100644
index a3d9ec08fef..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test No Name, '=' in Value (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameEqualsInValue'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html
index e4f208cc974..755d1066799 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, Multiple Values</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameMultipleValues'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/no_name_multiple_values.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html
index a3ff0cebb8e..29cde813fc3 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, Multiple Values (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameMultipleValues'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/no_name_multiple_values.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html
deleted file mode 100644
index 8e61be6381f..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test No Name, Multiple Values (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameMultipleValues'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html
deleted file mode 100644
index 6d2a684922e..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test No Name, Multiple Values (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testNoNameMultipleValues'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/observation.tentative.html b/tests/wpt/web-platform-tests/cookie-store/observation.tentative.html
deleted file mode 100644
index d2c9e6a87e7..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/observation.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test Observation</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testObservation'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html
deleted file mode 100644
index 11ee8e46968..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test Observation (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testObservation'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html
deleted file mode 100644
index 422ab39ed79..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test Observation (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testObservation'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html
deleted file mode 100644
index 323dc86a1ea..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: Test Observation (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testObservation'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html
index 1ca217ee4bc..b1d264cde1b 100644
--- a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: One simple origin cookie</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testOneSimpleOriginCookie'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/one_simple_origin_cookie.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html
index f27f7f4f2b6..132d8ccb575 100644
--- a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html
@@ -1,14 +1,8 @@
<!DOCTYPE html>
<meta charset="utf-8">
-<meta name="timeout" content="long">
<title>Async Cookies: One simple origin cookie (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testOneSimpleOriginCookie'});
-</script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/one_simple_origin_cookie.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html
deleted file mode 100644
index 88bd8ba37ca..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: One simple origin cookie (Static)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testOneSimpleOriginCookie'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html
deleted file mode 100644
index f53d81a21f9..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<meta name="timeout" content="long">
-<title>Async Cookies: One simple origin cookie (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script src="resources/cookie-store-tests.js"></script>
-<script>
-'use strict';
-
-suite({testName: 'testOneSimpleOriginCookie'});
-</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/ordering.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/ordering.tentative.https.html
new file mode 100644
index 00000000000..1873ed4e9c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/ordering.tentative.https.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Async Cookies: ordering (HTTPS)</title>
+<meta name="help" href="https://github.com/WICG/cookie-store/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/ordering.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js b/tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js
deleted file mode 100644
index 413dee98f86..00000000000
--- a/tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js
+++ /dev/null
@@ -1,1114 +0,0 @@
-'use strict';
-
-// Buffered exceptions re-thrown at end of suite
-let savedExceptions = [];
-
-// Observer-based document.cookie simulator
-let observer;
-let observationLog = [];
-let observedStore = [];
-
-// Note on cookie naming conventions:
-//
-// A simple origin cookie is a cookie named with the __Host- prefix
-// which is always secure-flagged, always implicit-domain, always
-// /-scoped, and hence always unambiguous in the cookie jar serialization
-// and origin-scoped. It can be treated as a simple key/value pair.
-//
-// "LEGACY" in a cookie name here means it is an old-style unprefixed
-// cookie name, so you can't tell e.g. whether it is Secure-flagged or
-// /-pathed just by looking at it, and its flags, domain and path may
-// vary even in a single cookie jar serialization leading to apparent
-// duplicate entries, ambiguities, and complexity (it cannot be
-// treated as a simple key/value pair.)
-//
-// Cookie names used in the tests are intended to be
-// realistic. Traditional session cookie names are typically
-// all-upper-case for broad framework compatibility. The more modern
-// "__Host-" prefix has only one allowed casing. An expected upgrade
-// path from traditional "legacy" cookie names to simple origin cookie
-// names is simply to prefix the traditional name with the "__Host-"
-// prefix.
-//
-// Many of the used cookie names are non-ASCII to ensure
-// straightforward internationalization is possible at every API surface.
-// These work in many modern browsers, though not yet all of them.
-
-// Approximate async observer-based equivalent to the document.cookie
-// getter but with important differences: an empty cookie jar returns
-// undefined. Introduces unfortunate but apparently unavoidable delays
-// to ensure the observer has time to run.
-//
-// Timeouts here are intended to give observers enough time to sense
-// a change. It can't be changed to wait indefinitely as it is
-// sometimes used to verify observers were not notified of any
-// change.
-const getCookieStringObserved = opt_name => {
- // Run later to ensure the cookie scanner (which runs one task
- // later, at least in the polyfill) has a chance.
- //
- // We cannot use the s\u0065tTimeout identifier unescaped inside WPT
- // tests (the linter does not allow it.) However we need an actual
- // delay to allow batched observers to fire.
- const initialLength = observationLog.length;
- return (async () => {
- assert_not_equals(observer, undefined, 'observer should not be undefined');
- await new Promise(resolve => s\u0065tTimeout(resolve));
- const lengthAfterImplicit0msSetTimeout = observationLog.length;
- if (lengthAfterImplicit0msSetTimeout === initialLength) {
- await new Promise(resolve => s\u0065tTimeout(resolve, 4));
- const lengthAfter4msSetTimeout = observationLog.length;
- if (lengthAfter4msSetTimeout === initialLength) {
- let lengthAfterRequestAnimationFrame = lengthAfter4msSetTimeout;
- if (typeof requestAnimationFrame !== 'undefined') {
- await new Promise(resolve => requestAnimationFrame(resolve));
- lengthAfterRequestAnimationFrame = observationLog.length;
- }
- if (lengthAfterRequestAnimationFrame === initialLength) {
- await new Promise(
- resolve => s\u0065tTimeout(resolve, kExtraObserverDelay));
- }
- }
- }
- let filtered = observedStore;
- if (opt_name != null) filtered = filtered.filter(
- cookie => cookie.name === opt_name);
- return cookieString(filtered);
- })();
-};
-
-const assertEmptyCookieJar = async (testCase, messageSuffix) => {
- assert_equals(
- await getCookieString(),
- undefined,
- 'No cookies ' + messageSuffix);
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'No HTTP cookies ' + messageSuffix);
- if (kHasDocument) assert_equals(
- await getCookieStringDocument(),
- undefined,
- 'No document.cookie cookies ' + messageSuffix);
-};
-
-const suite = ({testName = undefined} = {}) => {
- promise_test(async testCase => {
- testOverride = testName;
- observer = undefined;
- observationLog.length = 0;
- observedStore.length = 0;
- savedExceptions.length = 0;
- // Start with a clean slate.
- //
- // Attempt testDeleteCookies first too, since otherwise an earlier
- // failed test can cause all subsequent tests to fail.
- await testDeleteCookies(testCase);
- await assertEmptyCookieJar(testCase, 'at start of test');
- let unfinished = true;
- try {
- if (includeTest('testObservation')) {
- observer = await testObservation();
- assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'No observed cookies at start of test');
- }
- // These use the same cookie names and so cannot run interleaved
- if (includeTest('testNoNameAndNoValue')) await testNoNameAndNoValue();
- if (includeTest('testNoNameMultipleValues')) {
- await testNoNameMultipleValues();
- }
- if (includeTest('testNoNameEqualsInValue')) {
- await testNoNameEqualsInValue();
- }
- if (includeTest('testMetaHttpEquivSetCookie')) {
- await testMetaHttpEquivSetCookie();
- }
- if (includeTest('testDocumentCookie', !kHasDocument)) {
- await testDocumentCookie();
- }
- if (includeTest('testHttpCookieAndSetCookieHeaders', kIsStatic)) {
- await testHttpCookieAndSetCookieHeaders();
- }
- if (includeTest('testGetSetGetAll')) {
- await testGetSetGetAll();
- }
- if (includeTest('testOneSimpleOriginCookie')) {
- await testOneSimpleOriginCookie(testCase);
- }
- if (includeTest('testExpiration')) {
- await testExpiration(testCase);
- }
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- testThreeSimpleOriginSessionCookiesSetSequentially(),
- '__Host- cookies only writable from secure contexts' +
- ' (testThreeSimpleOriginSessionCookiesSetSequentially)');
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- testThreeSimpleOriginSessionCookiesSetNonsequentially(),
- '__Host- cookies only writable from secure contexts' +
- ' (testThreeSimpleOriginSessionCookiesSetNonsequentially)');
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- setExpiredSecureCookieWithDomainPathAndFallbackValue(),
- 'Secure cookies only writable from secure contexts' +
- ' (setExpiredSecureCookieWithDomainPathAndFallbackValue)');
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- deleteSimpleOriginCookie(),
- '__Host- cookies only writable from secure contexts' +
- ' (deleteSimpleOriginCookie)');
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- deleteSecureCookieWithDomainAndPath(),
- 'Secure cookies only writable from secure contexts' +
- ' (deleteSecureCookieWithDomainAndPath)');
- if (kIsUnsecured) {
- assert_equals(
- await getCookieString(),
- includeTest('testGetSetGetAll') ? 'TEST=value' : undefined,
- (includeTest('testGetSetGetAll') ?
- 'Only one unsecured cookie' :
- 'No unsecured cookies') +
- ' before testDeleteCookies at end of test');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- includeTest('testGetSetGetAll') ? 'TEST=value' : undefined,
- (includeTest('testGetSetGetAll') ?
- 'Only one observed unsecured cookie' :
- 'No observed unsecured cookies') +
- ' before testDeleteCookies at end of test');
- } else {
- assert_equals(
- await getCookieString(),
- (includeTest('testGetSetGetAll') ? 'TEST=value; ' : '') +
- '__Host-1🍪=🔵cookie-value1🔴; ' +
- '__Host-2🌟=🌠cookie-value2🌠; ' +
- '__Host-3🌱=🔶cookie-value3🔷; ' +
- '__Host-unordered1🍪=🔵unordered-cookie-value1🔴; ' +
- '__Host-unordered2🌟=🌠unordered-cookie-value2🌠; ' +
- '__Host-unordered3🌱=🔶unordered-cookie-value3🔷',
- 'All residual cookies before testDeleteCookies at end of test');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- (includeTest('testGetSetGetAll') ? 'TEST=value; ' : '') +
- '__Host-1🍪=🔵cookie-value1🔴; ' +
- '__Host-2🌟=🌠cookie-value2🌠; ' +
- '__Host-3🌱=🔶cookie-value3🔷; ' +
- '__Host-unordered1🍪=🔵unordered-cookie-value1🔴; ' +
- '__Host-unordered2🌟=🌠unordered-cookie-value2🌠; ' +
- '__Host-unordered3🌱=🔶unordered-cookie-value3🔷',
- 'All residual observed cookies before testDeleteCookies ' +
- 'at end of test');
- }
- if (kIsUnsecured) {
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- includeTest('testGetSetGetAll') ? 'TEST=value' : undefined,
- (includeTest('testGetSetGetAll') ?
- 'Only one unsecured HTTP cookie' :
- 'No unsecured HTTP cookies') +
- ' before testDeleteCookies at end of test');
- } else {
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- (includeTest('testGetSetGetAll') ? 'TEST=value; ' : '') +
- '__Host-1🍪=🔵cookie-value1🔴; ' +
- '__Host-2🌟=🌠cookie-value2🌠; ' +
- '__Host-3🌱=🔶cookie-value3🔷; ' +
- '__Host-unordered1🍪=🔵unordered-cookie-value1🔴; ' +
- '__Host-unordered2🌟=🌠unordered-cookie-value2🌠; ' +
- '__Host-unordered3🌱=🔶unordered-cookie-value3🔷',
- 'All residual HTTP cookies before testDeleteCookies ' +
- 'at end of test');
- }
- if (kIsUnsecured) {
- if (kHasDocument) assert_equals(
- await getCookieStringDocument(),
- includeTest('testGetSetGetAll') ? 'TEST=value' : undefined,
- (includeTest('testGetSetGetAll') ?
- 'Only one unsecured document.cookie cookie' :
- 'No unsecured document.cookie cookies') +
- ' before testDeleteCookies at end of test');
- } else {
- if (kHasDocument) assert_equals(
- await getCookieStringDocument(),
- (includeTest('testGetSetGetAll') ? 'TEST=value; ' : '') +
- '__Host-1🍪=🔵cookie-value1🔴; ' +
- '__Host-2🌟=🌠cookie-value2🌠; ' +
- '__Host-3🌱=🔶cookie-value3🔷; ' +
- '__Host-unordered1🍪=🔵unordered-cookie-value1🔴; ' +
- '__Host-unordered2🌟=🌠unordered-cookie-value2🌠; ' +
- '__Host-unordered3🌱=🔶unordered-cookie-value3🔷',
- 'All residual document.cookie cookies before testDeleteCookies ' +
- 'at end of test');
- }
- unfinished = false;
- assert_equals(
- savedExceptions.length,
- 0,
- 'Found saved exceptions: ' + savedExceptions);
- } finally {
- try {
- await testDeleteCookies(testCase);
- if (observer) observer.disconnect();
- await assertEmptyCookieJar(testCase, 'at end of test');
- } catch (e) {
- // only re-throw testDeleteCookies failures if finished to avoid masking
- // earlier failures
- if (!unfinished) throw e;
- }
- }
- }, 'Cookie Store Tests (' + (testName || 'all') + ')');
-};
-
-
-// Try to clean up cookies and observers used by tests. Also
-// verifies delete() behavior for secure contexts and unsecured
-// contexts.
-//
-// Parameters:
-// - testCase: (TestCase) Context in which the testDeleteCookies is run.
-const testDeleteCookies = async testCase => {
- await cookieStore.delete('');
- await cookieStore.delete('TEST');
- await cookieStore.delete('META-🍪');
- await cookieStore.delete('DOCUMENT-🍪');
- await cookieStore.delete('HTTP-🍪');
- if (!kIsStatic) await setCookieStringHttp(
- 'HTTPONLY-🍪=DELETED; path=/; max-age=0; httponly');
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- cookieStore.delete('__Host-COOKIENAME'));
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- cookieStore.delete('__Host-1🍪'));
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- cookieStore.delete('__Host-2🌟'));
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- cookieStore.delete('__Host-3🌱'));
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- cookieStore.delete('__Host-unordered1🍪'));
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- cookieStore.delete('__Host-unordered2🌟'));
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- cookieStore.delete('__Host-unordered3🌱'));
-};
-
-// Helper to verify first-of-name get using async/await.
-//
-// Returns the first script-visible value of the __Host-COOKIENAME cookie or
-// undefined if no matching cookies are script-visible.
-let getOneSimpleOriginCookie = async () => {
- let cookie = await cookieStore.get('__Host-COOKIENAME');
- if (!cookie) return undefined;
- return cookie.value;
-};
-
-// Returns the number of script-visible cookies whose names start with
-// __Host-COOKIEN
-let countMatchingSimpleOriginCookies = async () => {
- let cookieList = await cookieStore.getAll({
- name: '__Host-COOKIEN',
- matchType: 'startsWith'
- });
- return cookieList.length;
-};
-
-// Set the secure implicit-domain cookie __Host-COOKIENAME with value
-// cookie-value on path / and session duration.
-let setOneSimpleOriginSessionCookie = async () => {
- await cookieStore.set('__Host-COOKIENAME', 'cookie-value');
-};
-
-// Set the secure example.org-domain cookie __Secure-COOKIENAME with
-// value cookie-value on path /cgi-bin/ and 24 hour duration; domain
-// and path will be rewritten below.
-//
-// This uses a Date object for expiration.
-let setOneDaySecureCookieWithDate = async () => {
- // one day ahead, ignoring a possible leap-second
- let inTwentyFourHours = new Date(Date.now() + 24 * 60 * 60 * 1000);
- await cookieStore.set('__Secure-COOKIENAME', 'cookie-value', {
- path: '/cgi-bin/',
- expires: inTwentyFourHours,
- secure: true,
- domain: 'example.org'
- });
-};
-
-// Set the unsecured example.org-domain cookie LEGACYCOOKIENAME with
-// value cookie-value on path /cgi-bin/ and 24 hour duration; domain
-// and path will be rewritten below.
-//
-// This uses milliseconds since the start of the Unix epoch for
-// expiration.
-let setOneDayUnsecuredCookieWithMillisecondsSinceEpoch = async () => {
- // one day ahead, ignoring a possible leap-second
- let inTwentyFourHours = Date.now() + 24 * 60 * 60 * 1000;
- await cookieStore.set('LEGACYCOOKIENAME', 'cookie-value', {
- path: '/cgi-bin/',
- expires: inTwentyFourHours,
- secure: false,
- domain: 'example.org'
- });
-};
-
-// Delete the cookie written by
-// setOneDayUnsecuredCookieWithMillisecondsSinceEpoch.
-let deleteUnsecuredCookieWithDomainAndPath = async () => {
- await cookieStore.delete('LEGACYCOOKIENAME', {
- path: '/cgi-bin/',
- secure: false,
- domain: 'example.org'
- });
-};
-
-
-// Set the secured example.org-domain cookie __Secure-COOKIENAME with
-// value cookie-value on path /cgi-bin/ and expiration in June of next
-// year; domain and path will be rewritten below.
-//
-// This uses an HTTP-style date string for expiration.
-let setSecureCookieWithHttpLikeExpirationString = async () => {
- const year = (new Date()).getUTCFullYear() + 1;
- const date = new Date('07 Jun ' + year + ' 07:07:07 UTC');
- const day = ('Sun Mon Tue Wed Thu Fri Sat'.split(' '))[date.getUTCDay()];
- await cookieStore.set('__Secure-COOKIENAME', 'cookie-value', {
- path: '/cgi-bin/',
- expires: day + ', 07 Jun ' + year + ' 07:07:07 GMT',
- secure: true,
- domain: 'example.org'
- });
-};
-
-// Set three simple origin session cookies sequentially and ensure
-// they all end up in the cookie jar in order.
-let testThreeSimpleOriginSessionCookiesSetSequentially = async () => {
- await cookieStore.set('__Host-1🍪', '🔵cookie-value1🔴');
- await cookieStore.set('__Host-2🌟', '🌠cookie-value2🌠');
- await cookieStore.set('__Host-3🌱', '🔶cookie-value3🔷');
- // NOTE: this assumes no concurrent writes from elsewhere; it also
- // uses three separate cookie jar read operations where a single getAll
- // would be more efficient, but this way the CookieStore does the filtering
- // for us.
- let matchingValues = await Promise.all([ '1🍪', '2🌟', '3🌱' ].map(
- async suffix => (await cookieStore.get('__Host-' + suffix)).value));
- let actual = matchingValues.join(';');
- let expected = '🔵cookie-value1🔴;🌠cookie-value2🌠;🔶cookie-value3🔷';
- if (actual !== expected) throw new Error(
- 'Expected ' + JSON.stringify(expected) +
- ' but got ' + JSON.stringify(actual));
-};
-
-// Set three simple origin session cookies in undefined order using
-// Promise.all and ensure they all end up in the cookie jar in any
-// order.
-let testThreeSimpleOriginSessionCookiesSetNonsequentially = async () => {
- await Promise.all([
- cookieStore.set('__Host-unordered1🍪', '🔵unordered-cookie-value1🔴'),
- cookieStore.set('__Host-unordered2🌟', '🌠unordered-cookie-value2🌠'),
- cookieStore.set('__Host-unordered3🌱', '🔶unordered-cookie-value3🔷')
- ]);
- // NOTE: this assumes no concurrent writes from elsewhere; it also
- // uses three separate cookie jar read operations where a single getAll
- // would be more efficient, but this way the CookieStore does the filtering
- // for us and we do not need to sort.
- let matchingCookies = await Promise.all([ '1🍪', '2🌟', '3🌱' ].map(
- suffix => cookieStore.get('__Host-unordered' + suffix)));
- let actual = matchingCookies.map(({ value }) => value).join(';');
- let expected =
- '🔵unordered-cookie-value1🔴;' +
- '🌠unordered-cookie-value2🌠;' +
- '🔶unordered-cookie-value3🔷';
- if (actual !== expected) throw new Error(
- 'Expected ' + JSON.stringify(expected) +
- ' but got ' + JSON.stringify(actual));
-};
-
-// Set an already-expired cookie.
-let setExpiredSecureCookieWithDomainPathAndFallbackValue = async () => {
- let theVeryRecentPast = Date.now();
- let expiredCookieSentinelValue = 'EXPIRED';
- await cookieStore.set('__Secure-COOKIENAME', expiredCookieSentinelValue, {
- path: '/cgi-bin/',
- expires: theVeryRecentPast,
- secure: true,
- domain: 'example.org'
- });
-};
-
-// Delete the __Host-COOKIENAME cookie created above.
-let deleteSimpleOriginCookie = async () => {
- await cookieStore.delete('__Host-COOKIENAME');
-};
-
-// Delete the __Secure-COOKIENAME cookie created above.
-let deleteSecureCookieWithDomainAndPath = async () => {
- await cookieStore.delete('__Secure-COOKIENAME', {
- path: '/cgi-bin/',
- domain: 'example.org',
- secure: true
- });
-};
-
-// Test for CookieObserver. Used in implementation of async observer-based
-// document.cookie simulator. This is passed to the Promise constructor after
-// rewriting.
-let testObservation_ = (resolve, reject) => {
- // This will get invoked (asynchronously) shortly after the
- // observe(...) call to provide an initial snapshot; in that case
- // the length of cookieChanges may be 0, indicating no matching
- // script-visible cookies for any URL+cookieStore currently
- // observed. The CookieObserver instance is passed as the second
- // parameter to allow additional calls to observe or disconnect.
- let callback = (cookieChanges, observer) => {
- var logEntry = [];
- observationLog.push(logEntry);
- const cookieChangesStrings = changes => changes.map(
- ({type, name, value, index}) => cookieString(Object.assign(
- new Array(observedStore.length),
- {[index]: {
- name: ((type === 'visible') ? '+' : '-') + name,
- value: value
- }})));
- logEntry.push(['before', cookieString(observedStore)]);
- logEntry.push(['changes', cookieChangesStrings(cookieChanges)]);
- const newObservedStore = observedStore.slice(0);
- try {
- const insertions = [], deletions = [];
- cookieChanges.forEach(({
- cookieStore,
- type,
- url,
- name,
- value,
- index,
- all
- }) => {
- switch (type) {
- case 'visible':
- // Creation or modification (e.g. change in value, or
- // removal of HttpOnly), or appearance to script due to
- // change in policy or permissions
- insertions.push([index, {name: name, value: value}]);
- break;
- case 'hidden':
- // Deletion/expiration or disappearance (e.g. due to
- // modification adding HttpOnly), or disappearance from
- // script due to change in policy or permissions
- assert_object_equals(
- {name: name, value: value},
- observedStore[index],
- 'Hidden cookie at index ' + index +
- ' was not the expected one: ' + JSON.stringify({
- got: {name: name, value: value},
- expected: observedStore[index]
- }));
- deletions.push(index);
- break;
- default:
- savedExceptions.push('Unexpected CookieChange type ' + type);
- if (reject) reject(savedExceptions[savedExceptions.length - 1]);
- throw savedExceptions[savedExceptions.length - 1];
- }
- });
- deletions.sort((a, b) => b - a).forEach(
- index => newObservedStore.splice(index, 1));
- let bias = 0;
- insertions.sort(([a], [b]) => a - b).forEach(([ index, cookie ]) => {
- if (newObservedStore[index + bias] !== undefined) {
- newObservedStore.splice(index, 0, cookie);
- --bias;
- } else {
- newObservedStore[index] = cookie;
- }
- });
- observedStore = newObservedStore.filter(entry => entry !== undefined);
- logEntry.push(['after', cookieString(observedStore)]);
- const reported =
- cookieChanges && cookieChanges.length ?
- cookieChanges[cookieChanges.length - 1].all :
- [];
- assert_equals(
- cookieString(reported),
- cookieString(observedStore),
- 'Mismatch between observed store and reported store.' +
- '\n observed:\n ' + cookieString(observedStore) +
- '\n reported:\n ' + cookieString(reported) +
- '\n log:\n ' + observationLog.map(JSON.stringify).join('\n '));
- } catch (e) {
- logEntry.push([' *** ⚠ *** ERROR: EXCEPTION THROWN *** ⚠ *** ']);
- savedExceptions.push('Exception in observer');
- savedExceptions.push(e);
- if (reject) reject(e);
- throw e;
- }
- // Resolve promise after first callback
- if (resolve) resolve(observer);
- resolve = null;
- reject = null;
- };
- CookieObserver.startTimer_ = (handler, ignoredDelay) => {
- var timer = {shouldRun: true, fingerPrint: Math.random()};
- new Promise(resolve => s\u0065tTimeout(resolve)).then(() => {
- if (!timer.shouldRun) return;
- CookieObserver.stopTimer_(timer);
- handler();
- });
- return timer;
- };
- CookieObserver.stopTimer_ = timer => {
- timer.shouldRun = false;
- };
- let observer = new CookieObserver(callback);
- // If null or omitted this defaults to location.pathname up to and
- // including the final '/' in a document context, or worker scope up
- // to and including the final '/' in a service worker context.
- let url = (location.pathname).replace(/[^\/]+$/, '');
- // If null or omitted this defaults to interest in all
- // script-visible cookies.
- let interests = [
- // Interested in all secure cookies named '__Secure-COOKIENAME';
- // the default matchType is 'equals' at the given URL.
- { name: '__Secure-COOKIENAME', url: url },
- // Interested in all simple origin cookies named like
- // /^__Host-COOKIEN.*$/ at the default URL.
- { name: '__Host-COOKIEN', matchType: 'startsWith' },
- // Interested in all simple origin cookies named '__Host-1🍪'
- // at the default URL.
- { name: '__Host-1🍪' },
- // Interested in all cookies named 'OLDCOOKIENAME' at the given URL.
- { name: 'OLDCOOKIENAME', matchType: 'equals', url: url },
- // Interested in all simple origin cookies named like
- // /^__Host-AUTHTOKEN.*$/ at the given URL.
- { name: '__Host-AUTHTOKEN', matchType: 'startsWith', url: url + 'auth/' }
- ];
- observer.observe(cookieStore, interests);
- // Default interest: all script-visible changes, default URL
- observer.observe(cookieStore);
-};
-
-// Rewrite testObservation_ to use a path we are allowed to see from a
-// document context.
-//
-// FIXME: remove this once ServiceWorker support is implemented and
-// path observation can actually be verified at a sub-path.
-if (kHasDocument) {
- testObservation_ = eval(String(testObservation_).split('auth/').join('auth'));
-}
-
-// Wrap testObservation_ to work as a promise.
-const testObservation = () => new Promise(testObservation_);
-
-// Verify behavior of no-name and no-value cookies.
-let testNoNameAndNoValue = async () => {
- await cookieStore.set('', 'first-value');
- let actual1 =
- (await cookieStore.getAll('')).map(({ value }) => value).join(';');
- let expected1 = 'first-value';
- if (actual1 !== expected1) throw new Error(
- 'Expected ' + JSON.stringify(expected1) +
- ' but got ' + JSON.stringify(actual1));
- await cookieStore.set('', '');
- let actual2 =
- (await cookieStore.getAll('')).map(({ value }) => value).join(';');
- let expected2 = '';
- if (actual2 !== expected2) throw new Error(
- 'Expected ' + JSON.stringify(expected) +
- ' but got ' + JSON.stringify(actual));
- await cookieStore.delete('');
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after testNoNameAndNoValue');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after testNoNameAndNoValue');
- if (kHasDocument) assert_equals(
- await getCookieStringDocument(),
- undefined,
- 'Empty document.cookie cookie jar after testNoNameAndNoValue');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after testNoNameAndNoValue');
-};
-
-// Verify behavior of multiple no-name cookies.
-let testNoNameMultipleValues = async () => {
- await cookieStore.set('', 'first-value');
- let actual1 =
- (await cookieStore.getAll('')).map(({ value }) => value).join(';');
- let expected1 = 'first-value';
- if (actual1 !== expected1) throw new Error(
- 'Expected ' + JSON.stringify(expected1) +
- ' but got ' + JSON.stringify(actual1));
- await cookieStore.set('', 'second-value');
- let actual2 =
- (await cookieStore.getAll('')).map(({ value }) => value).join(';');
- let expected2 = 'second-value';
- if (actual2 !== expected2) throw new Error(
- 'Expected ' + JSON.stringify(expected2) +
- ' but got ' + JSON.stringify(actual2));
- await cookieStore.delete('');
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after testNoNameMultipleValues');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after testNoNameMultipleValues');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after testNoNameMultipleValues');
-};
-
-// Verify that attempting to set a cookie with no name and with '=' in
-// the value does not work.
-let testNoNameEqualsInValue = async () => {
- await cookieStore.set('', 'first-value');
- let actual1 =
- (await cookieStore.getAll('')).map(({ value }) => value).join(';');
- let expected1 = 'first-value';
- if (actual1 !== expected1) throw new Error(
- 'Expected ' + JSON.stringify(expected1) +
- ' but got ' + JSON.stringify(actual1));
- try {
- await cookieStore.set('', 'suspicious-value=resembles-name-and-value');
- } catch (expectedError) {
- let actual2 =
- (await cookieStore.getAll('')).map(({ value }) => value).join(';');
- let expected2 = 'first-value';
- if (actual2 !== expected2) throw new Error(
- 'Expected ' + JSON.stringify(expected2) +
- ' but got ' + JSON.stringify(actual2));
- assert_equals(
- await getCookieString(),
- 'first-value',
- 'Earlier cookie jar after rejected part of testNoNameEqualsInValue');
- await cookieStore.delete('');
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after cleanup in testNoNameEqualsInValue');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after cleanup in testNoNameEqualsInValue');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after cleanup in testNoNameEqualsInValue');
- return;
- }
- throw new Error(
- 'Expected promise rejection' +
- ' when setting a cookie with no name and "=" in value');
-};
-
-// https://github.com/whatwg/html/issues/3076#issuecomment-332920132
-// proposes to remove <meta http-equiv="set-cookie" ... > but it is
-// not yet an accepted part of the HTML spec.
-//
-// Until the feature is gone, it interacts with other cookie APIs,
-// including this one.
-//
-// When kMetaHttpEquivSetCookieIsGone is set, verify that <meta
-// http-equiv="set-cookie" ... > no longer works. Otherwise, verify
-// its interoperability with other APIs.
-let testMetaHttpEquivSetCookie = async () => {
- await setCookieStringMeta('META-🍪=🔵; path=/');
- if (kMetaHttpEquivSetCookieIsGone) {
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after no-longer-supported' +
- ' <meta http-equiv="set-cookie" ... >');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after no-longer-supported' +
- ' <meta http-equiv="set-cookie" ... >');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after no-longer-supported' +
- ' <meta http-equiv="set-cookie" ... >');
- } else {
- assert_equals(
- await getCookieString(),
- 'META-🍪=🔵',
- 'Cookie we wrote using' +
- ' <meta http-equiv="set-cookie" ... > in cookie jar');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- 'META-🍪=🔵',
- 'Cookie we wrote using' +
- ' <meta http-equiv="set-cookie" ... > in HTTP cookie jar');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- 'META-🍪=🔵',
- 'Cookie we wrote using' +
- ' <meta http-equiv="set-cookie" ... > in observed cookie jar');
- await setCookieStringMeta('META-🍪=DELETED; path=/; max-age=0');
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after <meta http-equiv="set-cookie" ... >' +
- ' cookie-clearing using max-age=0');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after <meta http-equiv="set-cookie" ... >' +
- ' cookie-clearing using max-age=0');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after <meta http-equiv="set-cookie" ... >' +
- ' cookie-clearing using max-age=0');
- }
-};
-
-// Verify interoperability of document.cookie with other APIs.
-let testDocumentCookie = async () => {
- await setCookieStringDocument('DOCUMENT-🍪=🔵; path=/');
- assert_equals(
- await getCookieString(),
- 'DOCUMENT-🍪=🔵',
- 'Cookie we wrote using document.cookie in cookie jar');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- 'DOCUMENT-🍪=🔵',
- 'Cookie we wrote using document.cookie in HTTP cookie jar');
- assert_equals(
- await getCookieStringDocument(),
- 'DOCUMENT-🍪=🔵',
- 'Cookie we wrote using document.cookie in document.cookie');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- 'DOCUMENT-🍪=🔵',
- 'Cookie we wrote using document.cookie in observed cookie jar');
- await setCookieStringDocument('DOCUMENT-🍪=DELETED; path=/; max-age=0');
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after document.cookie' +
- ' cookie-clearing using max-age=0');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after document.cookie' +
- ' cookie-clearing using max-age=0');
- assert_equals(
- await getCookieStringDocument(),
- undefined,
- 'Empty document.cookie cookie jar after document.cookie' +
- ' cookie-clearing using max-age=0');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after document.cookie cookie-clearing' +
- ' using max-age=0');
-};
-
-// Verify interoperability of HTTP Set-Cookie: with other APIs.
-let testHttpCookieAndSetCookieHeaders = async () => {
- await setCookieStringHttp('HTTP-🍪=🔵; path=/');
- assert_equals(
- await getCookieString(),
- 'HTTP-🍪=🔵',
- 'Cookie we wrote using HTTP in cookie jar');
- assert_equals(
- await getCookieStringHttp(),
- 'HTTP-🍪=🔵',
- 'Cookie we wrote using HTTP in HTTP cookie jar');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- 'HTTP-🍪=🔵',
- 'Cookie we wrote using HTTP in observed cookie jar');
- await setCookieStringHttp('HTTP-🍪=DELETED; path=/; max-age=0');
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after HTTP cookie-clearing using max-age=0');
- assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after HTTP cookie-clearing using max-age=0');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after HTTP cookie-clearing' +
- ' using max-age=0');
- await setCookieStringHttp('HTTPONLY-🍪=🔵; path=/; httponly');
- assert_equals(
- await getCookieString(),
- undefined,
- 'HttpOnly cookie we wrote using HTTP in cookie jar' +
- ' is invisible to script');
- assert_equals(
- await getCookieStringHttp(),
- 'HTTPONLY-🍪=🔵',
- 'HttpOnly cookie we wrote using HTTP in HTTP cookie jar');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'HttpOnly cookie we wrote using HTTP is invisible to observer');
- await setCookieStringHttp(
- 'HTTPONLY-🍪=DELETED; path=/; max-age=0; httponly');
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after HTTP cookie-clearing using max-age=0');
- assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after HTTP cookie-clearing using max-age=0');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after HTTP cookie-clearing' +
- ' using max-age=0');
- // Non-UTF-8 byte sequences cause the Set-Cookie to be dropped.
- await setCookieBinaryHttp(
- unescape(encodeURIComponent('HTTP-🍪=🔵')) + '\xef\xbf\xbd; path=/');
- assert_equals(
- await getCookieString(),
- 'HTTP-🍪=🔵\ufffd',
- 'Binary cookie we wrote using HTTP in cookie jar');
- assert_equals(
- await getCookieStringHttp(),
- 'HTTP-🍪=🔵\ufffd',
- 'Binary cookie we wrote using HTTP in HTTP cookie jar');
- assert_equals(
- decodeURIComponent(escape(await getCookieBinaryHttp())),
- 'HTTP-🍪=🔵\ufffd',
- 'Binary cookie we wrote in binary HTTP cookie jar');
- assert_equals(
- await getCookieBinaryHttp(),
- unescape(encodeURIComponent('HTTP-🍪=🔵')) + '\xef\xbf\xbd',
- 'Binary cookie we wrote in binary HTTP cookie jar');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- 'HTTP-🍪=🔵\ufffd',
- 'Binary cookie we wrote using HTTP in observed cookie jar');
- await setCookieBinaryHttp(
- unescape(encodeURIComponent('HTTP-🍪=DELETED; path=/; max-age=0')));
- assert_equals(
- await getCookieString(),
- undefined,
- 'Empty cookie jar after binary HTTP cookie-clearing using max-age=0');
- assert_equals(
- await getCookieStringHttp(),
- undefined,
- 'Empty HTTP cookie jar after' +
- ' binary HTTP cookie-clearing using max-age=0');
- assert_equals(
- await getCookieBinaryHttp(),
- undefined,
- 'Empty binary HTTP cookie jar after' +
- ' binary HTTP cookie-clearing using max-age=0');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- undefined,
- 'Empty observed cookie jar after binary HTTP cookie-clearing' +
- ' using max-age=0');
-};
-
-const testGetSetGetAll = async () => {
- await cookieStore.set('TEST', 'value0');
- assert_equals(
- await getCookieString(),
- 'TEST=value0',
- 'Cookie jar contains only cookie we set');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- 'TEST=value0',
- 'HTTP cookie jar contains only cookie we set');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- 'TEST=value0',
- 'Observed cookie jar contains only cookie we set');
- await cookieStore.set('TEST', 'value');
- assert_equals(
- await getCookieString(),
- 'TEST=value',
- 'Cookie jar contains only cookie we overwrote');
- if (!kIsStatic) assert_equals(
- await getCookieStringHttp(),
- 'TEST=value',
- 'HTTP cookie jar contains only cookie we overwrote');
- if (observer) assert_equals(
- await getCookieStringObserved(),
- 'TEST=value',
- 'Observed cookie jar contains only cookie we overwrote');
- let allCookies = await cookieStore.getAll();
- assert_equals(
- allCookies[0].name,
- 'TEST',
- 'First entry in allCookies should be named TEST');
- assert_equals(
- allCookies[0].value,
- 'value',
- 'First entry in allCookies should have value "value"');
- assert_equals(
- allCookies.length,
- 1,
- 'Only one cookie should exist in allCookies');
- let firstCookie = await cookieStore.get();
- assert_equals(
- firstCookie.name,
- 'TEST',
- 'First cookie should be named TEST');
- assert_equals(
- firstCookie.value,
- 'value',
- 'First cookie should have value "value"');
- let allCookies_TEST = await cookieStore.getAll('TEST');
- assert_equals(
- allCookies_TEST[0].name,
- 'TEST',
- 'First entry in allCookies_TEST should be named TEST');
- assert_equals(
- allCookies_TEST[0].value,
- 'value',
- 'First entry in allCookies_TEST should have value "value"');
- assert_equals(
- allCookies_TEST.length,
- 1,
- 'Only one cookie should exist in allCookies_TEST');
- let firstCookie_TEST = await cookieStore.get('TEST');
- assert_equals(
- firstCookie_TEST.name,
- 'TEST',
- 'First TEST cookie should be named TEST');
- assert_equals(
- firstCookie_TEST.value,
- 'value',
- 'First TEST cookie should have value "value"');
-};
-
-const testOneSimpleOriginCookie = async testCase => {
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- setOneSimpleOriginSessionCookie(),
- '__Host- prefix only writable from' +
- ' secure contexts (setOneSimpleOriginSessionCookie)');
- if (!kIsUnsecured) {
- assert_equals(
- await getOneSimpleOriginCookie(),
- 'cookie-value',
- '__Host-COOKIENAME cookie should be found' +
- ' in a secure context (getOneSimpleOriginCookie)');
- } else {
- assert_equals(
- await getOneSimpleOriginCookie(),
- undefined,
- '__Host-COOKIENAME cookie should not be found' +
- ' in an unsecured context (getOneSimpleOriginCookie)');
- }
- if (kIsUnsecured) {
- assert_equals(
- await countMatchingSimpleOriginCookies(),
- 0,
- 'No __Host-COOKIEN* cookies should be found' +
- ' in an unsecured context (countMatchingSimpleOriginCookies)');
- } else {
- assert_equals(
- await countMatchingSimpleOriginCookies(),
- 1,
- 'One __Host-COOKIEN* cookie should be found' +
- ' in a secure context (countMatchingSimpleOriginCookies)');
- }
-};
-
-const testExpiration = async testCase => {
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- setOneDaySecureCookieWithDate(),
- 'Secure cookies only writable' +
- ' from secure contexts (setOneDaySecureCookieWithDate)');
- await setOneDayUnsecuredCookieWithMillisecondsSinceEpoch();
- assert_equals(
- await getCookieString('LEGACYCOOKIENAME'),
- 'LEGACYCOOKIENAME=cookie-value',
- 'Ensure unsecured cookie we set is visible');
- if (observer) assert_equals(
- await getCookieStringObserved('LEGACYCOOKIENAME'),
- 'LEGACYCOOKIENAME=cookie-value',
- 'Ensure unsecured cookie we set is visible to observer');
- await deleteUnsecuredCookieWithDomainAndPath();
- await promise_rejects_when_unsecured(
- testCase,
- new TypeError(),
- setSecureCookieWithHttpLikeExpirationString(),
- 'Secure cookies only writable from secure contexts' +
- ' (setSecureCookieWithHttpLikeExpirationString)');
-};
-
-// Rewrite domain and path in affected cases to match current test
-// domain and directory.
-//
-// FIXME: remove these once ServiceWorker support and cross-domain
-// testing are added and full domain and path coverage is possible.
-setOneDaySecureCookieWithDate =
- eval(String(setOneDaySecureCookieWithDate).split(
- '/cgi-bin/').join(location.pathname.replace(/[^/]+$/, '')));
-setOneDaySecureCookieWithDate =
- eval(String(setOneDaySecureCookieWithDate).split(
- 'example.org').join(location.hostname));
-setOneDayUnsecuredCookieWithMillisecondsSinceEpoch =
- eval(String(setOneDayUnsecuredCookieWithMillisecondsSinceEpoch).split(
- '/cgi-bin/').join(location.pathname.replace(/[^/]+$/, '')));
-setOneDayUnsecuredCookieWithMillisecondsSinceEpoch =
- eval(String(setOneDayUnsecuredCookieWithMillisecondsSinceEpoch).split(
- 'example.org').join(location.hostname));
-deleteUnsecuredCookieWithDomainAndPath =
- eval(String(deleteUnsecuredCookieWithDomainAndPath).split(
- '/cgi-bin/').join(location.pathname.replace(/[^/]+$/, '')));
-deleteUnsecuredCookieWithDomainAndPath =
- eval(String(deleteUnsecuredCookieWithDomainAndPath).split(
- 'example.org').join(location.hostname));
-setSecureCookieWithHttpLikeExpirationString =
- eval(String(setSecureCookieWithHttpLikeExpirationString).split(
- '/cgi-bin/').join(location.pathname.replace(/[^/]+$/, '')));
-setSecureCookieWithHttpLikeExpirationString =
- eval(String(setSecureCookieWithHttpLikeExpirationString).split(
- 'example.org').join(location.hostname));
-setExpiredSecureCookieWithDomainPathAndFallbackValue =
- eval(String(setExpiredSecureCookieWithDomainPathAndFallbackValue).split(
- '/cgi-bin/').join(location.pathname.replace(/[^/]+$/, '')));
-setExpiredSecureCookieWithDomainPathAndFallbackValue =
- eval(String(setExpiredSecureCookieWithDomainPathAndFallbackValue).split(
- 'example.org').join(location.hostname));
-deleteSecureCookieWithDomainAndPath =
- eval(String(deleteSecureCookieWithDomainAndPath).split(
- '/cgi-bin/').join(location.pathname.replace(/[^/]+$/, '')));
-deleteSecureCookieWithDomainAndPath =
- eval(String(deleteSecureCookieWithDomainAndPath).split(
- 'example.org').join(location.hostname));
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/testharness-helpers.js b/tests/wpt/web-platform-tests/cookie-store/resources/cookie-test-helpers.js
index 7e644c78039..20f67e3f876 100644
--- a/tests/wpt/web-platform-tests/cookie-store/resources/testharness-helpers.js
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/cookie-test-helpers.js
@@ -1,71 +1,14 @@
'use strict';
-// Length of final setTimeout when observer callback has not fired.
-//
-const kExtraObserverDelay = 0; // For builtin implementation
-
-// NOTE: A polyfill was used for pre-implementation testing. To revive
-// it uncomment these and comment out the preceding line:
-//
-// const kExtraObserverDelay = 200; // Polyfill when not running on battery
-// // const kExtraObserverDelay = 5000; // ... when running on battery
-// document.open();
-// document.write(`
-// <script>delete cookieStore</script>
-// <script src="https://wicg.github.io/cookie-store/cookies.js">
-// </script>
-// `);
-// document.close()
-
-// See https://github.com/whatwg/html/pull/3011#issuecomment-331187136
-// and https://www.chromestatus.com/feature/6170540112871424
-const kMetaHttpEquivSetCookieIsGone = true;
+// TODO(jsbell): Once ServiceWorker is supported, add arbitrary path coverage.
+const kPath = location.pathname.replace(/[^/]+$/, '');
// True when running in a document context as opposed to a worker context
const kHasDocument = typeof document !== 'undefined';
-// Override for named test inclusion. Set by suite().
-let testOverride = undefined;
-
-// Determines whether the named test should be included in this run of the
-// suite. Only usable in a test runner context as this uses assert_equals.
-//
-// Parameters:
-//
-// - testName: (string) test name; must be an identifier starting with 'test'
-// - opt_excludeFromAll: (optional; boolean) if true, explicit or implicit
-// #...&test=all (which is the default) will not activate this test.
-const includeTest = (testName, opt_excludeFromAll) => {
- assert_equals(!!testName.match(/^test\w+/), true, 'includeTest: ' + testName);
- assert_equals(typeof eval(testName), 'function', 'includeTest: ' + testName);
- let testParams =
- (location.hash || '#').substr(1).split('&').filter(
- x => x.match(/^test=/)).map(x => decodeURIComponent(x));
- if (!testParams.length) {
- testParams = ['test=all'];
- if (testOverride !== undefined) {
- testParams = ['test=' + testOverride];
- }
- }
- const filterSet =
- testParams.map(x => x.split('=', 2)[1]).join(',').split(',').reduce(
- (set, name) => Object.assign(set, {[name]: true}), {});
- for (let name in filterSet) {
- if (name === 'all' || !filterSet.hasOwnProperty(name)) continue;
- assert_equals(!!name.match(/^test\w+/), true, '#test=' + testName);
- assert_equals(typeof eval(name), 'function', '#test=' + testName);
- }
- return (filterSet.all && !opt_excludeFromAll) ||
- filterSet.hasOwnProperty(testName) && filterSet[testName];
-}
-
// True when running on unsecured 'http:' rather than secured 'https:'.
const kIsUnsecured = location.protocol !== 'https:';
-// True when no CGI/no active wptserve handlers should be used.
-const kIsStatic = !!((location.hash || '#').match(/(^#|&)static=true(&|$)/) ||
- location.pathname.match(/_static\./));
-
const kCookieHelperCgi = 'resources/cookie_helper.py';
// Async wrapper for an async function or promise that is expected
@@ -79,13 +22,13 @@ const kCookieHelperCgi = 'resources/cookie_helper.py';
// - promise: (thenable) test code
// - message: (optional; string) message to forward to promise_rejects in
// unsecured context
-const promise_rejects_when_unsecured = async (
- testCase,
- code,
- promise,
- message = 'Feature unavailable from unsecured contexts'
-) => {
- if (kIsUnsecured) await promise_rejects(testCase, code, promise, message);
+async function promise_rejects_when_unsecured(
+ testCase,
+ code,
+ promise,
+ message = 'Feature unavailable from unsecured contexts') {
+ if (kIsUnsecured)
+ await promise_rejects(testCase, code, promise, message);
else await promise;
};
@@ -97,9 +40,11 @@ const promise_rejects_when_unsecured = async (
//
// Returns a string serializing the records, or undefined if no records were
// given.
-const cookieString = cookies => cookies.length ? cookies.map((
+function cookieString(cookies) {
+ return cookies.length ? cookies.map((
{name, value}) => (name ? (name + '=') : '') + value).join('; ') :
- undefined;
+ undefined;
+}
// Approximate async equivalent to the document.cookie getter but with
// important differences: optional additional getAll arguments are
@@ -110,7 +55,7 @@ const cookieString = cookies => cookies.length ? cookies.map((
// assert_equals in failing cases than assert_object_equals would
// using parsed cookie jar contents and also allows expectations to be
// written more compactly.
-const getCookieString = async (...args) => {
+async function getCookieString(...args) {
return cookieString(await cookieStore.getAll(...args));
}
@@ -120,8 +65,7 @@ const getCookieString = async (...args) => {
//
// Unlike document.cookie, this returns undefined when no cookies are
// present.
-const getCookieStringHttp = async (extraPath = null) => {
- if (kIsStatic) throw 'CGI not available in static HTML test';
+async function getCookieStringHttp(extraPath = null) {
const url =
kCookieHelperCgi + ((extraPath == null) ? '' : ('/' + extraPath));
const response = await fetch(url, { credentials: 'include' });
@@ -134,7 +78,8 @@ const getCookieStringHttp = async (extraPath = null) => {
response.headers.get('content-type'),
'text/plain; charset=utf-8',
'CGI did not return UTF-8 text in getCookieStringHttp');
- if (text === '') return undefined;
+ if (text === '')
+ return undefined;
assert_equals(
text.indexOf('cookie='),
0,
@@ -148,8 +93,7 @@ const getCookieStringHttp = async (extraPath = null) => {
//
// Unlike document.cookie, this returns undefined when no cookies are
// present.
-const getCookieBinaryHttp = async (extraPath = null) => {
- if (kIsStatic) throw 'CGI not available in static HTML test';
+async function getCookieBinaryHttp(extraPath = null) {
const url =
kCookieHelperCgi +
((extraPath == null) ?
@@ -165,7 +109,8 @@ const getCookieBinaryHttp = async (extraPath = null) => {
response.headers.get('content-type'),
'text/plain; charset=iso-8859-1',
'CGI did not return ISO 8859-1 text in getCookieBinaryHttp');
- if (text === '') return undefined;
+ if (text === '')
+ return undefined;
assert_equals(
text.indexOf('cookie='),
0,
@@ -175,8 +120,7 @@ const getCookieBinaryHttp = async (extraPath = null) => {
// Approximate async equivalent to the document.cookie setter but from
// the server's point of view.
-const setCookieStringHttp = async setCookie => {
- if (kIsStatic) throw 'CGI not available in static HTML test';
+async function setCookieStringHttp(setCookie) {
const encodedSetCookie = encodeURIComponent(setCookie);
const url = kCookieHelperCgi;
const headers = new Headers();
@@ -205,13 +149,12 @@ const setCookieStringHttp = async setCookie => {
text,
'set-cookie=' + encodedSetCookie,
'CGI did not faithfully echo the set-cookie value');
-};
+}
// Approximate async equivalent to the document.cookie setter but from
// the server's point of view. This version sets a binary cookie rather
// than a UTF-8 one.
-const setCookieBinaryHttp = async setCookie => {
- if (kIsStatic) throw 'CGI not available in static HTML test';
+async function setCookieBinaryHttp(setCookie) {
const encodedSetCookie = escape(setCookie).split('/').join('%2F');
const url = kCookieHelperCgi + '?charset=iso-8859-1';
const headers = new Headers();
@@ -238,49 +181,90 @@ const setCookieBinaryHttp = async setCookie => {
text,
'set-cookie=' + encodedSetCookie,
'CGI did not faithfully echo the set-cookie value');
-};
-
-// Approximate async equivalent to the document.cookie setter but using
-// <meta http-equiv="set-cookie" content="..."> written into a temporary
-// IFRAME. Merely appending the node to HEAD works in some browsers (e.g.
-// Chromium) but not others (e.g. Firefox.)
-const setCookieStringMeta = async setCookie => {
- if (document.readyState !== 'complete') {
- await new Promise(resolve => addEventListener('load', resolve, true));
- }
- const meta = Object.assign(document.createElement('meta'), {
- httpEquiv: 'set-cookie',
- content: setCookie
- });
- const ifr = document.createElement('iframe');
- await new Promise(resolve => document.body.appendChild(Object.assign(
- ifr,
- {
- onload: resolve
- })));
- try {
- ifr.contentWindow.document.open('text/html; charset=utf-8');
- ifr.contentWindow.document.write([
- '<!DOCTYPE html>',
- '<meta charset="utf-8">',
- meta.outerHTML
- ].join('\r\n'));
- ifr.contentWindow.document.close();
- } finally {
- if (ifr.parentNode) ifr.parentNode.removeChild(ifr);
- }
-};
+}
// Async document.cookie getter; converts '' to undefined which loses
// information in the edge case where a single ''-valued anonymous
// cookie is visible.
-const getCookieStringDocument = async () => {
- if (!kHasDocument) throw 'document.cookie not available in this context';
+async function getCookieStringDocument() {
+ if (!kHasDocument)
+ throw 'document.cookie not available in this context';
return String(document.cookie || '') || undefined;
-};
+}
// Async document.cookie setter
-const setCookieStringDocument = async setCookie => {
- if (!kHasDocument) throw 'document.cookie not available in this context';
+async function setCookieStringDocument(setCookie) {
+ if (!kHasDocument)
+ throw 'document.cookie not available in this context';
document.cookie = setCookie;
-};
+}
+
+// Observe the next 'change' event on the cookieStore. Typical usage:
+//
+// const eventPromise = observeNextCookieChangeEvent();
+// await /* something that modifies cookies */
+// await verifyCookieChangeEvent(
+// eventPromise, {changed: [{name: 'name', value: 'value'}]});
+//
+function observeNextCookieChangeEvent() {
+ return new Promise(resolve => {
+ cookieStore.addEventListener('change', e => resolve(e), {once: true});
+ });
+}
+
+async function verifyCookieChangeEvent(eventPromise, expected, description) {
+ description = description ? description + ': ' : '';
+ expected = Object.assign({changed:[], deleted:[]}, expected);
+ const event = await eventPromise;
+ assert_equals(event.changed.length, expected.changed.length,
+ description + 'number of changed cookies');
+ for (let i = 0; i < event.changed.length; ++i) {
+ assert_equals(event.changed[i].name, expected.changed[i].name,
+ description + 'changed cookie name');
+ assert_equals(event.changed[i].value, expected.changed[i].value,
+ description + 'changed cookie value');
+ }
+ assert_equals(event.deleted.length, expected.deleted.length,
+ description + 'number of deleted cookies');
+ for (let i = 0; i < event.deleted.length; ++i) {
+ assert_equals(event.deleted[i].name, expected.deleted[i].name,
+ description + 'deleted cookie name');
+ assert_equals(event.deleted[i].value, expected.deleted[i].value,
+ description + 'deleted cookie value');
+ }
+}
+
+// Helper function for promise_test with cookies; cookies
+// named in these tests are cleared before/after the test
+// body function is executed.
+async function cookie_test(func, description) {
+
+ // Wipe cookies used by tests before and after the test.
+ async function deleteTestCookies() {
+ await cookieStore.delete('');
+ await cookieStore.delete('TEST');
+ await cookieStore.delete('META-🍪');
+ await cookieStore.delete('DOCUMENT-🍪');
+ await cookieStore.delete('HTTP-🍪');
+ await setCookieStringHttp(
+ 'HTTPONLY-🍪=DELETED; path=/; max-age=0; httponly');
+ if (!kIsUnsecured) {
+ await cookieStore.delete('__Host-COOKIENAME');
+ await cookieStore.delete('__Host-1🍪');
+ await cookieStore.delete('__Host-2🌟');
+ await cookieStore.delete('__Host-3🌱');
+ await cookieStore.delete('__Host-unordered1🍪');
+ await cookieStore.delete('__Host-unordered2🌟');
+ await cookieStore.delete('__Host-unordered3🌱');
+ }
+ }
+
+ return promise_test(async t => {
+ await deleteTestCookies();
+ try {
+ return await func(t);
+ } finally {
+ await deleteTestCookies();
+ }
+ }, description);
+}
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/delete_cookies.js b/tests/wpt/web-platform-tests/cookie-store/resources/delete_cookies.js
new file mode 100644
index 00000000000..21adadbda9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/delete_cookies.js
@@ -0,0 +1,44 @@
+'use strict';
+
+cookie_test(async testCase => {
+ // TODO: This test doesn't create cookies and doesn't assert
+ // the behavior of delete(). Improve or remove it.
+
+ await cookieStore.delete('');
+ await cookieStore.delete('TEST');
+ await cookieStore.delete('META-🍪');
+ await cookieStore.delete('DOCUMENT-🍪');
+ await cookieStore.delete('HTTP-🍪');
+
+ await setCookieStringHttp(
+ 'HTTPONLY-🍪=DELETED; path=/; max-age=0; httponly');
+
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-COOKIENAME'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-1🍪'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-2🌟'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-3🌱'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-unordered1🍪'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-unordered2🌟'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-unordered3🌱'));
+}, 'Test cookieStore.delete');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/document_cookie.js b/tests/wpt/web-platform-tests/cookie-store/resources/document_cookie.js
new file mode 100644
index 00000000000..1809b883501
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/document_cookie.js
@@ -0,0 +1,43 @@
+'use strict';
+
+cookie_test(async t => {
+ let eventPromise = observeNextCookieChangeEvent();
+ await setCookieStringDocument('DOCUMENT-🍪=🔵; path=/');
+ assert_equals(
+ await getCookieString(),
+ 'DOCUMENT-🍪=🔵',
+ 'Cookie we wrote using document.cookie in cookie jar');
+ assert_equals(
+ await getCookieStringHttp(),
+ 'DOCUMENT-🍪=🔵',
+ 'Cookie we wrote using document.cookie in HTTP cookie jar');
+ assert_equals(
+ await getCookieStringDocument(),
+ 'DOCUMENT-🍪=🔵',
+ 'Cookie we wrote using document.cookie in document.cookie');
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: 'DOCUMENT-🍪', value: '🔵'}]},
+ 'Cookie we wrote using document.cookie is observed');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await setCookieStringDocument('DOCUMENT-🍪=DELETED; path=/; max-age=0');
+ assert_equals(
+ await getCookieString(),
+ undefined,
+ 'Empty cookie jar after document.cookie' +
+ ' cookie-clearing using max-age=0');
+ assert_equals(
+ await getCookieStringHttp(),
+ undefined,
+ 'Empty HTTP cookie jar after document.cookie' +
+ ' cookie-clearing using max-age=0');
+ assert_equals(
+ await getCookieStringDocument(),
+ undefined,
+ 'Empty document.cookie cookie jar after document.cookie' +
+ ' cookie-clearing using max-age=0');
+ await verifyCookieChangeEvent(
+ eventPromise, {deleted: [{name: 'DOCUMENT-🍪'}]},
+ 'Deletion observed after document.cookie cookie-clearing' +
+ ' using max-age=0');
+}, 'Verify interoperability of document.cookie with other APIs.');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/expiration.js b/tests/wpt/web-platform-tests/cookie-store/resources/expiration.js
new file mode 100644
index 00000000000..816ace48693
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/expiration.js
@@ -0,0 +1,89 @@
+'use strict';
+
+// Set the secure example.org-domain cookie __Secure-COOKIENAME with
+// value cookie-value on path /cgi-bin/ and 24 hour duration; domain
+// and path will be rewritten below.
+//
+// This uses a Date object for expiration.
+async function setOneDaySecureCookieWithDate() {
+ // one day ahead, ignoring a possible leap-second
+ let inTwentyFourHours = new Date(Date.now() + 24 * 60 * 60 * 1000);
+ await cookieStore.set('__Secure-COOKIENAME', 'cookie-value', {
+ path: kPath,
+ expires: inTwentyFourHours,
+ secure: true,
+ domain: location.hostname
+ });
+}
+
+// Set the secured example.org-domain cookie __Secure-COOKIENAME with
+// value cookie-value on path /cgi-bin/ and expiration in June of next
+// year; domain and path will be rewritten below.
+//
+// This uses an HTTP-style date string for expiration.
+async function setSecureCookieWithHttpLikeExpirationString() {
+ const year = (new Date()).getUTCFullYear() + 1;
+ const date = new Date('07 Jun ' + year + ' 07:07:07 UTC');
+ const day = ('Sun Mon Tue Wed Thu Fri Sat'.split(' '))[date.getUTCDay()];
+ await cookieStore.set('__Secure-COOKIENAME', 'cookie-value', {
+ path: kPath,
+ expires: day + ', 07 Jun ' + year + ' 07:07:07 GMT',
+ secure: true,
+ domain: location.hostname
+ });
+}
+
+// Set the unsecured example.org-domain cookie LEGACYCOOKIENAME with
+// value cookie-value on path /cgi-bin/ and 24 hour duration; domain
+// and path will be rewritten below.
+//
+// This uses milliseconds since the start of the Unix epoch for
+// expiration.
+async function setOneDayUnsecuredCookieWithMillisecondsSinceEpoch() {
+ // one day ahead, ignoring a possible leap-second
+ let inTwentyFourHours = Date.now() + 24 * 60 * 60 * 1000;
+ await cookieStore.set('LEGACYCOOKIENAME', 'cookie-value', {
+ path: kPath,
+ expires: inTwentyFourHours,
+ secure: false,
+ domain: location.hostname
+ });
+}
+
+// Delete the cookie written by
+// setOneDayUnsecuredCookieWithMillisecondsSinceEpoch.
+async function deleteUnsecuredCookieWithDomainAndPath() {
+ await cookieStore.delete('LEGACYCOOKIENAME', {
+ path: kPath,
+ secure: false,
+ domain: location.hostname
+ });
+}
+
+cookie_test(async testCase => {
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ setOneDaySecureCookieWithDate(),
+ 'Secure cookies only writable from secure contexts');
+
+ const eventPromise = observeNextCookieChangeEvent();
+
+ await setOneDayUnsecuredCookieWithMillisecondsSinceEpoch();
+ assert_equals(
+ await getCookieString('LEGACYCOOKIENAME'),
+ 'LEGACYCOOKIENAME=cookie-value',
+ 'Ensure unsecured cookie we set is visible');
+
+ await verifyCookieChangeEvent(
+ eventPromise,
+ {changed: [{name: 'LEGACYCOOKIENAME', value: 'cookie-value'}]},
+ 'Ensure unsecured cookie we set is visible to observer');
+
+ await deleteUnsecuredCookieWithDomainAndPath();
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ setSecureCookieWithHttpLikeExpirationString(),
+ 'Secure cookies only writable from secure contexts');
+}, 'expiration');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/get_set_get_all.js b/tests/wpt/web-platform-tests/cookie-store/resources/get_set_get_all.js
new file mode 100644
index 00000000000..7c9a094d3e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/get_set_get_all.js
@@ -0,0 +1,74 @@
+'use strict';
+
+cookie_test(async t => {
+ let eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.set('TEST', 'value0');
+ assert_equals(
+ await getCookieString(),
+ 'TEST=value0',
+ 'Cookie jar contains only cookie we set');
+ assert_equals(
+ await getCookieStringHttp(),
+ 'TEST=value0',
+ 'HTTP cookie jar contains only cookie we set');
+ await verifyCookieChangeEvent(
+ eventPromise,
+ {changed: [{name: 'TEST', value: 'value0'}]},
+ 'Observed value that was set');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.set('TEST', 'value');
+ assert_equals(
+ await getCookieString(),
+ 'TEST=value',
+ 'Cookie jar contains only cookie we overwrote');
+ await verifyCookieChangeEvent(
+ eventPromise,
+ {changed: [{name: 'TEST', value: 'value'}]},
+ 'Observed value that was overwritten');
+
+ let allCookies = await cookieStore.getAll();
+ assert_equals(
+ allCookies[0].name,
+ 'TEST',
+ 'First entry in allCookies should be named TEST');
+ assert_equals(
+ allCookies[0].value,
+ 'value',
+ 'First entry in allCookies should have value "value"');
+ assert_equals(
+ allCookies.length,
+ 1,
+ 'Only one cookie should exist in allCookies');
+ let firstCookie = await cookieStore.get();
+ assert_equals(
+ firstCookie.name,
+ 'TEST',
+ 'First cookie should be named TEST');
+ assert_equals(
+ firstCookie.value,
+ 'value',
+ 'First cookie should have value "value"');
+ let allCookies_TEST = await cookieStore.getAll('TEST');
+ assert_equals(
+ allCookies_TEST[0].name,
+ 'TEST',
+ 'First entry in allCookies_TEST should be named TEST');
+ assert_equals(
+ allCookies_TEST[0].value,
+ 'value',
+ 'First entry in allCookies_TEST should have value "value"');
+ assert_equals(
+ allCookies_TEST.length,
+ 1,
+ 'Only one cookie should exist in allCookies_TEST');
+ let firstCookie_TEST = await cookieStore.get('TEST');
+ assert_equals(
+ firstCookie_TEST.name,
+ 'TEST',
+ 'First TEST cookie should be named TEST');
+ assert_equals(
+ firstCookie_TEST.value,
+ 'value',
+ 'First TEST cookie should have value "value"');
+}, 'Get/set/get all cookies in store');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/http_cookie_and_set_cookie_headers.js b/tests/wpt/web-platform-tests/cookie-store/resources/http_cookie_and_set_cookie_headers.js
new file mode 100644
index 00000000000..73534c743ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/http_cookie_and_set_cookie_headers.js
@@ -0,0 +1,112 @@
+'use strict';
+
+cookie_test(async t => {
+ let eventPromise = observeNextCookieChangeEvent();
+ await setCookieStringHttp('HTTP-🍪=🔵; path=/');
+ assert_equals(
+ await getCookieString(),
+ 'HTTP-🍪=🔵',
+ 'Cookie we wrote using HTTP in cookie jar');
+ assert_equals(
+ await getCookieStringHttp(),
+ 'HTTP-🍪=🔵',
+ 'Cookie we wrote using HTTP in HTTP cookie jar');
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: 'HTTP-🍪', value: '🔵'}]},
+ 'Cookie we wrote using HTTP is observed');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await setCookieStringHttp('HTTP-🍪=DELETED; path=/; max-age=0');
+ assert_equals(
+ await getCookieString(),
+ undefined,
+ 'Empty cookie jar after HTTP cookie-clearing using max-age=0');
+ assert_equals(
+ await getCookieStringHttp(),
+ undefined,
+ 'Empty HTTP cookie jar after HTTP cookie-clearing using max-age=0');
+ await verifyCookieChangeEvent(
+ eventPromise, {deleted: [{name: 'HTTP-🍪'}]},
+ 'Deletion observed after HTTP cookie-clearing using max-age=0');
+ await cookieStore.delete('HTTP-🍪');
+}, 'Interoperability of HTTP Set-Cookie: with other APIs');
+
+cookie_test(async t => {
+ let eventPromise = observeNextCookieChangeEvent();
+ await setCookieStringHttp('HTTPONLY-🍪=🔵; path=/; httponly');
+ assert_equals(
+ await getCookieString(),
+ undefined,
+ 'HttpOnly cookie we wrote using HTTP in cookie jar' +
+ ' is invisible to script');
+ assert_equals(
+ await getCookieStringHttp(),
+ 'HTTPONLY-🍪=🔵',
+ 'HttpOnly cookie we wrote using HTTP in HTTP cookie jar');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await setCookieStringHttp(
+ 'HTTPONLY-🍪=DELETED; path=/; max-age=0; httponly');
+ assert_equals(
+ await getCookieString(),
+ undefined,
+ 'Empty cookie jar after HTTP cookie-clearing using max-age=0');
+ assert_equals(
+ await getCookieStringHttp(),
+ undefined,
+ 'Empty HTTP cookie jar after HTTP cookie-clearing using max-age=0');
+
+ // HTTPONLY cookie changes should not have been observed; perform
+ // a dummy change to verify that nothing else was queued up.
+ await cookieStore.set('TEST', 'dummy');
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: 'TEST', value: 'dummy'}]},
+ 'HttpOnly cookie deletion was not observed');
+}, 'HttpOnly cookies are not observed');
+
+cookie_test(async t => {
+ // Non-UTF-8 byte sequences cause the Set-Cookie to be dropped.
+ let eventPromise = observeNextCookieChangeEvent();
+ await setCookieBinaryHttp(
+ unescape(encodeURIComponent('HTTP-🍪=🔵')) + '\xef\xbf\xbd; path=/');
+ assert_equals(
+ await getCookieString(),
+ 'HTTP-🍪=🔵\ufffd',
+ 'Binary cookie we wrote using HTTP in cookie jar');
+ assert_equals(
+ await getCookieStringHttp(),
+ 'HTTP-🍪=🔵\ufffd',
+ 'Binary cookie we wrote using HTTP in HTTP cookie jar');
+ assert_equals(
+ decodeURIComponent(escape(await getCookieBinaryHttp())),
+ 'HTTP-🍪=🔵\ufffd',
+ 'Binary cookie we wrote in binary HTTP cookie jar');
+ assert_equals(
+ await getCookieBinaryHttp(),
+ unescape(encodeURIComponent('HTTP-🍪=🔵')) + '\xef\xbf\xbd',
+ 'Binary cookie we wrote in binary HTTP cookie jar');
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: 'HTTP-🍪', value: '🔵\ufffd'}]},
+ 'Binary cookie we wrote using HTTP is observed');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await setCookieBinaryHttp(
+ unescape(encodeURIComponent('HTTP-🍪=DELETED; path=/; max-age=0')));
+ assert_equals(
+ await getCookieString(),
+ undefined,
+ 'Empty cookie jar after binary HTTP cookie-clearing using max-age=0');
+ assert_equals(
+ await getCookieStringHttp(),
+ undefined,
+ 'Empty HTTP cookie jar after' +
+ ' binary HTTP cookie-clearing using max-age=0');
+ assert_equals(
+ await getCookieBinaryHttp(),
+ undefined,
+ 'Empty binary HTTP cookie jar after' +
+ ' binary HTTP cookie-clearing using max-age=0');
+ await verifyCookieChangeEvent(
+ eventPromise, {deleted: [{name: 'HTTP-🍪'}]},
+ 'Deletion observed after binary HTTP cookie-clearing using max-age=0');
+}, 'Binary HTTP cookies');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/no_name_and_no_value.js b/tests/wpt/web-platform-tests/cookie-store/resources/no_name_and_no_value.js
new file mode 100644
index 00000000000..e0c11a6cb65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/no_name_and_no_value.js
@@ -0,0 +1,45 @@
+'use strict';
+
+cookie_test(async t => {
+ let eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.set('', 'first-value');
+ const actual1 =
+ (await cookieStore.getAll('')).map(({ value }) => value).join(';');
+ const expected1 = 'first-value';
+ assert_equals(actual1, expected1);
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: '', value: 'first-value'}]},
+ 'Observed no-name change');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.set('', '');
+ const actual2 =
+ (await cookieStore.getAll('')).map(({ value }) => value).join(';');
+ const expected2 = '';
+ assert_equals(actual2, expected2);
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: '', value: ''}]},
+ 'Observed no-name change');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.delete('');
+ await verifyCookieChangeEvent(
+ eventPromise, {deleted: [{name: ''}]},
+ 'Observed no-name deletion');
+
+ assert_equals(
+ await getCookieString(),
+ undefined,
+ 'Empty cookie jar');
+ assert_equals(
+ await getCookieStringHttp(),
+ undefined,
+ 'Empty HTTP cookie jar');
+ if (kHasDocument) {
+ assert_equals(
+ await getCookieStringDocument(),
+ undefined,
+ 'Empty document.cookie cookie jar');
+ }
+
+}, 'Verify behavior of no-name and no-value cookies.');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/no_name_equals_in_value.js b/tests/wpt/web-platform-tests/cookie-store/resources/no_name_equals_in_value.js
new file mode 100644
index 00000000000..3dc73e80799
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/no_name_equals_in_value.js
@@ -0,0 +1,46 @@
+'use strict';
+
+cookie_test(async t => {
+ let eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.set('', 'first-value');
+ const actual1 =
+ (await cookieStore.getAll('')).map(({ value }) => value).join(';');
+ const expected1 = 'first-value';
+ assert_equals(actual1, expected1);
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: '', value: 'first-value'}]},
+ 'Observed no-name change');
+
+ await promise_rejects(
+ t,
+ new TypeError(),
+ cookieStore.set('', 'suspicious-value=resembles-name-and-value'),
+ 'Expected promise rejection when setting a cookie with' +
+ ' no name and "=" in value');
+
+ const actual2 =
+ (await cookieStore.getAll('')).map(({ value }) => value).join(';');
+ const expected2 = 'first-value';
+ assert_equals(actual2, expected2);
+ assert_equals(
+ await getCookieString(),
+ 'first-value',
+ 'Earlier cookie jar after rejected');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.delete('');
+ await verifyCookieChangeEvent(
+ eventPromise, {deleted: [{name: '', value: ''}]},
+ 'Observed no-name deletion');
+
+ assert_equals(
+ await getCookieString(),
+ undefined,
+ 'Empty cookie jar after cleanup');
+ assert_equals(
+ await getCookieStringHttp(),
+ undefined,
+ 'Empty HTTP cookie jar after cleanup');
+
+}, "Verify that attempting to set a cookie with no name and with '=' in" +
+ " the value does not work.");
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/no_name_multiple_values.js b/tests/wpt/web-platform-tests/cookie-store/resources/no_name_multiple_values.js
new file mode 100644
index 00000000000..51ea5281c2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/no_name_multiple_values.js
@@ -0,0 +1,38 @@
+'use strict';
+
+cookie_test(async t => {
+ let eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.set('', 'first-value');
+ let actual1 =
+ (await cookieStore.getAll('')).map(({ value }) => value).join(';');
+ let expected1 = 'first-value';
+ assert_equals(actual1, expected1);
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: '', value: 'first-value'}]},
+ 'Observed no-name change');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.set('', 'second-value');
+ let actual2 =
+ (await cookieStore.getAll('')).map(({ value }) => value).join(';');
+ let expected2 = 'second-value';
+ assert_equals(actual2, expected2);
+ await verifyCookieChangeEvent(
+ eventPromise, {changed: [{name: '', value: 'second-value'}]},
+ 'Observed no-name change');
+
+ eventPromise = observeNextCookieChangeEvent();
+ await cookieStore.delete('');
+ await verifyCookieChangeEvent(
+ eventPromise, {deleted: [{name: ''}]},
+ 'Observed no-name change');
+
+ assert_equals(
+ await getCookieString(),
+ undefined,
+ 'Empty cookie jar after testNoNameMultipleValues');
+ assert_equals(
+ await getCookieStringHttp(),
+ undefined,
+ 'Empty HTTP cookie jar after testNoNameMultipleValues');
+}, 'Verify behavior of multiple no-name cookies');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/one_simple_origin_cookie.js b/tests/wpt/web-platform-tests/cookie-store/resources/one_simple_origin_cookie.js
new file mode 100644
index 00000000000..cbaf73d3443
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/one_simple_origin_cookie.js
@@ -0,0 +1,57 @@
+'use strict';
+
+// Helper to verify first-of-name get using async/await.
+//
+// Returns the first script-visible value of the __Host-COOKIENAME cookie or
+// undefined if no matching cookies are script-visible.
+async function getOneSimpleOriginCookie() {
+ let cookie = await cookieStore.get('__Host-COOKIENAME');
+ if (!cookie) return undefined;
+ return cookie.value;
+}
+
+// Returns the number of script-visible cookies whose names start with
+// __Host-COOKIEN
+async function countMatchingSimpleOriginCookies() {
+ let cookieList = await cookieStore.getAll({
+ name: '__Host-COOKIEN',
+ matchType: 'startsWith'
+ });
+ return cookieList.length;
+}
+
+// Set the secure implicit-domain cookie __Host-COOKIENAME with value
+// cookie-value on path / and session duration.
+async function setOneSimpleOriginSessionCookie() {
+ await cookieStore.set('__Host-COOKIENAME', 'cookie-value');
+};
+
+cookie_test(async testCase => {
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ setOneSimpleOriginSessionCookie(),
+ '__Host- prefix only writable from secure contexts');
+ if (!kIsUnsecured) {
+ assert_equals(
+ await getOneSimpleOriginCookie(),
+ 'cookie-value',
+ '__Host-COOKIENAME cookie should be found in a secure context');
+ } else {
+ assert_equals(
+ await getOneSimpleOriginCookie(),
+ undefined,
+ '__Host-COOKIENAME cookie should not be found in an unsecured context');
+ }
+ if (kIsUnsecured) {
+ assert_equals(
+ await countMatchingSimpleOriginCookies(),
+ 0,
+ 'No __Host-COOKIEN* cookies should be found in an unsecured context');
+ } else {
+ assert_equals(
+ await countMatchingSimpleOriginCookies(),
+ 1,
+ 'One __Host-COOKIEN* cookie should be found in a secure context');
+ }
+}, 'One simple origin cookie');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/ordering.js b/tests/wpt/web-platform-tests/cookie-store/resources/ordering.js
new file mode 100644
index 00000000000..884361b9df0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/ordering.js
@@ -0,0 +1,41 @@
+'use strict';
+
+// TODO(jsbell): Does this test really need simple origin ('__Host-') cookies?
+
+cookie_test(async t => {
+ await cookieStore.set('__Host-1🍪', '🔵cookie-value1🔴');
+ await cookieStore.set('__Host-2🌟', '🌠cookie-value2🌠');
+ await cookieStore.set('__Host-3🌱', '🔶cookie-value3🔷');
+ // NOTE: this assumes no concurrent writes from elsewhere; it also
+ // uses three separate cookie jar read operations where a single getAll
+ // would be more efficient, but this way the CookieStore does the filtering
+ // for us.
+ const matchingValues = await Promise.all([ '1🍪', '2🌟', '3🌱' ].map(
+ async suffix => (await cookieStore.get('__Host-' + suffix)).value));
+ const actual = matchingValues.join(';');
+ const expected = '🔵cookie-value1🔴;🌠cookie-value2🌠;🔶cookie-value3🔷';
+ assert_equals(actual, expected);
+}, 'Set three simple origin session cookies sequentially and ensure ' +
+ 'they all end up in the cookie jar in order.');
+
+cookie_test(async t => {
+ await Promise.all([
+ cookieStore.set('__Host-unordered1🍪', '🔵unordered-cookie-value1🔴'),
+ cookieStore.set('__Host-unordered2🌟', '🌠unordered-cookie-value2🌠'),
+ cookieStore.set('__Host-unordered3🌱', '🔶unordered-cookie-value3🔷')
+ ]);
+ // NOTE: this assumes no concurrent writes from elsewhere; it also
+ // uses three separate cookie jar read operations where a single getAll
+ // would be more efficient, but this way the CookieStore does the filtering
+ // for us and we do not need to sort.
+ const matchingCookies = await Promise.all([ '1🍪', '2🌟', '3🌱' ].map(
+ suffix => cookieStore.get('__Host-unordered' + suffix)));
+ const actual = matchingCookies.map(({ value }) => value).join(';');
+ const expected =
+ '🔵unordered-cookie-value1🔴;' +
+ '🌠unordered-cookie-value2🌠;' +
+ '🔶unordered-cookie-value3🔷';
+ assert_equals(actual, expected);
+}, 'Set three simple origin session cookies in undefined order using ' +
+ 'Promise.all and ensure they all end up in the cookie jar in any ' +
+ 'order. ');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/secure_cookies.js b/tests/wpt/web-platform-tests/cookie-store/resources/secure_cookies.js
new file mode 100644
index 00000000000..9f600ecdf3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/secure_cookies.js
@@ -0,0 +1,46 @@
+
+cookie_test(async t => {
+ const theVeryRecentPast = Date.now();
+ const expiredCookieSentinelValue = 'EXPIRED';
+ await promise_rejects_when_unsecured(
+ t,
+ new TypeError(),
+ cookieStore.set('__Secure-COOKIENAME', expiredCookieSentinelValue, {
+ path: kPath,
+ expires: theVeryRecentPast,
+ secure: true,
+ domain: location.hostname
+ }),
+ 'Secure cookies only writable from secure contexts');
+
+}, 'Set an already-expired secure cookie');
+
+['__Host-', '__Secure-'].forEach(prefix => {
+ cookie_test(async t => {
+ const name = prefix + 'COOKIENAME';
+ const value = 'cookie-value';
+
+ await promise_rejects_when_unsecured(
+ t,
+ new TypeError(),
+ cookieStore.set(name, value),
+ `Setting ${prefix} cookies should fail in non-secure contexts`);
+
+ // Getting does not produce an exception, even in non-secure contexts.
+ const pair = await cookieStore.get(name);
+
+ if (kIsUnsecured) {
+ assert_equals(pair, null);
+ } else {
+ assert_equals(pair.value, value);
+ }
+
+ await promise_rejects_when_unsecured(
+ t,
+ new TypeError(),
+ cookieStore.delete(name),
+ `Deleting ${prefix} cookies should fail in non-secure contexts`);
+
+ assert_equals(await cookieStore.get(name), null);
+ }, `${prefix} cookies only writable from secure context`);
+});
diff --git a/tests/wpt/web-platform-tests/cookie-store/secure_cookies.tentative.html b/tests/wpt/web-platform-tests/cookie-store/secure_cookies.tentative.html
new file mode 100644
index 00000000000..4bbf718e3df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/secure_cookies.tentative.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Async Cookies: __Secure- and __Host- cookies</title>
+<meta name="help" href="https://github.com/WICG/cookie-store/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/secure_cookies.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/secure_cookies.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/secure_cookies.tentative.https.html
new file mode 100644
index 00000000000..2fa9a412fc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/secure_cookies.tentative.https.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Async Cookies: __Secure- and __Host- cookies (HTTPS)</title>
+<meta name="help" href="https://github.com/WICG/cookie-store/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/cookie-test-helpers.js"></script>
+<script src="resources/secure_cookies.js"></script>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-001.html
new file mode 100644
index 00000000000..118440912de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-001.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage margins</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage margins are resolved against the inline size of their grid area (in a fixed size track).">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: 100px;
+ width: 500px;
+ justify-items: start;
+ position: relative;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 100%;
+ height: 10px;
+}
+
+.marginLeft50Percent { margin-left: 50%; }
+.marginRight50Percent { margin-right: 50%; }
+.marginTop50Percent { margin-top: 50%; }
+.marginBottom50Percent { margin-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="490" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="440" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-002.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-002.html
new file mode 100644
index 00000000000..b056d3edf53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-002.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage margins</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage margins are resolved against the inline size of their grid area (in a track with fixed max sizing function and intrinsic min).">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: minmax(auto, 100px);
+ width: 500px;
+ justify-items: start;
+ position: relative;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 100%;
+ height: 10px;
+}
+
+.marginLeft50Percent { margin-left: 50%; }
+.marginRight50Percent { margin-right: 50%; }
+.marginTop50Percent { margin-top: 50%; }
+.marginBottom50Percent { margin-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="490" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="440" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-001.html
new file mode 100644
index 00000000000..82df77ffca7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-001.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage margins vertical-lr</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage margins are resolved against the inline size of their grid area (in a fixed size track) in a vertical-lr grid container.">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: 100px;
+ height: 500px;
+ justify-items: start;
+ position: relative;
+ writing-mode: vertical-lr;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 10px;
+ height: 100%;
+}
+
+.marginLeft50Percent { margin-left: 50%; }
+.marginRight50Percent { margin-right: 50%; }
+.marginTop50Percent { margin-top: 50%; }
+.marginBottom50Percent { margin-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="10" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="10" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="490" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="10" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="440" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="10" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-002.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-002.html
new file mode 100644
index 00000000000..168eeaf28c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-lr-002.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage margins vertical-lr</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage margins are resolved against the inline size of their grid area (in a track with fixed max sizing function and intrinsic min) in a vertical-lr grid container.">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: minmax(auto, 100px);
+ height: 500px;
+ justify-items: start;
+ position: relative;
+ writing-mode: vertical-lr;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 10px;
+ height: 100%;
+}
+
+.marginLeft50Percent { margin-left: 50%; }
+.marginRight50Percent { margin-right: 50%; }
+.marginTop50Percent { margin-top: 50%; }
+.marginBottom50Percent { margin-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="10" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="10" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="490" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="10" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="440" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="10" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-001.html
new file mode 100644
index 00000000000..415a07df172
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-001.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage margins vertical-rl</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage margins are resolved against the inline size of their grid area (in a fixed size track) in a vertical-rl grid container.">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: 100px;
+ height: 500px;
+ justify-items: start;
+ position: relative;
+ writing-mode: vertical-rl;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 10px;
+ height: 100%;
+}
+
+.marginLeft50Percent { margin-left: 50%; }
+.marginRight50Percent { margin-right: 50%; }
+.marginTop50Percent { margin-top: 50%; }
+.marginBottom50Percent { margin-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="60" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="10" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-expected-x="60" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-expected-x="10" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-expected-y="490" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-expected-y="440" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-002.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-002.html
new file mode 100644
index 00000000000..6f3db26275c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-margins-vertical-rl-002.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage margins vertical-rl</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage margins are resolved against the inline size of their grid area (in a track with fixed max sizing function and intrinsic min) in a vertical-rl grid container.">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: minmax(auto, 100px);
+ height: 500px;
+ justify-items: start;
+ position: relative;
+ writing-mode: vertical-rl;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 10px;
+ height: 100%;
+}
+
+.marginLeft50Percent { margin-left: 50%; }
+.marginRight50Percent { margin-right: 50%; }
+.marginTop50Percent { margin-top: 50%; }
+.marginBottom50Percent { margin-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-offset-x="60" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-offset-x="10" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-offset-y="50" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-offset-y="0" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item margin-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginLeft50Percent" data-expected-margin-left="50" data-expected-x="60" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginRight50Percent" data-expected-margin-right="50" data-expected-x="10" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginTop50Percent" data-expected-margin-top="50" data-expected-y="490" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item margin-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="marginBottom50Percent" data-expected-margin-bottom="50" data-expected-y="440" data-expected-width="10" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-001.html
new file mode 100644
index 00000000000..3989d8f5c69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-001.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage paddings</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage paddings are resolved against the inline size of their grid area (in a fixed size track).">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: 100px;
+ width: 500px;
+ justify-items: start;
+ position: relative;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 100%;
+ height: 10px;
+}
+
+.paddingLeft50Percent { padding-left: 50%; }
+.paddingRight50Percent { padding-right: 50%; }
+.paddingTop50Percent { padding-top: 50%; }
+.paddingBottom50Percent { padding-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="400" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="400" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-002.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-002.html
new file mode 100644
index 00000000000..a358b38b3d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-002.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage paddings</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage paddings are resolved against the inline size of their grid area (in a track with fixed max sizing function and intrinsic min).">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: minmax(auto, 100px);
+ width: 500px;
+ justify-items: start;
+ position: relative;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 100%;
+ height: 10px;
+}
+
+.paddingLeft50Percent { padding-left: 50%; }
+.paddingRight50Percent { padding-right: 50%; }
+.paddingTop50Percent { padding-top: 50%; }
+.paddingBottom50Percent { padding-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="400" data-offset-y="10" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="400" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="400" data-offset-y="60" data-expected-width="100" data-expected-height="10"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-001.html
new file mode 100644
index 00000000000..21ed53a2c70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-001.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage paddings vertical-lr</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage paddings are resolved against the inline size of their grid area (in a fixed size track) in a vertical-lr grid container.">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: 100px;
+ height: 500px;
+ justify-items: start;
+ position: relative;
+ writing-mode: vertical-lr;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 10px;
+ height: 100%;
+}
+
+.paddingLeft50Percent { padding-left: 50%; }
+.paddingRight50Percent { padding-right: 50%; }
+.paddingTop50Percent { padding-top: 50%; }
+.paddingBottom50Percent { padding-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="10" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="10" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="10" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="10" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-002.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-002.html
new file mode 100644
index 00000000000..d4d8aa29d7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-lr-002.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage paddings vertical-lr</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage paddings are resolved against the inline size of their grid area (in a track with fixed max sizing function and intrinsic min) in a vertical-lr grid container.">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: minmax(auto, 100px);
+ height: 500px;
+ justify-items: start;
+ position: relative;
+ writing-mode: vertical-lr;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 10px;
+ height: 100%;
+}
+
+.paddingLeft50Percent { padding-left: 50%; }
+.paddingRight50Percent { padding-right: 50%; }
+.paddingTop50Percent { padding-top: 50%; }
+.paddingBottom50Percent { padding-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="10" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="10" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="60" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="10" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="10" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-001.html
new file mode 100644
index 00000000000..010f4b5fbd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-001.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage paddings vertical-rl</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage paddings are resolved against the inline size of their grid area (in a fixed size track) in a vertical-rl grid container.">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: 100px;
+ height: 500px;
+ justify-items: start;
+ position: relative;
+ writing-mode: vertical-rl;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 10px;
+ height: 100%;
+}
+
+.paddingLeft50Percent { padding-left: 50%; }
+.paddingRight50Percent { padding-right: 50%; }
+.paddingTop50Percent { padding-top: 50%; }
+.paddingBottom50Percent { padding-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-002.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-002.html
new file mode 100644
index 00000000000..bf38155e16f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-items-percentage-paddings-vertical-rl-002.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid items with percentage paddings vertical-rl</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#item-margins">
+<meta name="assert" content="Checks grid items percentage paddings are resolved against the inline size of their grid area (in a track with fixed max sizing function and intrinsic min) in a vertical-rl grid container.">
+<link rel="stylesheet" href="support/grid.css">
+<style>
+.grid {
+ font: 10px/1 Ahem;
+ grid-template-columns: minmax(auto, 100px);
+ height: 500px;
+ justify-items: start;
+ position: relative;
+ writing-mode: vertical-rl;
+}
+
+.grid > div:nth-child(1) { background: cyan; }
+.grid > div:nth-child(2) {
+ background: magenta;
+ width: 10px;
+ height: 100%;
+}
+
+.paddingLeft50Percent { padding-left: 50%; }
+.paddingRight50Percent { padding-right: 50%; }
+.paddingTop50Percent { padding-top: 50%; }
+.paddingBottom50Percent { padding-bottom: 50%; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>Direction LTR</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<h3>Direction RTL</h3>
+
+<pre>Item padding-left: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingLeft50Percent" data-expected-padding-left="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-right: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingRight50Percent" data-expected-padding-right="50" data-expected-width="60" data-expected-height="10">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-top: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingTop50Percent" data-expected-padding-top="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
+
+<pre>Item padding-bottom: 50%;</pre>
+
+<div class="grid directionRTL">
+ <div class="paddingBottom50Percent" data-expected-padding-bottom="50" data-expected-width="10" data-expected-height="60">X</div>
+ <div data-offset-x="0" data-offset-y="400" data-expected-width="10" data-expected-height="100"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html b/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html
index 8a757e5ca2a..20dc9713e58 100644
--- a/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html
+++ b/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html
@@ -84,10 +84,9 @@
assert_readonly(styleSheet, "parentStyleSheet");
assert_readonly(styleSheet, "href");
assert_readonly(styleSheet, "title");
- assert_readonly(styleSheet, "media");
}, "StyleSheet_properties",
{ assert: [ "type, disabled, ownerNode, parentStyleSheet, href, title, and media properties exist on StyleSheet",
- "type, ownerNode, parentStyleSheet, href, title, media properties are read only" ] });
+ "type, ownerNode, parentStyleSheet, href, and title properties are read only" ] });
test(function() {
assert_equals(styleSheet.type, "text/css");
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-registry/upgrade.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-registry/upgrade.html
index 3a72dbd753c..e020d95a576 100644
--- a/tests/wpt/web-platform-tests/custom-elements/custom-element-registry/upgrade.html
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-registry/upgrade.html
@@ -145,10 +145,13 @@ test(() => {
customElements.upgrade(template.content);
- assert_true(el1 instanceof Element1, "element 1 must now be upgraded");
- assert_true(el2 instanceof Element2, "element 2 must now be upgraded");
- assert_true(el3 instanceof Element3, "element 3 must now be upgraded");
- assert_true(el4 instanceof Element4, "element 4 must now be upgraded");
- assert_true(el5 instanceof Element5, "element 5 must now be upgraded");
+ // Template contents owner documents don't have a browsing context, so
+ // https://html.spec.whatwg.org/multipage/custom-elements.html#look-up-a-custom-element-definition does not find any
+ // custom element definition.
+ assert_false(el1 instanceof Element1, "element 1 must still not be upgraded after upgrading the template contents");
+ assert_false(el2 instanceof Element2, "element 2 must still not be upgraded after upgrading the template contents");
+ assert_false(el3 instanceof Element3, "element 3 must still not be upgraded after upgrading the template contents");
+ assert_false(el4 instanceof Element4, "element 4 must still not be upgraded after upgrading the template contents");
+ assert_false(el5 instanceof Element5, "element 5 must still not be upgraded after upgrading the template contents");
}, "Elements inside a template contents DocumentFragment node");
</script>
diff --git a/tests/wpt/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children.html b/tests/wpt/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children.html
index ef4689fac07..987bf8525fb 100644
--- a/tests/wpt/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children.html
+++ b/tests/wpt/web-platform-tests/custom-elements/parser/parser-sets-attributes-and-children.html
@@ -5,6 +5,7 @@
<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
<meta name="assert" content="HTML parser must set the attributes and append the children on a custom element">
<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/parsing.html#insert-a-foreign-element">
<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
@@ -14,8 +15,10 @@
<div id="log"></div>
<script>
-var numberOfAttributesInConstructor;
-var numberOfChildNodesInConstructor;
+var numberOfAttributesInConstructor = 0;
+var numberOfChildNodesInConstructor = 0;
+var numberOfChildNodesInAttributeChangedCallback = 0;
+var numberOfChildNodesInConnectedCallback = 0;
var attributesChangedCalls = [];
class MyCustomElement extends HTMLElement {
@@ -27,11 +30,16 @@ class MyCustomElement extends HTMLElement {
attributeChangedCallback(...args) {
attributesChangedCalls.push(create_attribute_changed_callback_log(this, ...args));
+ numberOfChildNodesInAttributeChangedCallback = this.childNodes.length;
}
static get observedAttributes() {
return ['id', 'class'];
}
+
+ connectedCallback() {
+ numberOfChildNodesInConnectedCallback = this.childNodes.length;
+ }
};
customElements.define('my-custom-element', MyCustomElement);
@@ -65,9 +73,21 @@ test(function () {
}, 'HTML parser must set the attributes or append children before calling constructor');
test(function () {
+ // https://html.spec.whatwg.org/multipage/parsing.html#insert-a-foreign-element
+ // 3.3. Pop the element queue from the custom element reactions
+ // stack, and invoke custom element reactions in that queue.
+ assert_equals(numberOfChildNodesInConnectedCallback, 0);
+}, 'HTML parser should call connectedCallback before appending child nodes.');
+
+test(function () {
assert_equals(attributesChangedCalls.length, 2);
assert_attribute_log_entry(attributesChangedCalls[0], {name: 'id', oldValue: null, newValue: 'custom-element-id', namespace: null});
assert_attribute_log_entry(attributesChangedCalls[1], {name: 'class', oldValue: null, newValue: 'class1 class2', namespace: null});
+ // https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token
+ // 9.2. Invoke custom element reactions in queue.
+ assert_equals(numberOfChildNodesInAttributeChangedCallback, 0,
+ 'attributeChangedCallback should be called ' +
+ 'before appending a child');
}, 'HTML parser must enqueue attributeChanged reactions');
</script>
diff --git a/tests/wpt/web-platform-tests/fetch/corb/img-mime-types-coverage.tentative.sub.html b/tests/wpt/web-platform-tests/fetch/corb/img-mime-types-coverage.tentative.sub.html
new file mode 100644
index 00000000000..4ed8f018e92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/corb/img-mime-types-coverage.tentative.sub.html
@@ -0,0 +1,75 @@
+<!-- Test verifies that cross-origin, nosniff images are 1) blocked when their
+ MIME type is covered by CORB and 2) allowed otherwise.
+
+ This test is very similar to fetch/nosniff/images.html, except that
+ 1) it deals with cross-origin images (CORB ignores same-origin fetches),
+ 2) it focuses on MIME types relevant to CORB.
+ There are opportunities to unify the test here with nosniff tests *if*
+ we can also start blocking same-origin (or cors-allowed) images. We
+ should try to gather data to quantify the impact of such change.
+-->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ var passes = [
+ // Empty or non-sensical MIME types
+ null, "", "x", "x/x",
+
+ // MIME-types not protected by CORB
+ "image/gif", "image/png", "image/png;blah", "image/svg+xml",
+ "application/javascript", "application/jsonp",
+
+ // MIME types that may seem to be JSON or XML, but really aren't - i.e.
+ // these MIME types are not covered by:
+ // - https://mimesniff.spec.whatwg.org/#json-mime-type
+ // - https://mimesniff.spec.whatwg.org/#xml-mime-type
+ // - https://tools.ietf.org/html/rfc6839
+ // - https://tools.ietf.org/html/rfc7303
+ "text/x-json", "text/json+blah", "application/json+blah",
+ "text/xml+blah", "application/xml+blah",
+ "application/blahjson", "text/blahxml",
+
+ var fails = [
+ // CORB-protected MIME-types - i.e. ones covered by:
+ // - https://mimesniff.spec.whatwg.org/#html-mime-type
+ // - https://mimesniff.spec.whatwg.org/#json-mime-type
+ // - https://mimesniff.spec.whatwg.org/#xml-mime-type
+ "text/html",
+ "text/json", "application/json", "text/xml", "application/xml",
+ "application/blah+json", "text/blah+json",
+ "application/blah+xml", "text/blah+xml",
+ "TEXT/HTML", "TEXT/JSON", "TEXT/BLAH+JSON", "APPLICATION/BLAH+XML"]
+
+ const get_url = (mime) => {
+ // www1 is cross-origin, so the HTTP response is CORB-eligible -->
+ url = "http://{{domains[www1]}}:{{ports[http][0]}}"
+ url = url + "/fetch/nosniff/resources/image.py"
+ if (mime != null) {
+ url += "?type=" + encodeURIComponent(mime)
+ }
+ return url
+ }
+
+ passes.forEach(function(mime) {
+ async_test(function(t) {
+ var img = document.createElement("img")
+ img.onerror = t.unreached_func("Unexpected error event")
+ img.onload = t.step_func_done(function(){
+ assert_equals(img.width, 96)
+ })
+ img.src = get_url(mime)
+ document.body.appendChild(img)
+ }, "CORB should allow the response if Content-Type is: '" + mime + "'. ")
+ })
+
+ fails.forEach(function(mime) {
+ async_test(function(t) {
+ var img = document.createElement("img")
+ img.onerror = t.step_func_done()
+ img.onload = t.unreached_func("Unexpected load event")
+ img.src = get_url(mime)
+ document.body.appendChild(img)
+ }, "CORB should block the response if Content-Type is: '" + mime + "'. ")
+ })
+</script>
diff --git a/tests/wpt/web-platform-tests/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html b/tests/wpt/web-platform-tests/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html
new file mode 100644
index 00000000000..cea80f2f89f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- This test verifies observable CORB impact on <link rel="preload"> elements.
+-->
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<script>
+async_test(function(t) {
+ // With CORB the link.onerror event will be reached
+ // (because CORB will block the cross-origin preload).
+ window.preloadErrorEvent = t.step_func_done();
+
+ // Without CORB the link.onload event will be reached.
+ window.preloadLoadEvent = t.unreached_func("link/preload onload event reached.");
+});
+</script>
+
+<!-- www1 is cross-origin, so the HTTP response is CORB-eligible -->
+<link rel="preload" as="image"
+ onerror="window.preloadErrorEvent()"
+ onload="window.preloadLoadEvent()"
+ href="http://{{domains[www1]}}:{{ports[http][0]}}/fetch/corb/resources/png-mislabeled-as-html-nosniff.png">
diff --git a/tests/wpt/web-platform-tests/fetch/nosniff/image.html b/tests/wpt/web-platform-tests/fetch/nosniff/image.html
index 3273f19fb1e..9dfdb94cf62 100644
--- a/tests/wpt/web-platform-tests/fetch/nosniff/image.html
+++ b/tests/wpt/web-platform-tests/fetch/nosniff/image.html
@@ -3,7 +3,19 @@
<div id=log></div>
<script>
// Note: images get always sniffed, nosniff doesn't do anything
- var passes = [null, "", "x", "x/x", "image/gif", "image/png", "image/png;blah"]
+ // (but note the tentative Cross-Origin Read Blocking (CORB) tests
+ // - for example wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html).
+ var passes = [
+ // Empty or non-sensical MIME types
+ null, "", "x", "x/x",
+
+ // Image MIME types
+ "image/gif", "image/png", "image/png;blah", "image/svg+xml",
+
+ // CORB-protected MIME types (but note that CORB doesn't apply here,
+ // because CORB ignores same-origin requests).
+ "text/html", "application/xml", "application/blah+xml"
+ ]
const get_url = (mime) => {
let url = "resources/image.py"
diff --git a/tests/wpt/web-platform-tests/fetch/nosniff/resources/image.py b/tests/wpt/web-platform-tests/fetch/nosniff/resources/image.py
index 8fb05edc658..623a40d58c1 100644
--- a/tests/wpt/web-platform-tests/fetch/nosniff/resources/image.py
+++ b/tests/wpt/web-platform-tests/fetch/nosniff/resources/image.py
@@ -3,7 +3,13 @@ import os.path
def main(request, response):
type = request.GET.first("type", None)
- body = open(os.path.join(os.path.dirname(__file__), "../../../images/blue96x96.png"), "rb").read()
+ if type != None and "svg" in type:
+ filename = "green-96x96.svg"
+ else:
+ filename = "blue96x96.png"
+
+ path = os.path.join(os.path.dirname(__file__), "../../../images", filename)
+ body = open(path, "rb").read()
response.add_required_headers = False
response.writer.write_status(200)
diff --git a/tests/wpt/web-platform-tests/images/green-96x96.svg b/tests/wpt/web-platform-tests/images/green-96x96.svg
new file mode 100644
index 00000000000..fdaffd920dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/green-96x96.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96">
+ <rect fill="lime" width="96" height="96"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-xhr-sync-on-worker.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-xhr-sync-on-worker.https.html
new file mode 100644
index 00000000000..9f18096aa29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-request-xhr-sync-on-worker.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>Service Worker: Synchronous XHR on Worker is intercepted</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+'use strict';
+
+promise_test((t) => {
+ const url = 'resources/fetch-request-xhr-sync-on-worker-worker.js';
+ const scope = 'resources/fetch-request-xhr-sync-on-worker-scope/';
+ const non_existent_file = 'non-existent-file.txt';
+
+ // In Chromium, the service worker scope matching for workers is based on
+ // the URL of the parent HTML. So this test creates an iframe which is
+ // controlled by the service worker first, and creates a worker from the
+ // iframe.
+ return service_worker_unregister_and_register(t, url, scope)
+ .then((registration) => {
+ t.add_cleanup(() => registration.unregister());
+ return wait_for_state(t, registration.installing, 'activated');
+ })
+ .then(() => { return with_iframe(scope + 'iframe_page'); })
+ .then((frame) => {
+ t.add_cleanup(() => frame.remove());
+ return frame.contentWindow.performSyncXHROnWorker(non_existent_file);
+ })
+ .then((result) => {
+ assert_equals(
+ result.status,
+ 200,
+ 'HTTP response status code for intercepted request'
+ );
+ assert_equals(
+ result.responseText,
+ 'Response from service worker',
+ 'HTTP response text for intercepted request'
+ );
+ });
+ }, 'Verify SyncXHR on Worker is intercepted');
+</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-sync-on-worker-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-sync-on-worker-worker.js
new file mode 100644
index 00000000000..0d24ffc1f33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-request-xhr-sync-on-worker-worker.js
@@ -0,0 +1,41 @@
+'use strict';
+
+self.onfetch = function(event) {
+ if (event.request.url.indexOf('non-existent-file.txt') !== -1) {
+ event.respondWith(new Response('Response from service worker'));
+ } else if (event.request.url.indexOf('/iframe_page') !== -1) {
+ event.respondWith(new Response(
+ '<!DOCTYPE html>\n' +
+ '<script>\n' +
+ 'function performSyncXHROnWorker(url) {\n' +
+ ' return new Promise((resolve) => {\n' +
+ ' var worker =\n' +
+ ' new Worker(\'./worker_script\');\n' +
+ ' worker.addEventListener(\'message\', (msg) => {\n' +
+ ' resolve(msg.data);\n' +
+ ' });\n' +
+ ' worker.postMessage({\n' +
+ ' url: url\n' +
+ ' });\n' +
+ ' });\n' +
+ '}\n' +
+ '</script>',
+ {
+ headers: [['content-type', 'text/html']]
+ }));
+ } else if (event.request.url.indexOf('/worker_script') !== -1) {
+ event.respondWith(new Response(
+ 'self.onmessage = (msg) => {' +
+ ' const syncXhr = new XMLHttpRequest();' +
+ ' syncXhr.open(\'GET\', msg.data.url, false);' +
+ ' syncXhr.send();' +
+ ' self.postMessage({' +
+ ' status: syncXhr.status,' +
+ ' responseText: syncXhr.responseText' +
+ ' });' +
+ '}',
+ {
+ headers: [['content-type', 'application/javascript']]
+ }));
+ }
+};