diff options
438 files changed, 10664 insertions, 2514 deletions
diff --git a/tests/wpt/meta-legacy-layout/css/CSS2/linebox/inline-negative-margin-001.html.ini b/tests/wpt/meta-legacy-layout/css/CSS2/linebox/inline-negative-margin-001.html.ini index a057f038339..5e3a96e5999 100644 --- a/tests/wpt/meta-legacy-layout/css/CSS2/linebox/inline-negative-margin-001.html.ini +++ b/tests/wpt/meta-legacy-layout/css/CSS2/linebox/inline-negative-margin-001.html.ini @@ -8,8 +8,5 @@ [[data-expected-height\] 3] expected: FAIL - [[data-expected-height\] 1] - expected: FAIL - - [[data-expected-height\] 2] + [[data-expected-height\] 4] expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-color/system-color-support.html.ini b/tests/wpt/meta-legacy-layout/css/css-color/system-color-support.html.ini new file mode 100644 index 00000000000..28563ddd87a --- /dev/null +++ b/tests/wpt/meta-legacy-layout/css/css-color/system-color-support.html.ini @@ -0,0 +1,57 @@ +[system-color-support.html] + [System color Canvas works] + expected: FAIL + + [System color CanvasText works] + expected: FAIL + + [System color LinkText works] + expected: FAIL + + [System color VisitedText works] + expected: FAIL + + [System color ActiveText works] + expected: FAIL + + [System color ButtonFace works] + expected: FAIL + + [System color ButtonText works] + expected: FAIL + + [System color ButtonBorder works] + expected: FAIL + + [System color Field works] + expected: FAIL + + [System color FieldText works] + expected: FAIL + + [System color Highlight works] + expected: FAIL + + [System color HighlightText works] + expected: FAIL + + [System color SelectedItem works] + expected: FAIL + + [System color SelectedItemText works] + expected: FAIL + + [System color Mark works] + expected: FAIL + + [System color MarkText works] + expected: FAIL + + [System color GrayText works] + expected: FAIL + + [System color AccentColor works] + expected: FAIL + + [System color AccentColorText works] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-color/t32-opacity-basic-0.6-a.xht.ini b/tests/wpt/meta-legacy-layout/css/css-color/t32-opacity-basic-0.6-a.xht.ini deleted file mode 100644 index 4c252ef57be..00000000000 --- a/tests/wpt/meta-legacy-layout/css/css-color/t32-opacity-basic-0.6-a.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[t32-opacity-basic-0.6-a.xht] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html.ini b/tests/wpt/meta-legacy-layout/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html.ini new file mode 100644 index 00000000000..48224fe6767 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html.ini @@ -0,0 +1,7 @@ +[font-palette-animation-not-specified-endpoints.html] + expected: TIMEOUT + [Verify font-palette is animated when `from` keyframe is not specified] + expected: NOTRUN + + [Verify font-palette is animated when `to` keyframe is not specified] + expected: NOTRUN diff --git a/tests/wpt/meta-legacy-layout/css/css-images/parsing/gradient-interpolation-method-computed.html.ini b/tests/wpt/meta-legacy-layout/css/css-images/parsing/gradient-interpolation-method-computed.html.ini index ac3cd32db81..9e15d59a455 100644 --- a/tests/wpt/meta-legacy-layout/css/css-images/parsing/gradient-interpolation-method-computed.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-images/parsing/gradient-interpolation-method-computed.html.ini @@ -815,12 +815,6 @@ [Property background-image value 'linear-gradient(in oklch decreasing hue to right bottom, color(srgb 1 0 0), blue)'] expected: FAIL - [Property background-image value 'radial-gradient(ellipse 50% 40em, red, blue)'] - expected: FAIL - - [Property background-image value 'radial-gradient(at right center, red, blue)'] - expected: FAIL - [Property background-image value 'radial-gradient(50px, color(srgb 1 0 0), blue)'] expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-text/inheritance.html.ini b/tests/wpt/meta-legacy-layout/css/css-text/inheritance.html.ini index 415926291db..5eb631e5b9b 100644 --- a/tests/wpt/meta-legacy-layout/css/css-text/inheritance.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-text/inheritance.html.ini @@ -46,3 +46,15 @@ [Property white-space-collapse inherits] expected: FAIL + + [Property text-wrap-mode has initial value wrap] + expected: FAIL + + [Property text-wrap-mode inherits] + expected: FAIL + + [Property text-wrap-style has initial value auto] + expected: FAIL + + [Property text-wrap-style inherits] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-computed.html.ini b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-computed.html.ini new file mode 100644 index 00000000000..dbe3756bbab --- /dev/null +++ b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-computed.html.ini @@ -0,0 +1,66 @@ +[text-wrap-computed.html] + [Property text-wrap value 'wrap'] + expected: FAIL + + [Property text-wrap value 'nowrap'] + expected: FAIL + + [Property text-wrap value 'auto'] + expected: FAIL + + [Property text-wrap value 'balance'] + expected: FAIL + + [Property text-wrap value 'stable'] + expected: FAIL + + [Property text-wrap value 'pretty'] + expected: FAIL + + [Property text-wrap value 'wrap auto'] + expected: FAIL + + [Property text-wrap value 'wrap balance'] + expected: FAIL + + [Property text-wrap value 'wrap pretty'] + expected: FAIL + + [Property text-wrap value 'wrap stable'] + expected: FAIL + + [Property text-wrap value 'auto wrap'] + expected: FAIL + + [Property text-wrap value 'balance wrap'] + expected: FAIL + + [Property text-wrap value 'pretty wrap'] + expected: FAIL + + [Property text-wrap value 'stable wrap'] + expected: FAIL + + [Property text-wrap value 'nowrap auto'] + expected: FAIL + + [Property text-wrap value 'nowrap balance'] + expected: FAIL + + [Property text-wrap value 'nowrap pretty'] + expected: FAIL + + [Property text-wrap value 'nowrap stable'] + expected: FAIL + + [Property text-wrap value 'auto nowrap'] + expected: FAIL + + [Property text-wrap value 'balance nowrap'] + expected: FAIL + + [Property text-wrap value 'pretty nowrap'] + expected: FAIL + + [Property text-wrap value 'stable nowrap'] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-mode-computed.html.ini b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-mode-computed.html.ini new file mode 100644 index 00000000000..f9739ca0b28 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-mode-computed.html.ini @@ -0,0 +1,6 @@ +[text-wrap-mode-computed.html] + [Property text-wrap-mode value 'wrap'] + expected: FAIL + + [Property text-wrap-mode value 'nowrap'] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-mode-valid.html.ini b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-mode-valid.html.ini new file mode 100644 index 00000000000..76dc7a87b4e --- /dev/null +++ b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-mode-valid.html.ini @@ -0,0 +1,21 @@ +[text-wrap-mode-valid.html] + [e.style['text-wrap-mode'\] = "wrap" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "nowrap" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "initial" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "inherit" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "unset" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "revert" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "revert-layer" should set the property value] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-style-computed.html.ini b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-style-computed.html.ini new file mode 100644 index 00000000000..8be1df9f7ff --- /dev/null +++ b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-style-computed.html.ini @@ -0,0 +1,12 @@ +[text-wrap-style-computed.html] + [Property text-wrap-style value 'auto'] + expected: FAIL + + [Property text-wrap-style value 'balance'] + expected: FAIL + + [Property text-wrap-style value 'pretty'] + expected: FAIL + + [Property text-wrap-style value 'stable'] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-style-valid.html.ini b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-style-valid.html.ini new file mode 100644 index 00000000000..fd637df85db --- /dev/null +++ b/tests/wpt/meta-legacy-layout/css/css-text/parsing/text-wrap-style-valid.html.ini @@ -0,0 +1,27 @@ +[text-wrap-style-valid.html] + [e.style['text-wrap-style'\] = "auto" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "balance" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "pretty" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "stable" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "initial" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "inherit" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "unset" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "revert" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "revert-layer" should set the property value] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/css-values/round-mod-rem-computed.html.ini b/tests/wpt/meta-legacy-layout/css/css-values/round-mod-rem-computed.html.ini index dc53d195dec..f4e2b78dd6f 100644 --- a/tests/wpt/meta-legacy-layout/css/css-values/round-mod-rem-computed.html.ini +++ b/tests/wpt/meta-legacy-layout/css/css-values/round-mod-rem-computed.html.ini @@ -706,3 +706,12 @@ [mod(4, -Infinity) should be used-value-equivalent to calc(NaN)] expected: FAIL + + [round(1px + 0%, 1px) should be used-value-equivalent to 1px] + expected: FAIL + + [mod(3px + 0%, 2px) should be used-value-equivalent to 1px] + expected: FAIL + + [rem(3px + 0%, 2px) should be used-value-equivalent to 1px] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/css/cssom-view/scroll-behavior-smooth-navigation.html.ini b/tests/wpt/meta-legacy-layout/css/cssom-view/scroll-behavior-smooth-navigation.html.ini index a3e30250229..977ef8f774c 100644 --- a/tests/wpt/meta-legacy-layout/css/cssom-view/scroll-behavior-smooth-navigation.html.ini +++ b/tests/wpt/meta-legacy-layout/css/cssom-view/scroll-behavior-smooth-navigation.html.ini @@ -1,6 +1,3 @@ [scroll-behavior-smooth-navigation.html] [Instant scrolling while doing history navigation.] expected: FAIL - - [Smooth scrolling while doing history navigation.] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html.ini new file mode 100644 index 00000000000..3274b486b81 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-no-referrer-when-downgrade.tentative.https.html] + [Test referer header https://web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html.ini new file mode 100644 index 00000000000..f9977a9008e --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-no-referrer.tentative.https.html] + [Test referer header ] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html.ini new file mode 100644 index 00000000000..38a364e11ea --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html.ini @@ -0,0 +1,6 @@ +[header-referrer-origin-when-cross-origin.tentative.https.html] + [Test referer header https://web-platform.test:8443] + expected: FAIL + + [Test referer header https://www1.web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html.ini new file mode 100644 index 00000000000..06fe8584f00 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-origin.tentative.https.html] + [Test referer header https://www1.web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html.ini new file mode 100644 index 00000000000..ea9ac6e351c --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html.ini @@ -0,0 +1,6 @@ +[header-referrer-same-origin.tentative.https.html] + [Test referer header ] + expected: FAIL + + [Test referer header https://www1.web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html.ini new file mode 100644 index 00000000000..0bf2b43e93f --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-strict-origin-when-cross-origin.tentative.https.html] + [Test referer header https://www1.web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html.ini new file mode 100644 index 00000000000..9c67727f1b1 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-strict-origin.tentative.https.html] + [Test referer header https://web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html.ini new file mode 100644 index 00000000000..979914e33f8 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-unsafe-url.tentative.https.html] + [Test referer header https://web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/iframe.tentative.https.window.js.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/iframe.tentative.https.window.js.ini new file mode 100644 index 00000000000..b3d4cb1d9f1 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/iframe.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[iframe.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/new-window.tentative.https.window.js.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/new-window.tentative.https.window.js.ini new file mode 100644 index 00000000000..1f36e0e5b51 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/new-window.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[new-window.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js.ini new file mode 100644 index 00000000000..357487889e9 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[csp-allowed.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js.ini new file mode 100644 index 00000000000..f6d883b2101 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[csp-blocked.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js.ini b/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js.ini new file mode 100644 index 00000000000..23cc9814012 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[csp-redirect-to-blocked.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/fetch/metadata/generated/css-images.sub.tentative.html.ini b/tests/wpt/meta-legacy-layout/fetch/metadata/generated/css-images.sub.tentative.html.ini index f0cfa5a9e3f..f9de5391ad6 100644 --- a/tests/wpt/meta-legacy-layout/fetch/metadata/generated/css-images.sub.tentative.html.ini +++ b/tests/wpt/meta-legacy-layout/fetch/metadata/generated/css-images.sub.tentative.html.ini @@ -146,12 +146,3 @@ [list-style-image sec-fetch-site - HTTPS downgrade-upgrade] expected: FAIL - - [background-image sec-fetch-site - HTTPS downgrade (header not sent)] - expected: TIMEOUT - - [border-image sec-fetch-site - HTTPS downgrade (header not sent)] - expected: FAIL - - [background-image sec-fetch-mode - Not sent to non-trustworthy same-origin destination] - expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/hr-time/raf-coarsened-time.https.html.ini b/tests/wpt/meta-legacy-layout/hr-time/raf-coarsened-time.https.html.ini new file mode 100644 index 00000000000..b4991611fcf --- /dev/null +++ b/tests/wpt/meta-legacy-layout/hr-time/raf-coarsened-time.https.html.ini @@ -0,0 +1,2 @@ +[raf-coarsened-time.https.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html.ini b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html.ini new file mode 100644 index 00000000000..46f10274f9f --- /dev/null +++ b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html.ini @@ -0,0 +1,4 @@ +[order-in-bfcache-restore.html] + expected: TIMEOUT + [pagereveal event fires and in correct order on restoration from BFCache] + expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html.ini b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html.ini new file mode 100644 index 00000000000..721a89932a1 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html.ini @@ -0,0 +1,3 @@ +[order-in-new-document-navigation.html] + [pagereveal event fires and in correct order on new-document navigation] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html.ini b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html.ini new file mode 100644 index 00000000000..b6c1d6dbec6 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html.ini @@ -0,0 +1,2 @@ +[order-in-prerender-activation.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html.ini b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html.ini index 1bca09f21d6..c5fc1407992 100644 --- a/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html.ini +++ b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html.ini @@ -1,4 +1,5 @@ [iframe-src-aboutblank-navigate-immediately.html] + expected: TIMEOUT [Navigating to a different document with window.open] expected: FAIL @@ -6,4 +7,4 @@ expected: FAIL [Navigating to a different document with form submission] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html.ini b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html.ini index 51fd557bd7f..d19311abec9 100644 --- a/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html.ini +++ b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html.ini @@ -7,3 +7,9 @@ [load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank#foo'] expected: FAIL + + [load & pageshow events do not fire on contentWindow of <iframe> element created with src=''] + expected: FAIL + + [load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank'] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.js.ini b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.js.ini new file mode 100644 index 00000000000..4ecd6d9f753 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.js.ini @@ -0,0 +1,3 @@ +[navigation-unload-cross-origin.sub.window.html] + [Cross-origin navigation started from unload handler must be ignored] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html.ini b/tests/wpt/meta-legacy-layout/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html.ini new file mode 100644 index 00000000000..addd810a23d --- /dev/null +++ b/tests/wpt/meta-legacy-layout/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html.ini @@ -0,0 +1,2 @@ +[canvas.2d.disconnected-font-size-math.html] + expected: CRASH diff --git a/tests/wpt/meta-legacy-layout/html/canvas/element/manual/text/canvas.2d.disconnected.html.ini b/tests/wpt/meta-legacy-layout/html/canvas/element/manual/text/canvas.2d.disconnected.html.ini index 17247137cb1..5cdcce07c65 100644 --- a/tests/wpt/meta-legacy-layout/html/canvas/element/manual/text/canvas.2d.disconnected.html.ini +++ b/tests/wpt/meta-legacy-layout/html/canvas/element/manual/text/canvas.2d.disconnected.html.ini @@ -1,2 +1,2 @@ [canvas.2d.disconnected.html] - expected: CRASH + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/dom/elements/global-attributes/dir-auto-form-associated.window.js.ini b/tests/wpt/meta-legacy-layout/html/dom/elements/global-attributes/dir-auto-form-associated.window.js.ini new file mode 100644 index 00000000000..9b19b29d20e --- /dev/null +++ b/tests/wpt/meta-legacy-layout/html/dom/elements/global-attributes/dir-auto-form-associated.window.js.ini @@ -0,0 +1,66 @@ +[dir-auto-form-associated.window.html] + [<input dir=auto type=hidden> directionality] + expected: FAIL + + [<input dir=auto type=text> directionality] + expected: FAIL + + [<input dir=auto type=search> directionality] + expected: FAIL + + [<input dir=auto type=tel> directionality] + expected: FAIL + + [<input dir=auto type=url> directionality] + expected: FAIL + + [<input dir=auto type=email> directionality] + expected: FAIL + + [<input dir=auto type=password> directionality] + expected: FAIL + + [<input dir=auto type=submit> directionality] + expected: FAIL + + [<input dir=auto type=reset> directionality] + expected: FAIL + + [<input dir=auto type=button> directionality] + expected: FAIL + + [<input dir=auto type=date> directionality] + expected: FAIL + + [<input dir=auto type=month> directionality] + expected: FAIL + + [<input dir=auto type=week> directionality] + expected: FAIL + + [<input dir=auto type=time> directionality] + expected: FAIL + + [<input dir=auto type=datetime-local> directionality] + expected: FAIL + + [<input dir=auto type=number> directionality] + expected: FAIL + + [<input dir=auto type=range> directionality] + expected: FAIL + + [<input dir=auto type=color> directionality] + expected: FAIL + + [<input dir=auto type=checkbox> directionality] + expected: FAIL + + [<input dir=auto type=radio> directionality] + expected: FAIL + + [<input dir=auto type=image> directionality] + expected: FAIL + + [<textarea dir=auto> directionality] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/dom/elements/global-attributes/lang-attribute.window.js.ini b/tests/wpt/meta-legacy-layout/html/dom/elements/global-attributes/lang-attribute.window.js.ini new file mode 100644 index 00000000000..9a9467a8817 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/html/dom/elements/global-attributes/lang-attribute.window.js.ini @@ -0,0 +1,3 @@ +[lang-attribute.window.html] + [unnamespaced lang attribute only works on elements in the HTML namespace] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html.ini index 25d9964f057..e5994e21efc 100644 --- a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html.ini +++ b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html.ini @@ -1,4 +1,5 @@ [iframe_sandbox_popups_escaping-1.html] type: testharness + expected: CRASH [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html.ini index 26704422bbe..841bafc6eca 100644 --- a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html.ini +++ b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html.ini @@ -1,4 +1,3 @@ [iframe_sandbox_popups_escaping-2.html] - expected: TIMEOUT [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini index fe55ddae3f1..eacbe5794ea 100644 --- a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini +++ b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html.ini @@ -1,4 +1,5 @@ [iframe_sandbox_popups_escaping-3.html] type: testharness + expected: TIMEOUT [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini index 6f7461b9472..f9138fb999a 100644 --- a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini +++ b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini @@ -1,4 +1,5 @@ [iframe_sandbox_popups_nonescaping-1.html] type: testharness + expected: TIMEOUT [Check that popups from a sandboxed iframe do not escape the sandbox] - expected: FAIL + expected: NOTRUN diff --git a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-img-element/non-active-document.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-img-element/non-active-document.html.ini index 47b45e65a1c..3cdeb8ebcbc 100644 --- a/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-img-element/non-active-document.html.ini +++ b/tests/wpt/meta-legacy-layout/html/semantics/embedded-content/the-img-element/non-active-document.html.ini @@ -1,9 +1,3 @@ [non-active-document.html] [DOMParser] expected: FAIL - - [createHTMLDocument] - expected: FAIL - - [<template>] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/semantics/forms/form-submission-0/text-plain.window.js.ini b/tests/wpt/meta-legacy-layout/html/semantics/forms/form-submission-0/text-plain.window.js.ini index d2d031e78b0..56543701e05 100644 --- a/tests/wpt/meta-legacy-layout/html/semantics/forms/form-submission-0/text-plain.window.js.ini +++ b/tests/wpt/meta-legacy-layout/html/semantics/forms/form-submission-0/text-plain.window.js.ini @@ -178,3 +178,9 @@ [text/plain: Basic test (formdata event)] expected: FAIL + + [text/plain: 0x00 in name (normal form)] + expected: FAIL + + [text/plain: double quote in name (formdata event)] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/semantics/forms/historical.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/forms/historical.html.ini deleted file mode 100644 index 5d8289307cc..00000000000 --- a/tests/wpt/meta-legacy-layout/html/semantics/forms/historical.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[historical.html] - [<input name=isindex> should not be supported] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/semantics/invokers/invokeelement-interface.tentative.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/invokers/invokeelement-interface.tentative.html.ini index e1534b63047..e8781936e24 100644 --- a/tests/wpt/meta-legacy-layout/html/semantics/invokers/invokeelement-interface.tentative.html.ini +++ b/tests/wpt/meta-legacy-layout/html/semantics/invokers/invokeelement-interface.tentative.html.ini @@ -31,3 +31,6 @@ [invokeAction reflects tostring value 2] expected: FAIL + + [invokeAction reflects same casing] + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html.ini index cc18f512574..071b4378add 100644 --- a/tests/wpt/meta-legacy-layout/html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html.ini +++ b/tests/wpt/meta-legacy-layout/html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html.ini @@ -11,6 +11,3 @@ [Check that rel=noopener with target=_parent does a normal load] expected: FAIL - - [Check that rel=noopener with target=_self does a normal load] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/semantics/scripting-1/the-script-element/defer-script/async-script.html.ini b/tests/wpt/meta-legacy-layout/html/semantics/scripting-1/the-script-element/defer-script/async-script.html.ini deleted file mode 100644 index 6339abba6d9..00000000000 --- a/tests/wpt/meta-legacy-layout/html/semantics/scripting-1/the-script-element/defer-script/async-script.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[async-script.html?reload] - expected: ERROR - -[async-script.html?default] diff --git a/tests/wpt/meta-legacy-layout/html/syntax/parsing/DOMContentLoaded-defer.html.ini b/tests/wpt/meta-legacy-layout/html/syntax/parsing/DOMContentLoaded-defer.html.ini deleted file mode 100644 index b8bdf33cb65..00000000000 --- a/tests/wpt/meta-legacy-layout/html/syntax/parsing/DOMContentLoaded-defer.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[DOMContentLoaded-defer.html] - [The end: DOMContentLoaded and defer scripts] - expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html.ini b/tests/wpt/meta-legacy-layout/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html.ini index 7237f5792de..dbe1def99e3 100644 --- a/tests/wpt/meta-legacy-layout/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html.ini +++ b/tests/wpt/meta-legacy-layout/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html.ini @@ -1,10 +1,9 @@ [promise-job-entry-different-function-realm.html] - expected: TIMEOUT [Fulfillment handler on fulfilled promise] expected: FAIL [Rejection handler on pending-then-rejected promise] - expected: TIMEOUT + expected: FAIL [Thenable resolution] expected: FAIL @@ -13,4 +12,4 @@ expected: FAIL [Fulfillment handler on pending-then-fulfilled promise] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini b/tests/wpt/meta-legacy-layout/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini index 4a48dd15a9d..1d71471b73c 100644 --- a/tests/wpt/meta-legacy-layout/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini +++ b/tests/wpt/meta-legacy-layout/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini @@ -1,6 +1,7 @@ [promise-rejection-events.html] + expected: TIMEOUT [delayed handling: delaying handling rejected promise created from createImageBitmap will cause both events to fire] - expected: FAIL + expected: TIMEOUT [unhandledrejection: from createImageBitmap which is UA triggered] expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/casts.tentative.any.js.ini b/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/casts.tentative.any.js.ini new file mode 100644 index 00000000000..0b499ced6d7 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/casts.tentative.any.js.ini @@ -0,0 +1,5 @@ +[casts.tentative.any.worker.html] + expected: ERROR + +[casts.tentative.any.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/exported-object.tentative.any.js.ini b/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/exported-object.tentative.any.js.ini new file mode 100644 index 00000000000..59dd05d2b08 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/exported-object.tentative.any.js.ini @@ -0,0 +1,5 @@ +[exported-object.tentative.any.worker.html] + expected: ERROR + +[exported-object.tentative.any.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/i31.tentative.any.js.ini b/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/i31.tentative.any.js.ini new file mode 100644 index 00000000000..485ae1ecd1c --- /dev/null +++ b/tests/wpt/meta-legacy-layout/wasm/jsapi/gc/i31.tentative.any.js.ini @@ -0,0 +1,5 @@ +[i31.tentative.any.worker.html] + expected: ERROR + +[i31.tentative.any.html] + expected: ERROR diff --git a/tests/wpt/meta-legacy-layout/webmessaging/with-ports/018.html.ini b/tests/wpt/meta-legacy-layout/webmessaging/with-ports/018.html.ini new file mode 100644 index 00000000000..b7b36c1d3a4 --- /dev/null +++ b/tests/wpt/meta-legacy-layout/webmessaging/with-ports/018.html.ini @@ -0,0 +1,4 @@ +[018.html] + expected: TIMEOUT + [origin of the script that invoked the method, javascript:] + expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/webmessaging/without-ports/017.html.ini b/tests/wpt/meta-legacy-layout/webmessaging/without-ports/017.html.ini deleted file mode 100644 index c7946fc91b4..00000000000 --- a/tests/wpt/meta-legacy-layout/webmessaging/without-ports/017.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[017.html] - expected: TIMEOUT - [origin of the script that invoked the method, about:blank] - expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html.ini b/tests/wpt/meta-legacy-layout/webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html.ini deleted file mode 100644 index aa6c9e5b826..00000000000 --- a/tests/wpt/meta-legacy-layout/webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html] - expected: TIMEOUT - [StorageKey: test 3P about:blank window opened from a 3P iframe] - expected: TIMEOUT diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 7495768a479..452da213d24 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -2349,13 +2349,6 @@ ] ] }, - "dynamic-counters-crash.html": [ - "41e98ce003750d702e2a0fa0fc144e83532b9060", - [ - null, - {} - ] - ], "list-item-counter-crash.html": [ "fc8a38c628026dc190d81e27150d8ebabb130ae2", [ @@ -3545,6 +3538,15 @@ ] ] }, + "css-scoping": { + "chrome-1492368-crash.html": [ + "04d48ef21532405548b80e23c482e848b3fc1ef6", + [ + null, + {} + ] + ] + }, "css-scroll-anchoring": { "fullscreen-crash.html": [ "545f2919b55ffe31f942e547d5299c00ee89d715", @@ -3911,6 +3913,13 @@ {} ] ], + "text-indent-each-line-crash.html": [ + "fb63175cf179871e76b8d30e3016401626725769", + [ + null, + {} + ] + ], "text-wrap-balance-float-crash.html": [ "a4767b07615925aebd31343e81b772c8712e8756", [ @@ -4510,6 +4519,13 @@ {} ] ], + "insert-dir-rule-crash.html": [ + "6cffa0c62a522f201f9dd531bc3774df46b7d394", + [ + null, + {} + ] + ], "insert-dir-rule-in-iframe-crash.html": [ "4c9d7530dc359719166e16dbd93ed0088c3ca7d5", [ @@ -153971,7 +153987,7 @@ ] ], "lch-009.html": [ - "472e7c138f720f995506100c04f661143f4136cb", + "375fd08de5833cc0ef0619e762c98b2bc289b13c", [ null, [ @@ -153984,7 +154000,7 @@ ] ], "lch-010.html": [ - "527e9cc7aff679a16da65f2ea10965b896cd99e6", + "965e05ff5dc0a16b169ba5f22d261c180f719a74", [ null, [ @@ -154309,7 +154325,7 @@ ] ], "oklch-009.html": [ - "5a4924a7e282885a6238011ec90492af49421c1a", + "1882c476c1c8678dd8e0e7d443735c25d63f02ca", [ null, [ @@ -154322,7 +154338,7 @@ ] ], "oklch-010.html": [ - "091b760bea29bed450a21c9620eec2b0823bdc84", + "b5f9ac206b45eb031ac0330fef22923a319cf472", [ null, [ @@ -155180,12 +155196,12 @@ ] ], "t32-opacity-basic-0.6-a.xht": [ - "3687d5392e30ed929fa3ab00d851b7e9754ab8ff", + "541964f8d6131e3b47b0edf6ea867cd331603a5d", [ null, [ [ - "/css/css-color/t32-opacity-basic-0.6-a-ref.html", + "/css/css-color/t32-opacity-basic-0.6-a-ref.xht", "==" ] ], @@ -155469,12 +155485,12 @@ ] ], "t422-rgba-a0.6-a.xht": [ - "2274eb3c3127c76862ade6b974ca55ccea47bab4", + "a710a0b62513969e8a7479a81fef70d09d87d956", [ null, [ [ - "/css/css-color/t32-opacity-basic-0.6-a-ref.html", + "/css/css-color/t422-rgba-a0.6-a-ref.xht", "==" ] ], @@ -155872,12 +155888,12 @@ ] ], "t425-hsla-basic-a.xht": [ - "3645a9acedf0e13af91ceff4733e1edd54adab16", + "435041b5fa9b0f003adb893e96550765f7effc3c", [ null, [ [ - "/css/css-color/t425-hsla-basic-a-ref.html", + "/css/css-color/t425-hsla-basic-a-ref.xht", "==" ] ], @@ -156145,7 +156161,7 @@ ] ], "xyz-d50-003.html": [ - "036bcb6c148fabb6b859a236caff248175b86ad8", + "7630115187454cab97615eec49e59a6e446da285", [ null, [ @@ -156158,7 +156174,7 @@ ] ], "xyz-d50-004.html": [ - "cc178590eaeeed69070cc48935ad73d43a89ae97", + "f4aa9a0a1d5730e5180fc06e6a21a9bb51908066", [ null, [ @@ -195311,7 +195327,7 @@ ] ], "custom-highlight-font-metrics-002.html": [ - "48ca92feef0f8bcbaa45371afee9365cbf6ccef7", + "58b2db5ce4e9a12b2298c24a1deda18553da6b5f", [ null, [ @@ -195327,7 +195343,7 @@ [ [ 0, - 120 + 128 ], [ 0, @@ -205937,6 +205953,32 @@ } ] ], + "clip-path-animation-ellipse-mixed-change.html": [ + "e42d3ee08ed599b72be97e078b296b8f49f22e2c", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-ellipse-ref.html", + "==" + ] + ], + {} + ] + ], + "clip-path-animation-ellipse.html": [ + "1c7c90ee844551c878b2ac2dd9453cdef92fb49f", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-ellipse-ref.html", + "==" + ] + ], + {} + ] + ], "clip-path-animation-filter.html": [ "a9809cbc30b5ca53fc464a125af9bdaeaeef9c60", [ @@ -206008,6 +206050,45 @@ } ] ], + "clip-path-animation-font-size-inherited.html": [ + "6836af5a2953611798e7b4c5a80b7a4b66ee6c78", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-font-size-ref.html", + "==" + ] + ], + {} + ] + ], + "clip-path-animation-font-size-mixed-change.html": [ + "9e24aa905c2c4ba2e77d8d5ce686ddcbc57a01ad", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-font-size-ref.html", + "==" + ] + ], + {} + ] + ], + "clip-path-animation-font-size.html": [ + "00563305e54267948fc23e441420008760c26637", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-font-size-ref.html", + "==" + ] + ], + {} + ] + ], "clip-path-animation-fragmented.html": [ "9f68c238faf2ee2d04940e2f65d303bf94444595", [ @@ -206163,6 +206244,61 @@ } ] ], + "clip-path-animation-path.html": [ + "20400ba5ece395864e96ce095918f562b415566e", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-path-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 10 + ], + [ + 0, + 200 + ] + ] + ] + ] + } + ] + ], + "clip-path-animation-polygon-mixed-change.html": [ + "569c0af66ae3ae66ddcc185392ad66e488fdffca", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-polygon-ref.html", + "==" + ] + ], + {} + ] + ], + "clip-path-animation-polygon.html": [ + "1a9d0cc168879dfba969cc534dd7b3d9edba7c47", + [ + null, + [ + [ + "/css/css-masking/clip-path/animations/clip-path-animation-polygon-ref.html", + "==" + ] + ], + {} + ] + ], "clip-path-animation-svg-zoom.html": [ "f7be6d25324ce92e6bf56921fffb3eeec27cfd98", [ @@ -210598,7 +210734,7 @@ ] ], "mask-image-3b.html": [ - "bd805cde975a844527eefca27d771cf5c39fc2c0", + "b6609fde6a4ac33ca1fb9fd6f87513e2fef9498d", [ null, [ @@ -210607,11 +210743,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 1 + ], + [ + 0, + 100 + ] + ] + ] + ] + } ] ], "mask-image-3c.html": [ - "32bd4454d715069524c8d6e0994aac489ccd6b22", + "91cc9f7bb100398e9789a39dead4bde623de18e7", [ null, [ @@ -210620,11 +210772,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 1 + ], + [ + 0, + 100 + ] + ] + ] + ] + } ] ], "mask-image-3d.html": [ - "f1ef1be7099b9f322aa5bf65db272d765a76be7c", + "468872fecbde8ec1a8b54abc7c83a7b3dfb4357b", [ null, [ @@ -210633,11 +210801,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 1 + ], + [ + 0, + 100 + ] + ] + ] + ] + } ] ], "mask-image-3e.html": [ - "15223e34d627e22356246f12f1717758898661d4", + "5e5393755453b30dd73c10ebeee3bfa95ded939b", [ null, [ @@ -210646,11 +210830,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 1 + ], + [ + 0, + 100 + ] + ] + ] + ] + } ] ], "mask-image-3f.html": [ - "e925105baacd81242c0bda3dd11175651e934f5b", + "0ecfd383652bc1a8fd57af6a1936685410dd4329", [ null, [ @@ -210659,11 +210859,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 1 + ], + [ + 0, + 100 + ] + ] + ] + ] + } ] ], "mask-image-3g.html": [ - "1236c0c33487ee825a2a3bb7f1b473a99fc70cea", + "133a69fa6094e7c002ac8340761df0244681f0fc", [ null, [ @@ -210672,7 +210888,23 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 1 + ], + [ + 0, + 100 + ] + ] + ] + ] + } ] ], "mask-image-3h.html": [ @@ -322185,7 +322417,7 @@ ] ], "lang-xmllang-01.html": [ - "9538f15ca8c808abcc5fb800ee47272367dc4e76", + "04d8b74e2d1260d24318f975fedc2552897e9327", [ null, [ @@ -322198,7 +322430,7 @@ ] ], "lang-xyzzy.html": [ - "d6e6aeb6475f3bdac8f9cfee9cb58d1c8edba86c", + "b950e1fac99168e76121eaa4553a014e7ed84bfb", [ null, [ @@ -326252,6 +326484,19 @@ {} ] ], + "iframe-loading-lazy-in-viewport-001.html": [ + "408e5309e57d621ca6e486f62533bbd985de0c48", + [ + null, + [ + [ + "/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-viewport-ref.html", + "==" + ] + ], + {} + ] + ], "iframe-modify-scrolling-attr-to-yes.html": [ "9d85aa543d2d1732b8534fcdfa62a42d11716586", [ @@ -330025,17 +330270,149 @@ ] }, "jpegxl": { - "srgb.html": [ - "9d131787ec3aeb1619b40811464cc823397ea901", + "3x3_jpeg_recompression.html": [ + "f28fca8fdce33b39ace86403a348195f910de481", [ null, [ [ - "/jpegxl/srgb-ref.html", + "/jpegxl/3x3_jpeg_recompression-ref.html", "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 1 + ], + [ + 0, + 9 + ] + ] + ] + ] + } + ] + ], + "3x3_srgb_lossless.html": [ + "589f11c68c4152eea3d395104c0d5ce4bbefbf4d", + [ + null, + [ + [ + "/jpegxl/3x3_srgb_lossless-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 4 + ], + [ + 0, + 9 + ] + ] + ] + ] + } + ] + ], + "3x3_srgb_lossy.html": [ + "3a92b2b7301d35570b4349513ccc1e1318a8ca8f", + [ + null, + [ + [ + "/jpegxl/3x3_srgb_lossy-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 10 + ], + [ + 0, + 9 + ] + ] + ] + ] + } + ] + ], + "3x3a_srgb_lossless.html": [ + "1de61a5ba2713b0fc876305666069cb58299de29", + [ + null, + [ + [ + "/jpegxl/3x3a_srgb_lossless-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 4 + ], + [ + 0, + 9 + ] + ] + ] + ] + } + ] + ], + "3x3a_srgb_lossy.html": [ + "59583a11a9aab8bf4114bad2de3f405dffc3f0cd", + [ + null, + [ + [ + "/jpegxl/3x3a_srgb_lossy-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 10 + ], + [ + 0, + 9 + ] + ] + ] + ] + } ] ] }, @@ -334618,7 +334995,7 @@ ] ], "masked.html": [ - "1c7a332d7f9e21dc85105793922b725aeb3891c2", + "a4ca2fd8521f06808d4c2515ce007027ebcac2a4", [ null, [ @@ -334634,7 +335011,7 @@ [ [ 0, - 37 + 138 ], [ 0, @@ -336314,6 +336691,21 @@ {} ] ] + }, + "scripted": { + "pattern-transform-clear.svg": [ + "6800fd8d20dfe3222f782140ca6106f3864e3db6", + [ + null, + [ + [ + "/svg/pservers/reftests/reference/green-100x100.svg", + "==" + ] + ], + {} + ] + ] } }, "render": { @@ -341148,7 +341540,7 @@ ], "workflows": { "documentation.yml": [ - "00c7bb226279e9a3a9dfddbe224edfe55a8688b3", + "1d57acc6256c14b664daf1c4f528ca849b7e22b6", [] ], "epochs.yml": [ @@ -341625,7 +342017,13 @@ "META.yml": [ "dbfac71522fa59318abb52edc530dc850fe66936", [] - ] + ], + "resources": { + "sensor-data.js": [ + "6f56cfdbeb6dfff65ccdbf9b6b49474c021c6ba7", + [] + ] + } }, "accessibility": { "ReadMe.md": [ @@ -341793,7 +342191,13 @@ "META.yml": [ "e173970b5d77af1fcff868fa026dc2787d7a3cc0", [] - ] + ], + "resources": { + "sensor-data.js": [ + "c1f7bd5ca0f7fb2722c17433b0dd1b0810223324", + [] + ] + } }, "animation-worklet": { "META.yml": [ @@ -345024,7 +345428,7 @@ ], "resources": { "helpers.js": [ - "c4c8c5b03261458ceabaeb7a7ed736cf812226a1", + "97a62309cd5b39c14ab9c31b9c1305b160ba5c7e", [] ] } @@ -345438,6 +345842,10 @@ [] ] }, + "top-layer.js": [ + "2dc8ce3893aa721ba1c03f4ac42ba8c52c8312f4", + [] + ], "utils.js": [ "62e742bee7f67cf3bd92a217a0a92b23fddf3017", [] @@ -366213,7 +366621,7 @@ ], "fedcm": { "accounts.py": [ - "3989de7f17c6da82f8e7a41aba7947dac051df1a", + "126f911a58c80a62de06b6062cdb4488549471b9", [] ], "client_metadata.py": [ @@ -366228,6 +366636,10 @@ "3c31bf5077d73ac258f4a96bb6b4f5e95802f184", [] ], + "error_with_code_and_url.py": [ + "71bfea00f463051e7bd496cf1c28f25208e2b41e", + [] + ], "intercept_service_worker.js": [ "773e38fd21b023b8314f732b6d1893ab6c65a3cd", [] @@ -366248,6 +366660,10 @@ "ba9ec9c9d47e7a5888b5d987b61ff51ad66bec80", [] ], + "manifest_id_assertion_endpoint_returns_error.json": [ + "e098cc4511a1980392097d0a26c020db3243ae35", + [] + ], "manifest_redirect_accounts.json": [ "6a8972feebd6d139cb279d2f0446d4c3957bc5fc", [] @@ -366256,6 +366672,10 @@ "affe34f8f31f61f5cf5a5c88c0588efb331b4d1e", [] ], + "manifest_token_with_http_error.json": [ + "691a1e8d3a63a3695ec1fd29267506363871af71", + [] + ], "manifest_with_auto_selected_flag.json": [ "591c927153b9a78695ded0663fed600cbae5bcb6", [] @@ -366308,8 +366728,12 @@ "93ccf3ee7e2277716dc1c9d5b02805b9e2b398cc", [] ], + "token_with_http_error.py": [ + "c8d95ab63d7ebda6d32a60307f123bd858f39891", + [] + ], "two_accounts.py": [ - "4ea6d76a7eb2ea489410c672494ff7500e4046f0", + "4022561ff78321d91605b07f76d03a1f8deb5297", [] ], "userinfo-iframe.html": [ @@ -366322,7 +366746,7 @@ ] }, "fedcm-helper.sub.js": [ - "ef10e41793a16c3ead78e12a2425b5e422851906", + "f02a76b3fe2b39763fc8fc3be510a73bb01ed1de", [] ], "fedcm-iframe-level2.html": [ @@ -366334,7 +366758,7 @@ [] ], "fedcm-mock.js": [ - "16a72b1d2c3ced916368c50c096376a319ea7a4c", + "b14bbaa80a72bc5157cbf80c6fa70f33e3e6e70f", [] ], "fedcm-mojojs-helper.js": [ @@ -366345,12 +366769,20 @@ "476f32688f91cede949edf2a1e650ef573525bd7", [] ], + "fencedframe-mark-signedin.html": [ + "532db7047a8a0903dfa8dec0fac943318c18e505", + [] + ], + "iframe-mark-signedin.html": [ + "4ca0125cde2e4ec7a404ba360becf22a66eb3e40", + [] + ], "mark_signedin": [ "d9adcaa762909e0ddef54daa989848169ede25dc", [] ], "mark_signedin.sub.headers": [ - "b87b36fa3b39fb75b986cb89d228841de6535ede", + "d560fade5a0e4237f751b0c90a87fc25f92aa14a", [] ], "mark_signedout": [ @@ -366358,7 +366790,7 @@ [] ], "mark_signedout.sub.headers": [ - "46a8c34b2180c78ed66800d860beaa052e6c1eee", + "69157b3a371e369df585331a2479144fee444f5c", [] ], "otpcredential-helper.js": [ @@ -388241,8 +388673,8 @@ "298c4890dffede87edc4b042c13a254a15a95f53", [] ], - "t32-opacity-basic-0.6-a-ref.html": [ - "fb906237b23dc65f95d5d3ab1b27f5b375bc9fa5", + "t32-opacity-basic-0.6-a-ref.xht": [ + "ae46348506556247a2f97a3cc1d6d3f76676a110", [] ], "t32-opacity-basic-1.0-a-ref.html": [ @@ -388289,6 +388721,10 @@ "b824200a06bcd4c27b05e19ae9da12ff96176a0b", [] ], + "t422-rgba-a0.6-a-ref.xht": [ + "ae46348506556247a2f97a3cc1d6d3f76676a110", + [] + ], "t422-rgba-a1.0-a-ref.html": [ "6aa32ae7bb6496f9359502feb4bcfa04bc3c8dd7", [] @@ -388401,8 +388837,8 @@ "ac42b1f86ce97a2e95aafe91f53cc5ff125ca73e", [] ], - "t425-hsla-basic-a-ref.html": [ - "32eb4cd46ccf0f66b30d986f0c054a8c32a2e4a3", + "t425-hsla-basic-a-ref.xht": [ + "bc21fe36a26a573b5922aa84b9934e003bcadb49", [] ], "t425-hsla-clip-outside-device-gamut-b-ref.html": [ @@ -388450,11 +388886,11 @@ [] ], "xyz-d50-003-ref.html": [ - "51f565e04b13fc35bfd39a6171f40ae193b86012", + "4223a511df5fa75901e01aa2758d567d7c0ce7ae", [] ], "xyz-d50-004-ref.html": [ - "9d211ae42a531efae3a3ec916755d260217882eb", + "4d1c08f2ae8052a5f6f198b7cd0f7c26e6ec6103", [] ], "xyz-d65-003-ref.html": [ @@ -404357,6 +404793,10 @@ "edaf92cb8ae763ed592810d19343e24a89ff1f0f", [] ], + "clip-path-animation-ellipse-ref.html": [ + "63b3174806f9751a6fcfebb3b81e508decd4ebbc", + [] + ], "clip-path-animation-filter-ref.html": [ "5bb9a9c7220f33e02b69bc7e909630ff10682de6", [] @@ -404369,6 +404809,10 @@ "a069e4d3ae5bc82ea9547b01e7958b8f7eead645", [] ], + "clip-path-animation-font-size-ref.html": [ + "912a8e8464266e98588bc3a6faf6b60d589198d7", + [] + ], "clip-path-animation-fragmented-ref.html": [ "8883679acaaa51a72c8b662701941fdf3a18fb3d", [] @@ -404397,6 +404841,14 @@ "154a56d5f07832fc7ef08b4db40acbb50faf8348", [] ], + "clip-path-animation-path-ref.html": [ + "d53067f5634265344f78962fbab011e742b0dbf3", + [] + ], + "clip-path-animation-polygon-ref.html": [ + "28e11e966d58ad6ed074ff1a3e8b232f56df8213", + [] + ], "clip-path-animation-ref.html": [ "b548c5d590edeef0d7aa8a8b4461fed72d2460c7", [] @@ -407641,7 +408093,7 @@ ], "resources": { "utils.js": [ - "fc3a5993cf566559505c1b92c6ff08d2e9484ad0", + "a952a4feedc5523219eccd231c9bf1c1dc624755", [] ] }, @@ -426402,7 +426854,7 @@ [] ], "formatblock.js": [ - "64e0d11d5948170f7506b20a4e646c93cc4dc63b", + "0161e4da01b455c698948687956ad32daa20a1a7", [] ], "forwarddelete.js": [ @@ -429892,7 +430344,17 @@ "README.md": [ "661e2b918438fabcdee9e160f79ba8dddb2877d4", [] - ] + ], + "resources": { + "fetch-later.html": [ + "b569e1a076ac210d87d01b51ded0a8943476eac0", + [] + ], + "header-referrer-helper.js": [ + "374097614ae92646ab6260948abcc64cbdaf4d8d", + [] + ] + } }, "h1-parsing": { "README.md": [ @@ -430556,12 +431018,12 @@ "fledge": { "tentative": { "TODO": [ - "2b6a1dc3c2d1cd64cbd84a629e0abd6148253b51", + "272a5e3ffb982366053c13ee0610e6a2dc5d8eab", [] ], "resources": { "bidding-logic.sub.py": [ - "58fe220880a2ff054a6eabf02082a68702d6bc04", + "c0d6114ab2c6102ba545e92a969a1eecce696d85", [] ], "decision-logic.sub.py": [ @@ -430577,11 +431039,19 @@ [] ], "fledge-util.sub.js": [ - "d500307a07939ece0c817daed5417f0cdbabcfd9", + "e19d85a558ff1fe885611daf7338bbead70a2012", + [] + ], + "fledge_http_server_util.py": [ + "a5c9c9715aa1013450b9cb60958a55c605b27701", [] ], "request-tracker.py": [ - "46da796f30102e0e32a82a4dab96fa9217154306", + "9fe20bf83ac0d83da8b26f71540151a92d10ca02", + [] + ], + "set-cookie.asis": [ + "96d9f07c578c34085dd789d2a11b37cd4a51c42c", [] ], "subordinate-frame.sub.html": [ @@ -430589,11 +431059,11 @@ [] ], "trusted-bidding-signals.py": [ - "86e4db8ad448ade94b4c5885ea6b99b9f80e2871", + "16272afc71ccedb19cdcd80305fa78dc0f974b03", [] ], "trusted-scoring-signals.py": [ - "43ff772a0e32f2928b01db727b0c1e9988a42cec", + "fc6ec79096c4708b347e0cfc277fa248bf8ba9c3", [] ] } @@ -432075,20 +432545,20 @@ [] ], "generic-sensor-iframe-tests.sub.js": [ - "7b816c01c745ab7fb41f4f0d8024d34b377430d6", + "8f13bd778e06e58c2c8417d58c2fcb1f7cda43ed", [] ], "generic-sensor-tests.js": [ - "3c8f478c541dcdb28d27012574dbdeb407902a16", + "3b23fe89191f42f6a404d56fd50d8d9b84adeff1", [] ], "resources": { "generic-sensor-helpers.js": [ - "9a51a591ce116e981310c0f1eb37cfc7eac722fd", + "146f4292ade4bf8fd965991c237a766b16cad84b", [] ], "iframe_sensor_handler.html": [ - "4528c57a6beeec84bc00e311be0691e595b2f167", + "80cdcf7c0d02ffe123b39b86cd2b9cdad5aee7cf", [] ] } @@ -432137,7 +432607,13 @@ "META.yml": [ "939d6d076043a414d3e8dccbfc9c57830dd913be", [] - ] + ], + "resources": { + "sensor-data.js": [ + "5bbad442929bf518930fa0294f4d270447deef1c", + [] + ] + } }, "graphics-aam": { "META.yml": [ @@ -432167,7 +432643,13 @@ "META.yml": [ "8f553a86ca3bf19fe429f4a31f20d97ed8b1babd", [] - ] + ], + "resources": { + "sensor-data.js": [ + "409ffef9a1750c4b058bafae9898e72bd9d59624", + [] + ] + } }, "hr-time": { "META.yml": [ @@ -432182,6 +432664,10 @@ "5f8621ef83660c66f0d037ea28fafefb558140f1", [] ], + "raf-coarsened-time.https.html.headers": [ + "5f8621ef83660c66f0d037ea28fafefb558140f1", + [] + ], "resources": { "clamped-time-origin.js": [ "09967ed6d17ec0c302455d878d85034046db89a2", @@ -432337,6 +432823,16 @@ "9e917227147346f0115330c3a6bc953f47349f06", [] ], + "pagereveal": { + "tentative": { + "resources": { + "order-in-prerender-activation-popup.html": [ + "78989adc172997dd379ea6e7aee578be45702b79", + [] + ] + } + } + }, "persisted-user-state-restoration": { "resources": { "blank1.html": [ @@ -437658,7 +438154,7 @@ [] ], "lang-xmllang-01-ref.html": [ - "1606bca21581d9ae30fb027f59f5caa205a34c7e", + "eacf73da16c2e7242eed98a415ce187510e44120", [] ], "lang-xyzzy-ref.html": [ @@ -443361,6 +443857,10 @@ "0484c397cd4bedd92f33a4c43f8d589ace6b1557", [] ], + "iframe-loading-lazy-in-viewport-ref.html": [ + "067bfa19202b237046f0e06261f039e1a2e74b92", + [] + ], "iframe-modify-scrolling-attr-to-yes-ref.html": [ "3758ea2cab4096beccb3722a1cc534b71c662a64", [] @@ -444698,7 +445198,7 @@ [] ], "popover-utils.js": [ - "f11291e5c2ff97ee03f0093d55fb33d3e18f8c99", + "bfc1f89ec1003bfaeca1a7aea115140858a85717", [] ] } @@ -448384,6 +448884,10 @@ "adbdc7bd93d71cee1fb318dfd36a8bd5cd305892", [] ], + "WEB_FEATURES.yml": [ + "1e208f268e303c3d470467894407b3e0cde6bda4", + [] + ], "idle-detection-allowed-by-permissions-policy.https.sub.html.headers": [ "2bf18afe5fe4d034619b3e0a62455649d4203e18", [] @@ -449253,6 +449757,14 @@ "6505d896a9c195614a89af06af6f9c11b8c5eb7b", [] ] + }, + "webdriver": { + "tests": { + "test_load_file.py.ini": [ + "7e6ef522c9b9544508654f63d12501560625608a", + [] + ] + } } }, "update_properties.json": [ @@ -450053,7 +450565,7 @@ [] ], "invokers.tentative.idl": [ - "67e2eb4ce196362fba16c7ab56d1168504be49c8", + "62f7398b82735670809610de90ad2f91a9dde06e", [] ], "is-input-pending.idl": [ @@ -450760,24 +451272,76 @@ } }, "jpegxl": { + "3x3_jpeg_recompression-ref.html": [ + "070243d6a7e66183f9a7bcbe77cd7263e0ecbcc0", + [] + ], + "3x3_srgb_lossless-ref.html": [ + "1bb50832409d6aa7a645a413622ccc5e2443bea8", + [] + ], + "3x3_srgb_lossy-ref.html": [ + "a5e95baba3b19607b9d7044328e4516937918784", + [] + ], + "3x3a_srgb_lossless-ref.html": [ + "75d8ba7452ede9efbe871e28637cc30120c88809", + [] + ], + "3x3a_srgb_lossy-ref.html": [ + "3a1c22e8a2775b32622ccc538e3cef14d527db5a", + [] + ], "META.yml": [ "d012c7f9bac05cd71119949a26996ae83bc65c8e", [] ], "resources": { - "3x3.png": [ - "96f86420a5fe51003c039eeb906bac4927e5bd98", + "3x3_jpeg_recompression.jxl": [ + "deee4257ff6729cb754cdefc5a1319e20f6ac865", + [] + ], + "3x3_jpeg_recompression.png": [ + "b147cb57bd8ef2ab413badd367754162fa105f75", + [] + ], + "3x3_srgb_lossless.jxl": [ + "bb9cf0bb2e487fb09bc394827a72f2f1c6275082", + [] + ], + "3x3_srgb_lossless.png": [ + "f314145a13949d190710a92e7d1c119d0ef302f5", + [] + ], + "3x3_srgb_lossy.jxl": [ + "a2d7a898e159b494bec5180b560eb03b0afd926b", + [] + ], + "3x3_srgb_lossy.png": [ + "ad5ef8117f688a05a11933a05be84bbbe0768369", + [] + ], + "3x3a_srgb_lossless.jxl": [ + "6bbb43d8e72f94a548d1cc38dc58981123d11979", + [] + ], + "3x3a_srgb_lossless.png": [ + "3c5f9c4e6b14b0e7d44e4160b3bc40cd1d51eff6", + [] + ], + "3x3a_srgb_lossy.jxl": [ + "0a4e952e3b83ec7f7179d12e9976d1087d9a607c", [] ], - "3x3_srgb.jxl": [ - "5e52b33641e1d27f2067bac9ce09894c7e903ac5", + "3x3a_srgb_lossy.png": [ + "885c5d0359201ba13d49c43d311ed914bda760b3", + [] + ], + "generate_resources.sh": [ + "359b2afd9ea77f2d524eb0b422b9d923ca7f5cf0", [] ] - }, - "srgb-ref.html": [ - "634567e4303bd9ea9b2e7f347050f8036c60cb4f", - [] - ] + } }, "js": { "META.yml": [ @@ -450988,7 +451552,7 @@ ] }, "lint.ignore": [ - "247d2950d55e7c4117728eb2881443f2b936176f", + "5a16051bbd4f6343d864c300cd6e3c4fcf7d4f96", [] ], "loading": { @@ -451262,6 +451826,10 @@ "b7544af4e5664e05f3ae66ed939b836273a25eec", [] ], + "stream-promise-generates-loaf.js": [ + "35e7920bb20a6b02438b3f0abf8019598355af9c", + [] + ], "utils.js": [ "574af6d6b8c716ba066f49014adabe4b6e1a537a", [] @@ -451321,7 +451889,13 @@ "Magnetometer-enabled-on-self-origin-by-feature-policy.https.html.headers": [ "4223f53ffa3d2cd8ff4497e7018bdc9750d17a99", [] - ] + ], + "resources": { + "sensor-data.js": [ + "32c2b1e2895b4883ee7bfb1d3042c77c12ac08c2", + [] + ] + } }, "managed": { "META.yml": [ @@ -453925,9 +454499,15 @@ [] ], "orientation-sensor-tests.js": [ - "88fd432d470d025b3dd9679e216221e5fc431b3d", + "d69fa3e54cdc70c60e10eb3c31ca426e3fee432b", [] - ] + ], + "resources": { + "sensor-data.js": [ + "d0b280fa6c4371e8f854554a9b1fa3bed3a0a3d6", + [] + ] + } }, "page-lifecycle": { "META.yml": [ @@ -460944,7 +461524,7 @@ [] ], "redirect.py": [ - "bb4c874aacee9479bd690bfae8dc956378d1ee64", + "025ea671c503f7816f634f23cfc80c78a815aa25", [] ] }, @@ -460962,7 +461542,7 @@ [] ], "worker_interception_redirect_webworker.py": [ - "bb4c874aacee9479bd690bfae8dc956378d1ee64", + "025ea671c503f7816f634f23cfc80c78a815aa25", [] ] }, @@ -461058,7 +461638,7 @@ [] ], "worker_interception_redirect_webworker.py": [ - "bb4c874aacee9479bd690bfae8dc956378d1ee64", + "025ea671c503f7816f634f23cfc80c78a815aa25", [] ] }, @@ -462633,7 +463213,7 @@ [] ], "helpers.js": [ - "7d259b21676329fcb3770cd7982a3342bf3bf7d3", + "24ed21a976b9fcb8a5539298be45e43db9736057", [] ], "resources": { @@ -462642,7 +463222,11 @@ [] ], "embedded_responder.js": [ - "634079289b01557189b1335ba7801c4eb6f6cc9b", + "e9cc39bc71ab658965696eb0fdbdb09827e0fa2f", + [] + ], + "embedded_worker.js": [ + "f3a0fb257adf204431a2df4ade796c74c0643950", [] ], "hasStorageAccess-ABA-iframe.https.html": [ @@ -462688,6 +463272,14 @@ "set-cookie-header.py": [ "e937ba2ca4eca2421ea0025c5a527d3bb6b574f4", [] + ], + "storage-access-beyond-cookies-iframe-iframe.html": [ + "348efc5dec45371cbedceac1000386ebfc3bba4f", + [] + ], + "storage-access-beyond-cookies-iframe.sub.html": [ + "fae51c2d547b4ea60ca1356dc9627b693a61e8a8", + [] ] } }, @@ -464096,7 +464688,7 @@ [] ], "ci_wptrunner_infrastructure.sh": [ - "ebe7870afa871fff063c206d17836156a468b420", + "fc6907f8de6e356dfc65850dfe08947f07bfd120", [] ], "commands.json": [ @@ -464148,7 +464740,7 @@ [] ], "taskcluster-run.py": [ - "c801f61e8e8914ab2d3a20fb9ded9e3ac6b64572", + "2917d8f3402e218ccf868485ebcb802e40001f25", [] ], "tc": { @@ -464182,7 +464774,7 @@ ], "tasks": { "test.yml": [ - "598a3395def60e2142d91352e2ede751f1637049", + "7c1a4df994c94cf2b6417b84c0a76aea8445b739", [] ] }, @@ -464218,7 +464810,7 @@ [] ], "test_valid.py": [ - "1d50115f91d2aaed1170f27e8fa85724592ee78b", + "36c2d0a986c36f128e9dbd950343feec20822069", [] ] } @@ -464720,7 +465312,7 @@ [] ], "update_manifest.py": [ - "a7f72b35b339a054482dbb35a444cdcf63e1a9fd", + "58b9ac4d84bfbddec73de67a0618389939142615", [] ] }, @@ -472431,7 +473023,7 @@ ], "webdriver": { "__init__.py": [ - "a81751407e70cbfc0637cf23b6641b078b5aac23", + "dfd264f8b2990a9d1e5dd851cac9d3c6a9176c1e", [] ], "bidi": { @@ -472487,7 +473079,7 @@ ] }, "client.py": [ - "f33fc34dac9ee53135239ef906b1e88b6f4c6114", + "e41df7f57640a6e40963de638872c130eae5d71d", [] ], "error.py": [ @@ -472495,11 +473087,11 @@ [] ], "protocol.py": [ - "1972c3fce2167b23ce515a295053c5e3447fa9ed", + "d6c89af22be2eb72068f4e59ab0040e5cbce1fd2", [] ], "transport.py": [ - "e1e16bdebadd5ac02a8c3ee744a078a6a4b7668d", + "ca1ff74ef96767afa76c200b159671d99762cb84", [] ] } @@ -472698,7 +473290,7 @@ [] ], "utils.py": [ - "b015b95e1ae2088b6d7a0b671cd75b61a8f0f424", + "5899dc3f3a967ff7d4b8b3c9e5340428ba6a9de8", [] ], "virtualenv.py": [ @@ -472746,7 +473338,7 @@ ] }, "requirements.txt": [ - "1c4316a9f8676ac527dfcd29e0db9793b36154a9", + "93c17bf3bff2dfeb73fc0f419926d893b0dc72f3", [] ], "requirements_chromium.txt": [ @@ -472828,7 +473420,7 @@ [] ], "content_shell.py": [ - "14956eeb786b09f411dfb7a8a37379891e574c46", + "23f4e99da62291005bb94450cde7d5ce592288a0", [] ], "edge.py": [ @@ -472924,7 +473516,7 @@ [] ], "base.py": [ - "1e66e60890e347acdd69644739f636046343ea92", + "e89b57b57acc533d57136fcb1c213f193f90bfca", [] ], "executorchrome.py": [ @@ -473079,7 +473671,7 @@ [] ], "stability.py": [ - "9ac6249c44cba029f92f39ce35e70aa226f9790e", + "029b237f98815d7a737706e7e655ea8999662ce0", [] ], "testdriver-extra.js": [ @@ -473119,7 +473711,7 @@ [] ], "testrunner.py": [ - "b84f1a52be3c25aa755d490b6c25862a4c17869b", + "a4f759c42a784e65eef8c8c1cfafc9b5105d8945", [] ], "tests": { @@ -473189,6 +473781,10 @@ "59aaaeadff7934b439029c8b1124e826dc0e8090", [] ], + "test_wptrunner.py": [ + "3c9a0bc1fd41de2c9f7fd6c62dbcc700f9a22c4c", + [] + ], "test_wpttest.py": [ "d2f68361bf853fd96ae3e5da7f514f853b81152c", [] @@ -473299,7 +473895,7 @@ } }, "wptrunner.py": [ - "a4ad268dce10a62a41737679dffba4b53c51b113", + "b9e5190105c1ab21dceed9c0c301a723c996e7f3", [] ], "wpttest.py": [ @@ -474712,7 +475308,7 @@ } }, "instanceTestFactory.js": [ - "6e6ec875bda4100a22b18f4059d22f35514843fd", + "2e015af8198a6112a528640bdc6c202dd5785c25", [] ], "memory": { @@ -474728,7 +475324,7 @@ ] }, "wasm-module-builder.js": [ - "3545c3a8da7bc9cec9798c261df953dfb5ad86c8", + "1d8db0a6e6fd71059963e4a1b767d796fa1a5eff", [] ] }, @@ -476079,7 +476675,7 @@ }, "webcodecs": { "META.yml": [ - "8570ee05e5a29b7835b28f9113db32b9677ca535", + "071ef88121b4033970b22d40db581e0ca7ed5c16", [] ], "README.md": [ @@ -476317,6 +476913,12 @@ [] ] }, + "context_destroyed": { + "__init__.py": [ + "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + [] + ] + }, "create": { "__init__.py": [ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", @@ -477103,7 +477705,7 @@ [] ], "asserts.py": [ - "04bd1993316be1bb449c81ccb22f0f623e38d215", + "9d31ff7b124347b73c47f83cd3e9725ad48f1482", [] ], "defaults.py": [ @@ -481889,41 +482491,41 @@ ], "auth1": { "auth.py": [ - "db4f7bc4c9fee9a31ff07a9708d6f6299f716c93", + "3797aaa52e9556387053712019550ee66af88f08", [] ] }, "auth10": { "auth.py": [ - "db4f7bc4c9fee9a31ff07a9708d6f6299f716c93", + "568d31e90687f1442ea6253fd24a4aae78934171", [] ] }, "auth11": { "auth.py": [ - "db4f7bc4c9fee9a31ff07a9708d6f6299f716c93", + "3797aaa52e9556387053712019550ee66af88f08", [] ] }, "auth2": { "auth.py": [ - "db4f7bc4c9fee9a31ff07a9708d6f6299f716c93", + "568d31e90687f1442ea6253fd24a4aae78934171", [] ], "corsenabled.py": [ - "bec6687dbe96c4acef0476e2ef3eecd7ab523c7a", + "7b9d3b65aba244e5c9f353bb56b8843bd91e00ed", [] ] }, "auth3": { "auth.py": [ - "db4f7bc4c9fee9a31ff07a9708d6f6299f716c93", + "3797aaa52e9556387053712019550ee66af88f08", [] ] }, "auth4": { "auth.py": [ - "db4f7bc4c9fee9a31ff07a9708d6f6299f716c93", + "3797aaa52e9556387053712019550ee66af88f08", [] ] }, @@ -481941,19 +482543,19 @@ }, "auth7": { "corsenabled.py": [ - "7a060627b70df5c77d5fb21ca24296bbc76cb3ea", + "c82ba4e6bc457df08bb361da904605776b34c652", [] ] }, "auth8": { "corsenabled-no-authorize.py": [ - "af8e7c4c170aa80e8eb2d19c0caedd5825862b2e", + "4fdf99e2658ce8a858c8c633640fa671cb9f8976", [] ] }, "auth9": { "auth.py": [ - "db4f7bc4c9fee9a31ff07a9708d6f6299f716c93", + "3797aaa52e9556387053712019550ee66af88f08", [] ] }, @@ -495836,10 +496438,11 @@ ] ], "Accelerometer-iframe-access.https.html": [ - "bec1705780f53e795949729a19bf8f3e4f03b432", + "56005696a7f5fb70ed5dd2c25fd5db75a4bf1c0c", [ null, { + "testdriver": true, "timeout": "long" } ] @@ -495852,10 +496455,11 @@ ] ], "Accelerometer.https.html": [ - "0db87d2efc3dd1a299898ec566b9c81458363b99", + "d422fef7264a6e301ca3f583389d632e7776a4c9", [ null, { + "testdriver": true, "timeout": "long" } ] @@ -495868,19 +496472,21 @@ ] ], "GravitySensor.https.html": [ - "6fb21e5572813ea6384a4ad5c679d161fceceb7b", + "0f98f3e00dec4038126d1451905ac9d77d90b22a", [ null, { + "testdriver": true, "timeout": "long" } ] ], "LinearAccelerationSensor.https.html": [ - "8dd3446f409169c044543b65f79a19f48fc5d1c0", + "91035cc9628bad32f411fdc6139915931a5641fb", [ null, { + "testdriver": true, "timeout": "long" } ] @@ -496059,10 +496665,12 @@ ] ], "AmbientLightSensor-iframe-access.https.html": [ - "5fedd5fb7a9b18ac36b75802667814097c23121e", + "765c1bee1f818924af037d8eb4e963198a464504", [ null, - {} + { + "testdriver": true + } ] ], "AmbientLightSensor-supported-by-feature-policy.html": [ @@ -496073,10 +496681,11 @@ ] ], "AmbientLightSensor.https.html": [ - "a8c65e4d3faf710bdc0064c5c968e1f486fe56ea", + "f2ed655082ed383b1c16bb5bec9f67e0950836f5", [ null, { + "testdriver": true, "timeout": "long" } ] @@ -505170,7 +505779,7 @@ ] ], "clipboard-item.https.html": [ - "9ed6f583bde5ce54877b5dbfab6549cff68dffbc", + "b50a1c97d746168fd4166726ead0964faa03aa39", [ null, {} @@ -505466,25 +506075,7 @@ ] ], "closewatcher-dialog-popover.html": [ - "f6443c4317ebd704c48ecff0ae377519d3159e2c", - [ - null, - { - "testdriver": true - } - ] - ], - "dialog-cancel-events-closewatcher.html": [ - "5b1da9a2e37811e389e60ddbc358fa99e89817a6", - [ - null, - { - "testdriver": true - } - ] - ], - "dialog-cancel-preventDefault-closewatcher.html": [ - "ef99578ca97dfa2f6ad48d577133b2ab6bf4157b", + "50d5cb7a4ca9425838f07d1ec916bb60e704b23a", [ null, { @@ -505563,7 +506154,7 @@ ] ], "user-activation-shared.html": [ - "6ecc2dc694d7486c18523be2d2301d30a306d1bc", + "77e748532a3309f16f2cd1203119b4a92ce24262", [ "close-watcher/user-activation-shared.html?CloseWatcher", { @@ -512691,10 +513282,12 @@ ] ], "prefetch-generate-directives.html": [ - "b08d885c1ecc5eff19c7bc8aa3c45fd0c415ed46", + "75c9485f0d77dcb51d9cdefa370dc0163c1ef2e3", [ null, - {} + { + "timeout": "long" + } ] ], "prefetch-ignores-prefetch-src.sub.html": [ @@ -516673,8 +517266,17 @@ {} ] ], + "fedcm-domainhint.https.html": [ + "d8ab79b2c5c78d6d82e9af2f1919f2a2953dc78d", + [ + null, + { + "testdriver": true + } + ] + ], "fedcm-endpoint-redirects.https.html": [ - "4aebc17f1ba6e7c407d708444708e2bb21bf8459", + "21d0a5867a76d810782d5ca06f34fc5aa518040d", [ null, { @@ -516682,8 +517284,8 @@ } ] ], - "fedcm-hosteddomain.https.html": [ - "5e39542fdef72dac98d52968fbe10f6e95d38986", + "fedcm-error-basic.https.html": [ + "18ab82d0bd7f976477a9db21ac1a2e8d667ee483", [ null, { @@ -516709,7 +517311,7 @@ ] ], "cross-origin-status.https.html": [ - "7c839306a479510d91d3cf6a8e379e43bb703c71", + "09a4aa31c6b2ba0680ec6b14d0e661dd93abb69b", [ null, { @@ -516903,6 +517505,24 @@ } ] ], + "fedcm-store.https.html": [ + "d1e6ef464c4f3eb8e2d4118d1a5e2dc498410e05", + [ + null, + { + "testdriver": true + } + ] + ], + "fedcm-token-returned-with-http-error.https.html": [ + "2337829add9f283983c78d9617941c18e74acb46", + [ + null, + { + "testdriver": true + } + ] + ], "fedcm-userinfo.https.html": [ "d460d82845282f00e0164590c552bcd73ca15255", [ @@ -516956,6 +517576,13 @@ {} ] ], + "otpcredential-store.https.html": [ + "fa2ae8933d354a16f872f3f38398989d1e927d06", + [ + null, + {} + ] + ], "passwordcredential-framed-get.sub.https.html": [ "b4afc1eb91e563ef59dd540dd1f6d90b2a59c854", [ @@ -522092,7 +522719,7 @@ ] ], "nested-color-mix-with-currentcolor.html": [ - "a4dd687dd5814af2e4660586a2c97c09ba34ffe4", + "2f24d62b547fb24200fa659d27a9e55777303aa5", [ null, {} @@ -522114,7 +522741,7 @@ ] ], "color-computed-color-mix-function.html": [ - "a48d6b20bcd0f2976e7c90069c7d994adc285304", + "cd5837d8b28dc587d700ad8cda232e4760b7b0cc", [ null, {} @@ -522372,6 +522999,13 @@ null, {} ] + ], + "system-color-support.html": [ + "a17ab6ab6eeea76f29e0015aab1600115e613331", + [ + null, + {} + ] ] }, "css-color-adjust": { @@ -526674,8 +527308,15 @@ }, "css-fonts": { "animations": { + "font-palette-animation-not-specified-endpoints.html": [ + "f3d103983c6747b28369704e81cff40f85674fab", + [ + null, + {} + ] + ], "font-palette-interpolation.html": [ - "66b0f00ebf01dac4cb4ad12aea9eece0d67b06f0", + "43e1368412e205c7ee22a326f3cfcb99a4f434e7", [ null, {} @@ -531590,7 +532231,7 @@ ], "parsing": { "gradient-interpolation-method-computed.html": [ - "9593a59777a5792332ba07d6cf4687eed09a0747", + "b4f8dee4393d0d11bbfbf438b8a3633f391707c3", [ null, {} @@ -533127,6 +533768,13 @@ {} ] ], + "mask-computed.html": [ + "28fc38defae2e5ea7b4bffab2a8755535921fa9d", + [ + null, + {} + ] + ], "mask-invalid.html": [ "f9999ca98284eba958eeb5236282fa3b852f41be", [ @@ -533191,7 +533839,7 @@ ] ], "mask-valid.sub.html": [ - "a377060ded8e6ee3b8ac4ede1b13378a0a24f2cb", + "c4d2d4eb2c039ab59712ead6f7577606837bf5c9", [ null, {} @@ -535354,7 +536002,7 @@ ] ], "custom-property-animation-transform-list-multiple-values.html": [ - "9ffaec830f8eae0a58fbadb64038b10af1efda64", + "1b2fc907f2548fffa8a9c71b3cfe63fa766506b0", [ null, {} @@ -535367,6 +536015,13 @@ {} ] ], + "custom-property-animation-transform-none.tentative.html": [ + "37abddd2271c6a28f954435b456c10c2a66ffdbf", + [ + null, + {} + ] + ], "custom-property-animation-url.html": [ "830b9e1f4966b865c6bc1b5bde6358f335685ea3", [ @@ -535500,6 +536155,34 @@ {} ] ], + "custom-property-transition-transform-function-box-size.tentative.html": [ + "23ac09b1fc9be7d6dea818c40c6391db20eb0491", + [ + null, + {} + ] + ], + "custom-property-transition-transform-function-matrix.html": [ + "00b5018142524fc358ee3bd932c04cffb6784201", + [ + null, + {} + ] + ], + "custom-property-transition-transform-function-none.tentative.html": [ + "29a5715fec89311b0413b3b71febda74737f4ed4", + [ + null, + {} + ] + ], + "custom-property-transition-transform-function-to-list.html": [ + "d09fb6416ac972722afa259e899c0fb1ce26e371", + [ + null, + {} + ] + ], "custom-property-transition-transform-function.html": [ "17ad1067a4dcfcf4f11b2f1e1a0367b1cf45ec96", [ @@ -535507,6 +536190,27 @@ {} ] ], + "custom-property-transition-transform-list-box-size.tentative.html": [ + "d1b882f70840686d0695880b45f6889c5cfdc532", + [ + null, + {} + ] + ], + "custom-property-transition-transform-list-matrix.html": [ + "8f1fa8429485fc30ecadcc87bd8308f87f414616", + [ + null, + {} + ] + ], + "custom-property-transition-transform-list-none.tentative.html": [ + "d09f5854b308b35d8aeb63b99dd385319191aeb8", + [ + null, + {} + ] + ], "custom-property-transition-transform-list.html": [ "c9d3cb94d143d2fd45e1a6b70b40f14538d32353", [ @@ -536335,6 +537039,20 @@ {} ] ], + "after-scrollable-range-shrinkage-003.html": [ + "c9127e79b5a42a94a0693f1b8a5d43acb03194d9", + [ + null, + {} + ] + ], + "after-scrollable-range-shrinkage-004.html": [ + "8509a1cca5e9a704e321d6084e02de63771f1785", + [ + null, + {} + ] + ], "ancestor-change-heuristic.html": [ "21adfbb6b7a56c0a098eda1843897926afb363f5", [ @@ -537422,6 +538140,13 @@ ] }, "scroll-start-target": { + "scroll-start-target-aligns-with-snap-align.tentative.html": [ + "6b133dea7d722bb77dde669ef2ef6c666c35551e", + [ + null, + {} + ] + ], "scroll-start-target-display-toggled.tentative.html": [ "527d7502678bab30c64cd351a2f76d56c50dd1f5", [ @@ -542084,7 +542809,7 @@ } }, "inheritance.html": [ - "83d1d4971eaf0fe9a1982df3c930cd8545944c87", + "2043afe999db7be2b519aeeb9ec03cc75241e4e2", [ null, {} @@ -542508,6 +543233,13 @@ {} ] ], + "text-wrap-computed.html": [ + "772f0abf4d975c04c582a1e36ac9b587a24e954b", + [ + null, + {} + ] + ], "text-wrap-invalid.html": [ "b67cecc183069358448e9ef9e5bbb9ddb064ba75", [ @@ -542515,6 +543247,48 @@ {} ] ], + "text-wrap-mode-computed.html": [ + "35e082b6474640710137f67982e1ff48c2e4037d", + [ + null, + {} + ] + ], + "text-wrap-mode-invalid.html": [ + "d63c1901c1196af37f41f603a1b30dd53d988ef2", + [ + null, + {} + ] + ], + "text-wrap-mode-valid.html": [ + "5dde8b377fb366422c709577ebb0b53bdc4dd6b6", + [ + null, + {} + ] + ], + "text-wrap-style-computed.html": [ + "0a4a22d9c5f7c1b4e7e3b7caa3774b32a69f31b6", + [ + null, + {} + ] + ], + "text-wrap-style-invalid.html": [ + "dcda82e465d22b1c1a30ef137589384fb763028b", + [ + null, + {} + ] + ], + "text-wrap-style-valid.html": [ + "b3ca09ef2c638bd178af31cc57dcd84003b8976e", + [ + null, + {} + ] + ], "text-wrap-valid.html": [ "a2eed8c429fa1d593ad3883f1d82ff0395d8aa49", [ @@ -548532,7 +549306,7 @@ ] ], "round-mod-rem-computed.html": [ - "320ab4a11a92ff5b3e567187cbd5f756b8c07a9c", + "eb6dfe4e8ce50d54322fbef7f211ebe3febf5cb6", [ null, {} @@ -551006,7 +551780,7 @@ ] ], "checkVisibility.html": [ - "c0146dc14e152cb7165609867c677a182419a677", + "c7bd5b69686c2d03b650fbb1a9f2124c1cad982b", [ null, {} @@ -552940,7 +553714,7 @@ ] ], "dir-pseudo-on-input-element.html": [ - "db528d4079b83d352c9470d160aef130930190e8", + "f4a0de193a06dd4bc309d83b09ce2ac3c00961fd", [ null, {} @@ -560151,20 +560925,6 @@ ] }, "domxpath": { - "001.html": [ - "4931417af301029c5bffb64093ab8ed382890753", - [ - null, - {} - ] - ], - "002.html": [ - "c5c1fcc52923ab38729a3e9dc74ecb0a0d70ca9e", - [ - null, - {} - ] - ], "booleans.html": [ "41522edf05f8bc752408eb2cdde10a05bd211a7a", [ @@ -560298,6 +561058,20 @@ {} ] ], + "text-html-attributes.html": [ + "2157dcd2d68c5701b47ba907f7b1c3b2176f9239", + [ + null, + {} + ] + ], + "text-html-elements.html": [ + "b895323fbad6bfee9a9c108b1aa3d9c85d2a1e42", + [ + null, + {} + ] + ], "xml_xpath_runner.html": [ "03edf50515c231a9f9fbf0a0587261627b949e19", [ @@ -560350,7 +561124,7 @@ ] ], "edit-context-input.tentative.html": [ - "0f05606a3564b4e27644e0035d42076ff6d1fda0", + "f65dfbc915de7ba9f50917768daa40d99687007e", [ null, { @@ -588884,6 +589658,124 @@ {} ] ], + "headers": { + "header-referrer-no-referrer-when-downgrade.tentative.https.html": [ + "38eada4513c4f17ee29bf10ccac750595e2d1e81", + [ + null, + {} + ] + ], + "header-referrer-no-referrer.tentative.https.html": [ + "75e9ece7ba511e4ba214427f63c0211d39006d50", + [ + null, + {} + ] + ], + "header-referrer-origin-when-cross-origin.tentative.https.html": [ + "b9f14171ba39671e6c258ecd0680398d19123ddd", + [ + null, + {} + ] + ], + "header-referrer-origin.tentative.https.html": [ + "ce7abf92039124d375d0a76302ce20bb0b672466", + [ + null, + {} + ] + ], + "header-referrer-same-origin.tentative.https.html": [ + "264beddc03a1b8a5933d7d657a0bc96c3f912f44", + [ + null, + {} + ] + ], + "header-referrer-strict-origin-when-cross-origin.tentative.https.html": [ + "9133f2496fe0a88f7d7b5c896a67d5fcffe60089", + [ + null, + {} + ] + ], + "header-referrer-strict-origin.tentative.https.html": [ + "943d70bbc583002c0b5a740cfe07f5f6c97c1319", + [ + null, + {} + ] + ], + "header-referrer-unsafe-url.tentative.https.html": [ + "a602e0003a49f1e10449eeecdc5507a7273d5e30", + [ + null, + {} + ] + ] + }, + "iframe.tentative.https.window.js": [ + "62505bc81d99e6f6b6c3b93b33f7c8963e0ffe17", + [ + "fetch/fetch-later/iframe.tentative.https.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/testharness.js" + ], + [ + "script", + "/resources/testharnessreport.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/pending-beacon/resources/pending_beacon-helper.js" + ] + ] + } + ] + ], + "new-window.tentative.https.window.js": [ + "37b38d7f1dc075535ac9ab9beeee8809e956f8f0", + [ + "fetch/fetch-later/new-window.tentative.https.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/testharness.js" + ], + [ + "script", + "/resources/testharnessreport.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/pending-beacon/resources/pending_beacon-helper.js" + ] + ] + } + ] + ], "non-secure.window.js": [ "2f2c3ea8d34b9dfaf8bbc6b12acc304a4beb791d", [ @@ -588902,6 +589794,110 @@ } ] ], + "policies": { + "csp-allowed.tentative.https.window.js": [ + "5aa759c2346bd76b6ecc5c04dc5094b7a48297fa", + [ + "fetch/fetch-later/policies/csp-allowed.tentative.https.window.html", + { + "script_metadata": [ + [ + "title", + "FetchLater: allowed by CSP" + ], + [ + "script", + "/resources/testharness.js" + ], + [ + "script", + "/resources/testharnessreport.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/pending-beacon/resources/pending_beacon-helper.js" + ] + ] + } + ] + ], + "csp-blocked.tentative.https.window.js": [ + "88490950d3a4ec8b10e6430aacdf74116cb1e680", + [ + "fetch/fetch-later/policies/csp-blocked.tentative.https.window.html", + { + "script_metadata": [ + [ + "title", + "FetchLater: blocked by CSP" + ], + [ + "script", + "/resources/testharness.js" + ], + [ + "script", + "/resources/testharnessreport.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/pending-beacon/resources/pending_beacon-helper.js" + ] + ] + } + ] + ], + "csp-redirect-to-blocked.tentative.https.window.js": [ + "c2019881cc2e277d93b7b94955e5978079551f35", + [ + "fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.html", + { + "script_metadata": [ + [ + "title", + "FetchLater: redirect blocked by CSP" + ], + [ + "script", + "/resources/testharness.js" + ], + [ + "script", + "/resources/testharnessreport.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/pending-beacon/resources/pending_beacon-helper.js" + ] + ] + } + ] + ] + }, "quota.tentative.https.window.js": [ "4fc5979374c0e214f44d28982c7f22b86454d22f", [ @@ -588933,7 +589929,7 @@ ] ], "send-on-deactivate.tentative.https.window.js": [ - "7a1ddc7ac3dac0e4be1a42ee6b7a51d6ab86c725", + "173c95ac12037c1dd7c7b20ca087a03f81bba8f3", [ "fetch/fetch-later/send-on-deactivate.tentative.https.window.html", { @@ -588975,7 +589971,7 @@ ] ], "send-on-discard.tentative.https.window.js": [ - "c4911b110551698dd761ed86e4f50ffbb5858638", + "e1ff9b9e3a68e9672fd87b0a098f74bf8e344452", [ "fetch/fetch-later/send-on-discard.tentative.https.window.html", { @@ -593308,7 +594304,7 @@ ] ], "auction-config.https.window.js": [ - "e4811b969651d129c2761a2e418c3ea97f574bb8", + "432be9cb10a5bcc456013c78f9686c563b1c77a6", [ "fledge/tentative/auction-config.https.window.html?1-5", { @@ -593351,7 +594347,11 @@ ], [ "variant", - "?21-last" + "?21-25" + ], + [ + "variant", + "?26-last" ] ], "timeout": "long" @@ -593399,7 +594399,11 @@ ], [ "variant", - "?21-last" + "?21-25" + ], + [ + "variant", + "?26-last" ] ], "timeout": "long" @@ -593447,14 +594451,70 @@ ], [ "variant", - "?21-last" + "?21-25" + ], + [ + "variant", + "?26-last" + ] + ], + "timeout": "long" + } + ], + [ + "fledge/tentative/auction-config.https.window.html?21-25", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/fledge-util.sub.js" + ], + [ + "script", + "/common/subset-tests.js" + ], + [ + "timeout", + "long" + ], + [ + "variant", + "?1-5" + ], + [ + "variant", + "?6-10" + ], + [ + "variant", + "?11-15" + ], + [ + "variant", + "?16-20" + ], + [ + "variant", + "?21-25" + ], + [ + "variant", + "?26-last" ] ], "timeout": "long" } ], [ - "fledge/tentative/auction-config.https.window.html?21-last", + "fledge/tentative/auction-config.https.window.html?26-last", { "script_metadata": [ [ @@ -593495,7 +594555,11 @@ ], [ "variant", - "?21-last" + "?21-25" + ], + [ + "variant", + "?26-last" ] ], "timeout": "long" @@ -593543,7 +594607,11 @@ ], [ "variant", - "?21-last" + "?21-25" + ], + [ + "variant", + "?26-last" ] ], "timeout": "long" @@ -594087,6 +595155,81 @@ } ] ], + "currency.https.window.js": [ + "97802ce1379eb2758621c3d5753e4f302df70ed3", + [ + "fledge/tentative/currency.https.window.html?1-4", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/fledge-util.sub.js" + ], + [ + "script", + "/common/subset-tests.js" + ], + [ + "timeout", + "long" + ], + [ + "variant", + "?1-4" + ], + [ + "variant", + "?5-last" + ] + ], + "timeout": "long" + } + ], + [ + "fledge/tentative/currency.https.window.html?5-last", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/fledge-util.sub.js" + ], + [ + "script", + "/common/subset-tests.js" + ], + [ + "timeout", + "long" + ], + [ + "variant", + "?1-4" + ], + [ + "variant", + "?5-last" + ] + ], + "timeout": "long" + } + ] + ], "fetch-ad-auction-headers-insecure-context.tentative.http.html": [ "d3bdb8017579414aee39ad672519ff029f9d0827", [ @@ -594259,7 +595402,7 @@ ] ], "join-leave-ad-interest-group.https.window.js": [ - "77da23a7a5b9d79f0fe149bfb137b97a75445ce2", + "107bd3b815ada1b175c1ca425f6bbdb0c2e3be44", [ "fledge/tentative/join-leave-ad-interest-group.https.window.html?1-10", { @@ -594837,6 +595980,89 @@ } ] ], + "network.https.window.js": [ + "9c29610578664a026ad5d9d73e3cb295569424cb", + [ + "fledge/tentative/network.https.window.html?1-5", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ], + [ + "script", + "/common/subset-tests.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/fledge-util.sub.js" + ], + [ + "timeout", + "long" + ], + [ + "variant", + "?1-5" + ], + [ + "variant", + "?6-last" + ] + ], + "timeout": "long" + } + ], + [ + "fledge/tentative/network.https.window.html?6-last", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ], + [ + "script", + "/common/subset-tests.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/fledge-util.sub.js" + ], + [ + "timeout", + "long" + ], + [ + "variant", + "?1-5" + ], + [ + "variant", + "?6-last" + ] + ], + "timeout": "long" + } + ] + ], "no-winner.https.window.js": [ "f252aece5bff52572395a64255f945f0030a6c72", [ @@ -598990,7 +600216,7 @@ ] ], "fullscreen-reordering.html": [ - "4b394bc20fc1a3ce9c904eed1c23be00789d3131", + "1aaf3c37c04703e226b0a8fa660692eb2ba109f1", [ null, { @@ -599499,10 +600725,12 @@ ] ], "GeolocationSensor-iframe-access.https.html": [ - "bb0541de32c374c0028de72c90cc195f02979d61", + "a3d39e3606f907ec132c075e7e5dbc96ed89c999", [ null, - {} + { + "testdriver": true + } ] ], "GeolocationSensor-supported-by-feature-policy.html": [ @@ -599513,10 +600741,12 @@ ] ], "GeolocationSensor.https.html": [ - "b71f964b1297f39257c1e80ce50a145c5283228f", + "3b4b94e5bbbcc7d46b98313b71f1cb003f887c13", [ null, - {} + { + "testdriver": true + } ] ], "GeolocationSensor_insecure_context.html": [ @@ -599600,10 +600830,12 @@ ] ], "Gyroscope-iframe-access.https.html": [ - "ed0183bef9ad414b451acc87712acd7b7b55a347", + "c94016764d5176b0703e1b19cd3f4cdbe0c43eb4", [ null, - {} + { + "testdriver": true + } ] ], "Gyroscope-supported-by-feature-policy.html": [ @@ -599614,10 +600846,11 @@ ] ], "Gyroscope.https.html": [ - "f85349f5315a27bdb06a3b6b4b0fa2c40612a15a", + "8aab94693abea6198bb9b7d03c2408cd4bec58a4", [ null, { + "testdriver": true, "timeout": "long" } ] @@ -599819,6 +601052,13 @@ {} ] ], + "raf-coarsened-time.https.html": [ + "c7cc723da6f4eccc4cb4182da7ee0289537743ae", + [ + null, + {} + ] + ], "test_cross_frame_start.html": [ "30e804bd7350315497115b75929a52ac1d82d3cb", [ @@ -602033,6 +603273,33 @@ {} ] ], + "pagereveal": { + "tentative": { + "order-in-bfcache-restore.html": [ + "f453c80a2aee8c2cff5bca12f361a6a7b7683be8", + [ + null, + { + "timeout": "long" + } + ] + ], + "order-in-new-document-navigation.html": [ + "d2c44511d3a3a175ceb09298302baec088ddbf76", + [ + null, + {} + ] + ], + "order-in-prerender-activation.html": [ + "b281b2b08810d59c32fe332cb869151946de8c96", + [ + null, + {} + ] + ] + } + }, "persisted-user-state-restoration": { "resume-timer-on-history-back.html": [ "77602b2d4258c87a7ac055475986d691da8dad90", @@ -633306,6 +634573,13 @@ {} ] ], + "dir-auto-form-associated.window.js": [ + "1777f75259bbc1e1bc440c075c06fef00395f797", + [ + "html/dom/elements/global-attributes/dir-auto-form-associated.window.html", + {} + ] + ], "dir-bdi-script.html": [ "30080430936213b034e09a2cb3fee14608350373", [ @@ -633355,6 +634629,13 @@ {} ] ], + "lang-attribute.window.js": [ + "de0c03e6f853ecf2b5eac9e41274df49ee96c9e0", + [ + "html/dom/elements/global-attributes/lang-attribute.window.html", + {} + ] + ], "mapped-attribute-adopt-001.html": [ "66ff3d64f13cdffe4413ee19534604af020203df", [ @@ -634815,6 +636096,13 @@ {} ] ], + "document-base-uri-synthetic-document.html": [ + "bed090aac42f2ce64ae78ba7fbd24c0bccbb123e", + [ + null, + {} + ] + ], "document-base-url-changes-about-srcdoc-2.https.html": [ "dab8d2122b64aea58bd9de3d5872a77b307218a8", [ @@ -642524,6 +643812,13 @@ {} ] ], + "img-src-in-synthetic-document.html": [ + "24c5567fb854bf278033d9287035734e65996d1e", + [ + null, + {} + ] + ], "img.complete.html": [ "d8d5a84eb7998044fb24847cc0ac5a1185b82bb6", [ @@ -642909,7 +644204,7 @@ ] ], "dirname-only-if-applies.html": [ - "1fd0476e3140422825d5ec1f7e431b1fc212cbdb", + "8af6826fa1359c704368df41c7286520c35d90aa", [ null, {} @@ -644215,6 +645510,15 @@ {} ] ], + "input-disabled-fieldset-dynamic.html": [ + "eefcd972bf1e3c713704c9ff9f2f6f61f0e20b14", + [ + null, + { + "testdriver": true + } + ] + ], "input-height.html": [ "dea4f41765284eb65d8c98cebc5782eb58f7f16e", [ @@ -645694,7 +646998,7 @@ ] ], "dialog-cancel-events.html": [ - "7133ce3ca04ec4c874e93a618ecf0e72065e7fd5", + "d583c4cd23c5357b1d358ee6f34bd395bf4c9650", [ null, { @@ -645703,7 +647007,7 @@ ] ], "dialog-cancel-preventDefault.html": [ - "79728b649f4f4a2ca5948b3857678cab762f7927", + "4daffc09a46c31205bb22b7b0fe53d5f1302f714", [ null, { @@ -645730,7 +647034,7 @@ ] ], "dialog-canceling.html": [ - "fc003d29d191f5f6ac684a8ce1b6b8acdef07a95", + "e368bde6fb30fb59cf5d254c07070c9b177fa892", [ null, { @@ -645898,6 +647202,15 @@ } ] ], + "focus-previous-iframe.tentative.html": [ + "c31daa48766214ffdeae52e03070f22d7b1bf194", + [ + null, + { + "testdriver": true + } + ] + ], "inert-does-not-match-disabled-selector.html": [ "b3b0c0a929732da1658487173bf096cc8884c9a7", [ @@ -646134,7 +647447,7 @@ ] ], "invokeelement-interface.tentative.html": [ - "69cfd80fe56447dc1486134b3bc0b535bf1636c2", + "b003daf20d4be5b9eac15b930d10ae2b859ec505", [ null, {} @@ -646150,7 +647463,7 @@ ] ], "invokeevent-interface.tentative.html": [ - "007c97e6fe545a77f2e65cd026720304c24751cf", + "82910b3d4418de12453d7ebbee762e3eb9724141", [ null, { @@ -646166,6 +647479,15 @@ "testdriver": true } ] + ], + "invoketarget-on-popover-behavior.tentative.html": [ + "9d9bbaee721edccef6bfca6f0b07f9eec1221227", + [ + null, + { + "testdriver": true + } + ] ] }, "links": { @@ -646484,6 +647806,15 @@ } ] ], + "popover-close-request.html": [ + "830a40e0608accfdcd4ff07890d78734593de0f7", + [ + null, + { + "testdriver": true + } + ] + ], "popover-css-properties.tentative.html": [ "93d388b02b533f8e8719ef8a9b54293f45a5cffd", [ @@ -646713,7 +648044,7 @@ ] ], "popover-top-layer-combinations.html": [ - "c6fae283874ceadb4c5b8a0ba849a5225c5b8c8f", + "024794f57853307e15532e7f1c5ff894a61fa51d", [ null, { @@ -646722,7 +648053,7 @@ ] ], "popover-top-layer-interactions.html": [ - "95da47a5e20df39a4649ed5dad2947285059c1c9", + "6d050ed99bb10e26113020dc6f582b7b9a8ada6f", [ null, { @@ -662368,6 +663699,15 @@ } ] ], + "loaf-stream-source-location.html": [ + "3b6b2b31608a915a28eff99f97114b678e341124", + [ + null, + { + "timeout": "long" + } + ] + ], "loaf-stream.html": [ "e35bc2f9aa7d7de7a6ac224b9befde30d128e85c", [ @@ -662650,10 +663990,12 @@ ] ], "Magnetometer-iframe-access.https.html": [ - "3dc90e3dd7f5ac52364f02712ad7083cc373ec6b", + "7aabd0eb61b3c7867619169c2da77ca0af128e7c", [ null, - {} + { + "testdriver": true + } ] ], "Magnetometer-supported-by-feature-policy.html": [ @@ -662664,10 +664006,11 @@ ] ], "Magnetometer.https.html": [ - "0cc443784bebb38fce406b7efe934dc10aa7f966", + "6beb534509d79f0079d8c4e121020eb529f7a160", [ null, { + "testdriver": true, "timeout": "long" } ] @@ -665006,7 +666349,7 @@ ] ], "MediaStreamTrack-video-stats.https.html": [ - "6901ed84e39cc081c9bda6f614e0906e71baf47f", + "f1b6a2074a4468fca704a8e53a92f25bc13d3200", [ null, { @@ -671630,17 +672973,20 @@ ] ], "AbsoluteOrientationSensor-iframe-access.https.html": [ - "e99b5c6365d3031b24aef5281c31da1f43d2eaa7", + "4831b5e719200d34903d2d20dce2675a70e3a3e5", [ null, - {} + { + "testdriver": true + } ] ], "AbsoluteOrientationSensor.https.html": [ - "e6f5dd913835a99ef2a1fce328041ad527b54da5", + "4c516da145169e29d0a1f5bbd1bf326404b722d5", [ null, { + "testdriver": true, "timeout": "long" } ] @@ -671688,17 +673034,20 @@ ] ], "RelativeOrientationSensor-iframe-access.https.html": [ - "5d30534841bfc45573a5720f411636533a37cb65", + "fe995e2d1b982db7dff6729da7e5148487d8fbd7", [ null, - {} + { + "testdriver": true + } ] ], "RelativeOrientationSensor.https.html": [ - "499e7df8ceac2408092972bcaa2f4c4b14a0bf82", + "35dc8c3111363721c0f6645778b1cd96ec1a6483", [ null, { + "testdriver": true, "timeout": "long" } ] @@ -675566,7 +676915,7 @@ ] ], "pointerevent_after_target_removed.html": [ - "5ab6040cc9ce1b4cb9ad6581c8aa29d3be715e7e", + "2dcc94c2b2321be2523d43e698d5c470373a24f6", [ "pointerevents/pointerevent_after_target_removed.html?mouse", { @@ -690344,7 +691693,7 @@ ] ], "callback-timeRemaining-cross-realm-method.html": [ - "383479d64a093709e4ffbf7b75a8a3f776ef8cd3", + "078e2c9379c8629dd971ad2fe3577d48890130c7", [ null, { @@ -704705,7 +706054,7 @@ ] }, "estimate-indexeddb.https.any.js": [ - "f0b82b9fa09fb1ef7000e398fb0fdb034504a008", + "6577b021ad52ef36ab8748102ec760dfd0f44205", [ "storage/estimate-indexeddb.https.any.html", { @@ -705003,7 +706352,7 @@ ] ], "storagemanager-estimate.https.any.js": [ - "c2f5c569dc528cb8e58e8c057ba95ce1354463a7", + "3b6f4d8edc4c2e51d6e9efbc2a2929e75d6b6725", [ "storage/storagemanager-estimate.https.any.html", { @@ -705283,6 +706632,32 @@ } ] ], + "requestStorageAccess-dedicated-worker.tentative.sub.https.window.js": [ + "86caf8191828712fc02733a55c87d54022c97d8c", + [ + "storage-access-api/requestStorageAccess-dedicated-worker.tentative.sub.https.window.html", + { + "script_metadata": [ + [ + "script", + "helpers.js" + ], + [ + "script", + "/cookies/resources/cookie-helper.sub.js" + ], + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ] + ] + } + ] + ], "requestStorageAccess-insecure.sub.window.js": [ "1ad04321db7f4ce9e55d8676fecee8fd6604c8ca", [ @@ -705448,6 +706823,78 @@ {} ] ], + "storage-access-beyond-cookies.indexedDB.tentative.sub.https.window.js": [ + "18c4317bbe9c6598551787feaf9df9d4ad5210db", + [ + "storage-access-api/storage-access-beyond-cookies.indexedDB.tentative.sub.https.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ] + ] + } + ] + ], + "storage-access-beyond-cookies.localStorage.tentative.sub.https.window.js": [ + "108e778766db5d89fb442ceb4d6ab37cf50aee38", + [ + "storage-access-api/storage-access-beyond-cookies.localStorage.tentative.sub.https.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ] + ] + } + ] + ], + "storage-access-beyond-cookies.locks.tentative.sub.https.window.js": [ + "83aa28c018e1a3e4fd0b5ffe794a2acb751de287", + [ + "storage-access-api/storage-access-beyond-cookies.locks.tentative.sub.https.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ] + ] + } + ] + ], + "storage-access-beyond-cookies.sessionStorage.tentative.sub.https.window.js": [ + "2e504851c22b58c60e79829f7bd9921424a877df", + [ + "storage-access-api/storage-access-beyond-cookies.sessionStorage.tentative.sub.https.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ] + ] + } + ] + ], "storage-access-permission.sub.https.window.js": [ "f0aadf4828dcb549c0d66ef4745b1e190d56f8d6", [ @@ -719784,7 +721231,7 @@ ] ], "invalid-roles.html": [ - "e16fb677044df6a283b2a34df9b6c0de2c2d89a1", + "3f4255083e1adf05202cad3a4ae8d4a58b7f5e07", [ null, { @@ -720329,7 +721776,7 @@ }, "exception": { "basic.tentative.any.js": [ - "869c64b6d303daed40c16e38bf68ee2dd559529d", + "cacce99d9cb227055754554b8369809c92885ded", [ null, { @@ -721024,6 +722471,155 @@ ] ] }, + "gc": { + "casts.tentative.any.js": [ + "cce06224fd40c70f037dbf575388c26106480a0e", + [ + null, + { + "jsshell": true, + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ], + [ + "wasm/jsapi/gc/casts.tentative.any.html", + { + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ], + [ + "wasm/jsapi/gc/casts.tentative.any.worker.html", + { + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ] + ], + "exported-object.tentative.any.js": [ + "b572f140067fda658eb18ab82c880b3697172aba", + [ + null, + { + "jsshell": true, + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ], + [ + "wasm/jsapi/gc/exported-object.tentative.any.html", + { + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ], + [ + "wasm/jsapi/gc/exported-object.tentative.any.worker.html", + { + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ] + ], + "i31.tentative.any.js": [ + "17fd82440cc8b29c6826d32e46f52b5c2a0323a1", + [ + null, + { + "jsshell": true, + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ], + [ + "wasm/jsapi/gc/i31.tentative.any.html", + { + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ], + [ + "wasm/jsapi/gc/i31.tentative.any.worker.html", + { + "script_metadata": [ + [ + "global", + "window,dedicatedworker,jsshell" + ], + [ + "script", + "/wasm/jsapi/wasm-module-builder.js" + ] + ] + } + ] + ] + }, "global": { "constructor.any.js": [ "f83f77a5c3ecf349ea63891f4ebcfc2109ae2606", @@ -722363,7 +723959,7 @@ ] ], "exports.any.js": [ - "499a2649b171739cfcee1087f9779b30bcde08bd", + "0c32e984a2cad1feba8dc949ae4a83f84a9db45e", [ null, { @@ -724413,6 +726009,13 @@ {} ] ], + "scrollbar-interpolation.html": [ + "bc02dd00b97ba84f55e132069833f16827164525", + [ + null, + {} + ] + ], "visibility.html": [ "f5a60b4e2c7bb3c70a45353c7734dd0dff51d780", [ @@ -727510,11 +729113,22 @@ {} ] ], - "audioparam-default-value.html": [ - "fe0cf15b43d38ad271a2b62105810de45b4e8791", + "audioparam-default-value.window.js": [ + "359df111846403c1ba9038792dabd6e8989f9d96", [ - null, - {} + "webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/testharness.js" + ], + [ + "script", + "/resources/testharnessreport.js" + ] + ] + } ] ], "audioparam-exceptional-values.html": [ @@ -729239,6 +730853,16 @@ {} ] ], + "storecredential.https.html": [ + "726b289fbd18e8bd7646f2d6ad0b88b718c16293", + [ + null, + { + "testdriver": true, + "timeout": "long" + } + ] + ], "webauthn-testdriver-basic.https.html": [ "5751928301ff6c75593881f6e0bb0c5f93076d8c", [ @@ -729369,7 +730993,7 @@ ] ], "audio-decoder.https.any.js": [ - "606b052edc891ec023c832b9e7f877e835b375cc", + "79ba22157abba6dcc890fd72b3328bdd0b7f7093", [ "webcodecs/audio-decoder.https.any.html", { @@ -729420,7 +731044,7 @@ ] ], "audio-encoder-config.https.any.js": [ - "98a9513b7dc301adce0e351307f0f7859f7f104c", + "3be8eb3f6d36d270808ca0a418387fc83245ea12", [ "webcodecs/audio-encoder-config.https.any.html", { @@ -731935,7 +733559,7 @@ ] ], "video-decoder.https.any.js": [ - "190a524dd6c75fdcb7675e936ee4f8813202d4a6", + "77a610bd4ea2ca090ba029cdf1239e83184873b8", [ "webcodecs/video-decoder.https.any.html", { @@ -731968,7 +733592,7 @@ ] ], "video-encoder-config.https.any.js": [ - "e4807361fcaa4ed9de459deb4f441c4cf2f9be40", + "5011bfdd0a8506f3c236d3cdaf197458f5cc9a45", [ "webcodecs/video-encoder-config.https.any.html", { @@ -751976,11 +753600,83 @@ } ] ], - "echo-large-bidirectional-streams.https.html": [ - "daa7c1b9b367890c9e29f0419648329f42a15eb9", + "echo-large-bidirectional-streams.https.any.js": [ + "3f46530327eea602c781a60a524b8c5cf5094e87", [ - null, - {} + "webtransport/echo-large-bidirectional-streams.https.any.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "resources/webtransport-test-helpers.sub.js" + ] + ] + } + ], + [ + "webtransport/echo-large-bidirectional-streams.https.any.serviceworker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "resources/webtransport-test-helpers.sub.js" + ] + ] + } + ], + [ + "webtransport/echo-large-bidirectional-streams.https.any.sharedworker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "resources/webtransport-test-helpers.sub.js" + ] + ] + } + ], + [ + "webtransport/echo-large-bidirectional-streams.https.any.worker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "resources/webtransport-test-helpers.sub.js" + ] + ] + } ] ], "idlharness.https.any.js": [ @@ -783246,6 +784942,15 @@ ] ] }, + "context_destroyed": { + "context_destroyed.py": [ + "5baac7abd2d4f35dc1ee753973926d7697309a31", + [ + null, + {} + ] + ] + }, "create": { "background.py": [ "f1effe05372af81564c605a2a243a5737c481a75", @@ -783558,7 +785263,7 @@ }, "user_prompt_opened": { "user_prompt_opened.py": [ - "a24a1e86abab3dd562b96f3951b7ca0836990012", + "a2d5d840a496bd3b6ab49283c36a49629a83d105", [ null, {} @@ -784008,7 +785713,7 @@ ] ], "result_node.py": [ - "9d09b9fc04ace5d463976ee1a0af6d6b163e9b72", + "47cbd42d22d00355bbed097c509d8e0d409d5145", [ null, {} @@ -784059,7 +785764,7 @@ }, "classic_interop": { "node_shared_id.py": [ - "82b39b42e1c64dad4e4c8a772b5e893f75713ef9", + "aeb2bc45978829877dbc554bc580151a341c5d44", [ null, {} @@ -784161,7 +785866,7 @@ ] ], "result_node.py": [ - "a3ca316d0275f566e4bc913beae24ffae58af36d", + "a0bfd0d4c0215b8a0b7fb8ba0276759c966af977", [ null, {} @@ -784471,7 +786176,7 @@ }, "element_clear": { "clear.py": [ - "9b0d7f2133f7686603449897c659c7e4220ec746", + "22c07b6a8ce241a7166511c539765f1cd959edcb", [ null, { @@ -784505,14 +786210,14 @@ ] ], "click.py": [ - "3c3f7d70e6c6b23932e7452f73e160a2d213a5ba", + "61acc923e8eb3f6883d09bb4bfa220d7f757bbb8", [ null, {} ] ], "events.py": [ - "30f2dfa0a4a9b5f643832d751f0b35ecfff89fc2", + "5e80b52e879c6c8383d47322cc090dfb3b2304b3", [ null, {} @@ -784614,7 +786319,7 @@ ] ], "send_keys.py": [ - "281c7ad719ddd05dac2ab7c6de343e9bebde4a5b", + "92002f294576b9108d29d5bbf39a13a248094e8d", [ null, {} @@ -784632,7 +786337,7 @@ }, "execute_async_script": { "arguments.py": [ - "ead6e0c186ea40771643aea56ccc7180e6cc28d7", + "81b30de26786a2620638e45f6648440bbfa17595", [ null, {} @@ -784653,14 +786358,14 @@ ] ], "execute_async.py": [ - "42cf4aacee8342939c515b5e56a40ef15a1cacfb", + "3c8cc6210d4b1a6a51c4b465f86e20001cb889b5", [ null, {} ] ], "node.py": [ - "53abda4b300597ade2f5b8d38260caad9cb17f31", + "2f1bf75e83c0e93020cdc16e8247e78bbccb44ff", [ null, {} @@ -784695,11 +786400,18 @@ "timeout": "long" } ] + ], + "window.py": [ + "f79bfdf49d9832c79a073de8709e626adf00770a", + [ + null, + {} + ] ] }, "execute_script": { "arguments.py": [ - "b8657ce0efae2a266158bb8c2846864cd63c1d5e", + "ab5c5234ba143c707d1b4ef97a1212cc99702fb0", [ null, {} @@ -784720,21 +786432,14 @@ ] ], "execute.py": [ - "fbccc98633867b9ab137b26f0f8818b98a29c81f", - [ - null, - {} - ] - ], - "json_serialize_windowproxy.py": [ - "8e76feda23809bf65a77c6bcd3994209aaba40e0", + "15ac1d0132a224ff836e38681733697a33dcc0ae", [ null, {} ] ], "node.py": [ - "caf85988f15413eca765c5d5cb019b06777d3b9d", + "61cf3463dcbbd454a6aad1cae40136a5aaa4432f", [ null, {} @@ -784769,6 +786474,13 @@ "timeout": "long" } ] + ], + "window.py": [ + "9ab45d7cb780389e7cc071ba0ae49c9ae3e2259e", + [ + null, + {} + ] ] }, "find_element": { @@ -784809,7 +786521,7 @@ }, "find_element_from_shadow_root": { "find.py": [ - "3f1b64a61c5bd336af86613eb7ce091b2bcecee7", + "c658152ee6910d9d00eaa4f843a3d60719787776", [ null, {} @@ -784863,7 +786575,7 @@ }, "find_elements_from_shadow_root": { "find.py": [ - "ffdaa7e84b05ead748b2f61e2bfc344652f65244", + "188fff29212efdafb123aa0ba0a578b5ab15dd77", [ null, {} @@ -784953,7 +786665,7 @@ }, "get_computed_label": { "get.py": [ - "0dc00a471a9a37509e4ed7a448c1213bb978eeda", + "e023b79cea52226e85fdd601a4516bd73cf8d936", [ null, {} @@ -784962,7 +786674,7 @@ }, "get_computed_role": { "get.py": [ - "51b6a8b3b6d1e302be8885e4b2976cc0c02ff4bd", + "1b8489675cea5a8c6c4183fc1bd989332e6cc308", [ null, {} @@ -785003,7 +786715,7 @@ }, "get_element_attribute": { "get.py": [ - "375f25032c06a10fecf78a884647056fbd826b9d", + "0fcfd00c97c5e9abe44dd39cc2ed7e04dbe785c3", [ null, {} @@ -785021,7 +786733,7 @@ }, "get_element_css_value": { "get.py": [ - "6f0a8a56395788be0f9152028f569f133fcd79ed", + "1f6f571149bd259a7b49393b6ef39ad31b843295", [ null, {} @@ -785039,7 +786751,7 @@ }, "get_element_property": { "get.py": [ - "bb63481dfcae75ee6f80503413c552db78d3c8ac", + "12d48a3abb5ae334219bf4103d5a693e5eed13ad", [ null, {} @@ -785057,7 +786769,7 @@ }, "get_element_rect": { "get.py": [ - "942f119f43c9bb30eaefd52f3c793d7e47cfbfc4", + "959ccc455ecdbd476874d546139816cc2955c7d8", [ null, {} @@ -785075,7 +786787,7 @@ }, "get_element_shadow_root": { "get.py": [ - "d9adde0b9e3aee402aa2e03db9d02259d968e81b", + "25e68c1bbac2e3cd041fd76af64cb9a24c754e20", [ null, {} @@ -785093,7 +786805,7 @@ }, "get_element_tag_name": { "get.py": [ - "3bb03d79886d88c6ba045d9f0bedae7414412025", + "d8bb3acc500b5aeb1c3a97c7c912e8f3ea5cbe3a", [ null, {} @@ -785111,7 +786823,7 @@ }, "get_element_text": { "get.py": [ - "e8d559cf661acee18a39cbc4b6bb03289385ca08", + "2a2363c0528eefa90981289ff608dd880ece4226", [ null, {} @@ -785262,7 +786974,7 @@ }, "is_element_enabled": { "enabled.py": [ - "fccff383a55a7929179810216407acbdea0a079c", + "24fc85fdad2daba04b6770c536d0ae4de9ee95bb", [ null, {} @@ -785280,7 +786992,7 @@ }, "is_element_selected": { "selected.py": [ - "1fb5b9ce86b521069f638956272e3101ea62cc5c", + "bf650de3e23b5ab5f04d7704f8c34e9edbbb4d47", [ null, {} @@ -785579,7 +787291,7 @@ ] ], "pointer_mouse.py": [ - "97295f56f41324dc19925b2ea5109815a8c89a78", + "6ccb7c404e0e803e20bb7be532f45b248bd9d455", [ null, { @@ -785851,7 +787563,7 @@ ] ], "screenshot.py": [ - "ea4cc290db4cdd603d9dc20bbc90914c4e241cb5", + "fdc0d65b1d9c515701147f88261c41d37deee8b9", [ null, {} diff --git a/tests/wpt/meta/css/CSS2/linebox/inline-negative-margin-001.html.ini b/tests/wpt/meta/css/CSS2/linebox/inline-negative-margin-001.html.ini index ba1ea35fa63..66a6e016faa 100644 --- a/tests/wpt/meta/css/CSS2/linebox/inline-negative-margin-001.html.ini +++ b/tests/wpt/meta/css/CSS2/linebox/inline-negative-margin-001.html.ini @@ -2,21 +2,6 @@ [[data-expected-height\] 7] expected: FAIL - [[data-expected-height\] 9] - expected: FAIL - - [[data-expected-height\] 10] - expected: FAIL - - [[data-expected-height\] 11] - expected: FAIL - - [[data-expected-height\] 12] - expected: FAIL - - [[data-expected-height\] 13] - expected: FAIL - [[data-expected-height\] 3] expected: FAIL diff --git a/tests/wpt/meta/css/css-color/system-color-support.html.ini b/tests/wpt/meta/css/css-color/system-color-support.html.ini new file mode 100644 index 00000000000..28563ddd87a --- /dev/null +++ b/tests/wpt/meta/css/css-color/system-color-support.html.ini @@ -0,0 +1,57 @@ +[system-color-support.html] + [System color Canvas works] + expected: FAIL + + [System color CanvasText works] + expected: FAIL + + [System color LinkText works] + expected: FAIL + + [System color VisitedText works] + expected: FAIL + + [System color ActiveText works] + expected: FAIL + + [System color ButtonFace works] + expected: FAIL + + [System color ButtonText works] + expected: FAIL + + [System color ButtonBorder works] + expected: FAIL + + [System color Field works] + expected: FAIL + + [System color FieldText works] + expected: FAIL + + [System color Highlight works] + expected: FAIL + + [System color HighlightText works] + expected: FAIL + + [System color SelectedItem works] + expected: FAIL + + [System color SelectedItemText works] + expected: FAIL + + [System color Mark works] + expected: FAIL + + [System color MarkText works] + expected: FAIL + + [System color GrayText works] + expected: FAIL + + [System color AccentColor works] + expected: FAIL + + [System color AccentColorText works] + expected: FAIL diff --git a/tests/wpt/meta/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html.ini b/tests/wpt/meta/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html.ini new file mode 100644 index 00000000000..48224fe6767 --- /dev/null +++ b/tests/wpt/meta/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html.ini @@ -0,0 +1,7 @@ +[font-palette-animation-not-specified-endpoints.html] + expected: TIMEOUT + [Verify font-palette is animated when `from` keyframe is not specified] + expected: NOTRUN + + [Verify font-palette is animated when `to` keyframe is not specified] + expected: NOTRUN diff --git a/tests/wpt/meta/css/css-fonts/variations/at-font-face-font-matching.html.ini b/tests/wpt/meta/css/css-fonts/variations/at-font-face-font-matching.html.ini index 02f4760ad1c..1ba53e3a2fc 100644 --- a/tests/wpt/meta/css/css-fonts/variations/at-font-face-font-matching.html.ini +++ b/tests/wpt/meta/css/css-fonts/variations/at-font-face-font-matching.html.ini @@ -20,9 +20,6 @@ [Matching font-weight: '430' should prefer '420 440' over '450 460'] expected: FAIL - [Matching font-weight: '430' should prefer '350 399' over '340 398'] - expected: FAIL - [Matching font-weight: '430' should prefer '501 550' over '502 560'] expected: FAIL @@ -56,9 +53,6 @@ [Matching font-style: 'oblique 20deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] expected: FAIL - [Matching font-style: 'oblique 10deg' should prefer 'italic' over 'oblique 0deg'] - expected: FAIL - [Matching font-style: 'oblique 10deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] expected: FAIL @@ -83,9 +77,6 @@ [Matching font-style: 'oblique -10deg' should prefer 'oblique 0deg 10deg' over 'oblique 40deg 50deg'] expected: FAIL - [Matching font-style: 'oblique -20deg' should prefer 'oblique 0deg' over 'oblique 30deg 60deg'] - expected: FAIL - [Matching font-style: 'oblique 21deg' should prefer 'oblique 40deg 50deg' over 'oblique 20deg'] expected: FAIL @@ -149,9 +140,6 @@ [Matching font-style: 'oblique 21deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] expected: FAIL - [Matching font-style: 'oblique -21deg' should prefer 'oblique 30deg 60deg' over 'oblique 40deg 50deg'] - expected: FAIL - [Matching font-style: 'oblique 21deg' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] expected: FAIL @@ -161,9 +149,6 @@ [Matching font-style: 'oblique -20deg' should prefer 'italic' over 'oblique 0deg'] expected: FAIL - [Matching font-style: 'normal' should prefer 'oblique 20deg 30deg' over 'oblique -50deg -20deg'] - expected: FAIL - [Matching font-style: 'italic' should prefer 'oblique -60deg -30deg' over 'oblique -50deg -40deg'] expected: FAIL @@ -185,9 +170,6 @@ [Matching font-weight: '430' should prefer '450 460' over '500'] expected: FAIL - [Matching font-style: 'italic' should prefer 'italic' over 'oblique 20deg'] - expected: FAIL - [Matching font-stretch: '100%' should prefer '100%' over '110% 120%'] expected: FAIL @@ -265,3 +247,51 @@ [Matching font-style: 'oblique -21deg' should prefer 'oblique -60deg -40deg' over 'oblique -10deg'] expected: FAIL + + [Matching font-weight: '400' should prefer '501 550' over '502 560'] + expected: FAIL + + [Matching font-weight: '501' should prefer '501' over '502 510'] + expected: FAIL + + [Matching font-stretch: '100%' should prefer '110% 120%' over '115% 116%'] + expected: FAIL + + [Matching font-stretch: '110%' should prefer '110% 120%' over '115% 116%'] + expected: FAIL + + [Matching font-style: 'normal' should prefer 'normal' over 'oblique 0deg'] + expected: FAIL + + [Matching font-style: 'normal' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'] + expected: FAIL + + [Matching font-style: 'italic' should prefer 'oblique 40deg 50deg' over 'oblique 5deg 10deg'] + expected: FAIL + + [Matching font-style: 'italic' should prefer 'normal' over 'oblique 0deg'] + expected: FAIL + + [Matching font-style: 'oblique 20deg' should prefer 'oblique 10deg' over 'italic'] + expected: FAIL + + [Matching font-style: 'oblique 20deg' should prefer 'italic' over 'oblique 0deg'] + expected: FAIL + + [Matching font-style: 'oblique 21deg' should prefer 'italic' over 'oblique 0deg'] + expected: FAIL + + [Matching font-style: 'oblique 10deg' should prefer 'oblique 10deg' over 'oblique 5deg'] + expected: FAIL + + [Matching font-style: 'oblique 10deg' should prefer 'oblique 5deg' over 'oblique 15deg 20deg'] + expected: FAIL + + [Matching font-style: 'oblique 0deg' should prefer 'oblique 0deg' over 'oblique 5deg'] + expected: FAIL + + [Matching font-style: 'oblique 0deg' should prefer 'oblique 5deg' over 'oblique 15deg 20deg'] + expected: FAIL + + [Matching font-style: 'oblique -21deg' should prefer 'oblique 0deg' over 'oblique 30deg 60deg'] + expected: FAIL diff --git a/tests/wpt/meta/css/css-images/parsing/gradient-interpolation-method-computed.html.ini b/tests/wpt/meta/css/css-images/parsing/gradient-interpolation-method-computed.html.ini index ac3cd32db81..9e15d59a455 100644 --- a/tests/wpt/meta/css/css-images/parsing/gradient-interpolation-method-computed.html.ini +++ b/tests/wpt/meta/css/css-images/parsing/gradient-interpolation-method-computed.html.ini @@ -815,12 +815,6 @@ [Property background-image value 'linear-gradient(in oklch decreasing hue to right bottom, color(srgb 1 0 0), blue)'] expected: FAIL - [Property background-image value 'radial-gradient(ellipse 50% 40em, red, blue)'] - expected: FAIL - - [Property background-image value 'radial-gradient(at right center, red, blue)'] - expected: FAIL - [Property background-image value 'radial-gradient(50px, color(srgb 1 0 0), blue)'] expected: FAIL diff --git a/tests/wpt/meta/css/css-text/inheritance.html.ini b/tests/wpt/meta/css/css-text/inheritance.html.ini index a8eba1c02e2..fe48e832022 100644 --- a/tests/wpt/meta/css/css-text/inheritance.html.ini +++ b/tests/wpt/meta/css/css-text/inheritance.html.ini @@ -76,3 +76,15 @@ [Property white-space-collapse inherits] expected: FAIL + + [Property text-wrap-mode has initial value wrap] + expected: FAIL + + [Property text-wrap-mode inherits] + expected: FAIL + + [Property text-wrap-style has initial value auto] + expected: FAIL + + [Property text-wrap-style inherits] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/parsing/text-wrap-computed.html.ini b/tests/wpt/meta/css/css-text/parsing/text-wrap-computed.html.ini new file mode 100644 index 00000000000..dbe3756bbab --- /dev/null +++ b/tests/wpt/meta/css/css-text/parsing/text-wrap-computed.html.ini @@ -0,0 +1,66 @@ +[text-wrap-computed.html] + [Property text-wrap value 'wrap'] + expected: FAIL + + [Property text-wrap value 'nowrap'] + expected: FAIL + + [Property text-wrap value 'auto'] + expected: FAIL + + [Property text-wrap value 'balance'] + expected: FAIL + + [Property text-wrap value 'stable'] + expected: FAIL + + [Property text-wrap value 'pretty'] + expected: FAIL + + [Property text-wrap value 'wrap auto'] + expected: FAIL + + [Property text-wrap value 'wrap balance'] + expected: FAIL + + [Property text-wrap value 'wrap pretty'] + expected: FAIL + + [Property text-wrap value 'wrap stable'] + expected: FAIL + + [Property text-wrap value 'auto wrap'] + expected: FAIL + + [Property text-wrap value 'balance wrap'] + expected: FAIL + + [Property text-wrap value 'pretty wrap'] + expected: FAIL + + [Property text-wrap value 'stable wrap'] + expected: FAIL + + [Property text-wrap value 'nowrap auto'] + expected: FAIL + + [Property text-wrap value 'nowrap balance'] + expected: FAIL + + [Property text-wrap value 'nowrap pretty'] + expected: FAIL + + [Property text-wrap value 'nowrap stable'] + expected: FAIL + + [Property text-wrap value 'auto nowrap'] + expected: FAIL + + [Property text-wrap value 'balance nowrap'] + expected: FAIL + + [Property text-wrap value 'pretty nowrap'] + expected: FAIL + + [Property text-wrap value 'stable nowrap'] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/parsing/text-wrap-mode-computed.html.ini b/tests/wpt/meta/css/css-text/parsing/text-wrap-mode-computed.html.ini new file mode 100644 index 00000000000..f9739ca0b28 --- /dev/null +++ b/tests/wpt/meta/css/css-text/parsing/text-wrap-mode-computed.html.ini @@ -0,0 +1,6 @@ +[text-wrap-mode-computed.html] + [Property text-wrap-mode value 'wrap'] + expected: FAIL + + [Property text-wrap-mode value 'nowrap'] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/parsing/text-wrap-mode-valid.html.ini b/tests/wpt/meta/css/css-text/parsing/text-wrap-mode-valid.html.ini new file mode 100644 index 00000000000..76dc7a87b4e --- /dev/null +++ b/tests/wpt/meta/css/css-text/parsing/text-wrap-mode-valid.html.ini @@ -0,0 +1,21 @@ +[text-wrap-mode-valid.html] + [e.style['text-wrap-mode'\] = "wrap" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "nowrap" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "initial" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "inherit" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "unset" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "revert" should set the property value] + expected: FAIL + + [e.style['text-wrap-mode'\] = "revert-layer" should set the property value] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/parsing/text-wrap-style-computed.html.ini b/tests/wpt/meta/css/css-text/parsing/text-wrap-style-computed.html.ini new file mode 100644 index 00000000000..8be1df9f7ff --- /dev/null +++ b/tests/wpt/meta/css/css-text/parsing/text-wrap-style-computed.html.ini @@ -0,0 +1,12 @@ +[text-wrap-style-computed.html] + [Property text-wrap-style value 'auto'] + expected: FAIL + + [Property text-wrap-style value 'balance'] + expected: FAIL + + [Property text-wrap-style value 'pretty'] + expected: FAIL + + [Property text-wrap-style value 'stable'] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/parsing/text-wrap-style-valid.html.ini b/tests/wpt/meta/css/css-text/parsing/text-wrap-style-valid.html.ini new file mode 100644 index 00000000000..fd637df85db --- /dev/null +++ b/tests/wpt/meta/css/css-text/parsing/text-wrap-style-valid.html.ini @@ -0,0 +1,27 @@ +[text-wrap-style-valid.html] + [e.style['text-wrap-style'\] = "auto" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "balance" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "pretty" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "stable" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "initial" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "inherit" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "unset" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "revert" should set the property value] + expected: FAIL + + [e.style['text-wrap-style'\] = "revert-layer" should set the property value] + expected: FAIL diff --git a/tests/wpt/meta/css/css-values/round-mod-rem-computed.html.ini b/tests/wpt/meta/css/css-values/round-mod-rem-computed.html.ini index d611c6fdc4c..25cc0592b87 100644 --- a/tests/wpt/meta/css/css-values/round-mod-rem-computed.html.ini +++ b/tests/wpt/meta/css/css-values/round-mod-rem-computed.html.ini @@ -700,3 +700,12 @@ [mod(4, -Infinity) should be used-value-equivalent to calc(NaN)] expected: FAIL + + [round(1px + 0%, 1px) should be used-value-equivalent to 1px] + expected: FAIL + + [mod(3px + 0%, 2px) should be used-value-equivalent to 1px] + expected: FAIL + + [rem(3px + 0%, 2px) should be used-value-equivalent to 1px] + expected: FAIL diff --git a/tests/wpt/meta/fetch/api/redirect/redirect-keepalive.any.js.ini b/tests/wpt/meta/fetch/api/redirect/redirect-keepalive.any.js.ini index f61eb5b8e17..73c79c76452 100644 --- a/tests/wpt/meta/fetch/api/redirect/redirect-keepalive.any.js.ini +++ b/tests/wpt/meta/fetch/api/redirect/redirect-keepalive.any.js.ini @@ -1,5 +1,4 @@ [redirect-keepalive.any.html] - expected: TIMEOUT [[keepalive\][new window\][unload\] same-origin redirect] expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html.ini b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html.ini new file mode 100644 index 00000000000..3274b486b81 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-no-referrer-when-downgrade.tentative.https.html] + [Test referer header https://web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html.ini b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html.ini new file mode 100644 index 00000000000..f9977a9008e --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-no-referrer.tentative.https.html] + [Test referer header ] + expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html.ini b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html.ini new file mode 100644 index 00000000000..38a364e11ea --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html.ini @@ -0,0 +1,6 @@ +[header-referrer-origin-when-cross-origin.tentative.https.html] + [Test referer header https://web-platform.test:8443] + expected: FAIL + + [Test referer header https://www1.web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html.ini b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html.ini new file mode 100644 index 00000000000..06fe8584f00 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-origin.tentative.https.html] + [Test referer header https://www1.web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html.ini b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html.ini new file mode 100644 index 00000000000..ea9ac6e351c --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html.ini @@ -0,0 +1,6 @@ +[header-referrer-same-origin.tentative.https.html] + [Test referer header ] + expected: FAIL + + [Test referer header https://www1.web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html.ini b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html.ini new file mode 100644 index 00000000000..0bf2b43e93f --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-strict-origin-when-cross-origin.tentative.https.html] + [Test referer header https://www1.web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html.ini b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html.ini new file mode 100644 index 00000000000..9c67727f1b1 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-strict-origin.tentative.https.html] + [Test referer header https://web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html.ini b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html.ini new file mode 100644 index 00000000000..979914e33f8 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html.ini @@ -0,0 +1,3 @@ +[header-referrer-unsafe-url.tentative.https.html] + [Test referer header https://web-platform.test:8443] + expected: FAIL diff --git a/tests/wpt/meta/fetch/fetch-later/iframe.tentative.https.window.js.ini b/tests/wpt/meta/fetch/fetch-later/iframe.tentative.https.window.js.ini new file mode 100644 index 00000000000..b3d4cb1d9f1 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/iframe.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[iframe.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta/fetch/fetch-later/new-window.tentative.https.window.js.ini b/tests/wpt/meta/fetch/fetch-later/new-window.tentative.https.window.js.ini new file mode 100644 index 00000000000..1f36e0e5b51 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/new-window.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[new-window.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js.ini b/tests/wpt/meta/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js.ini new file mode 100644 index 00000000000..357487889e9 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[csp-allowed.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js.ini b/tests/wpt/meta/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js.ini new file mode 100644 index 00000000000..f6d883b2101 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[csp-blocked.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js.ini b/tests/wpt/meta/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js.ini new file mode 100644 index 00000000000..23cc9814012 --- /dev/null +++ b/tests/wpt/meta/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js.ini @@ -0,0 +1,2 @@ +[csp-redirect-to-blocked.tentative.https.window.html] + expected: ERROR diff --git a/tests/wpt/meta/fetch/metadata/generated/css-images.sub.tentative.html.ini b/tests/wpt/meta/fetch/metadata/generated/css-images.sub.tentative.html.ini index 8099defc928..4b5c3e26586 100644 --- a/tests/wpt/meta/fetch/metadata/generated/css-images.sub.tentative.html.ini +++ b/tests/wpt/meta/fetch/metadata/generated/css-images.sub.tentative.html.ini @@ -185,6 +185,3 @@ [border-image sec-fetch-site - HTTPS downgrade (header not sent)] expected: FAIL - - [background-image sec-fetch-mode - Not sent to non-trustworthy same-site destination] - expected: TIMEOUT diff --git a/tests/wpt/meta/hr-time/raf-coarsened-time.https.html.ini b/tests/wpt/meta/hr-time/raf-coarsened-time.https.html.ini new file mode 100644 index 00000000000..b4991611fcf --- /dev/null +++ b/tests/wpt/meta/hr-time/raf-coarsened-time.https.html.ini @@ -0,0 +1,2 @@ +[raf-coarsened-time.https.html] + expected: ERROR diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html.ini b/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html.ini new file mode 100644 index 00000000000..46f10274f9f --- /dev/null +++ b/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html.ini @@ -0,0 +1,4 @@ +[order-in-bfcache-restore.html] + expected: TIMEOUT + [pagereveal event fires and in correct order on restoration from BFCache] + expected: TIMEOUT diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html.ini b/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html.ini new file mode 100644 index 00000000000..721a89932a1 --- /dev/null +++ b/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html.ini @@ -0,0 +1,3 @@ +[order-in-new-document-navigation.html] + [pagereveal event fires and in correct order on new-document navigation] + expected: FAIL diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html.ini b/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html.ini new file mode 100644 index 00000000000..b6c1d6dbec6 --- /dev/null +++ b/tests/wpt/meta/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html.ini @@ -0,0 +1,2 @@ +[order-in-prerender-activation.html] + expected: ERROR diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html.ini b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html.ini index bf5454c35e1..149bcb4ff8c 100644 --- a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html.ini +++ b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html.ini @@ -5,8 +5,8 @@ [load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank?foo'] expected: FAIL - [load & pageshow events do not fire on contentWindow of <iframe> element created with src=''] + [load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank#foo'] expected: FAIL - [load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank#foo'] + [load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank'] expected: FAIL diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html.ini b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html.ini index 324db3d9b35..5aef7ce66ce 100644 --- a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html.ini +++ b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html.ini @@ -10,3 +10,6 @@ [load event does not fire on window.open('about:blank?foo')] expected: FAIL + + [load event does not fire on window.open('about:blank')] + expected: FAIL diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling-dynamic.html.ini b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling-dynamic.html.ini index f27acdd3b9d..78240a2f463 100644 --- a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling-dynamic.html.ini +++ b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-return-value-handling-dynamic.html.ini @@ -4,3 +4,15 @@ [Test javascript URL string return values in direct and indirect (target) frame contexts. 9] expected: FAIL + + [0041 set in href="" targeting a frame and clicked] + expected: FAIL + + [0080 00FF set in href="" targeting a frame and clicked] + expected: FAIL + + [0080 00FF 0100 set in href="" targeting a frame and clicked] + expected: FAIL + + [D83D DE0D set in href="" targeting a frame and clicked] + expected: FAIL diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.js.ini b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.js.ini new file mode 100644 index 00000000000..4ecd6d9f753 --- /dev/null +++ b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.js.ini @@ -0,0 +1,3 @@ +[navigation-unload-cross-origin.sub.window.html] + [Cross-origin navigation started from unload handler must be ignored] + expected: FAIL diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.js.ini b/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.js.ini deleted file mode 100644 index 7dc346632a4..00000000000 --- a/tests/wpt/meta/html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.js.ini +++ /dev/null @@ -1,3 +0,0 @@ -[navigation-unload-same-origin.window.html] - [Same-origin navigation started from unload handler must be ignored] - expected: FAIL diff --git a/tests/wpt/meta/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/nav-cancelation-2.sub.html.ini b/tests/wpt/meta/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/nav-cancelation-2.sub.html.ini index 9f7f24f662e..0e40ffc0656 100644 --- a/tests/wpt/meta/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/nav-cancelation-2.sub.html.ini +++ b/tests/wpt/meta/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/nav-cancelation-2.sub.html.ini @@ -1,3 +1,4 @@ [nav-cancelation-2.sub.html] + expected: TIMEOUT [grandparent cancels a pending navigation in a cross-origin grandchild] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/meta/html/browsers/history/the-history-interface/traverse-during-unload.html.ini b/tests/wpt/meta/html/browsers/history/the-history-interface/traverse-during-unload.html.ini new file mode 100644 index 00000000000..f5b7b25324f --- /dev/null +++ b/tests/wpt/meta/html/browsers/history/the-history-interface/traverse-during-unload.html.ini @@ -0,0 +1,4 @@ +[traverse-during-unload.html] + expected: TIMEOUT + [Traversing the history during unload] + expected: TIMEOUT diff --git a/tests/wpt/meta-legacy-layout/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini b/tests/wpt/meta/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini index 7a5fcb79165..7a5fcb79165 100644 --- a/tests/wpt/meta-legacy-layout/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini +++ b/tests/wpt/meta/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini diff --git a/tests/wpt/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini b/tests/wpt/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini index 24c9e5d3926..90eb9ed743b 100644 --- a/tests/wpt/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini +++ b/tests/wpt/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini @@ -1,5 +1,4 @@ [cross-origin-objects.html] - expected: TIMEOUT [Basic sanity-checking (cross-origin)] expected: FAIL diff --git a/tests/wpt/meta-legacy-layout/html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html.ini b/tests/wpt/meta/html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html.ini index 4b4820d1729..4b4820d1729 100644 --- a/tests/wpt/meta-legacy-layout/html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html.ini +++ b/tests/wpt/meta/html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html.ini diff --git a/tests/wpt/meta/html/browsers/windows/embedded-opener-remove-frame.html.ini b/tests/wpt/meta/html/browsers/windows/embedded-opener-remove-frame.html.ini index 613bed9352d..9df06805f99 100644 --- a/tests/wpt/meta/html/browsers/windows/embedded-opener-remove-frame.html.ini +++ b/tests/wpt/meta/html/browsers/windows/embedded-opener-remove-frame.html.ini @@ -1,5 +1,5 @@ [embedded-opener-remove-frame.html] - expected: CRASH + expected: TIMEOUT [opener of discarded nested browsing context] expected: FAIL diff --git a/tests/wpt/meta/html/dom/elements/global-attributes/dir-auto-form-associated.window.js.ini b/tests/wpt/meta/html/dom/elements/global-attributes/dir-auto-form-associated.window.js.ini new file mode 100644 index 00000000000..9b19b29d20e --- /dev/null +++ b/tests/wpt/meta/html/dom/elements/global-attributes/dir-auto-form-associated.window.js.ini @@ -0,0 +1,66 @@ +[dir-auto-form-associated.window.html] + [<input dir=auto type=hidden> directionality] + expected: FAIL + + [<input dir=auto type=text> directionality] + expected: FAIL + + [<input dir=auto type=search> directionality] + expected: FAIL + + [<input dir=auto type=tel> directionality] + expected: FAIL + + [<input dir=auto type=url> directionality] + expected: FAIL + + [<input dir=auto type=email> directionality] + expected: FAIL + + [<input dir=auto type=password> directionality] + expected: FAIL + + [<input dir=auto type=submit> directionality] + expected: FAIL + + [<input dir=auto type=reset> directionality] + expected: FAIL + + [<input dir=auto type=button> directionality] + expected: FAIL + + [<input dir=auto type=date> directionality] + expected: FAIL + + [<input dir=auto type=month> directionality] + expected: FAIL + + [<input dir=auto type=week> directionality] + expected: FAIL + + [<input dir=auto type=time> directionality] + expected: FAIL + + [<input dir=auto type=datetime-local> directionality] + expected: FAIL + + [<input dir=auto type=number> directionality] + expected: FAIL + + [<input dir=auto type=range> directionality] + expected: FAIL + + [<input dir=auto type=color> directionality] + expected: FAIL + + [<input dir=auto type=checkbox> directionality] + expected: FAIL + + [<input dir=auto type=radio> directionality] + expected: FAIL + + [<input dir=auto type=image> directionality] + expected: FAIL + + [<textarea dir=auto> directionality] + expected: FAIL diff --git a/tests/wpt/meta/html/dom/elements/global-attributes/lang-attribute.window.js.ini b/tests/wpt/meta/html/dom/elements/global-attributes/lang-attribute.window.js.ini new file mode 100644 index 00000000000..9a9467a8817 --- /dev/null +++ b/tests/wpt/meta/html/dom/elements/global-attributes/lang-attribute.window.js.ini @@ -0,0 +1,3 @@ +[lang-attribute.window.html] + [unnamespaced lang attribute only works on elements in the HTML namespace] + expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html.ini b/tests/wpt/meta/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html.ini index 24903b5f66f..7d28d586f51 100644 --- a/tests/wpt/meta/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html.ini +++ b/tests/wpt/meta/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html.ini @@ -1,4 +1,3 @@ [iframe_sandbox_popups_escaping-1.html] - expected: TIMEOUT [Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini b/tests/wpt/meta/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini index bbc1f35d8d9..e8872b3585b 100644 --- a/tests/wpt/meta/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini +++ b/tests/wpt/meta/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html.ini @@ -1,3 +1,4 @@ [iframe_sandbox_popups_nonescaping-1.html] + expected: TIMEOUT [Check that popups from a sandboxed iframe do not escape the sandbox] - expected: FAIL + expected: NOTRUN diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-img-element/non-active-document.html.ini b/tests/wpt/meta/html/semantics/embedded-content/the-img-element/non-active-document.html.ini index 3cdeb8ebcbc..47b45e65a1c 100644 --- a/tests/wpt/meta/html/semantics/embedded-content/the-img-element/non-active-document.html.ini +++ b/tests/wpt/meta/html/semantics/embedded-content/the-img-element/non-active-document.html.ini @@ -1,3 +1,9 @@ [non-active-document.html] [DOMParser] expected: FAIL + + [createHTMLDocument] + expected: FAIL + + [<template>] + expected: FAIL diff --git a/tests/wpt/meta/html/semantics/invokers/invokeelement-interface.tentative.html.ini b/tests/wpt/meta/html/semantics/invokers/invokeelement-interface.tentative.html.ini index e1534b63047..e8781936e24 100644 --- a/tests/wpt/meta/html/semantics/invokers/invokeelement-interface.tentative.html.ini +++ b/tests/wpt/meta/html/semantics/invokers/invokeelement-interface.tentative.html.ini @@ -31,3 +31,6 @@ [invokeAction reflects tostring value 2] expected: FAIL + + [invokeAction reflects same casing] + expected: FAIL diff --git a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/document-write/module-static-import-delayed.html.ini b/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/document-write/module-static-import-delayed.html.ini new file mode 100644 index 00000000000..53acb938c1b --- /dev/null +++ b/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/document-write/module-static-import-delayed.html.ini @@ -0,0 +1,3 @@ +[module-static-import-delayed.html] + [document.write in an imported module] + expected: FAIL diff --git a/tests/wpt/meta/html/webappapis/scripting/events/compile-event-handler-settings-objects.html.ini b/tests/wpt/meta/html/webappapis/scripting/events/compile-event-handler-settings-objects.html.ini index 1053fb90051..6206f8c0210 100644 --- a/tests/wpt/meta/html/webappapis/scripting/events/compile-event-handler-settings-objects.html.ini +++ b/tests/wpt/meta/html/webappapis/scripting/events/compile-event-handler-settings-objects.html.ini @@ -2,6 +2,3 @@ expected: TIMEOUT [The incumbent settings object while executing the compiled callback via Web IDL's invoke must be that of the node document] expected: TIMEOUT - - [The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document] - expected: FAIL diff --git a/tests/wpt/meta/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html.ini b/tests/wpt/meta/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html.ini index dbe1def99e3..7237f5792de 100644 --- a/tests/wpt/meta/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html.ini +++ b/tests/wpt/meta/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html.ini @@ -1,9 +1,10 @@ [promise-job-entry-different-function-realm.html] + expected: TIMEOUT [Fulfillment handler on fulfilled promise] expected: FAIL [Rejection handler on pending-then-rejected promise] - expected: FAIL + expected: TIMEOUT [Thenable resolution] expected: FAIL @@ -12,4 +13,4 @@ expected: FAIL [Fulfillment handler on pending-then-fulfilled promise] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/meta/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry.html.ini b/tests/wpt/meta/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry.html.ini index 8bcf3a07de4..31bfd644df0 100644 --- a/tests/wpt/meta/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry.html.ini +++ b/tests/wpt/meta/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry.html.ini @@ -1,10 +1,9 @@ [promise-job-entry.html] - expected: TIMEOUT [Fulfillment handler on fulfilled promise] expected: FAIL [Rejection handler on pending-then-rejected promise] - expected: TIMEOUT + expected: FAIL [Sanity check: this all works as expected with no promises involved] expected: FAIL @@ -16,4 +15,4 @@ expected: FAIL [Fulfillment handler on pending-then-fulfilled promise] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/meta/resource-timing/content-type-parsing.html.ini b/tests/wpt/meta/resource-timing/content-type-parsing.html.ini index 49b17a921b5..71ca4ed5411 100644 --- a/tests/wpt/meta/resource-timing/content-type-parsing.html.ini +++ b/tests/wpt/meta/resource-timing/content-type-parsing.html.ini @@ -94,10 +94,10 @@ expected: FAIL [mime-type 16 : text/html;charset=\x0bgbk] - expected: TIMEOUT + expected: FAIL [mime-type 17 : text/html;charset=\x0cgbk] - expected: NOTRUN + expected: TIMEOUT [mime-type 18 : text/html;\x0bcharset=gbk] expected: NOTRUN diff --git a/tests/wpt/meta/wasm/jsapi/functions/entry.html.ini b/tests/wpt/meta/wasm/jsapi/functions/entry.html.ini index 145d4a8fe37..2ab19558726 100644 --- a/tests/wpt/meta/wasm/jsapi/functions/entry.html.ini +++ b/tests/wpt/meta/wasm/jsapi/functions/entry.html.ini @@ -1,6 +1,7 @@ [entry.html] + expected: TIMEOUT [Start function] - expected: FAIL + expected: TIMEOUT [Sanity check: this all works as expected synchronously] expected: FAIL diff --git a/tests/wpt/meta/wasm/jsapi/gc/casts.tentative.any.js.ini b/tests/wpt/meta/wasm/jsapi/gc/casts.tentative.any.js.ini new file mode 100644 index 00000000000..0b499ced6d7 --- /dev/null +++ b/tests/wpt/meta/wasm/jsapi/gc/casts.tentative.any.js.ini @@ -0,0 +1,5 @@ +[casts.tentative.any.worker.html] + expected: ERROR + +[casts.tentative.any.html] + expected: ERROR diff --git a/tests/wpt/meta/wasm/jsapi/gc/exported-object.tentative.any.js.ini b/tests/wpt/meta/wasm/jsapi/gc/exported-object.tentative.any.js.ini new file mode 100644 index 00000000000..59dd05d2b08 --- /dev/null +++ b/tests/wpt/meta/wasm/jsapi/gc/exported-object.tentative.any.js.ini @@ -0,0 +1,5 @@ +[exported-object.tentative.any.worker.html] + expected: ERROR + +[exported-object.tentative.any.html] + expected: ERROR diff --git a/tests/wpt/meta/wasm/jsapi/gc/i31.tentative.any.js.ini b/tests/wpt/meta/wasm/jsapi/gc/i31.tentative.any.js.ini new file mode 100644 index 00000000000..07c9b76b544 --- /dev/null +++ b/tests/wpt/meta/wasm/jsapi/gc/i31.tentative.any.js.ini @@ -0,0 +1,5 @@ +[i31.tentative.any.html] + expected: ERROR + +[i31.tentative.any.worker.html] + expected: ERROR diff --git a/tests/wpt/meta/webmessaging/with-ports/017.html.ini b/tests/wpt/meta/webmessaging/with-ports/017.html.ini deleted file mode 100644 index c7946fc91b4..00000000000 --- a/tests/wpt/meta/webmessaging/with-ports/017.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[017.html] - expected: TIMEOUT - [origin of the script that invoked the method, about:blank] - expected: TIMEOUT diff --git a/tests/wpt/meta/webmessaging/with-ports/018.html.ini b/tests/wpt/meta/webmessaging/with-ports/018.html.ini new file mode 100644 index 00000000000..b7b36c1d3a4 --- /dev/null +++ b/tests/wpt/meta/webmessaging/with-ports/018.html.ini @@ -0,0 +1,4 @@ +[018.html] + expected: TIMEOUT + [origin of the script that invoked the method, javascript:] + expected: TIMEOUT diff --git a/tests/wpt/meta/webmessaging/without-ports/018.html.ini b/tests/wpt/meta/webmessaging/without-ports/018.html.ini new file mode 100644 index 00000000000..b7b36c1d3a4 --- /dev/null +++ b/tests/wpt/meta/webmessaging/without-ports/018.html.ini @@ -0,0 +1,4 @@ +[018.html] + expected: TIMEOUT + [origin of the script that invoked the method, javascript:] + expected: TIMEOUT diff --git a/tests/wpt/meta/workers/constructors/Worker/Worker-constructor.html.ini b/tests/wpt/meta/workers/constructors/Worker/Worker-constructor.html.ini deleted file mode 100644 index 80f9a4f15b8..00000000000 --- a/tests/wpt/meta/workers/constructors/Worker/Worker-constructor.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[Worker-constructor.html] - expected: ERROR diff --git a/tests/wpt/tests/.github/workflows/documentation.yml b/tests/wpt/tests/.github/workflows/documentation.yml index 00c7bb22627..1d57acc6256 100644 --- a/tests/wpt/tests/.github/workflows/documentation.yml +++ b/tests/wpt/tests/.github/workflows/documentation.yml @@ -21,7 +21,7 @@ jobs: with: python-version: '3.11' - name: Set up Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '14' - name: Set up Virtualenv diff --git a/tests/wpt/tests/accelerometer/Accelerometer-iframe-access.https.html b/tests/wpt/tests/accelerometer/Accelerometer-iframe-access.https.html index bec1705780f..56005696a7f 100644 --- a/tests/wpt/tests/accelerometer/Accelerometer-iframe-access.https.html +++ b/tests/wpt/tests/accelerometer/Accelerometer-iframe-access.https.html @@ -6,12 +6,15 @@ <link rel="help" href="https://www.w3.org/TR/accelerometer/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-iframe-tests.sub.js"></script> <script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script> +<script src="resources/sensor-data.js"></script> <div id="log"></div> <script> -run_generic_sensor_iframe_tests('Accelerometer'); -run_generic_sensor_iframe_tests('LinearAccelerationSensor'); -run_generic_sensor_iframe_tests('GravitySensor'); +run_generic_sensor_iframe_tests(kAccelerometerSensorData, kAccelerometerReadings); +run_generic_sensor_iframe_tests(kLinearAccelerationSensorData, kAccelerometerReadings); +run_generic_sensor_iframe_tests(kGravitySensorData, kAccelerometerReadings); </script> diff --git a/tests/wpt/tests/accelerometer/Accelerometer.https.html b/tests/wpt/tests/accelerometer/Accelerometer.https.html index 0db87d2efc3..d422fef7264 100644 --- a/tests/wpt/tests/accelerometer/Accelerometer.https.html +++ b/tests/wpt/tests/accelerometer/Accelerometer.https.html @@ -6,28 +6,12 @@ <link rel="help" href="https://www.w3.org/TR/accelerometer/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> - -'use strict'; - -const kReadings = { - readings: [ - [1.12345, 2.12345, 3.12345] - ], - expectedReadings: [ - [1.12345, 2.12345, 3.12345] - ], - expectedRemappedReadings: [ - [-2.12345, 1.12345, 3.12345] - ] -}; - -runGenericSensorTests( - 'Accelerometer', - kReadings, - verifyXyzSensorReading, - ['accelerometer']); - +runGenericSensorTests(kAccelerometerSensorData, kAccelerometerReadings); </script> diff --git a/tests/wpt/tests/accelerometer/GravitySensor.https.html b/tests/wpt/tests/accelerometer/GravitySensor.https.html index 6fb21e55728..0f98f3e00de 100644 --- a/tests/wpt/tests/accelerometer/GravitySensor.https.html +++ b/tests/wpt/tests/accelerometer/GravitySensor.https.html @@ -6,28 +6,16 @@ <link rel="help" href="https://www.w3.org/TR/accelerometer/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> 'use strict'; -const kReadings = { - readings: [ - [1.12345, 2.12345, 3.12345] - ], - expectedReadings: [ - [1.12345, 2.12345, 3.12345] - ], - expectedRemappedReadings: [ - [-2.12345, 1.12345, 3.12345] - ] -}; - -runGenericSensorTests( - 'GravitySensor', - kReadings, - verifyXyzSensorReading, - ['accelerometer']); +runGenericSensorTests(kGravitySensorData, kAccelerometerReadings); </script> diff --git a/tests/wpt/tests/accelerometer/LinearAccelerationSensor.https.html b/tests/wpt/tests/accelerometer/LinearAccelerationSensor.https.html index 8dd3446f409..91035cc9628 100644 --- a/tests/wpt/tests/accelerometer/LinearAccelerationSensor.https.html +++ b/tests/wpt/tests/accelerometer/LinearAccelerationSensor.https.html @@ -6,28 +6,16 @@ <link rel="help" href="https://www.w3.org/TR/accelerometer/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> 'use strict'; -const kReadings = { - readings: [ - [1.12345, 2.12345, 3.12345] - ], - expectedReadings: [ - [1.12345, 2.12345, 3.12345] - ], - expectedRemappedReadings: [ - [-2.12345, 1.12345, 3.12345] - ] -}; - -runGenericSensorTests( - 'LinearAccelerationSensor', - kReadings, - verifyXyzSensorReading, - ['accelerometer']); +runGenericSensorTests(kLinearAccelerationSensorData, kAccelerometerReadings); </script> diff --git a/tests/wpt/tests/accelerometer/resources/sensor-data.js b/tests/wpt/tests/accelerometer/resources/sensor-data.js new file mode 100644 index 00000000000..6f56cfdbeb6 --- /dev/null +++ b/tests/wpt/tests/accelerometer/resources/sensor-data.js @@ -0,0 +1,34 @@ +'use strict'; + +const kAccelerometerSensorData = { + sensorName: 'Accelerometer', + permissionName: 'accelerometer', + testDriverName: 'accelerometer', + featurePolicyNames: ['accelerometer'] +}; + +const kGravitySensorData = { + sensorName: 'GravitySensor', + permissionName: 'accelerometer', + testDriverName: 'gravity', + featurePolicyNames: ['accelerometer'] +}; + +const kLinearAccelerationSensorData = { + sensorName: 'LinearAccelerationSensor', + permissionName: 'accelerometer', + testDriverName: 'linear-acceleration', + featurePolicyNames: ['accelerometer'] +}; + +const kAccelerometerReadings = { + readings: [ + { x: 1.12345, y: 2.12345, z: 3.12345 } + ], + expectedReadings: [ + { x: 1.1, y: 2.1, z: 3.1 } + ], + expectedRemappedReadings: [ + { x: -2.1, y: 1.1, z: 3.1 } + ] +}; diff --git a/tests/wpt/tests/ambient-light/AmbientLightSensor-iframe-access.https.html b/tests/wpt/tests/ambient-light/AmbientLightSensor-iframe-access.https.html index 5fedd5fb7a9..765c1bee1f8 100644 --- a/tests/wpt/tests/ambient-light/AmbientLightSensor-iframe-access.https.html +++ b/tests/wpt/tests/ambient-light/AmbientLightSensor-iframe-access.https.html @@ -5,10 +5,13 @@ <link rel="help" href="https://w3c.github.io/ambient-light/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-iframe-tests.sub.js"></script> <script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script> +<script src="resources/sensor-data.js"></script> <div id="log"></div> <script> -run_generic_sensor_iframe_tests('AmbientLightSensor'); +run_generic_sensor_iframe_tests(kSensorData, kReadings); </script> diff --git a/tests/wpt/tests/ambient-light/AmbientLightSensor.https.html b/tests/wpt/tests/ambient-light/AmbientLightSensor.https.html index a8c65e4d3fa..f2ed655082e 100644 --- a/tests/wpt/tests/ambient-light/AmbientLightSensor.https.html +++ b/tests/wpt/tests/ambient-light/AmbientLightSensor.https.html @@ -6,58 +6,12 @@ <link rel="help" href="https://www.w3.org/TR/ambient-light/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> - -'use strict'; - -const kReadings = { - readings: [ - // Readings are selected so that illuminance significance check causes - // the following to happen: - // 1. First two values test situation when two values would be rounded - // to same value. As the second value would be rounded to same value - // as first it won't trigger reading event. - // 2. New value is set to 24. And test checks it is correctly rounded to - // 0. - // 3. New reading is attempted to set to 35. - // 4. Value is read from sensor and compared new reading. But as new - // reading was not significantly different compared to initial, for - // privacy reasons, service returns the initial value. - // 5. New value is set to 49. And test checks it is correctly rounded to - // 50. New value is allowed as it is significantly different compared - // to old value (24). - // 6. New reading is attempted to set to 35. - // 7. Value is read from sensor and compared new reading. But as new - // reading was not significantly different compared to initial, for - // privacy reasons, service returns the initial value. - // 8. New value is set to 23. And test checks it is correctly rounded to - // 0. New value is allowed as it is significantly different compared - // to old value (49). - // - // Note: Readings and expectedReadings wraps around correctly as next - // value would be 150 (output from 127). - [127], - [165], - [24], - [35], - [49], - [35], - [23] - ], - expectedReadings: [ - [150], // output from 127 - [0], // output from 24 - [50], // output from 49 - [0] // output from 23 - ] -}; - -runGenericSensorTests( - 'AmbientLightSensor', - kReadings, - verifyAlsSensorReading, - ['ambient-light-sensor']); - +runGenericSensorTests(kSensorData, kReadings); </script> diff --git a/tests/wpt/tests/ambient-light/resources/sensor-data.js b/tests/wpt/tests/ambient-light/resources/sensor-data.js new file mode 100644 index 00000000000..c1f7bd5ca0f --- /dev/null +++ b/tests/wpt/tests/ambient-light/resources/sensor-data.js @@ -0,0 +1,47 @@ +'use strict'; + +const kSensorData = { + sensorName: 'AmbientLightSensor', + permissionName: 'ambient-light-sensor', + testDriverName: 'ambient-light', + featurePolicyNames: ['ambient-light-sensor'] +}; + +const kReadings = { + readings: [ + // Readings are selected so that illuminance significance check causes + // the following to happen: + // 1. First two values test situation when two values would be rounded + // to same value. As the second value would be rounded to same value + // as first it won't trigger reading event. + // 2. New value is set to 24. And test checks it is correctly rounded to + // 0. + // 3. New reading is attempted to set to 35. + // 4. Value is read from sensor and compared new reading. But as new + // reading was not significantly different compared to initial, for + // privacy reasons, service returns the initial value. + // 5. New value is set to 49. And test checks it is correctly rounded to + // 50. New value is allowed as it is significantly different compared + // to old value (24). + // 6. New reading is attempted to set to 35. + // 7. Value is read from sensor and compared new reading. But as new + // reading was not significantly different compared to initial, for + // privacy reasons, service returns the initial value. + // 8. New value is set to 23. And test checks it is correctly rounded to + // 0. New value is allowed as it is significantly different compared + // to old value (49). + // + // Note: Readings and expectedReadings wraps around correctly as next + // value would be 150 (output from 127). + { illuminance: 127 }, { illuminance: 165 }, { illuminance: 24 }, { + illuminance: + 35 + }, { illuminance: 49 }, { illuminance: 35 }, { illuminance: 23 } + ], + expectedReadings: [ + { illuminance: 150 }, // output from 127 + { illuminance: 0 }, // output from 24 + { illuminance: 50 }, // output from 49 + { illuminance: 0 } // output from 23 + ] +}; diff --git a/tests/wpt/tests/clipboard-apis/clipboard-item.https.html b/tests/wpt/tests/clipboard-apis/clipboard-item.https.html index 9ed6f583bde..b50a1c97d74 100644 --- a/tests/wpt/tests/clipboard-apis/clipboard-item.https.html +++ b/tests/wpt/tests/clipboard-apis/clipboard-item.https.html @@ -95,4 +95,18 @@ promise_test(async () => { const text = await (new Response(blob)).text(); assert_equals(text, 'xxx'); }, "getType(DOMString invalid type) converts DOMString to Blob"); + +promise_test(async () => { + assert_true(ClipboardItem.supports('text/plain')); + assert_true(ClipboardItem.supports('text/html')); + assert_true(ClipboardItem.supports('image/png')); + assert_false(ClipboardItem.supports('web ')); + assert_false(ClipboardItem.supports('web')); // without space. + assert_false(ClipboardItem.supports('web foo')); + assert_false(ClipboardItem.supports('foo/bar')); + assert_true(ClipboardItem.supports('web foo/bar')); + assert_true(ClipboardItem.supports('web text/html')); + assert_false(ClipboardItem.supports('image/svg+xml')); + assert_false(ClipboardItem.supports('not a/real type')); +}, "supports(DOMString) returns true for types that are supported, false otherwise"); </script> diff --git a/tests/wpt/tests/close-watcher/closewatcher-dialog-popover.html b/tests/wpt/tests/close-watcher/closewatcher-dialog-popover.html index f6443c4317e..50d5cb7a4ca 100644 --- a/tests/wpt/tests/close-watcher/closewatcher-dialog-popover.html +++ b/tests/wpt/tests/close-watcher/closewatcher-dialog-popover.html @@ -6,6 +6,7 @@ <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-vendor.js"></script> <script src="/resources/testdriver-actions.js"></script> +<script src="/common/top-layer.js"></script> <script src="resources/helpers.js"></script> <button id=b0>button</button> @@ -73,19 +74,22 @@ promise_test(async t => { assert_true(dialog.hasAttribute('open'), 'The dialog should be open.'); assert_true(popover.matches(':popover-open'), 'The popover should be open.'); - await dialogResilientBless(popover, () => sendCloseRequest()); + await blessTopLayer(popover); + await sendCloseRequest(); await waitForPotentialCloseEvent(); assert_false(popover.matches(':popover-open'), 'First close request: The popover should be closed.'); assert_true(dialog.hasAttribute('open'), 'First close request: The dialog should be open.'); assert_array_equals(events, []); - await dialogResilientBless(dialog, () => sendCloseRequest()); + await blessTopLayer(dialog); + await sendCloseRequest(); await waitForPotentialCloseEvent(); assert_false(popover.matches(':popover-open'), 'Second close request: The popover should be closed.'); assert_false(dialog.hasAttribute('open'), 'Second close request: The dialog should be closed.'); assert_array_equals(events, ['dialog cancel', 'dialog close']); - await dialogResilientBless(closeWatcher, () => sendCloseRequest()); + await test_driver.bless(); + await sendCloseRequest(); await waitForPotentialCloseEvent(); assert_false(popover.matches(':popover-open'), 'Third close request: The popover should be closed.'); assert_false(dialog.hasAttribute('open'), 'Third close request: The dialog should be closed.'); diff --git a/tests/wpt/tests/close-watcher/dialog-cancel-events-closewatcher.html b/tests/wpt/tests/close-watcher/dialog-cancel-events-closewatcher.html deleted file mode 100644 index 5b1da9a2e37..00000000000 --- a/tests/wpt/tests/close-watcher/dialog-cancel-events-closewatcher.html +++ /dev/null @@ -1,55 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title>Test cancel event is fired when the dialog is closed by user interaction</title> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="/resources/testdriver.js"></script> - <script src="/resources/testdriver-vendor.js"></script> - <link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=227534"> - <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322947"> -</head> -<body> -<p>Test cancel event is fired when the dialog is closed by user interaction</p> -<dialog> - <p>Hello World</p> - <button>user activation button</button> -</dialog> -<script> - setup({ single_test: true }); - - var hasCancelEventFired = false; - var hasCloseEventFired = false; - - const dialog = document.querySelector("dialog"); - - dialog.addEventListener("cancel", function(event) { - assert_true(true, "cancel event is fired"); - assert_true(event.cancelable, "cancel event should be cancelable"); - assert_false(hasCancelEventFired, "cancel event should only be fired once"); - assert_false(hasCloseEventFired, "close event should be fired after cancel event"); - hasCancelEventFired = true; - }); - - dialog.addEventListener("close", function() { - assert_true(true, "close event is fired"); - assert_false(hasCloseEventFired, "close event should only be fired once"); - assert_true(hasCancelEventFired, "cancel event should be fired before close event"); - hasCloseEventFired = true; - done(); - }); - - dialog.showModal(); - - (async () => { - // Pressing escape on the dialog needs user activation or else the cancel event won't be fired. - const button = dialog.querySelector('button'); - const buttonClickPromise = new Promise(resolve => button.onclick = resolve); - await test_driver.click(button); - await buttonClickPromise; - - test_driver.send_keys(document.documentElement, "\uE00C"); // ESC key - })(); -</script> -</body> -</html> diff --git a/tests/wpt/tests/close-watcher/dialog-cancel-preventDefault-closewatcher.html b/tests/wpt/tests/close-watcher/dialog-cancel-preventDefault-closewatcher.html deleted file mode 100644 index ef99578ca97..00000000000 --- a/tests/wpt/tests/close-watcher/dialog-cancel-preventDefault-closewatcher.html +++ /dev/null @@ -1,55 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title>Test cancel event with preventDefault on cancel event for dialog element</title> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="/resources/testdriver.js"></script> - <script src="/resources/testdriver-vendor.js"></script> - <link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=227534"> - <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322947"> -</head> -<body> -<p>Test cancel event with preventDefault on cancel event for dialog element</p> -<dialog> - <p>Hello World</p> - <button>user activation button</button> -</dialog> -<script> - setup({ single_test: true }); - - var hasCancelEventFired = false; - - const dialog = document.querySelector("dialog"); - - const verify = () => { - assert_true(hasCancelEventFired, "cancel is fired"); - done(); - }; - - dialog.addEventListener("cancel", function(event) { - hasCancelEventFired = true; - event.preventDefault(); - step_timeout(function() { - verify(); - }, 0) - }); - - dialog.addEventListener("close", function() { - assert_true(false, "close event should not be fired"); - }); - - dialog.showModal(); - - (async () => { - // Pressing escape on the dialog needs user activation or else the cancel event won't be fired. - const button = dialog.querySelector('button'); - const buttonClickPromise = new Promise(resolve => button.onclick = resolve); - await test_driver.click(button); - await buttonClickPromise; - - test_driver.send_keys(document.documentElement, "\uE00C"); // ESC key - })(); -</script> -</body> -</html> diff --git a/tests/wpt/tests/close-watcher/resources/helpers.js b/tests/wpt/tests/close-watcher/resources/helpers.js index c4c8c5b0326..97a62309cd5 100644 --- a/tests/wpt/tests/close-watcher/resources/helpers.js +++ b/tests/wpt/tests/close-watcher/resources/helpers.js @@ -1,11 +1,11 @@ -window.createRecordingCloseWatcher = (t, events, name, type, parent) => { +window.createRecordingCloseWatcher = (t, events, name, type, parentWatcher) => { let watcher = null; if (type === 'dialog') { watcher = document.createElement('dialog'); watcher.textContent = 'hello world'; t.add_cleanup(() => watcher.remove()); - if (parent) { - parent.appendChild(watcher); + if (parentWatcher?.appendChild) { + parentWatcher.appendChild(watcher); } else { document.body.appendChild(watcher); } @@ -15,8 +15,8 @@ window.createRecordingCloseWatcher = (t, events, name, type, parent) => { watcher.setAttribute('popover', 'auto'); watcher.textContent = 'hello world'; t.add_cleanup(() => watcher.remove()); - if (parent) { - parent.appendChild(watcher); + if (parentWatcher?.appendChild) { + parentWatcher.appendChild(watcher); } else { document.body.appendChild(watcher); } @@ -33,8 +33,9 @@ window.createRecordingCloseWatcher = (t, events, name, type, parent) => { return watcher; }; -window.createBlessedRecordingCloseWatcher = async (t, events, name, type, dialog) => { - return dialogResilientBless(dialog, () => createRecordingCloseWatcher(t, events, name, type, dialog)); +window.createBlessedRecordingCloseWatcher = async (t, events, name, type, parentWatcher) => { + await maybeTopLayerBless(parentWatcher); + return createRecordingCloseWatcher(t, events, name, type, parentWatcher); }; window.sendEscKey = () => { @@ -52,20 +53,9 @@ window.sendEscKey = () => { // function, but not update the sendEscKey function above. window.sendCloseRequest = window.sendEscKey; -// This function is a version of test_driver.bless which works on dialog elements: -// https://github.com/web-platform-tests/wpt/issues/41218 -window.dialogResilientBless = async (watcher, fn) => { +window.maybeTopLayerBless = (watcher) => { if (watcher instanceof HTMLElement) { - const button = document.createElement('button'); - watcher.appendChild(button); - await test_driver.click(button); - button.remove(); - if (typeof fn === 'function') { - return fn(); - } else { - return null; - } - } else { - return await test_driver.bless('dialogResilientBless', fn); + return blessTopLayer(watcher); } + return test_driver.bless(); }; diff --git a/tests/wpt/tests/close-watcher/user-activation-shared.html b/tests/wpt/tests/close-watcher/user-activation-shared.html index 6ecc2dc694d..77e748532a3 100644 --- a/tests/wpt/tests/close-watcher/user-activation-shared.html +++ b/tests/wpt/tests/close-watcher/user-activation-shared.html @@ -6,6 +6,7 @@ <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-vendor.js"></script> <script src="/resources/testdriver-actions.js"></script> +<script src="/common/top-layer.js"></script> <script src="resources/helpers.js"></script> <body> @@ -22,7 +23,8 @@ promise_test(async t => { const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type); freeWatcher.addEventListener("cancel", e => e.preventDefault()); - await dialogResilientBless(freeWatcher, () => freeWatcher.close()); + await maybeTopLayerBless(freeWatcher); + freeWatcher.close(); await waitForPotentialCloseEvent(); assert_array_equals(events, ["freeWatcher close"]); @@ -32,7 +34,8 @@ promise_test(async t => { const events = []; const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type); - await dialogResilientBless(freeWatcher, () => sendCloseRequest()); + await maybeTopLayerBless(freeWatcher); + await sendCloseRequest(); await waitForPotentialCloseEvent(); assert_array_equals(events, ["freeWatcher cancel", "freeWatcher close"]); @@ -43,7 +46,8 @@ promise_test(async t => { const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type); freeWatcher.addEventListener("cancel", e => e.preventDefault()); - await dialogResilientBless(freeWatcher, () => sendCloseRequest()); + await maybeTopLayerBless(freeWatcher); + await sendCloseRequest(); await waitForPotentialCloseEvent(); assert_array_equals(events, ["freeWatcher cancel"]); @@ -79,11 +83,13 @@ promise_test(async t => { const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type); const activationWatcher = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher", type, freeWatcher); - await dialogResilientBless(activationWatcher, () => sendCloseRequest()); + await maybeTopLayerBless(activationWatcher); + await sendCloseRequest(); await waitForPotentialCloseEvent(); assert_array_equals(events, ["activationWatcher cancel", "activationWatcher close"]); - await dialogResilientBless(freeWatcher, () => sendCloseRequest()); + await maybeTopLayerBless(freeWatcher); + await sendCloseRequest(); await waitForPotentialCloseEvent(); assert_array_equals(events, ["activationWatcher cancel", "activationWatcher close", "freeWatcher cancel", "freeWatcher close"]); }, "Creating a close watcher from user activation, and closing close watchers with a close request after user activation, fires cancel"); diff --git a/tests/wpt/tests/common/top-layer.js b/tests/wpt/tests/common/top-layer.js new file mode 100644 index 00000000000..2dc8ce3893a --- /dev/null +++ b/tests/wpt/tests/common/top-layer.js @@ -0,0 +1,29 @@ +// This function is a version of test_driver.bless which works while there are +// elements in the top layer: +// https://github.com/web-platform-tests/wpt/issues/41218. +// Pass it the element at the top of the top layer stack. +window.blessTopLayer = async (topLayerElement) => { + const button = document.createElement('button'); + topLayerElement.append(button); + let wait_click = new Promise(resolve => button.addEventListener("click", resolve, {once: true})); + await test_driver.click(button); + await wait_click; + button.remove(); +}; + +window.isTopLayer = (el) => { + // A bit of a hack. Just test a few properties of the ::backdrop pseudo + // element that change when in the top layer. + const properties = ['right','background']; + const testEl = document.createElement('div'); + document.body.appendChild(testEl); + const computedStyle = getComputedStyle(testEl, '::backdrop'); + const nonTopLayerValues = properties.map(p => computedStyle[p]); + testEl.remove(); + for(let i=0;i<properties.length;++i) { + if (getComputedStyle(el,'::backdrop')[properties[i]] !== nonTopLayerValues[i]) { + return true; + } + } + return false; +}; diff --git a/tests/wpt/tests/content-security-policy/resource-hints/prefetch-generate-directives.html b/tests/wpt/tests/content-security-policy/resource-hints/prefetch-generate-directives.html index b08d885c1ec..75c9485f0d7 100644 --- a/tests/wpt/tests/content-security-policy/resource-hints/prefetch-generate-directives.html +++ b/tests/wpt/tests/content-security-policy/resource-hints/prefetch-generate-directives.html @@ -1,6 +1,7 @@ <!DOCTYPE html> <html> <head> +<meta name="timeout" content="long"> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script> <script src='/common/utils.js'></script> diff --git a/tests/wpt/tests/credential-management/fedcm-hosteddomain.https.html b/tests/wpt/tests/credential-management/fedcm-domainhint.https.html index 5e39542fdef..d8ab79b2c5c 100644 --- a/tests/wpt/tests/credential-management/fedcm-hosteddomain.https.html +++ b/tests/wpt/tests/credential-management/fedcm-domainhint.https.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<title>Federated Credential Management API hosted domain tests.</title> +<title>Federated Credential Management API domain hint tests.</title> <link rel="help" href="https://fedidcg.github.io/FedCM"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -10,40 +10,40 @@ <script type="module"> import { fedcm_test, - request_options_with_hosted_domain, + request_options_with_domain_hint, select_manifest, fedcm_get_and_select_first_account } from './support/fedcm-helper.sub.js'; fedcm_test(async t => { - let options = request_options_with_hosted_domain('manifest.py', + let options = request_options_with_domain_hint('manifest.py', 'nomatch'); const cred = fedcm_get_and_select_first_account(t, options); return promise_rejects_dom(t, "NetworkError", cred); -}, "No hosted domain matches an account."); +}, "No domain hint matches an account."); fedcm_test(async t => { - const options = request_options_with_hosted_domain('manifest.py', + const options = request_options_with_domain_hint('manifest.py', 'idp.example'); const cred = await fedcm_get_and_select_first_account(t, options); assert_equals(cred.token, 'token'); -}, "Hosted domain matches an account."); +}, "Domain hint matches an account."); fedcm_test(async t => { - let options = request_options_with_hosted_domain( + let options = request_options_with_domain_hint( 'manifest_with_two_accounts.json', 'example'); await select_manifest(t, options); const cred = await fedcm_get_and_select_first_account(t, options); assert_equals(cred.token, 'account_id=john_doe'); -}, "Hosted domain matches an account from two accounts."); +}, "Domain hint matches an account from two accounts."); fedcm_test(async t => { - let options = request_options_with_hosted_domain( + let options = request_options_with_domain_hint( 'manifest_with_two_accounts.json', '*'); await select_manifest(t, options); const cred = await fedcm_get_and_select_first_account(t, options); assert_equals(cred.token, 'account_id=john_doe'); -}, "Hosted domain '*' matches an account with any hosted domain."); +}, "Domain hint '*' matches an account with any domain hint."); </script> diff --git a/tests/wpt/tests/credential-management/fedcm-endpoint-redirects.https.html b/tests/wpt/tests/credential-management/fedcm-endpoint-redirects.https.html index 4aebc17f1ba..21d0a5867a7 100644 --- a/tests/wpt/tests/credential-management/fedcm-endpoint-redirects.https.html +++ b/tests/wpt/tests/credential-management/fedcm-endpoint-redirects.https.html @@ -24,7 +24,13 @@ fedcm_test(async t => { let test_options = request_options_with_mediation_required("manifest_redirect_token.json"); await select_manifest(t, test_options); - const cred = fedcm_get_and_select_first_account(t, test_options); - return promise_rejects_dom(t, 'NetworkError', cred); + try { + const cred = await fedcm_get_and_select_first_account(t, test_options); + assert_unreached("An IdentityCredentialError exception should be thrown."); + } catch (e) { + assert_true(e instanceof DOMException); + assert_equals(e.name, "IdentityCredentialError"); + assert_equals(e.code, "server_error"); + } }, 'Test that token endpoint does not follow redirects'); </script> diff --git a/tests/wpt/tests/credential-management/fedcm-error-basic.https.html b/tests/wpt/tests/credential-management/fedcm-error-basic.https.html new file mode 100644 index 00000000000..18ab82d0bd7 --- /dev/null +++ b/tests/wpt/tests/credential-management/fedcm-error-basic.https.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>Federated Credential Management API Error API tests.</title> +<link rel="help" href="https://fedidcg.github.io/FedCM"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<script type="module"> +import {request_options_with_mediation_required, + fedcm_test, + manifest_origin, + select_manifest, + fedcm_get_and_select_first_account} from './support/fedcm-helper.sub.js'; + +const url_prefix = manifest_origin + '/credential-management/support/fedcm/'; + +fedcm_test(async t => { + let test_options = + request_options_with_mediation_required("manifest_id_assertion_endpoint_returns_error.json"); + await select_manifest(t, test_options); + + try { + const cred = await fedcm_get_and_select_first_account(t, test_options); + assert_unreached("An IdentityCredentialError exception should be thrown."); + } catch (e) { + assert_true(e instanceof DOMException); + assert_equals(e.name, "IdentityCredentialError"); + assert_equals(e.code, "unauthorized_client"); + assert_equals(e.url, url_prefix + "error.html"); + } +}, 'Test that the promise is rejected with proper error details'); + +</script> diff --git a/tests/wpt/tests/credential-management/fedcm-login-status/cross-origin-status.https.html b/tests/wpt/tests/credential-management/fedcm-login-status/cross-origin-status.https.html index 7c839306a47..09a4aa31c6b 100644 --- a/tests/wpt/tests/credential-management/fedcm-login-status/cross-origin-status.https.html +++ b/tests/wpt/tests/credential-management/fedcm-login-status/cross-origin-status.https.html @@ -10,6 +10,7 @@ import {fedcm_test, alt_manifest_origin, alt_request_options_with_mediation_required, + open_and_wait_for_popup, mark_signed_out} from '../support/fedcm-helper.sub.js'; const url_prefix = alt_manifest_origin + '/credential-management/support/'; @@ -53,5 +54,14 @@ fedcm_test(async t => { return promise_rejects_dom(t, 'NetworkError', result); }, 'Status header should be ignored from cross-origin iframe that contains a subresource with the header'); +fedcm_test(async t => { + await mark_signed_out(alt_manifest_origin); + await open_and_wait_for_popup(alt_manifest_origin, "/credential-management/support/fencedframe-mark-signedin.html"); + + const config = alt_request_options_with_mediation_required(); + const result = navigator.credentials.get(config); + return promise_rejects_dom(t, 'NetworkError', result); +}, 'Status header should be ignored from a fenced frame, even if it is same-origin'); + </script> diff --git a/tests/wpt/tests/credential-management/fedcm-store.https.html b/tests/wpt/tests/credential-management/fedcm-store.https.html new file mode 100644 index 00000000000..d1e6ef464c4 --- /dev/null +++ b/tests/wpt/tests/credential-management/fedcm-store.https.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Federated Credential Management API store() tests.</title> +<link rel="help" href="https://fedidcg.github.io/FedCM"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<script type="module"> +import {fedcm_test, + request_options_with_mediation_required, + fedcm_get_and_select_first_account} from "./support/fedcm-helper.sub.js"; + +fedcm_test(async t => { + const cred = await fedcm_get_and_select_first_account(t, request_options_with_mediation_required()); + return promise_rejects_dom(t, "NotSupportedError", navigator.credentials.store(cred)); +}, "navigator.credentials.store() with an identity credential returns NotSupportedError"); + +</script> diff --git a/tests/wpt/tests/credential-management/fedcm-token-returned-with-http-error.https.html b/tests/wpt/tests/credential-management/fedcm-token-returned-with-http-error.https.html new file mode 100644 index 00000000000..2337829add9 --- /dev/null +++ b/tests/wpt/tests/credential-management/fedcm-token-returned-with-http-error.https.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<title>Federated Credential Management API token response tests</title> +<link rel="help" href="https://fedidcg.github.io/FedCM"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<script type="module"> +import {request_options_with_mediation_required, + fedcm_test, + select_manifest, + fedcm_get_and_select_first_account} from './support/fedcm-helper.sub.js'; + +fedcm_test(async t => { + const test_options = + request_options_with_mediation_required("manifest_token_with_http_error.json"); + await select_manifest(t, test_options); + + const cred = fedcm_get_and_select_first_account(t, test_options); + return promise_rejects_dom(t, 'NetworkError', cred); +}, 'Test that the promise will be rejected if the response has http error'); +</script> diff --git a/tests/wpt/tests/credential-management/otpcredential-store.https.html b/tests/wpt/tests/credential-management/otpcredential-store.https.html new file mode 100644 index 00000000000..fa2ae8933d3 --- /dev/null +++ b/tests/wpt/tests/credential-management/otpcredential-store.https.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<link rel="help" href="https://github.com/WICG/WebOTP"> +<title>Tests OTPCredential handing of store()</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module"> +import {Status, expectOTPRequest} from "./support/otpcredential-helper.js"; + +promise_test(async t => { + await expectOTPRequest().andReturn( + () => ({status: Status.SUCCESS, otp: "ABC"})); + + const cred = await navigator.credentials.get({otp: {transport: ["sms"]}}); + return promise_rejects_dom(t, "NotSupportedError", navigator.credentials.store(cred)); +}, "navigator.credentials.store() with an otp credential returns NotSupportedError"); + +</script> diff --git a/tests/wpt/tests/credential-management/support/fedcm-helper.sub.js b/tests/wpt/tests/credential-management/support/fedcm-helper.sub.js index ef10e41793a..f02a76b3fe2 100644 --- a/tests/wpt/tests/credential-management/support/fedcm-helper.sub.js +++ b/tests/wpt/tests/credential-management/support/fedcm-helper.sub.js @@ -1,31 +1,31 @@ -const manifest_origin = "https://{{host}}:{{ports[https][0]}}"; +export const manifest_origin = "https://{{host}}:{{ports[https][0]}}"; export const alt_manifest_origin = 'https://{{hosts[alt][]}}:{{ports[https][0]}}'; -function open_and_wait_for_popup(origin, path, resolve) { - let popup_window = window.open(origin + path); +export function open_and_wait_for_popup(origin, path) { + return new Promise(resolve => { + let popup_window = window.open(origin + path); - // We rely on the popup page to send us a message when done. - const popup_message_handler = (event) => { - if (event.origin == origin) { - popup_window.close(); - window.removeEventListener('message', popup_message_handler); - resolve(); - } - }; + // We rely on the popup page to send us a message when done. + const popup_message_handler = (event) => { + if (event.origin == origin) { + popup_window.close(); + window.removeEventListener('message', popup_message_handler); + resolve(); + } + }; - window.addEventListener('message', popup_message_handler); + window.addEventListener('message', popup_message_handler); + }); } // Set the identity provider cookie. export function set_fedcm_cookie(host) { - return new Promise(resolve => { - if (host == undefined) { - document.cookie = 'cookie=1; SameSite=Strict; Path=/credential-management/support; Secure'; - resolve(); - } else { - open_and_wait_for_popup(host, '/credential-management/support/set_cookie', resolve); - } - }); + if (host == undefined) { + document.cookie = 'cookie=1; SameSite=Strict; Path=/credential-management/support; Secure'; + return Promise.resolve(); + } else { + return open_and_wait_for_popup(host, '/credential-management/support/set_cookie'); + } } // Set the alternate identity provider cookie. @@ -34,15 +34,11 @@ export function set_alt_fedcm_cookie() { } export function mark_signed_in(origin = manifest_origin) { - return new Promise(resolve => { - open_and_wait_for_popup(origin, '/credential-management/support/mark_signedin', resolve); - }); + return open_and_wait_for_popup(origin, '/credential-management/support/mark_signedin'); } export function mark_signed_out(origin = manifest_origin) { - return new Promise(resolve => { - open_and_wait_for_popup(origin, '/credential-management/support/mark_signedout', resolve); - }); + return open_and_wait_for_popup(origin, '/credential-management/support/mark_signedout'); } // Returns FedCM CredentialRequestOptions for which navigator.credentials.get() @@ -156,9 +152,9 @@ export function request_options_with_login_hint(manifest_filename, login_hint) { return options; } -export function request_options_with_hosted_domain(manifest_filename, hosted_domain) { +export function request_options_with_domain_hint(manifest_filename, domain_hint) { let options = request_options_with_mediation_required(manifest_filename); - options.identity.providers[0].hostedDomain = hosted_domain; + options.identity.providers[0].domainHint = domain_hint; return options; } diff --git a/tests/wpt/tests/credential-management/support/fedcm-mock.js b/tests/wpt/tests/credential-management/support/fedcm-mock.js index 16a72b1d2c3..b14bbaa80a7 100644 --- a/tests/wpt/tests/credential-management/support/fedcm-mock.js +++ b/tests/wpt/tests/credential-management/support/fedcm-mock.js @@ -1,4 +1,4 @@ -import { RequestTokenStatus, LogoutRpsStatus, FederatedAuthRequest, FederatedAuthRequestReceiver } from '/gen/third_party/blink/public/mojom/webid/federated_auth_request.mojom.m.js'; +import { RequestTokenStatus, LogoutRpsStatus, RevokeStatus, FederatedAuthRequest, FederatedAuthRequestReceiver } from '/gen/third_party/blink/public/mojom/webid/federated_auth_request.mojom.m.js'; function toMojoTokenStatus(status) { return RequestTokenStatus["k" + status]; @@ -17,6 +17,7 @@ export class MockFederatedAuthRequest { this.selected_identity_provider_config_url_ = null; this.status_ = RequestTokenStatus.kError; this.logoutRpsStatus_ = LogoutRpsStatus.kError; + this.revokeStatus_ = RevokeStatus.kError; this.returnPending_ = false; this.pendingPromiseResolve_ = null; } @@ -52,6 +53,15 @@ export class MockFederatedAuthRequest { this.logoutRpsStatus_ = validated; } + // Causes the subsequent `FederatedCredential.revoke` to reject with this + // status. + revokeReturn(status) { + let validated = RevokeStatus[status]; + if (validated === undefined) + throw new Error("Invalid status: " + status); + this.revokeStatus_ = validated; + } + // Implements // RequestToken(array<IdentityProviderGetParameters> idp_get_params) => // (RequestTokenStatus status, @@ -96,6 +106,12 @@ export class MockFederatedAuthRequest { }); } + async revoke(provider, client_id, account_id) { + return Promise.resolve({ + status: this.revokeStatus_ + }); + } + async setIdpSigninStatus(origin, status) { } @@ -119,6 +135,7 @@ export class MockFederatedAuthRequest { this.selected_identity_provider_config_url_ = null; this.status_ = RequestTokenStatus.kError; this.logoutRpsStatus_ = LogoutRpsStatus.kError; + this.revokeStatus_ = RevokeStatus.kError; this.receiver_.$.close(); this.interceptor_.stop(); diff --git a/tests/wpt/tests/credential-management/support/fedcm/accounts.py b/tests/wpt/tests/credential-management/support/fedcm/accounts.py index 3989de7f17c..126f911a58c 100644 --- a/tests/wpt/tests/credential-management/support/fedcm/accounts.py +++ b/tests/wpt/tests/credential-management/support/fedcm/accounts.py @@ -18,7 +18,7 @@ def main(request, response): "picture": "https://idp.example/profile/123", "approved_clients": ["123", "456", "789"], "login_hints": ["john_doe"], - "hosted_domains": ["idp.example", "example"] + "domain_hints": ["idp.example", "example"] }] } """ diff --git a/tests/wpt/tests/credential-management/support/fedcm/error_with_code_and_url.py b/tests/wpt/tests/credential-management/support/fedcm/error_with_code_and_url.py new file mode 100644 index 00000000000..71bfea00f46 --- /dev/null +++ b/tests/wpt/tests/credential-management/support/fedcm/error_with_code_and_url.py @@ -0,0 +1,12 @@ +import importlib +error_checker = importlib.import_module("credential-management.support.fedcm.request-params-check") + +def main(request, response): + request_error = error_checker.tokenCheck(request) + if (request_error): + return request_error + + response.headers.set(b"Content-Type", b"application/json") + response.status = (401, b"Unauthorized") + + return "{\"error\": {\"code\": \"unauthorized_client\", \"url\": \"error.html\"}}" diff --git a/tests/wpt/tests/credential-management/support/fedcm/manifest_id_assertion_endpoint_returns_error.json b/tests/wpt/tests/credential-management/support/fedcm/manifest_id_assertion_endpoint_returns_error.json new file mode 100644 index 00000000000..e098cc4511a --- /dev/null +++ b/tests/wpt/tests/credential-management/support/fedcm/manifest_id_assertion_endpoint_returns_error.json @@ -0,0 +1,6 @@ +{ + "accounts_endpoint": "accounts.py", + "client_metadata_endpoint": "client_metadata.py", + "id_assertion_endpoint": "error_with_code_and_url.py", + "login_url": "login.html" +} diff --git a/tests/wpt/tests/credential-management/support/fedcm/manifest_token_with_http_error.json b/tests/wpt/tests/credential-management/support/fedcm/manifest_token_with_http_error.json new file mode 100644 index 00000000000..691a1e8d3a6 --- /dev/null +++ b/tests/wpt/tests/credential-management/support/fedcm/manifest_token_with_http_error.json @@ -0,0 +1,6 @@ +{ + "accounts_endpoint": "accounts.py", + "client_metadata_endpoint": "client_metadata.py", + "id_assertion_endpoint": "token_with_http_error.py", + "login_url": "login.html" +} diff --git a/tests/wpt/tests/credential-management/support/fedcm/token_with_http_error.py b/tests/wpt/tests/credential-management/support/fedcm/token_with_http_error.py new file mode 100644 index 00000000000..c8d95ab63d7 --- /dev/null +++ b/tests/wpt/tests/credential-management/support/fedcm/token_with_http_error.py @@ -0,0 +1,12 @@ +import importlib +error_checker = importlib.import_module("credential-management.support.fedcm.request-params-check") + +def main(request, response): + request_error = error_checker.tokenCheck(request) + if (request_error): + return request_error + + response.headers.set(b"Content-Type", b"application/json") + response.status = (403, b"Forbidden") + + return "{\"token\": \"token\"}" diff --git a/tests/wpt/tests/credential-management/support/fedcm/two_accounts.py b/tests/wpt/tests/credential-management/support/fedcm/two_accounts.py index 4ea6d76a7eb..4022561ff78 100644 --- a/tests/wpt/tests/credential-management/support/fedcm/two_accounts.py +++ b/tests/wpt/tests/credential-management/support/fedcm/two_accounts.py @@ -27,7 +27,7 @@ def main(request, response): "picture": "https://idp.example/profile/123", "approved_clients": ["123", "456", "789"], "login_hints": ["john_doe"], - "hosted_domains": ["idp.example", "example"] + "domain_hints": ["idp.example", "example"] } ] } diff --git a/tests/wpt/tests/credential-management/support/fencedframe-mark-signedin.html b/tests/wpt/tests/credential-management/support/fencedframe-mark-signedin.html new file mode 100644 index 00000000000..532db7047a8 --- /dev/null +++ b/tests/wpt/tests/credential-management/support/fencedframe-mark-signedin.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>A page that uses fencedframe to set the login status to signed in</title> + +<fencedframe></fencedframe> +<script> +const url = new URL("mark_signedin", location.href); +document.querySelector("fencedframe").config = new FencedFrameConfig(url); + +// If this page was opened as a popup, notify the opener when we are done loading. +if (window.opener) { + window.onload = function() { + window.opener.postMessage("done_loading", "*"); + }; +} +</script> diff --git a/tests/wpt/tests/credential-management/support/iframe-mark-signedin.html b/tests/wpt/tests/credential-management/support/iframe-mark-signedin.html new file mode 100644 index 00000000000..4ca0125cde2 --- /dev/null +++ b/tests/wpt/tests/credential-management/support/iframe-mark-signedin.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<title>A page that includes mark_signedin, for use in an iframe</title> + +<img src="mark_signedin"> diff --git a/tests/wpt/tests/credential-management/support/mark_signedin.sub.headers b/tests/wpt/tests/credential-management/support/mark_signedin.sub.headers index b87b36fa3b3..d560fade5a0 100644 --- a/tests/wpt/tests/credential-management/support/mark_signedin.sub.headers +++ b/tests/wpt/tests/credential-management/support/mark_signedin.sub.headers @@ -2,3 +2,4 @@ Content-Type: text/html Set-Login: logged-in Access-Control-Allow-Origin: https://{{host}}:{{ports[https][0]}} Access-Control-Allow-Credentials: true +Supports-Loading-Mode: fenced-frame diff --git a/tests/wpt/tests/credential-management/support/mark_signedout.sub.headers b/tests/wpt/tests/credential-management/support/mark_signedout.sub.headers index 46a8c34b218..69157b3a371 100644 --- a/tests/wpt/tests/credential-management/support/mark_signedout.sub.headers +++ b/tests/wpt/tests/credential-management/support/mark_signedout.sub.headers @@ -2,3 +2,4 @@ Content-Type: text/html Set-Login: logged-out Access-Control-Allow-Origin: https://{{host}}:{{ports[https][0]}} Access-Control-Allow-Credentials: true +Supports-Loading-Mode: fenced-frame diff --git a/tests/wpt/tests/css/css-color/lch-009.html b/tests/wpt/tests/css/css-color/lch-009.html index 472e7c138f7..375fd08de58 100644 --- a/tests/wpt/tests/css/css-color/lch-009.html +++ b/tests/wpt/tests/css/css-color/lch-009.html @@ -7,10 +7,10 @@ <meta name="assert" content="lch() with no alpha"> <style> body { background-color: grey; } - .test { background-color: hsl(47, 100%, 63%); width: 12em; height: 12em; } + .test { background-color: hsl(0, 100%, 63%); width: 12em; height: 12em; } .test { background-color: lch(100% 110 60); } /* l = 100% should always be white */ </style> <body> - <p>Test passes if you see a white square, and no yellow.</p> + <p>Test passes if you see a white square, and no red.</p> <div class="test"></div> </body> diff --git a/tests/wpt/tests/css/css-color/lch-010.html b/tests/wpt/tests/css/css-color/lch-010.html index 527e9cc7aff..965e05ff5dc 100644 --- a/tests/wpt/tests/css/css-color/lch-010.html +++ b/tests/wpt/tests/css/css-color/lch-010.html @@ -6,10 +6,10 @@ <link rel="match" href="blacksquare-ref.html"> <meta name="assert" content="lch() with no alpha"> <style> - .test { background-color: hsl(360, 100%, 15%); width: 12em; height: 12em; } + .test { background-color: hsl(0, 100%, 63%); width: 12em; height: 12em; } .test { background-color: lch(0% 110 60); } /* l = 0% should always be black */ </style> <body> - <p>Test passes if you see a black square, and no dark red.</p> + <p>Test passes if you see a black square, and no red.</p> <div class="test"></div> </body> diff --git a/tests/wpt/tests/css/css-color/nested-color-mix-with-currentcolor.html b/tests/wpt/tests/css/css-color/nested-color-mix-with-currentcolor.html index a4dd687dd58..2f24d62b547 100644 --- a/tests/wpt/tests/css/css-color/nested-color-mix-with-currentcolor.html +++ b/tests/wpt/tests/css/css-color/nested-color-mix-with-currentcolor.html @@ -19,6 +19,6 @@ </div> <script> test(() => { - assert_equals(getComputedStyle(child).backgroundColor, "lch(0 0 0)"); + assert_equals(getComputedStyle(child).backgroundColor, "lch(0 0 none)"); }, "Nested color-mix function with inner currentColor should inherit unresolved"); </script> diff --git a/tests/wpt/tests/css/css-color/oklch-009.html b/tests/wpt/tests/css/css-color/oklch-009.html index 5a4924a7e28..1882c476c1c 100644 --- a/tests/wpt/tests/css/css-color/oklch-009.html +++ b/tests/wpt/tests/css/css-color/oklch-009.html @@ -8,10 +8,10 @@ <meta name="assert" content="oklch() with no alpha"> <style> body { background-color: grey; } - .test { background-color: hsl(120, 100%, 50%); width: 12em; height: 12em; } + .test { background-color: hsl(0, 100%, 50%); width: 12em; height: 12em; } .test { background-color: oklch(100% 110 60); } /* l = 100% should always be white */ </style> <body> - <p>Test passes if you see a white square, and no green.</p> + <p>Test passes if you see a white square, and no red.</p> <div class="test"></div> </body> diff --git a/tests/wpt/tests/css/css-color/oklch-010.html b/tests/wpt/tests/css/css-color/oklch-010.html index 091b760bea2..b5f9ac206b4 100644 --- a/tests/wpt/tests/css/css-color/oklch-010.html +++ b/tests/wpt/tests/css/css-color/oklch-010.html @@ -7,10 +7,10 @@ <link rel="match" href="blacksquare-ref.html"> <meta name="assert" content="oklch() with no alpha"> <style> - .test { background-color: hsl(120, 100%, 50%); width: 12em; height: 12em; } + .test { background-color: hsl(0, 100%, 50%); width: 12em; height: 12em; } .test { background-color: oklch(0% 1.1 60); } /* l = 0% should always be black */ </style> <body> - <p>Test passes if you see a black square, and no green.</p> + <p>Test passes if you see a black square, and no red.</p> <div class="test"></div> </body> diff --git a/tests/wpt/tests/css/css-color/parsing/color-computed-color-mix-function.html b/tests/wpt/tests/css/css-color/parsing/color-computed-color-mix-function.html index a48d6b20bcd..cd5837d8b28 100644 --- a/tests/wpt/tests/css/css-color/parsing/color-computed-color-mix-function.html +++ b/tests/wpt/tests/css/css-color/parsing/color-computed-color-mix-function.html @@ -77,7 +77,7 @@ fuzzy_test_computed_color(`color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))`, `color(srgb 0.75 0.25 0.333333)`); fuzzy_test_computed_color(`color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))`, `color(srgb 0.25 0.75 0.666667)`); - fuzzy_test_computed_color(`color-mix(in hsl, hsl(none none none), hsl(none none none))`, `color(srgb none none none)`); + fuzzy_test_computed_color(`color-mix(in hsl, hsl(none none none), hsl(none none none))`, `color(srgb 0 0 0)`); fuzzy_test_computed_color(`color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))`, `color(srgb 0.88 0.8 0.72)`); fuzzy_test_computed_color(`color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))`, `color(srgb 0.32 0.48 0.32)`); fuzzy_test_computed_color(`color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))`, `color(srgb 0.66 0.72 0.48)`); @@ -149,7 +149,7 @@ fuzzy_test_computed_color(`color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))`, `color(srgb 0.6 0.3 0.35)`); fuzzy_test_computed_color(`color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))`, `color(srgb 0.3 0.6 0.55)`); - fuzzy_test_computed_color(`color-mix(in hwb, hwb(none none none), hwb(none none none))`, `color(srgb none none none)`); + fuzzy_test_computed_color(`color-mix(in hwb, hwb(none none none), hwb(none none none))`, `color(srgb 1 0 0)`); fuzzy_test_computed_color(`color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))`, `color(srgb 0.6 0.45 0.3)`); fuzzy_test_computed_color(`color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))`, `color(srgb 0.1 0.8 0.1)`); fuzzy_test_computed_color(`color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))`, `color(srgb 0.5 0.6 0.2)`); diff --git a/tests/wpt/tests/css/css-color/system-color-support.html b/tests/wpt/tests/css/css-color/system-color-support.html new file mode 100644 index 00000000000..a17ab6ab6ee --- /dev/null +++ b/tests/wpt/tests/css/css-color/system-color-support.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="utf-8"> + <title>CSS Color 4: System color support</title> + <link rel="author" title="Luuk Lamers" href="mailto:xaddict@protonmail.com"> + <link rel="help" href="https://www.w3.org/TR/css-color-4/#css-system-colors"> + <meta name="assert" content="system colors as defined are supported by the browser"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <style> + .group { + display: flex; + margin-bottom: 2px; + gap: 1em; + } + .group > div { + height: 1em; + width: 50%; + } + </style> +</head> +<body> + <div style="display: none"> + <div id="test"></div> + </div> + <script> + const testRoot = document.getElementById('test') + const systemColors = [ + 'Canvas', + 'CanvasText', + 'LinkText', + 'VisitedText', + 'ActiveText', + 'ButtonFace', + 'ButtonText', + 'ButtonBorder', + 'Field', + 'FieldText', + 'Highlight', + 'HighlightText', + 'SelectedItem', + 'SelectedItemText', + 'Mark', + 'MarkText', + 'GrayText', + 'AccentColor', + 'AccentColorText' + ] + + systemColors.forEach(systemColor => { + const testGroup = document.createElement('div') + testGroup.id = systemColor + testGroup.className = 'group' + testGroup.innerHTML = ` + <div style="background-color: black; background-color: ${systemColor}"></div> + <div style="background-color: white; background-color: ${systemColor}"></div>` + testRoot.appendChild(testGroup) + }) + + systemColors.forEach(systemColor => { + let group = document.getElementById(systemColor) + let blackElement = group.firstElementChild + let whiteElement = group.lastElementChild + test(function() { + let blackValue = getComputedStyle(blackElement).getPropertyValue('background-color'); + let whiteValue = getComputedStyle(whiteElement).getPropertyValue('background-color'); + assert_equals(blackValue, whiteValue); + }, `System color ${systemColor} works`); + }) + </script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a-ref.html b/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a-ref.html deleted file mode 100644 index fb906237b23..00000000000 --- a/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a-ref.html +++ /dev/null @@ -1,12 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Reference</title> -<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> -<style> - .test { font-family: Ahem; color: rgb(102, 102, 102); } -</style> -<body> - <p>The test passes if the two lines below look identical:</p> - <p class="test">This text should be the same color as the line below.</p> - <p class="test">This text should be the same color as the line above.</p> -</body> diff --git a/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a-ref.xht b/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a-ref.xht new file mode 100644 index 00000000000..ae463485065 --- /dev/null +++ b/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a-ref.xht @@ -0,0 +1,18 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>CSS Test: rgba() colors</title> + <link rel="author" title="L. David Baron" href="https://dbaron.org/" /> + <link rel="author" title="Chris Lilley" href="https://svgees.us" /> + <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" /> + <style type="text/css"><![CDATA[ + html, body { background: white; color: black; } + #one, #two { width: 12em; height: 12em; } + #one { background-color: rgb(102, 102, 102); margin-bottom: 0 } + ]]></style> + </head> + <body> + <p>The test passes if you see a gray square:</p> + <p id="one"></p> + </body> +</html> diff --git a/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a.xht b/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a.xht index 3687d5392e3..541964f8d61 100644 --- a/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a.xht +++ b/tests/wpt/tests/css/css-color/t32-opacity-basic-0.6-a.xht @@ -6,19 +6,18 @@ <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" /> <link rel="help" href="http://www.w3.org/TR/css3-color/#transparency" /> <link rel="help" href="http://www.w3.org/TR/css3-color/#rgb-color" /> - <link rel="match" href="t32-opacity-basic-0.6-a-ref.html" /> - <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <link rel="match" href="t32-opacity-basic-0.6-a-ref.xht" /> <meta name="assert" content="Opacity of 0.6 makes box partially opaque. Colors are in sRGB color space (may test)." /> <style type="text/css"><![CDATA[ html, body { background: white; color: black; } - #one, #two { font-family: Ahem; } - #one { color: rgb(102, 102, 102); } + #one, #two { width: 12em; height: 12em; } + #one { background-color: rgb(102, 102, 102); } #two { opacity: 0.6; } ]]></style> </head> <body> - <p>The test passes if the two lines below look identical:</p> - <p id="one">This text should be the same color as the line below.</p> - <p id="two">This text should be the same color as the line above.</p> + <p>The test passes if you see a gray square:</p> + <p id="one"></p> + <p id="two"></p> </body> </html> diff --git a/tests/wpt/tests/css/css-color/t422-rgba-a0.6-a-ref.xht b/tests/wpt/tests/css/css-color/t422-rgba-a0.6-a-ref.xht new file mode 100644 index 00000000000..ae463485065 --- /dev/null +++ b/tests/wpt/tests/css/css-color/t422-rgba-a0.6-a-ref.xht @@ -0,0 +1,18 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>CSS Test: rgba() colors</title> + <link rel="author" title="L. David Baron" href="https://dbaron.org/" /> + <link rel="author" title="Chris Lilley" href="https://svgees.us" /> + <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" /> + <style type="text/css"><![CDATA[ + html, body { background: white; color: black; } + #one, #two { width: 12em; height: 12em; } + #one { background-color: rgb(102, 102, 102); margin-bottom: 0 } + ]]></style> + </head> + <body> + <p>The test passes if you see a gray square:</p> + <p id="one"></p> + </body> +</html> diff --git a/tests/wpt/tests/css/css-color/t422-rgba-a0.6-a.xht b/tests/wpt/tests/css/css-color/t422-rgba-a0.6-a.xht index 2274eb3c312..a710a0b6251 100644 --- a/tests/wpt/tests/css/css-color/t422-rgba-a0.6-a.xht +++ b/tests/wpt/tests/css/css-color/t422-rgba-a0.6-a.xht @@ -3,22 +3,22 @@ <head> <title>CSS Test: rgba() colors</title> <link rel="author" title="L. David Baron" href="https://dbaron.org/" /> + <link rel="author" title="Chris Lilley" href="https://svgees.us" /> <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" /> <link rel="help" href="http://www.w3.org/TR/css3-color/#rgba-color" /> <link rel="help" href="http://www.w3.org/TR/css3-color/#rgb-color" /> - <link rel="match" href="t32-opacity-basic-0.6-a-ref.html" /> - <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> - <meta name="assert" content="Opacity of 0.6 makes text partially opaque. Colors are in sRGB color space (may test)." /> + <link rel="match" href="t422-rgba-a0.6-a-ref.xht" /> + <meta name="assert" content="Opacity of 0.6 makes background partially opaque. Colors are in sRGB color space (may test)." /> <style type="text/css"><![CDATA[ html, body { background: white; color: black; } - #one, #two { font-family: Ahem; } - #one { color: rgb(102, 102, 102); } - #two { color: rgba(0, 0, 0, 0.6); } + #one, #two { width: 12em; height: 6em; } + #one { background-color: rgb(102, 102, 102); margin-bottom: 0 } + #two { background-color: rgba(0, 0, 0, 0.6); margin-top:0 } ]]></style> </head> <body> - <p>The test passes if the two lines below look identical:</p> - <p id="one">This text should be the same color as the line below.</p> - <p id="two">This text should be the same color as the line above.</p> + <p>The test passes if you see a gray square:</p> + <p id="one"></p> + <p id="two"></p> </body> </html> diff --git a/tests/wpt/tests/css/css-color/t425-hsla-basic-a-ref.html b/tests/wpt/tests/css/css-color/t425-hsla-basic-a-ref.html deleted file mode 100644 index 32eb4cd46cc..00000000000 --- a/tests/wpt/tests/css/css-color/t425-hsla-basic-a-ref.html +++ /dev/null @@ -1,11 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Reference</title> -<style> - div { width: 600px; height: 30px; margin-bottom: 10px; background-color: #66FF66; } -</style> -<body> - <p>Test passes if the two boxes below are the same color.</p> - <div></div> - <div></div> -</body> diff --git a/tests/wpt/tests/css/css-color/t425-hsla-basic-a-ref.xht b/tests/wpt/tests/css/css-color/t425-hsla-basic-a-ref.xht new file mode 100644 index 00000000000..bc21fe36a26 --- /dev/null +++ b/tests/wpt/tests/css/css-color/t425-hsla-basic-a-ref.xht @@ -0,0 +1,17 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>CSS Test: hsla()</title> + <link rel="author" title="L. David Baron" href="https://dbaron.org/" /> + <link rel="author" title="Chris Lilley" href="https://svgees.us" /> + <style type="text/css"><![CDATA[ + html, body { background: white; } + div { width: 12em; height: 12em; } + #one { background-color: hsla(120, 100%, 70%, 1.0); margin-bottom: 0 } + ]]></style> + </head> + <body> + <p>Test passes if you see a light green square.</p> + <div id="one"></div> + </body> +</html> diff --git a/tests/wpt/tests/css/css-color/t425-hsla-basic-a.xht b/tests/wpt/tests/css/css-color/t425-hsla-basic-a.xht index 3645a9acedf..435041b5fa9 100644 --- a/tests/wpt/tests/css/css-color/t425-hsla-basic-a.xht +++ b/tests/wpt/tests/css/css-color/t425-hsla-basic-a.xht @@ -3,19 +3,29 @@ <head> <title>CSS Test: hsla()</title> <link rel="author" title="L. David Baron" href="https://dbaron.org/" /> + <link rel="author" title="Chris Lilley" href="https://svgees.us" /> <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" /> <link rel="help" href="http://www.w3.org/TR/css3-color/#hsla-color" /> - <link rel="match" href="t425-hsla-basic-a-ref.html" /> + <link rel="match" href="t425-hsla-basic-a-ref.xht" /> <meta name="assert" content="Test basic functioning of hsla() colors." /> <style type="text/css"><![CDATA[ html, body { background: white; } - div { width: 600px; height: 30px; margin-bottom: 10px; } - #one { background-color: hsla(120, 100%, 70%, 1.0); } - #two { background-color: hsla(120, 100%, 50%, 0.6); } + div { width: 12em; height: 6em; } + #one { background-color: hsla(120, 100%, 70%, 1.0); margin-bottom: 0 } + #two { background-color: hsla(120, 100%, 50%, 0.6); margin-top:0 } ]]></style> + /* + hsla(120, 100%, 70%, 1.0) is rgb(40% 100% 40%) + hsla(120, 100%, 50%, 0.6) is rgb(0% 100% 0% / 0.6) + composite rgb values at 60% over white in sRGB = rgb(40% 100% 40%) + BUT if compositing is done with used values, in device RGB + you will get a mismatch on WCG screen + because the red and blue components will not be zero + and the green will not be 100% + */ </head> <body> - <p>Test passes if the two boxes below are the same color.</p> + <p>Test passes if you see a light green square.</p> <div id="one"></div> <div id="two"></div> </body> diff --git a/tests/wpt/tests/css/css-color/xyz-d50-003-ref.html b/tests/wpt/tests/css/css-color/xyz-d50-003-ref.html index 51f565e04b1..4223a511df5 100644 --- a/tests/wpt/tests/css/css-color/xyz-d50-003-ref.html +++ b/tests/wpt/tests/css/css-color/xyz-d50-003-ref.html @@ -3,7 +3,7 @@ <title>CSS Color 4: CSS Color 4: xyz-d50</title> <style> body { background-color: grey; } - .test { background-color: lab(100% 6.1097 -13.2268); width: 12em; height: 12em; } /* color(xyz-d50 1 1 1) converted to Lab */ + .test { background-color: color(srgb 1.01139 0.987129 1.10222); width: 12em; height: 12em; } /* color(xyz-d50 1 1 1) converted to srgb*/ </style> <body> <p>Test passes if you see a single square, and not two rectangles of different colors.</p> diff --git a/tests/wpt/tests/css/css-color/xyz-d50-003.html b/tests/wpt/tests/css/css-color/xyz-d50-003.html index 036bcb6c148..76301151874 100644 --- a/tests/wpt/tests/css/css-color/xyz-d50-003.html +++ b/tests/wpt/tests/css/css-color/xyz-d50-003.html @@ -8,7 +8,7 @@ <style> body { background-color: grey; } .test { background-color: red; width: 12em; height: 6em; margin-top: 0; } - .ref { background-color: lab(100% 6.1097 -13.2268); width: 12em; height: 6em; margin-bottom: 0; } /* color(xyz-d50 1 1 1) converted to Lab */ + .ref { background-color: color(srgb 1.01139 0.987129 1.10222); width: 12em; height: 6em; margin-bottom: 0; } /* color(xyz-d50 1 1 1) converted to sRGB */ .test { background-color: color(xyz-d50 1 1 1); } </style> <body> diff --git a/tests/wpt/tests/css/css-color/xyz-d50-004-ref.html b/tests/wpt/tests/css/css-color/xyz-d50-004-ref.html index 9d211ae42a5..4d1c08f2ae8 100644 --- a/tests/wpt/tests/css/css-color/xyz-d50-004-ref.html +++ b/tests/wpt/tests/css/css-color/xyz-d50-004-ref.html @@ -2,7 +2,7 @@ <meta charset="utf-8"> <title>CSS Color 4: CSS Color 4: xyz-d50</title> <style> - .test { background-color: lab(100% -431.0345 172.4138); width: 12em; height: 12em; } /* color(xyz-d50 0 1 0) converted to Lab */ + .test { background-color: color(srgb -1.20716 1.3163 -0.489014); width: 12em; height: 12em; } /* color(xyz-d50 0 1 0) converted to srgb */ </style> <body> <p>Test passes if you see a single square, and not two rectangles of different colors.</p> diff --git a/tests/wpt/tests/css/css-color/xyz-d50-004.html b/tests/wpt/tests/css/css-color/xyz-d50-004.html index cc178590eae..f4aa9a0a1d5 100644 --- a/tests/wpt/tests/css/css-color/xyz-d50-004.html +++ b/tests/wpt/tests/css/css-color/xyz-d50-004.html @@ -7,7 +7,7 @@ <meta name="assert" content="xyz-d50 with no alpha"> <style> .test { background-color: red; width: 12em; height: 6em; margin-top: 0; } - .ref { background-color: lab(100% -431.0345 172.4138); width: 12em; height: 6em; margin-bottom: 0; } /* color(xyz-d50 0 1 0) converted to Lab */ + .ref { background-color: color(srgb -1.20716 1.3163 -0.489014); width: 12em; height: 6em; margin-bottom: 0; } /* color(xyz-d50 0 1 0) converted to sRGB */ .test { background-color: color(xyz-d50 0 1 0); } </style> <body> diff --git a/tests/wpt/tests/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html b/tests/wpt/tests/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html new file mode 100644 index 00000000000..f3d103983c6 --- /dev/null +++ b/tests/wpt/tests/css/css-fonts/animations/font-palette-animation-not-specified-endpoints.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>Font-palette animation with unspecified endpoints keyframes</title> +<link rel="help" href="https://www.w3.org/TR/css-fonts-4/#propdef-font-palette"> +<meta name="assert" content="Font-palette should be animated if `from` and `to` keyframes are not specified."> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + @font-face { + font-family: "COLR-test-font"; + src: url("../resources/COLR-palettes-test-font.ttf") format("truetype"); + } + @font-palette-values --custom { + font-family: "COLR-test-font"; + base-palette: 3; + } + @keyframes animFrom { + from { + font-palette: --custom; + } + } + @keyframes animTo { + to { + font-palette: --custom; + } + } + .demo { + font-family: "COLR-test-font"; + font-size: 130px; + } + .animFrom { + animation: animFrom 0.1s forwards; + } + .animTo { + animation: animTo 0.1s forwards; + } +</style> + +<body> + <div class="demo"> + <div id="a" class="animTo">A</div> + <div id="b" class="animFrom">A</div> + </div> +</body> + +<script> + var afterPaletteAnimationTest1 = async_test( + "Verify font-palette is animated when `from` keyframe is not specified" + ); + document.getElementById("a").addEventListener("animationend", + afterPaletteAnimationTest1.step_func_done(function() { + assert_equals(window.getComputedStyle( + document.getElementById("a")) + .getPropertyValue('font-palette'), "--custom"); + })); + + var afterPaletteAnimationTest2 = async_test( + "Verify font-palette is animated when `to` keyframe is not specified" + ); + document.getElementById("b").addEventListener("animationstart", + afterPaletteAnimationTest2.step_func_done(function() { + assert_not_equals(window.getComputedStyle( + document.getElementById("b")) + .getPropertyValue('font-palette'), "normal"); + })); +</script> diff --git a/tests/wpt/tests/css/css-fonts/animations/font-palette-interpolation.html b/tests/wpt/tests/css/css-fonts/animations/font-palette-interpolation.html index 66b0f00ebf0..43e1368412e 100644 --- a/tests/wpt/tests/css/css-fonts/animations/font-palette-interpolation.html +++ b/tests/wpt/tests/css/css-fonts/animations/font-palette-interpolation.html @@ -126,7 +126,7 @@ test(t => { { fontPalette: ['normal', 'dark'] }, { duration: 1000, - /* Should not affect anything, since <Color> type is not additive, + /* Should work like 'replace', since <Color> type is not additive, compare: https://drafts.csswg.org/css-values-4/#combine-colors. */ composite: "add" } @@ -136,7 +136,7 @@ test(t => { animation.currentTime = 500; }); assert_equals(getComputedStyle(target).fontPalette, - "palette-mix(in oklab, light, normal)"); + "palette-mix(in oklab, normal, dark)"); }, "Test additive animations"); </script>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-highlight-api/painting/custom-highlight-font-metrics-002.html b/tests/wpt/tests/css/css-highlight-api/painting/custom-highlight-font-metrics-002.html index 48ca92feef0..58b2db5ce4e 100644 --- a/tests/wpt/tests/css/css-highlight-api/painting/custom-highlight-font-metrics-002.html +++ b/tests/wpt/tests/css/css-highlight-api/painting/custom-highlight-font-metrics-002.html @@ -5,7 +5,7 @@ <link rel="help" href="https://drafts.csswg.org/css-pseudo/#highlight-styling"> <link rel="match" href="custom-highlight-font-metrics-002-ref.html"> <meta name="assert" value="fonts relative units take the correct values, with correct cascade"> -<meta name="fuzzy" content="0-120;0-8"> +<meta name="fuzzy" content="0-128;0-8"> <head> <style> :root { diff --git a/tests/wpt/tests/css/css-images/parsing/gradient-interpolation-method-computed.html b/tests/wpt/tests/css/css-images/parsing/gradient-interpolation-method-computed.html index 9593a59777a..b4f8dee4393 100644 --- a/tests/wpt/tests/css/css-images/parsing/gradient-interpolation-method-computed.html +++ b/tests/wpt/tests/css/css-images/parsing/gradient-interpolation-method-computed.html @@ -23,13 +23,13 @@ const LINEAR_GRADIENT_SPECIFIERS = [ const RADIAL_GRADIENT_SPECIFIERS = [ { input: '50px' }, - { input: 'ellipse 50% 40em', output: '50% 40em' }, - { input: 'at right center' }, + { input: 'ellipse 50% 40em', output: '50% 640px' }, + { input: 'at right center', output: 'at 100% 50%' }, ]; const CONIC_GRADIENT_SPECIFIERS = [ { input: 'from 30deg' }, - { input: 'at left 10px top 50em' }, + { input: 'at left 10px top 50em', output: 'at 10px 800px' }, ]; const legacy_stops = "red, blue" diff --git a/tests/wpt/tests/css/css-lists/dynamic-counters-crash.html b/tests/wpt/tests/css/css-lists/dynamic-counters-crash.html deleted file mode 100644 index 41e98ce0037..00000000000 --- a/tests/wpt/tests/css/css-lists/dynamic-counters-crash.html +++ /dev/null @@ -1,39 +0,0 @@ -<!DOCTYPE html> -<html class="reftest-wait"> -<link rel="help" href="http://crbug.com/1492599"> -<style type="text/css"> -.c0:nth-last-child(odd) { counter-reset: counter; } -.c1:nth-last-child(even) { counter-reset: counter; } -.c1 + .c13 { counter-increment: counter -1; } -.c10[class~="c10"] { counter-reset: counter; } -</style> -<script type="text/javascript"> -var nodes = Array(); -function boom() { - nodes[16] = document.createElement('em'); - nodes[16].setAttribute('class', 'c0'); - document.documentElement.appendChild(nodes[16]); - nodes[18] = document.createElement('colgroup'); - nodes[52] = document.createElement('table'); - document.documentElement.appendChild(nodes[52]); - nodes[53] = document.createElement('abbr'); - nodes[53].setAttribute('class', 'c1'); - document.documentElement.appendChild(nodes[53]); - nodes[54] = document.createElement('source'); - nodes[54].setAttribute('class', 'c10'); - nodes[55] = document.createElement('hgroup'); - nodes[55].setAttribute('class', 'c13'); - document.documentElement.appendChild(nodes[55]); - nodes[66] = document.createElement('img'); - document.documentElement.appendChild(nodes[66]); - nodes[71] = document.createElement('samp'); - document.documentElement.appendChild(nodes[71]); - nodes[97] = document.createElement('del'); - document.documentElement.appendChild(nodes[97]); - nodes[52].appendChild(nodes[54]); - setTimeout('try { nodes[18].appendChild(nodes[71]); } catch(e) {}'); - document.documentElement.classList.remove("reftest-wait"); -} -window.onload = boom; -</script> -</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse-mixed-change.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse-mixed-change.html new file mode 100644 index 00000000000..e42d3ee08ed --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse-mixed-change.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#basic-shape-interpolation"> +<link rel="match" href="clip-path-animation-ellipse-ref.html"> +<style> + .container { + width: 50px; + height: 50px; + background-color: green; + animation: clippath 20s steps(2, jump-end) -9.999s; + } + + @keyframes clippath { + 0% { + clip-path: ellipse(60% 30% at 40px 80px); + } + + 100% { + clip-path: ellipse(10% 20% at 10px 20px); + } + } +</style> +<script src="/common/reftest-wait.js"></script> +<script src="../../../../web-animations/resources/timing-utils.js"></script> + +<body> + <div id="target" class="container"></div> + + <script> + document.getAnimations()[0].ready.then(() => { + document.getElementById('target').style.width = "100px"; + document.getElementById('target').style.height = "100px"; + waitForAnimationTime(document.getAnimations()[0], 1).then(takeScreenshot); + }); + </script> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse-ref.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse-ref.html new file mode 100644 index 00000000000..63b3174806f --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse-ref.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<style> + .container { + width: 100px; + height: 100px; + background-color: green; + clip-path: ellipse(35% 25% at 25% 50%); + } +</style> + +<body> + <div class="container"></div> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse.html new file mode 100644 index 00000000000..1c7c90ee844 --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-ellipse.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#basic-shape-interpolation"> +<link rel="match" href="clip-path-animation-ellipse-ref.html"> +<style> + .container { + width: 100px; + height: 100px; + background-color: green; + animation: clippath 20s steps(2, jump-end) -9.999s; + } + + @keyframes clippath { + 0% { + clip-path: ellipse(60% 30% at 40% 80%); + } + + 100% { + clip-path: ellipse(10% 20% at 10% 20%); + } + } +</style> +<script src="/common/reftest-wait.js"></script> +<script src="../../../../web-animations/resources/timing-utils.js"></script> + +<body> + <div class="container"></div> + + <script> + waitForAnimationTime(document.getAnimations()[0], 1).then(takeScreenshot); + </script> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-inherited.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-inherited.html new file mode 100644 index 00000000000..6836af5a295 --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-inherited.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#basic-shape-interpolation"> +<link rel="match" href="clip-path-animation-font-size-ref.html"> +<style> + body { + font-size: 20px; + } + + .container { + width: 100px; + height: 100px; + background-color: green; + animation: clippath 20s steps(2, jump-end) -9.999s; + } + + @keyframes clippath { + 0% { + clip-path: circle(1em); + } + + 100% { + clip-path: circle(2em); + } + } +</style> +<script src="/common/reftest-wait.js"></script> +<script src="../../../../web-animations/resources/timing-utils.js"></script> + +<body> + <div class="container"></div> + + <script> + waitForAnimationTime(document.getAnimations()[0], 1).then(takeScreenshot); + </script> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-mixed-change.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-mixed-change.html new file mode 100644 index 00000000000..9e24aa905c2 --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-mixed-change.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#basic-shape-interpolation"> +<link rel="match" href="clip-path-animation-font-size-ref.html"> +<style> + .container { + width: 100px; + height: 100px; + font-size: 10px; + background-color: green; + /* Use a long animation that start at 50% progress where the slope of the + selected timing function is zero. By setting up the animation in this way, + we accommodate lengthy delays in running the test without a potential drift + in the animated property value. This is important for avoiding flakes, + especially on debug builds. The screenshots are taken as soon as the + animation is ready, thus the long animation duration has no bearing on + the actual duration of the test. */ + animation: clippath 20s steps(2, jump-end) -9.999999s; + } + + @keyframes clippath { + 0% { + clip-path: circle(20px); + } + + 100% { + clip-path: circle(2em); + } + } +</style> +<script src="/common/reftest-wait.js"></script> + +<body> + <div id="target" class="container"></div> + + <script> + document.getAnimations()[0].ready.then(() => { + document.getElementById('target').style.fontSize = "20px"; + window.requestAnimationFrame(() => { + takeScreenshot(); + }) + }); + </script> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-ref.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-ref.html new file mode 100644 index 00000000000..912a8e84642 --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size-ref.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<style> + .container { + width: 100px; + height: 100px; + background-color: green; + font-size: 20px; + clip-path: circle(1.5em); + } +</style> + +<body> + <div class="container"></div> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size.html new file mode 100644 index 00000000000..00563305e54 --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-font-size.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#basic-shape-interpolation"> +<link rel="match" href="clip-path-animation-font-size-ref.html"> +<style> + .container { + width: 100px; + height: 100px; + font-size: 20px; + background-color: green; + animation: clippath 20s steps(2, jump-end) -9.999s; + } + + @keyframes clippath { + 0% { + clip-path: circle(1em); + } + + 100% { + clip-path: circle(2em); + } + } +</style> +<script src="/common/reftest-wait.js"></script> +<script src="../../../../web-animations/resources/timing-utils.js"></script> + +<body> + <div class="container"></div> + + <script> + waitForAnimationTime(document.getAnimations()[0], 1).then(takeScreenshot); + </script> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-path-ref.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-path-ref.html new file mode 100644 index 00000000000..d53067f5634 --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-path-ref.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<style> + .container { + width: 200px; + height: 200px; + background-color: green; + clip-path: path('M 0 150 L 15,75 A 5,5 0,0,1 150,75 L 150 150 z'); + } +</style> + +<body> + <div class="container"></div> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-path.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-path.html new file mode 100644 index 00000000000..20400ba5ece --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-path.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#basic-shape-interpolation"> +<link rel="match" href="clip-path-animation-path-ref.html"> +<meta name=fuzzy content="0-10;0-200"> +<style> + .container { + width: 200px; + height: 200px; + background-color: green; + animation: clippath 20s steps(2, jump-end) -9.999s; + } + + @keyframes clippath { + 0% { + clip-path: path('M 0 200 L 0,75 A 5,5 0,0,1 150,75 L 150 200 z'); + } + + 100% { + clip-path: path('M 0 100 L 30,75 A 5,5 0,0,1 150,75 L 150 100 z'); + } + } +</style> +<script src="/common/reftest-wait.js"></script> +<script src="../../../../web-animations/resources/timing-utils.js"></script> + +<body> + <div class="container"></div> + + <script> + waitForAnimationTime(document.getAnimations()[0], 1).then(takeScreenshot); + </script> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon-mixed-change.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon-mixed-change.html new file mode 100644 index 00000000000..569c0af66ae --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon-mixed-change.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#basic-shape-interpolation"> +<link rel="match" href="clip-path-animation-polygon-ref.html"> +<style> + .container { + width: 50px; + height: 50px; + background-color: green; + animation: clippath 20s steps(2, jump-end) -9.999s; + } + + @keyframes clippath { + 0% { + clip-path: polygon(0px 0px, 100% 0%, 50% 100%) + } + + 100% { + clip-path: polygon(20px 20px, 80% 20%, 50% 80%) + } + } +</style> +<script src="/common/reftest-wait.js"></script> +<script src="../../../../web-animations/resources/timing-utils.js"></script> + +<body> + <div id="target" class="container"></div> + + <script> + document.getAnimations()[0].ready.then(() => { + document.getElementById('target').style.width = "100px"; + document.getElementById('target').style.height = "100px"; + waitForAnimationTime(document.getAnimations()[0], 1).then(takeScreenshot); + }); + </script> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon-ref.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon-ref.html new file mode 100644 index 00000000000..28e11e966d5 --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon-ref.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<style> + .container { + width: 100px; + height: 100px; + background-color: green; + clip-path: polygon(10% 10%, 90% 10%, 50% 90%); + } +</style> + +<body> + <div class="container"></div> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon.html b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon.html new file mode 100644 index 00000000000..1a9d0cc1688 --- /dev/null +++ b/tests/wpt/tests/css/css-masking/clip-path/animations/clip-path-animation-polygon.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#basic-shape-interpolation"> +<link rel="match" href="clip-path-animation-polygon-ref.html"> +<style> + .container { + width: 100px; + height: 100px; + background-color: green; + animation: clippath 20s steps(2, jump-end) -9.999s; + } + + @keyframes clippath { + 0% { + clip-path: polygon(0% 0%, 100% 0%, 50% 100%) + } + + 100% { + clip-path: polygon(20% 20%, 80% 20%, 50% 80%) + } + } +</style> +<script src="/common/reftest-wait.js"></script> +<script src="../../../../web-animations/resources/timing-utils.js"></script> + +<body> + <div class="container"></div> + + <script> + waitForAnimationTime(document.getAnimations()[0], 1).then(takeScreenshot); + </script> +</body> + +</html> diff --git a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3b.html b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3b.html index bd805cde975..b6609fde6a4 100644 --- a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3b.html +++ b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3b.html @@ -8,6 +8,7 @@ <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-image"> <link rel="match" href="mask-image-3-ref.html"> <meta name="assert" content="Test checks whether SVG mask and image as mask layer works correctly or not."> + <meta name="fuzzy" content="0-1; 0-100"> <svg height="0"> <mask id="mask1" x="0" y="0" width="1" height="1" > <circle cx="50" cy="50" r="25" style="stroke:none; fill: #ffffff"/> diff --git a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3c.html b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3c.html index 32bd4454d71..91cc9f7bb10 100644 --- a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3c.html +++ b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3c.html @@ -8,6 +8,7 @@ <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-image"> <link rel="match" href="mask-image-3-ref.html"> <meta name="assert" content="Test checks whether SVG mask and image as mask layer works correctly or not."> + <meta name="fuzzy" content="0-1; 0-100"> <svg height="0"> <mask id="mask1" x="0" y="0" width="1" height="1" > <circle cx="50" cy="50" r="25" style="stroke:none; fill: #ffffff"/> diff --git a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3d.html b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3d.html index f1ef1be7099..468872fecbd 100644 --- a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3d.html +++ b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3d.html @@ -7,6 +7,7 @@ <link rel="author" title="Mozilla" href="https://www.mozilla.org"> <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-image"> <link rel="match" href="mask-image-3-ref.html"> + <meta name="fuzzy" content="0-1; 0-100"> <meta name="assert" content="Test checks whether SVG mask and image as mask layer works correctly or not."> <svg height="0"> <mask id="mask1" x="10%" y="10%" width="0.8" height="0.8" > diff --git a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3e.html b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3e.html index 15223e34d62..5e539375545 100644 --- a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3e.html +++ b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3e.html @@ -8,6 +8,7 @@ <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-image"> <link rel="match" href="mask-image-3-ref.html"> <meta name="assert" content="Test checks whether SVG mask and image as mask layer works correctly or not."> + <meta name="fuzzy" content="0-1; 0-100"> <svg height="0"> <mask id="mask1" x="0" y="0" width="1" height="1" > <circle cx="50" cy="50" r="25" style="stroke:none; fill: #ffffff"/> diff --git a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3f.html b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3f.html index e925105baac..0ecfd383652 100644 --- a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3f.html +++ b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3f.html @@ -8,6 +8,7 @@ <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-image"> <link rel="match" href="mask-image-3-ref.html"> <meta name="assert" content="Test checks whether SVG mask layer can be positioned on box-shadow area correctly or not."> + <meta name="fuzzy" content="0-1; 0-100"> <svg height="0"> <mask id="mask1" x="-100" y="-100" width="300" height="300" maskUnits="userSpaceOnUse"> <rect x="-100" y="-100" width="50" height="50" style="stroke:none; fill: #ffffff"/> diff --git a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3g.html b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3g.html index 1236c0c3348..133a69fa609 100644 --- a/tests/wpt/tests/css/css-masking/mask-image/mask-image-3g.html +++ b/tests/wpt/tests/css/css-masking/mask-image/mask-image-3g.html @@ -8,6 +8,7 @@ <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-image"> <link rel="match" href="mask-image-3-ref.html"> <meta name="assert" content="Test checks whether apply transfrom to a SVG mask layer works correctly or not."> + <meta name="fuzzy" content="0-1; 0-100"> <svg height="0"> <mask id="mask1" x="-100" y="-100" width="300" height="300" maskUnits="userSpaceOnUse"> <rect x="-100" y="-100" width="50" height="50" style="stroke:none; fill: #ffffff"/> diff --git a/tests/wpt/tests/css/css-masking/parsing/mask-computed.html b/tests/wpt/tests/css/css-masking/parsing/mask-computed.html new file mode 100644 index 00000000000..28fc38defae --- /dev/null +++ b/tests/wpt/tests/css/css-masking/parsing/mask-computed.html @@ -0,0 +1,94 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Masking Module Level 1: getComputedStyle().mask</title> +<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask"> +<meta name="assert" content="mask computed value is as specified."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +// value: <mask-layer># +// <mask-layer> = +// <mask-reference> || +// <position> [ / <bg-size> ]? || +// <repeat-style> || +// <geometry-box> || +// [ <geometry-box> | no-clip ] || +// <compositing-operator> || +// <masking-mode> + +// <mask-reference> = none | <image> | <mask-source> +test_computed_value('mask', 'none'); +test_computed_value('mask', + 'linear-gradient(to left bottom, red, blue)', + 'linear-gradient(to left bottom, rgb(255, 0, 0), rgb(0, 0, 255))'); +test_computed_value('mask', + 'linear-gradient(to left bottom, red, blue) luminance', + 'linear-gradient(to left bottom, rgb(255, 0, 0), rgb(0, 0, 255)) luminance'); +test_computed_value('mask', 'url("https://example.com/")'); + +// <position> [ / <bg-size> ]? +test_computed_value('mask', + 'linear-gradient(to left bottom, red, blue) 1px 2px', + 'linear-gradient(to left bottom, rgb(255, 0, 0), rgb(0, 0, 255)) 1px 2px'); +test_computed_value('mask', 'url("https://example.com/") 1px 2px / contain'); + +// <repeat-style> = repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2} +test_computed_value('mask', 'repeat-y'); + +// <geometry-box> = <shape-box> | fill-box | stroke-box | view-box +// <shape-box> = <box> +// <box> = border-box | padding-box | content-box +test_computed_value('mask', 'border-box', 'none'); +test_computed_value('mask', + 'linear-gradient(to left bottom, red, blue) padding-box', + 'linear-gradient(to left bottom, rgb(255, 0, 0), rgb(0, 0, 255)) padding-box'); +test_computed_value('mask', 'content-box'); +test_computed_value('mask', 'url("https://example.com/") fill-box'); +test_computed_value('mask', + 'linear-gradient(to left bottom, red, blue) stroke-box', + 'linear-gradient(to left bottom, rgb(255, 0, 0), rgb(0, 0, 255)) stroke-box'); +test_computed_value('mask', 'view-box'); + +// [ <geometry-box> | no-clip ] +test_computed_value('mask', 'no-clip'); + +// <compositing-operator> = add | subtract | intersect | exclude +test_computed_value('mask', + 'url("https://example.com/") add', + 'url("https://example.com/")'); +test_computed_value('mask', 'subtract'); +test_computed_value('mask', 'url("https://example.com/") intersect'); +test_computed_value('mask', + 'linear-gradient(to left bottom, red, blue) exclude', + 'linear-gradient(to left bottom, rgb(255, 0, 0), rgb(0, 0, 255)) exclude'); + +// <masking-mode> = alpha | luminance | auto +test_computed_value('mask', 'alpha'); +test_computed_value('mask', 'url("https://example.com/") alpha'); + +// Test the combination of mask-origin and mask-clip. +test_computed_value('mask', 'border-box border-box', 'none'); +test_computed_value('mask', 'content-box content-box', 'content-box'); +test_computed_value('mask', 'border-box content-box', 'border-box content-box'); +test_computed_value('mask', 'border-box no-clip', 'no-clip'); + +// <mask-layer> = <mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || +// <geometry-box> || [ <geometry-box> | no-clip ] || <compositing-operator> || <masking-mode> +test_computed_value('mask', + 'intersect no-clip space round 1px 2px / contain stroke-box linear-gradient(to left bottom, red, blue) luminance', + 'linear-gradient(to left bottom, rgb(255, 0, 0), rgb(0, 0, 255)) 1px 2px / contain space round stroke-box no-clip intersect luminance'); +test_computed_value('mask', + 'intersect no-clip space round 1px 2px / contain view-box, stroke-box linear-gradient(to left bottom, red, blue) luminance', + '1px 2px / contain space round view-box no-clip intersect, linear-gradient(to left bottom, rgb(255, 0, 0), rgb(0, 0, 255)) stroke-box luminance'); + +test_computed_value('mask', 'none alpha', 'alpha'); + +</script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-masking/parsing/mask-valid.sub.html b/tests/wpt/tests/css/css-masking/parsing/mask-valid.sub.html index a377060ded8..c4d2d4eb2c0 100644 --- a/tests/wpt/tests/css/css-masking/parsing/mask-valid.sub.html +++ b/tests/wpt/tests/css/css-masking/parsing/mask-valid.sub.html @@ -51,6 +51,12 @@ test_valid_value('mask', 'linear-gradient(to left bottom, red, blue) exclude'); test_valid_value('mask', 'alpha'); test_valid_value('mask', 'url("https://{{host}}/") alpha'); +// Test the combination of mask-origin and mask-clip. +test_valid_value('mask', 'border-box border-box', 'none'); +test_valid_value('mask', 'content-box content-box', 'content-box'); +test_valid_value('mask', 'border-box content-box', 'border-box content-box'); +test_valid_value('mask', 'border-box no-clip', 'no-clip'); + // <mask-layer> = <mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || // <geometry-box> || [ <geometry-box> | no-clip ] || <compositing-operator> || <masking-mode> test_valid_value('mask', diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html index 9ffaec830f8..1b2fc907f25 100644 --- a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-animation-transform-list-multiple-values.html @@ -3,6 +3,7 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="../resources/utils.js"></script> +<script src="/web-animations/testcommon.js"></script> <div id="target"></div> <script> @@ -60,7 +61,8 @@ animation_test({ initialValue: "translateX(0px)" }, { keyframes: ["translateX(100px) scale(2)", "rotate(180deg)"], - expected: "matrix(0, -1.5, 1.5, 0, 50, 0)" + expected: "matrix(0, -1.5, 1.5, 0, 50, 0)", + assert_function: assert_matrix_equals }, 'Animating a custom property of type <transform-list> containing multiple values and with mismatching list lengths'); </script> diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-animation-transform-none.tentative.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-animation-transform-none.tentative.html new file mode 100644 index 00000000000..37abddd2271 --- /dev/null +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-animation-transform-none.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/9522"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/utils.js"></script> +<div id="target"></div> +<script> + +// Move to custom-property-animation-transform-list-single-values.html when no longer tentative +animation_test({ + syntax: "<transform-list>|none", + inherits: false, + initialValue: "none" +}, { + keyframes: ["translateX(200px)"], + expected: "translateX(200px)" +}, 'Animating a custom property of type "<transform-list>|none" from "none" to <transform-list> value'); + +// Move to custom-property-animation-transform-function.html when no longer tentative +animation_test({ + syntax: "<transform-function>|none", + inherits: false, + initialValue: "none" +}, { + keyframes: ["translateX(200px)"], + expected: "translateX(200px)" +}, 'Animating a custom property of type "<transform-function>|none" from "none" to <transform-function> value'); + +</script> diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-box-size.tentative.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-box-size.tentative.html new file mode 100644 index 00000000000..23ac09b1fc9 --- /dev/null +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-box-size.tentative.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#interpolate"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/2854"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/utils.js"></script> +<div id="target"></div> +<script> + +transition_test({ + syntax: "<transform-function>", + from: "translateX(50%)", + to: "scale(4)", + expected: "mix(50%; translateX(50%); scale(4))", + behavior: 'allow-discrete', +}, 'A custom property of type <transform-function> yields a CSS Transition using the mix function for a box size dependent matrix interpolation'); + +</script> diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-matrix.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-matrix.html new file mode 100644 index 00000000000..00b50181425 --- /dev/null +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-matrix.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/utils.js"></script> +<div id="target"></div> +<script> + +transition_test({ + syntax: "<transform-function>", + from: "translateZ(100px)", + to: "scale(4)", + expected: "matrix3d(2.5, 0, 0, 0, 0, 2.5, 0, 0, 0, 0, 1, 0, 0, 0, 50, 1)", + behavior: 'allow-discrete', +}, 'A custom property of type <transform-function> can yield a CSS Transition between different function types'); + +</script> diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-none.tentative.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-none.tentative.html new file mode 100644 index 00000000000..29a5715fec8 --- /dev/null +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-none.tentative.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/9522"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/utils.js"></script> +<div id="target"></div> +<script> + +transition_test({ + syntax: "<transform-function>|none", + from: "none", + to: "translateX(200px)", + expected: "translateX(200px)", + behavior: 'allow-discrete', +}, 'A custom property keyword none is not a <transform-function> value and is not interpolable with <transform-function> values'); + +</script> diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-to-list.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-to-list.html new file mode 100644 index 00000000000..d09fb6416ac --- /dev/null +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-function-to-list.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/utils.js"></script> +<div id="target"></div> +<script> + +transition_test({ + syntax: "<transform-function>|<transform-list>", + from: "translateX(100px)", + to: "translateX(200px) rotate(90deg)", + expected: "translateX(200px) rotate(90deg)", + behavior: 'allow-discrete', +}, 'A custom property cannot yield a CSS Transition from <transform-function> to <transform-list>'); + +</script> diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-box-size.tentative.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-box-size.tentative.html new file mode 100644 index 00000000000..d1b882f7084 --- /dev/null +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-box-size.tentative.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#interpolate"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/2854"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/utils.js"></script> +<div id="target"></div> +<script> + +transition_test({ + syntax: "<transform-list>", + from: "translateX(50%)", + to: "scale(4)", + expected: "mix(50%; translateX(50%); scale(4))", + behavior: 'allow-discrete', +}, 'A custom property of type <transform-list> yields a CSS Transition using the mix function for a box size dependent matrix interpolation'); + +</script> diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-matrix.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-matrix.html new file mode 100644 index 00000000000..8f1fa842948 --- /dev/null +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-matrix.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/utils.js"></script> +<div id="target"></div> +<script> + +transition_test({ + syntax: "<transform-list>", + from: "translateZ(100px)", + to: "scale(4)", + expected: "matrix3d(2.5, 0, 0, 0, 0, 2.5, 0, 0, 0, 0, 1, 0, 0, 0, 50, 1)", + behavior: 'allow-discrete', +}, 'A custom property of type <transform-list> can yield a CSS Transition between different function types'); + +</script> diff --git a/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-none.tentative.html b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-none.tentative.html new file mode 100644 index 00000000000..d09f5854b30 --- /dev/null +++ b/tests/wpt/tests/css/css-properties-values-api/animation/custom-property-transition-transform-list-none.tentative.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/9522"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/utils.js"></script> +<div id="target"></div> +<script> + +transition_test({ + syntax: "<transform-list>|none", + from: "none", + to: "translateX(200px)", + expected: "translateX(200px)", + behavior: 'allow-discrete', +}, 'A custom property keyword none is not a <transform-list> value and is not interpolable with <transform-list> values'); + +</script> diff --git a/tests/wpt/tests/css/css-properties-values-api/resources/utils.js b/tests/wpt/tests/css/css-properties-values-api/resources/utils.js index fc3a5993cf5..a952a4feedc 100644 --- a/tests/wpt/tests/css/css-properties-values-api/resources/utils.js +++ b/tests/wpt/tests/css/css-properties-values-api/resources/utils.js @@ -144,7 +144,8 @@ function animation_test(property, values, description) { // iterationComposite is set to something other than "replace". animation.currentTime = duration * 2.5; - assert_equals(getComputedStyle(target).getPropertyValue(name), values.expected); + const assert_equals_function = values.assert_function || assert_equals; + assert_equals_function(getComputedStyle(target).getPropertyValue(name), values.expected); }, description); }; diff --git a/tests/wpt/tests/css/css-scoping/chrome-1492368-crash.html b/tests/wpt/tests/css/css-scoping/chrome-1492368-crash.html new file mode 100644 index 00000000000..04d48ef2153 --- /dev/null +++ b/tests/wpt/tests/css/css-scoping/chrome-1492368-crash.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<title>Chrome crash re-assigning to slots with display:none slot</title> +<link rel="help" href="https://crbug.com/1492368"> +<div id="host"> + <span id="slotted" style="display:none"></span> +</div> +<script> + let root = host.attachShadow({mode:"open"}); + root.innerHTML = ` + <slot></slot> + <slot name="s1" style="display:none"></slot> + `; + host.offsetTop; + slotted.setAttribute("slot", "s1"); + slotted.style.color = "green"; + host.offsetTop; +</script> diff --git a/tests/wpt/tests/css/css-scroll-anchoring/after-scrollable-range-shrinkage-003.html b/tests/wpt/tests/css/css-scroll-anchoring/after-scrollable-range-shrinkage-003.html new file mode 100644 index 00000000000..c9127e79b5a --- /dev/null +++ b/tests/wpt/tests/css/css-scroll-anchoring/after-scrollable-range-shrinkage-003.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<meta name="viewport" content="width=device-width"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="author" title="Mozilla" href="https://mozilla.org"> +<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring/"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1856088"> +<div style="height: 500vh;"></div> +<div id="anchor" style="height: 10px; background-color: blue;"></div> +<div style="height: 200vh;"></div> +<script> +promise_test(async t => { + assert_equals(window.scrollY, 0); + + let anchorRect = anchor.getBoundingClientRect(); + // Scroll to the anchor node. + window.scrollBy(0, anchorRect.y); + assert_equals(window.scrollY, anchorRect.y); + + await new Promise(resolve => t.step_timeout(resolve, 0)); + + // Shrink the first element so that scroll anchoring happens. + document.querySelectorAll("div")[0].style.height = "200vh"; + // Flush the change. + document.querySelectorAll("div")[0].getBoundingClientRect(); + + await new Promise(resolve => window.addEventListener("scroll", resolve)); + + // Revert the height change in a scroll event handler. + document.querySelectorAll("div")[0].style.height = "500vh"; + + await new Promise(resolve => requestAnimationFrame(resolve)); + await new Promise(resolve => requestAnimationFrame(resolve)); + + assert_equals(window.scrollY, anchorRect.y); +}, "Scroll anchoring properly works after scrollable range shrinkage"); +</script> +</html> diff --git a/tests/wpt/tests/css/css-scroll-anchoring/after-scrollable-range-shrinkage-004.html b/tests/wpt/tests/css/css-scroll-anchoring/after-scrollable-range-shrinkage-004.html new file mode 100644 index 00000000000..8509a1cca5e --- /dev/null +++ b/tests/wpt/tests/css/css-scroll-anchoring/after-scrollable-range-shrinkage-004.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html> +<meta name="viewport" content="width=device-width"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="author" title="Mozilla" href="https://mozilla.org"> +<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring/"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1856088"> +<div style="height: 500vh;"></div> +<div id="anchor" style="height: 10px; background-color: blue;"></div> +<div style="height: 200vh;"></div> +<script> +promise_test(async t => { + assert_equals(window.scrollY, 0); + + let anchorRect = anchor.getBoundingClientRect(); + // Scroll to the anchor node. + window.scrollBy(0, anchorRect.y); + assert_equals(window.scrollY, anchorRect.y); + + await new Promise(resolve => t.step_timeout(resolve, 0)); + + // Shrink the first element so that scroll anchoring happens. + document.querySelectorAll("div")[0].style.height = "200vh"; + // Flush the change. + document.querySelectorAll("div")[0].getBoundingClientRect(); + + await new Promise(resolve => window.addEventListener("scroll", resolve)); + + // Shrink the first element more. + document.querySelectorAll("div")[0].style.height = "100vh"; + + await new Promise(resolve => requestAnimationFrame(resolve)); + await new Promise(resolve => requestAnimationFrame(resolve)); + + const scrollAnchorPosition = window.scrollY; + + // Scroll back to (0, 0) to calculate the expected scroll anchor element + // position. + window.scrollTo(0, 0); + anchorRect = anchor.getBoundingClientRect(); + assert_equals(scrollAnchorPosition, anchorRect.y); +}, "Scroll anchoring properly works after scrollable range shrinkage"); +</script> +</html> diff --git a/tests/wpt/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-aligns-with-snap-align.tentative.html b/tests/wpt/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-aligns-with-snap-align.tentative.html new file mode 100644 index 00000000000..6b133dea7d7 --- /dev/null +++ b/tests/wpt/tests/css/css-scroll-snap-2/scroll-start-target/scroll-start-target-aligns-with-snap-align.tentative.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title> CSS Scroll Snap 2 Test: scroll-start-target*</title> + <link rel="help" href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/dom/events/scrolling/scroll_support.js"></script> + </head> + <body> + <style> + #space { + width: 1000px; + height: 1000px; + border: solid 1px red; + } + #scroller { + width: 400px; + height: 400px; + overflow: hidden; + border: solid 1px blue; + position: absolute; + } + #target { + width: 100px; + height: 100px; + background-color: pink; + scroll-start-target: auto auto; + position: absolute; + top: 400px; + left: 400px; + } + </style> + <div id="scroller"> + <div id="space"></div> + <div id="target"></div> + </div> + <script> + promise_test(async (t) => { + await waitForCompositorCommit(); + + assert_equals(scroller.scrollTop, 400, + "scroller is vertically scrolled to target"); + assert_equals(scroller.scrollLeft, 400, + "scroller is horizontally scrolled to target"); + + target.style.scrollSnapAlign = "center"; + await waitForCompositorCommit(); + + assert_equals(scroller.scrollTop, 250, + "scroller is vertically aligned to target's center"); + assert_equals(scroller.scrollLeft, 250, + "scroller is horizontally aligned to target's center"); + + target.style.scrollSnapAlign = "end"; + await waitForCompositorCommit(); + + assert_equals(scroller.scrollTop, 100, + "scroller is vertically aligned to target's bottom"); + assert_equals(scroller.scrollLeft, 100, + "scroller is horizontally aligned to target's right"); + + target.style.scrollSnapAlign = "start"; + await waitForCompositorCommit(); + + assert_equals(scroller.scrollTop, 400, + "scroller is vertically aligned to target's top"); + assert_equals(scroller.scrollLeft, 400, + "scroller is horizontally aligned to target's left"); + }, "scroll-start-target aligns with scroll-snap-align"); + </script> + </body> +</html> diff --git a/tests/wpt/tests/css/css-text/crashtests/text-indent-each-line-crash.html b/tests/wpt/tests/css/css-text/crashtests/text-indent-each-line-crash.html new file mode 100644 index 00000000000..fb63175cf17 --- /dev/null +++ b/tests/wpt/tests/css/css-text/crashtests/text-indent-each-line-crash.html @@ -0,0 +1,14 @@ +<style> +*:scope { + text-indent: 41% each-line; + columns: 0; +} +#a { + float: right; + writing-mode: tb; +} +</style> +<shadow id="a"> +A +</shadow> +<details>
\ No newline at end of file diff --git a/tests/wpt/tests/css/css-text/inheritance.html b/tests/wpt/tests/css/css-text/inheritance.html index 83d1d4971ea..2043afe999d 100644 --- a/tests/wpt/tests/css/css-text/inheritance.html +++ b/tests/wpt/tests/css/css-text/inheritance.html @@ -28,6 +28,8 @@ assert_inherited('text-indent', '0px', '10px'); assert_inherited('text-justify', 'auto', 'inter-character'); assert_inherited('text-transform', 'none', 'uppercase'); assert_inherited('text-wrap', 'wrap', 'nowrap'); +assert_inherited('text-wrap-mode', 'wrap', 'nowrap'); +assert_inherited('text-wrap-style', 'auto', 'balance'); assert_inherited('white-space', 'normal', 'pre-wrap'); assert_inherited('white-space-collapse', 'collapse', 'preserve'); assert_inherited('word-break', 'normal', 'break-all'); diff --git a/tests/wpt/tests/css/css-text/parsing/text-wrap-computed.html b/tests/wpt/tests/css/css-text/parsing/text-wrap-computed.html new file mode 100644 index 00000000000..772f0abf4d9 --- /dev/null +++ b/tests/wpt/tests/css/css-text/parsing/text-wrap-computed.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Text: getComputedStyle().textWrap</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap"> +<meta name="assert" content="text-wrap computed value is '<text-wrap-mode> || <text-wrap-style>'."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("text-wrap", "wrap"); +test_computed_value("text-wrap", "nowrap"); + +test_computed_value("text-wrap", "auto", "wrap"); +test_computed_value("text-wrap", "balance"); +test_computed_value("text-wrap", "stable"); +test_computed_value("text-wrap", "pretty"); + +test_computed_value("text-wrap", "wrap auto", "wrap"); +test_computed_value("text-wrap", "wrap balance", "balance"); +test_computed_value("text-wrap", "wrap pretty", "pretty"); +test_computed_value("text-wrap", "wrap stable", "stable"); +test_computed_value("text-wrap", "auto wrap", "wrap"); +test_computed_value("text-wrap", "balance wrap", "balance"); +test_computed_value("text-wrap", "pretty wrap", "pretty"); +test_computed_value("text-wrap", "stable wrap", "stable"); + +test_computed_value("text-wrap", "nowrap auto", "nowrap"); +test_computed_value("text-wrap", "nowrap balance"); +test_computed_value("text-wrap", "nowrap pretty"); +test_computed_value("text-wrap", "nowrap stable"); +test_computed_value("text-wrap", "auto nowrap", "nowrap"); +test_computed_value("text-wrap", "balance nowrap", "nowrap balance"); +test_computed_value("text-wrap", "pretty nowrap", "nowrap pretty"); +test_computed_value("text-wrap", "stable nowrap", "nowrap stable"); +</script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-computed.html b/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-computed.html new file mode 100644 index 00000000000..35e082b6474 --- /dev/null +++ b/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-computed.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Text: getComputedStyle().textWrapMode</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap-mode"> +<meta name="assert" content="text-wrap-mode computed value is wrap | nowrap"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("text-wrap-mode", "wrap"); +test_computed_value("text-wrap-mode", "nowrap"); +</script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-invalid.html b/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-invalid.html new file mode 100644 index 00000000000..d63c1901c11 --- /dev/null +++ b/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-invalid.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Text Module Test: parsing text-wrap-mode with invalid values</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap-mode"> +<meta name="assert" content="text-wrap-mode supports only the grammar '<text-wrap-mode>'."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +</head> +<body> +<script> +test_invalid_value("text-wrap-mode", "auto"); +test_invalid_value("text-wrap-mode", "normal"); +test_invalid_value("text-wrap-mode", "none"); +test_invalid_value("text-wrap-mode", "balance"); +test_invalid_value("text-wrap-mode", "pretty"); +test_invalid_value("text-wrap-mode", "stable"); +test_invalid_value("text-wrap-mode", "wrap stable"); +test_invalid_value("text-wrap-mode", "nowrap stable"); +test_invalid_value("text-wrap-mode", "wrap auto"); +test_invalid_value("text-wrap-mode", "balance balance"); +test_invalid_value("text-wrap-mode", "pretty pretty"); +test_invalid_value("text-wrap-mode", "stable stable"); +test_invalid_value("text-wrap-mode", "wrap nowrap"); +test_invalid_value("text-wrap-mode", "pretty balance"); +test_invalid_value("text-wrap-mode", "balance stable"); +test_invalid_value("text-wrap-mode", "stable pretty"); +test_invalid_value("text-wrap-mode", "delicious wrap"); +test_invalid_value("text-wrap-mode", "5px"); +</script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-valid.html b/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-valid.html new file mode 100644 index 00000000000..5dde8b377fb --- /dev/null +++ b/tests/wpt/tests/css/css-text/parsing/text-wrap-mode-valid.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Text Module Test: parsing text-wrap-mode with valid values</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap-mode"> +<meta name="assert" content="text-wrap-mode supports the full grammar."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +</head> +<body> +<script> +test_valid_value("text-wrap-mode", "wrap"); +test_valid_value("text-wrap-mode", "nowrap"); + +test_valid_value("text-wrap-mode", "initial"); +test_valid_value("text-wrap-mode", "inherit"); +test_valid_value("text-wrap-mode", "unset"); +test_valid_value("text-wrap-mode", "revert"); +test_valid_value("text-wrap-mode", "revert-layer"); +</script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-text/parsing/text-wrap-style-computed.html b/tests/wpt/tests/css/css-text/parsing/text-wrap-style-computed.html new file mode 100644 index 00000000000..0a4a22d9c5f --- /dev/null +++ b/tests/wpt/tests/css/css-text/parsing/text-wrap-style-computed.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Text: getComputedStyle().textWrapStyle</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap-style"> +<meta name="assert" content="text-wrap-style computed value is auto | balance | pretty | stable"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_computed_value("text-wrap-style", "auto"); +test_computed_value("text-wrap-style", "balance"); +test_computed_value("text-wrap-style", "pretty"); +test_computed_value("text-wrap-style", "stable"); +</script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-text/parsing/text-wrap-style-invalid.html b/tests/wpt/tests/css/css-text/parsing/text-wrap-style-invalid.html new file mode 100644 index 00000000000..dcda82e465d --- /dev/null +++ b/tests/wpt/tests/css/css-text/parsing/text-wrap-style-invalid.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Text Module Test: parsing text-wrap-style with invalid values</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap-style"> +<meta name="assert" content="text-wrap-style supports only the grammar '<text-wrap-style>'."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +</head> +<body> +<script> +test_invalid_value("text-wrap-style", "normal"); +test_invalid_value("text-wrap-style", "none"); +test_invalid_value("text-wrap-style", "wrap"); +test_invalid_value("text-wrap-style", "nowrap"); +test_invalid_value("text-wrap-style", "wrap wrap"); +test_invalid_value("text-wrap-style", "nowrap nowrap"); +test_invalid_value("text-wrap-style", "wrap nowrap"); +test_invalid_value("text-wrap-style", "pretty balance"); +test_invalid_value("text-wrap-style", "balance stable"); +test_invalid_value("text-wrap-style", "stable pretty"); +test_invalid_value("text-wrap-style", "delicious wrap"); +test_invalid_value("text-wrap-style", "5px"); +</script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-text/parsing/text-wrap-style-valid.html b/tests/wpt/tests/css/css-text/parsing/text-wrap-style-valid.html new file mode 100644 index 00000000000..b3ca09ef2c6 --- /dev/null +++ b/tests/wpt/tests/css/css-text/parsing/text-wrap-style-valid.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Text Module Test: parsing text-wrap-style with valid values</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap-style"> +<meta name="assert" content="text-wrap-style supports the full grammar."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +</head> +<body> +<script> +test_valid_value("text-wrap-style", "auto"); +test_valid_value("text-wrap-style", "balance"); +test_valid_value("text-wrap-style", "pretty"); +test_valid_value("text-wrap-style", "stable"); + +test_valid_value("text-wrap-style", "initial"); +test_valid_value("text-wrap-style", "inherit"); +test_valid_value("text-wrap-style", "unset"); +test_valid_value("text-wrap-style", "revert"); +test_valid_value("text-wrap-style", "revert-layer"); +</script> +</body> +</html> diff --git a/tests/wpt/tests/css/css-values/round-mod-rem-computed.html b/tests/wpt/tests/css/css-values/round-mod-rem-computed.html index 320ab4a11a9..eb6dfe4e8ce 100644 --- a/tests/wpt/tests/css/css-values/round-mod-rem-computed.html +++ b/tests/wpt/tests/css/css-values/round-mod-rem-computed.html @@ -155,6 +155,10 @@ test_math_used('calc(round(1px + 0%, 1px + 0%))', '1px'); test_math_used('calc(mod(3px + 0%, 2px + 0%))', '1px'); test_math_used('calc(rem(3px + 0%, 2px + 0%))', '1px'); +test_math_used('round(1px + 0%, 1px)', '1px'); +test_math_used('mod(3px + 0%, 2px)', '1px'); +test_math_used('rem(3px + 0%, 2px)', '1px'); + // In round(A, B), if B is 0, the result is NaN. If A and B are both infinite, the result is NaN. // In mod(A, B) or rem(A, B), if B is 0, the result is NaN. If A is infinite, the result is NaN. for (let operator of ['round', 'mod', 'rem']) { diff --git a/tests/wpt/tests/css/cssom-view/checkVisibility.html b/tests/wpt/tests/css/cssom-view/checkVisibility.html index c0146dc14e1..c7bd5b69686 100644 --- a/tests/wpt/tests/css/cssom-view/checkVisibility.html +++ b/tests/wpt/tests/css/cssom-view/checkVisibility.html @@ -141,4 +141,10 @@ test(() => { cvhiddenwithupdate.getBoundingClientRect(); assert_true(cvhiddenwithupdate.checkVisibility()); }, 'checkVisibility on content-visibility:hidden element after forced layout update.'); + +test(() => { + document.documentElement.style.contentVisibility = "hidden"; + assert_true(document.documentElement.checkVisibility()); + document.documentElement.style.removeProperty("content-visibility"); +}, 'checkVisibility on root element with content-visibility: hidden returns true.'); </script> diff --git a/tests/wpt/tests/css/cssom/insert-dir-rule-crash.html b/tests/wpt/tests/css/cssom/insert-dir-rule-crash.html new file mode 100644 index 00000000000..6cffa0c62a5 --- /dev/null +++ b/tests/wpt/tests/css/cssom/insert-dir-rule-crash.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title>CSSOM Test: Chrome crash inserting :dir rule</title> +<link rel="help" href="https://crbug.com/1486351"> +<p>PASS if no crash.</p> +<style id="sheet"> </style> +<div id="host"></div> +<script> + let root = host.attachShadow({mode:"open"}); + root.innerHTML = "<slot></slot>"; + host.offsetTop; + host.innerHTML = "<span>Green</span>"; + sheet.sheet.insertRule("html:dir(ltr) { color: green; }"); + document.fonts.size(); +</script> diff --git a/tests/wpt/tests/css/selectors/dir-pseudo-on-input-element.html b/tests/wpt/tests/css/selectors/dir-pseudo-on-input-element.html index db528d4079b..f4a0de193a0 100644 --- a/tests/wpt/tests/css/selectors/dir-pseudo-on-input-element.html +++ b/tests/wpt/tests/css/selectors/dir-pseudo-on-input-element.html @@ -84,7 +84,7 @@ test(() => { document.body.removeChild(container); }, 'input element whose type attribute is in the telephone state in a RTL block'); -for (let type of ['text', 'search', 'url', 'email']) { +for (const type of ['password', 'text', 'search', 'url', 'email', 'submit', 'reset', 'button']) { test(() => { const input = document.createElement('input'); input.type = type; @@ -143,7 +143,7 @@ test(() => { assert_true(input.matches(':dir(rtl)')); // Changing to a different type that does't use value causes the bidi rule to no longer apply. - input.type = 'password'; + input.type = 'radio'; assert_true(input.matches(':dir(ltr)')); assert_false(input.matches(':dir(rtl)')); @@ -153,8 +153,7 @@ test(() => { assert_true(input.matches(':dir(rtl)')); }, 'dynamic changes to type of input elements affect whether value is used for dir=auto'); -for (let type of ['password', 'date', 'time', 'number', 'range', 'color', - 'checkbox', 'radio', 'submit', 'image', 'reset', 'button']) { +for (const type of ['date', 'time', 'number', 'range', 'color', 'checkbox', 'radio', 'image']) { test(() => { const input = document.createElement('input'); input.type = type; diff --git a/tests/wpt/tests/domxpath/001.html b/tests/wpt/tests/domxpath/001.html deleted file mode 100644 index 4931417af30..00000000000 --- a/tests/wpt/tests/domxpath/001.html +++ /dev/null @@ -1,60 +0,0 @@ -<!doctype html> -<meta charset="utf8"> -<title>XPath in text/html: elements</title> -<link rel="help" href="http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#Interfaces"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<body> -<div id="log"><span></span></div> -<div><span></span></div> -<dØdd></dØdd> -<svg> -<path /> -<path /> -</svg> - -<script> -function test_xpath_succeeds(path, expected, resolver) { - resolver = resolver ? resolver : null; - var res = document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - actual = []; - for (var i=0;;i++) { - var node = res.snapshotItem(i); - if (node === null) { - break; - } - actual.push(node); - } - assert_array_equals(actual, expected); -} - -function test_xpath_throws(path, error_code, resolver) { - resolver = resolver ? resolver : null; - assert_throws_dom(error_code, function() {document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)}) -} - -function ns_resolver(x) { - map = {"html":"http://www.w3.org/1999/xhtml", - "svg":"http://www.w3.org/2000/svg", - "math":"http://www.w3.org/1998/Math/MathML"}; - var rv = map.hasOwnProperty(x) ? map[x] : null; - return rv; -} - -generate_tests(test_xpath_succeeds,[ - ["HTML elements no namespace prefix", "//div", document.getElementsByTagName("div")], - ["HTML elements namespace prefix", "//html:div", document.getElementsByTagName("div"), ns_resolver], - ["HTML elements mixed use of prefix", "//html:div/span", document.getElementsByTagName("span"), ns_resolver], - ["SVG elements no namespace prefix", "//path", []], - ["SVG elements namespace prefix", "//svg:path", document.getElementsByTagName("path"), ns_resolver], - ["HTML elements mixed case", "//DiV", document.getElementsByTagName("div")], - ["SVG elements mixed case selector", "//svg:PatH", [], ns_resolver], - ["Non-ascii HTML element", "//dØdd", document.getElementsByTagName("dØdd"), ns_resolver], - ["Non-ascii HTML element2", "//dødd", [], ns_resolver], - ["Non-ascii HTML element3", "//DØDD", document.getElementsByTagName("dØdd"), ns_resolver] -]) - -generate_tests(test_xpath_throws, [ - ["Throw with invalid prefix", "//invalid:path", "NAMESPACE_ERR"], -]) -</script> diff --git a/tests/wpt/tests/domxpath/002.html b/tests/wpt/tests/domxpath/002.html deleted file mode 100644 index c5c1fcc5292..00000000000 --- a/tests/wpt/tests/domxpath/002.html +++ /dev/null @@ -1,60 +0,0 @@ -<!doctype html> -<meta charset="utf8"> -<title>XPath in text/html: attributes</title> -<link rel="help" href="http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#Interfaces"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<body> -<div id="log" nonÄsciiAttribute><span></span></div> -<svg xmlns="http://www.w3.org/2000/svg", xmlns:xlink="http://www.w3.org/1999/xlink"> -<path id="a" refx /> -<path id="b" nonÄscii xlink:href /> -</svg> - -<script> -function test_xpath_succeeds(path, expected, resolver) { - resolver = resolver ? resolver : null; - var res = document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - actual = []; - for (var i=0;;i++) { - var node = res.snapshotItem(i); - if (node === null) { - break; - } - actual.push(node); - } - assert_array_equals(actual, expected); -} - -function test_xpath_throws(path, error_code, resolver) { - resolver = resolver ? resolver : null; - assert_throws_dom(error_code, function() {document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)}) -} - -function ns_resolver(x) { - map = {"html":"http://www.w3.org/1999/xhtml", - "svg":"http://www.w3.org/2000/svg", - "math":"http://www.w3.org/1998/Math/MathML", - "xlink":"http://www.w3.org/1999/xlink"}; - var rv = map.hasOwnProperty(x) ? map[x] : null; - return rv; -} - -generate_tests(test_xpath_succeeds,[ - ["Select html element based on attribute", "//div[@id='log']", [document.getElementById("log")]], - ["Select html element based on attribute mixed case", "//div[@Id='log']", [document.getElementById("log")]], - ["Select both HTML and SVG elements based on attribute", "//*[@id]", [document.getElementById("log")].concat(Array.prototype.slice.call(document.getElementsByTagName("path")))], - ["Select HTML element with non-ascii attribute 1", "//*[@nonÄsciiattribute]", [document.getElementById("log")]], - ["Select HTML element with non-ascii attribute 2", "//*[@nonäsciiattribute]", []], - ["Select HTML element with non-ascii attribute 3", "//*[@nonÄsciiAttribute]", [document.getElementById("log")]], - ["Select SVG element based on mixed case attribute", "//svg:path[@Id]", [], ns_resolver], - ["Select both HTML and SVG elements based on mixed case attribute", "//*[@Id]", [document.getElementById("log")]], - ["Select SVG elements with refX attribute", "//*[@refX]", [document.getElementById("a")]], - ["Select SVG elements with refX attribute incorrect case", "//*[@Refx]", []], - ["Select SVG elements with refX attribute lowercase", "//*[@refx]", []], - ["Select SVG element with non-ascii attribute 1", "//*[@nonÄscii]", [document.getElementById("b")]], - ["Select SVG element with non-ascii attribute 2", "//*[@nonäscii]", []], - ["xmlns attribute", "//*[@xmlns]", []], - ["svg element with XLink attribute", "//*[@xlink:href]", [document.getElementById("b")], ns_resolver] -]) -</script> diff --git a/tests/wpt/tests/domxpath/text-html-attributes.html b/tests/wpt/tests/domxpath/text-html-attributes.html new file mode 100644 index 00000000000..2157dcd2d68 --- /dev/null +++ b/tests/wpt/tests/domxpath/text-html-attributes.html @@ -0,0 +1,102 @@ +<!doctype html> +<meta charset="utf8"> +<title>XPath in text/html: attributes</title> +<link rel="help" href="http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#Interfaces"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<div id="log" nonÄsciiAttribute><span></span></div> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<path id="a" refx /> +<path id="b" nonÄscii xlink:href /> +</svg> + +<script> +function test_xpath_succeeds(path, expected, resolver) { + resolver = resolver ? resolver : null; + var res = document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + actual = []; + for (var i=0;;i++) { + var node = res.snapshotItem(i); + if (node === null) { + break; + } + actual.push(node); + } + assert_array_equals(actual, expected); +} + +function test_xpath_throws(path, error_code, resolver) { + resolver = resolver ? resolver : null; + assert_throws_dom(error_code, function() {document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)}) +} + +function ns_resolver(x) { + map = {"html":"http://www.w3.org/1999/xhtml", + "svg":"http://www.w3.org/2000/svg", + "math":"http://www.w3.org/1998/Math/MathML", + "xlink":"http://www.w3.org/1999/xlink"}; + var rv = map.hasOwnProperty(x) ? map[x] : null; + return rv; +} + +test(function() { + test_xpath_succeeds("//div[@id='log']", [document.getElementById("log")]); +}, "Select html element based on attribute"); + +test(function() { + test_xpath_succeeds("//div[@Id='log']", [document.getElementById("log")]); +}, "Select html element based on attribute mixed case"); + +test(function() { + test_xpath_succeeds("//*[@id]", [document.getElementById("log")].concat(Array.prototype.slice.call(document.getElementsByTagName("path")))); +}, "Select both HTML and SVG elements based on attribute"); + +test(function() { + test_xpath_succeeds("//*[@nonÄsciiattribute]", [document.getElementById("log")]); +}, "Select HTML element with non-ascii attribute 1"); + +test(function() { + test_xpath_succeeds("//*[@nonäsciiattribute]", []); +}, "Select HTML element with non-ascii attribute 2"); + +test(function() { + test_xpath_succeeds("//*[@nonÄsciiAttribute]", [document.getElementById("log")]); +}, "Select HTML element with non-ascii attribute 3"); + +test(function() { + test_xpath_succeeds("//svg:path[@Id]", [], ns_resolver); +}, "Select SVG element based on mixed case attribute"); + +test(function() { + test_xpath_succeeds("//*[@Id]", [document.getElementById("log")]); +}, "Select both HTML and SVG elements based on mixed case attribute"); + +test(function() { + test_xpath_succeeds("//*[@refX]", [document.getElementById("a")]); +}, "Select SVG elements with refX attribute"); + +test(function() { + test_xpath_succeeds("//*[@Refx]", []); +}, "Select SVG elements with refX attribute incorrect case"); + +test(function() { + test_xpath_succeeds("//*[@refx]", []); +}, "Select SVG elements with refX attribute lowercase"); + +test(function() { + test_xpath_succeeds("//*[@nonÄscii]", [document.getElementById("b")]); +}, "Select SVG element with non-ascii attribute 1"); + +test(function() { + test_xpath_succeeds("//*[@nonäscii]", []); +}, "Select SVG element with non-ascii attribute 2"); + +test(function() { + test_xpath_succeeds("//*[@xmlns]", []); +}, "xmlns attribute"); + +test(function() { + test_xpath_succeeds("//*[@xlink:href]", [document.getElementById("b")], ns_resolver); +}, "svg element with XLink attribute"); +</script> diff --git a/tests/wpt/tests/domxpath/text-html-elements.html b/tests/wpt/tests/domxpath/text-html-elements.html new file mode 100644 index 00000000000..b895323fbad --- /dev/null +++ b/tests/wpt/tests/domxpath/text-html-elements.html @@ -0,0 +1,87 @@ +<!doctype html> +<meta charset="utf8"> +<title>XPath in text/html: elements</title> +<link rel="help" href="http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#Interfaces"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<div id="log"><span></span></div> +<div><span></span></div> +<dØdd></dØdd> +<svg> +<path /> +<path /> +</svg> + +<script> +function test_xpath_succeeds(path, expected, resolver) { + resolver = resolver ? resolver : null; + var res = document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + actual = []; + for (var i=0;;i++) { + var node = res.snapshotItem(i); + if (node === null) { + break; + } + actual.push(node); + } + assert_array_equals(actual, expected); +} + +function test_xpath_throws(path, error_code, resolver) { + resolver = resolver ? resolver : null; + assert_throws_dom(error_code, function() {document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)}) +} + +function ns_resolver(x) { + map = {"html":"http://www.w3.org/1999/xhtml", + "svg":"http://www.w3.org/2000/svg", + "math":"http://www.w3.org/1998/Math/MathML"}; + var rv = map.hasOwnProperty(x) ? map[x] : null; + return rv; +} + +test(function() { + test_xpath_succeeds("//div", document.getElementsByTagName("div")); +}, "HTML elements no namespace prefix"); + +test(function() { + test_xpath_succeeds("//html:div", document.getElementsByTagName("div"), ns_resolver); +}, "HTML elements namespace prefix"); + +test(function() { + test_xpath_succeeds("//html:div/span", document.getElementsByTagName("span"), ns_resolver); +}, "HTML elements mixed use of prefix"); + +test(function() { + test_xpath_succeeds("//path", []); +}, "SVG elements no namespace prefix"); + +test(function() { + test_xpath_succeeds("//svg:path", document.getElementsByTagName("path"), ns_resolver); +}, "SVG elements namespace prefix"); + +test(function() { + test_xpath_succeeds("//DiV", document.getElementsByTagName("div")); +}, "HTML elements mixed case"); + +test(function() { + test_xpath_succeeds("//svg:PatH", [], ns_resolver); +}, "SVG elements mixed case selector"); + +test(function() { + test_xpath_succeeds("//dØdd", document.getElementsByTagName("dØdd"), ns_resolver); +}, "Non-ascii HTML element"); + +test(function() { + test_xpath_succeeds("//dødd", [], ns_resolver); +}, "Non-ascii HTML element2"); + +test(function() { + test_xpath_succeeds("//DØDD", document.getElementsByTagName("dØdd"), ns_resolver); +}, "Non-ascii HTML element3"); + +test(function() { + test_xpath_throws("//invalid:path", "NAMESPACE_ERR"); +}, "Throw with invalid prefix"); +</script> diff --git a/tests/wpt/tests/editing/data/formatblock.js b/tests/wpt/tests/editing/data/formatblock.js index 64e0d11d594..0161e4da01b 100644 --- a/tests/wpt/tests/editing/data/formatblock.js +++ b/tests/wpt/tests/editing/data/formatblock.js @@ -147,14 +147,14 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"div"]}], ["<blockquote>[foobar]</blockquote>", [["defaultparagraphseparator","div"],["formatblock","<div>"]], - "<blockquote><div>[foobar]</div></blockquote>", + "<div>[foobar]</div>", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"blockquote",false,false,"div"]}], ["<blockquote>[foobar]</blockquote>", [["defaultparagraphseparator","p"],["formatblock","<div>"]], - "<blockquote><div>[foobar]</div></blockquote>", + "<div>[foobar]</div>", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"blockquote",false,false,"div"]}], ["<h1>[foobar]</h1>", [["defaultparagraphseparator","div"],["formatblock","<div>"]], "<div>[foobar]</div>", @@ -239,12 +239,12 @@ var browserTests = [ [["defaultparagraphseparator","div"],["formatblock","<div>"]], "<div>[foo</div><div>bar]</div>", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[true,false,"dt",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[true,false,"dl",false,false,"div"]}], ["<dl><dt>[foo<dd>bar]</dl>", [["defaultparagraphseparator","p"],["formatblock","<div>"]], "<div>[foo</div><div>bar]</div>", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[true,false,"dt",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[true,false,"dl",false,false,"div"]}], ["<ol><li>[foobar]</ol>", [["defaultparagraphseparator","div"],["formatblock","<div>"]], "<ol><li><div>[foobar]</div></li></ol>", @@ -287,14 +287,14 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"pre",false,false,"div"]}], ["<article>[foobar]</article>", [["defaultparagraphseparator","div"],["formatblock","<div>"]], - "<article><div>[foobar]</div></article>", + "<div>[foobar]</div>", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"article",false,false,"div"]}], ["<article>[foobar]</article>", [["defaultparagraphseparator","p"],["formatblock","<div>"]], - "<article><div>[foobar]</div></article>", + "<div>[foobar]</div>", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"article",false,false,"div"]}], ["<ins>[foobar]</ins>", [["defaultparagraphseparator","div"],["formatblock","<div>"]], "<div><ins>[foobar]</ins></div>", @@ -482,14 +482,14 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<blockquote>[foobar]</blockquote>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], - "<blockquote><p>[foobar]</p></blockquote>", + "<p>[foobar]</p>", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"blockquote",false,false,"p"]}], ["<blockquote>[foobar]</blockquote>", [["defaultparagraphseparator","p"],["formatblock","<p>"]], - "<blockquote><p>[foobar]</p></blockquote>", + "<p>[foobar]</p>", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"blockquote",false,false,"p"]}], ["<h1>[foobar]</h1>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], "<p>[foobar]</p>", @@ -574,12 +574,12 @@ var browserTests = [ [["defaultparagraphseparator","div"],["formatblock","<p>"]], "<p>[foo</p><p>bar]</p>", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[true,false,"dt",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[true,false,"dl",false,false,"p"]}], ["<dl><dt>[foo<dd>bar]</dl>", [["defaultparagraphseparator","p"],["formatblock","<p>"]], "<p>[foo</p><p>bar]</p>", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[true,false,"dt",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[true,false,"dl",false,false,"p"]}], ["<ol><li>[foobar]</ol>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], "<ol><li><p>[foobar]</p></li></ol>", @@ -622,34 +622,34 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"pre",false,false,"p"]}], ["<listing>[foobar]</listing>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], - "<p>[foobar]</p>", + "<p><listing>[foobar]</listing></p>", [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], ["<listing>[foobar]</listing>", [["defaultparagraphseparator","p"],["formatblock","<p>"]], - "<p>[foobar]</p>", + "<p><listing>[foobar]</listing></p>", [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], ["<xmp>[foobar]</xmp>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], - "<p>[foobar]</p>", + "<p><xmp>[foobar]</xmp></p>", [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], ["<xmp>[foobar]</xmp>", [["defaultparagraphseparator","p"],["formatblock","<p>"]], - "<p>[foobar]</p>", + "<p><xmp>[foobar]</xmp></p>", [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], ["<article>[foobar]</article>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], - "<article><p>[foobar]</p></article>", + "<p>[foobar]</p>", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"article",false,false,"p"]}], ["<article>[foobar]</article>", [["defaultparagraphseparator","p"],["formatblock","<p>"]], - "<article><p>[foobar]</p></article>", + "<p>[foobar]</p>", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"article",false,false,"p"]}], ["<ins>[foobar]</ins>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], "<p><ins>[foobar]</ins></p>", @@ -693,43 +693,46 @@ var browserTests = [ ["<blockquote>[foo]</blockquote><p>extra", [["formatblock","<blockquote>"]], "<blockquote>[foo]</blockquote><p>extra</p>", - [false], - {"formatblock":[false,false,"",false,false,""]}], + [true], + {"formatblock":[false,false,"blockquote",false,false,"blockquote"]}], ["<blockquote><p>[foo]<p>bar</blockquote><p>extra", [["formatblock","<blockquote>"]], - "<blockquote><p>[foo]</p><p>bar</p></blockquote><p>extra</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<blockquote><blockquote>[foo]</blockquote><p>bar</p></blockquote><p>extra</p>", + [true], + {"formatblock":[false,false,"p",false,false,"blockquote"]}], ["[foo]<blockquote>bar</blockquote><p>extra", [["formatblock","<blockquote>"]], - "[foo]<blockquote>bar</blockquote><p>extra</p>", - [false], - {"formatblock":[false,false,"",false,false,""]}], + "<blockquote>[foo]</blockquote><blockquote>bar</blockquote><p>extra</p>", + [true], + {"formatblock":[false,false,"",false,false,"blockquote"]}], ["<p>[foo<p>bar]<p>baz", [["formatblock","<blockquote>"]], - "<p>[foo</p><p>bar]</p><p>baz</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<blockquote>[foo<br>bar]</blockquote><p>baz</p>", + "<blockquote>[foo</blockquote><blockquote>bar]</blockquote><p>baz</p>", + ] + [true], + {"formatblock":[false,false,"",false,false,"blockquote"]}], ["<section>[foo]</section>", [["formatblock","<blockquote>"]], - "<section>[foo]</section>", - [false], - {"formatblock":[false,false,"",false,false,""]}], + "<blockquote>[foo]</blockquote>", + [true], + {"formatblock":[false,false,"section",false,false,"blockquote"]}], ["<section><p>[foo]</section>", [["formatblock","<blockquote>"]], - "<section><p>[foo]</p></section>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<section><blockquote>[foo]</blockquote></section>", + [true], + {"formatblock":[false,false,"p",false,false,"blockquote"]}], ["<section><hgroup><h1>[foo]</h1><h2>bar</h2></hgroup><p>baz</section>", [["formatblock","<blockquote>"]], - "<section><hgroup><h1>[foo]</h1><h2>bar</h2></hgroup><p>baz</p></section>", - [false], - {"formatblock":[false,false,"h1",false,false,"h1"]}], + "<section><hgroup><blockquote>[foo]</blockquote><h2>bar</h2></hgroup><p>baz</p></section>", + [true], + {"formatblock":[false,false,"h1",false,false,"blockquote"]}], ["<section>[foo]</section>", [["formatblock","<article>"]], - "<section>[foo]</section>", - [false], - {"formatblock":[false,false,"",false,false,""]}], + "<article>[foo]</article>", + [true], + {"formatblock":[false,false,"section",false,false,"article"]}], ["<div>[foobar]</div>", [["defaultparagraphseparator","div"],["formatblock","<address>"]], "<address>[foobar]</address>", @@ -742,14 +745,14 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"div",false,false,"address"]}], ["<div>[foobar]</div>", [["formatblock","<article>"]], - "<div>[foobar]</div>", - [false], - {"formatblock":[false,false,"div",false,false,"div"]}], + "<article>[foobar]</article>", + [true], + {"formatblock":[false,false,"div",false,false,"article"]}], ["<div>[foobar]</div>", [["formatblock","<blockquote>"]], - "<div>[foobar]</div>", - [false], - {"formatblock":[false,false,"div",false,false,"div"]}], + "<blockquote>[foobar]</blockquote>", + [true], + {"formatblock":[false,false,"div",false,false,"blockquote"]}], ["<div>[foobar]</div>", [["defaultparagraphseparator","div"],["formatblock","<dd>"]], "<dl><dd>[foobar]</dd></dl>", @@ -882,19 +885,19 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"address"]}], ["<p>[foobar]</p>", [["formatblock","<article>"]], - "<p>[foobar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<article>[foobar]</article>", + [true], + {"formatblock":[false,false,"p",false,false,"article"]}], ["<p>[foobar]</p>", [["formatblock","<aside>"]], - "<p>[foobar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<aside>[foobar]</aside>", + [true], + {"formatblock":[false,false,"p",false,false,"aside"]}], ["<p>[foobar]</p>", [["formatblock","<blockquote>"]], - "<p>[foobar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<blockquote>[foobar]</blockquote>", + [true], + {"formatblock":[false,false,"p",false,false,"blockquote"]}], ["<p>[foobar]</p>", [["formatblock","<body>"]], "<p>[foobar]</p>", @@ -957,9 +960,9 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foobar]</p>", [["formatblock","<footer>"]], - "<p>[foobar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<footer>[foobar]</footer>", + [true], + {"formatblock":[false,false,"p",false,false,"footer"]}], ["<p>[foobar]</p>", [["formatblock","<form>"]], "<p>[foobar]</p>", @@ -1027,9 +1030,9 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"h6"]}], ["<p>[foobar]</p>", [["formatblock","<header>"]], - "<p>[foobar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<header>[foobar]</header>", + [true], + {"formatblock":[false,false,"p",false,false,"header"]}], ["<p>[foobar]</p>", [["formatblock","<head>"]], "<p>[foobar]</p>", @@ -1037,9 +1040,9 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foobar]</p>", [["formatblock","<hgroup>"]], - "<p>[foobar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<hgroup>[foobar]</hgroup>", + [true], + {"formatblock":[false,false,"p",false,false,"hgroup"]}], ["<p>[foobar]</p>", [["formatblock","<hr>"]], "<p>[foobar]</p>", @@ -1072,9 +1075,9 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foobar]</p>", [["formatblock","<nav>"]], - "<p>[foobar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<nav>[foobar]</nav>", + [true], + {"formatblock":[false,false,"p",false,false,"nav"]}], ["<p>[foobar]</p>", [["formatblock","<ol>"]], "<p>[foobar]</p>", @@ -1097,9 +1100,9 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"pre"]}], ["<p>[foobar]</p>", [["formatblock","<section>"]], - "<p>[foobar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + "<section>[foobar]</section>", + [true], + {"formatblock":[false,false,"p",false,false,"section"]}], ["<p>[foobar]</p>", [["formatblock","<ul>"]], "<p>[foobar]</p>", @@ -1117,29 +1120,44 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<address>"]], - "<address>[foo<br>bar]</address>", + [ + "<address>[foo<br>bar]</address>", + "<address>[foo</address><address>bar]</address>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"address"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","p"],["formatblock","<address>"]], - "<address>[foo<br>bar]</address>", + [ + "<address>[foo<br>bar]</address>", + "<address>[foo</address><address>bar]</address>", + ], [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"address"]}], ["<p>[foo<p>bar]", [["formatblock","<article>"]], - "<p>[foo</p><p>bar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<article>[foo<br>bar]</article>", + "<article>[foo</article><article>bar]</article>", + ], + [true], + {"formatblock":[false,false,"p",false,false,"article"]}], ["<p>[foo<p>bar]", [["formatblock","<aside>"]], - "<p>[foo</p><p>bar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<aside>[foo<br>bar]</aside>", + "<aside>[foo</aside><aside>bar]</aside>", + ], + [true], + {"formatblock":[false,false,"p",false,false,"aside"]}], ["<p>[foo<p>bar]", [["formatblock","<blockquote>"]], - "<p>[foo</p><p>bar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<blockquote>[foo<br>bar]</blockquote>", + "<blockquote>[foo</blockquote><blockquote>bar]</blockquote>", + ], + [true], + {"formatblock":[false,false,"p",false,false,"blockquote"]}], ["<p>[foo<p>bar]", [["formatblock","<body>"]], "<p>[foo</p><p>bar]</p>", @@ -1172,12 +1190,18 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<div>"]], - "<div>[foo</div><div>bar]</div>", + [ + "<div>[foo<br>bar]</div>", + "<div>[foo</div><div>bar]</div>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"div"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","p"],["formatblock","<div>"]], - "<div>[foo</div><div>bar]</div>", + [ + "<div>[foo<br>bar]</div>", + "<div>[foo</div><div>bar]</div>", + ], [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"div"]}], ["<p>[foo<p>bar]", @@ -1212,9 +1236,12 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foo<p>bar]", [["formatblock","<footer>"]], - "<p>[foo</p><p>bar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<footer>[foo<br>bar]</footer>", + "<footer>[foo</footer><footer>bar]</footer>", + ], + [true], + {"formatblock":[false,false,"p",false,false,"footer"]}], ["<p>[foo<p>bar]", [["formatblock","<form>"]], "<p>[foo</p><p>bar]</p>", @@ -1222,69 +1249,108 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<h1>"]], - "<h1>[foo<br>bar]</h1>", + [ + "<h1>[foo<br>bar]</h1>", + "<h1>[foo</h1><h1>bar]</h1>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"h1"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","p"],["formatblock","<h1>"]], - "<h1>[foo<br>bar]</h1>", + [ + "<h1>[foo<br>bar]</h1>", + "<h1>[foo</h1><h1>bar]</h1>", + ], [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"h1"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<h2>"]], - "<h2>[foo<br>bar]</h2>", + [ + "<h2>[foo<br>bar]</h2>", + "<h2>[foo</h2><h2>bar]</h2>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"h2"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","p"],["formatblock","<h2>"]], - "<h2>[foo<br>bar]</h2>", + [ + "<h2>[foo<br>bar]</h2>", + "<h2>[foo</h2><h2>bar]</h2>", + ], [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"h2"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<h3>"]], - "<h3>[foo<br>bar]</h3>", + [ + "<h3>[foo<br>bar]</h3>", + "<h3>[foo</h3><h3>bar]</h3>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"h3"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","p"],["formatblock","<h3>"]], - "<h3>[foo<br>bar]</h3>", + [ + "<h3>[foo<br>bar]</h3>", + "<h3>[foo</h3><h3>bar]</h3>", + ], [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"h3"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<h4>"]], - "<h4>[foo<br>bar]</h4>", + [ + "<h4>[foo<br>bar]</h4>", + "<h4>[foo</h4><h4>bar]</h4>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"h4"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","p"],["formatblock","<h4>"]], - "<h4>[foo<br>bar]</h4>", + [ + "<h4>[foo<br>bar]</h4>", + "<h4>[foo</h4><h4>bar]</h4>", + ], [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"h4"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<h5>"]], - "<h5>[foo<br>bar]</h5>", + [ + "<h5>[foo<br>bar]</h5>", + "<h5>[foo</h5><h5>bar]</h5>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"h5"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","p"],["formatblock","<h5>"]], - "<h5>[foo<br>bar]</h5>", + [ + "<h5>[foo<br>bar]</h5>", + "<h5>[foo</h5><h5>bar]</h5>", + ], [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"h5"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<h6>"]], - "<h6>[foo<br>bar]</h6>", + [ + "<h6>[foo<br>bar]</h6>", + "<h6>[foo</h6><h6>bar]</h6>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"h6"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","p"],["formatblock","<h6>"]], - "<h6>[foo<br>bar]</h6>", + [ + "<h6>[foo<br>bar]</h6>", + "<h6>[foo</h6><h6>bar]</h6>", + ], [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"h6"]}], ["<p>[foo<p>bar]", [["formatblock","<header>"]], - "<p>[foo</p><p>bar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<header>[foo<br>bar]</header>", + "<header>[foo</header><header>bar]</header>", + ], + [true], + {"formatblock":[false,false,"p",false,false,"header"]}], ["<p>[foo<p>bar]", [["formatblock","<head>"]], "<p>[foo</p><p>bar]</p>", @@ -1292,9 +1358,12 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foo<p>bar]", [["formatblock","<hgroup>"]], - "<p>[foo</p><p>bar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<hgroup>[foo<br>bar]</hgroup>", + "<hgroup>[foo</hgroup><hgroup>bar]</hgroup>", + ], + [true], + {"formatblock":[false,false,"p",false,false,"hgroup"]}], ["<p>[foo<p>bar]", [["formatblock","<hr>"]], "<p>[foo</p><p>bar]</p>", @@ -1327,9 +1396,12 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foo<p>bar]", [["formatblock","<nav>"]], - "<p>[foo</p><p>bar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<nav>[foo<br>bar]</nav>", + "<nav>[foo</nav><nav>bar]</nav>", + ], + [true], + {"formatblock":[false,false,"p",false,false,"nav"]}], ["<p>[foo<p>bar]", [["formatblock","<ol>"]], "<p>[foo</p><p>bar]</p>", @@ -1347,7 +1419,10 @@ var browserTests = [ {"formatblock":[false,false,"p",false,false,"p"]}], ["<p>[foo<p>bar]", [["defaultparagraphseparator","div"],["formatblock","<pre>"]], - "<pre>[foo<br>bar]</pre>", + [ + "<pre>[foo<br>bar]</pre>", + "<pre>[foo</pre><pre>bar]</pre>", + ], [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"p",false,false,"pre"]}], ["<p>[foo<p>bar]", @@ -1357,9 +1432,12 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"p",false,false,"pre"]}], ["<p>[foo<p>bar]", [["formatblock","<section>"]], - "<p>[foo</p><p>bar]</p>", - [false], - {"formatblock":[false,false,"p",false,false,"p"]}], + [ + "<section>[foo<br>bar]</section>", + "<section>[foo</section><section>bar]</section>", + ], + [true], + {"formatblock":[false,false,"p",false,false,"section"]}], ["<p>[foo<p>bar]", [["formatblock","<ul>"]], "<p>[foo</p><p>bar]</p>", @@ -1672,44 +1750,44 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[true,false,"",false,false,"h1"]}], ["<div>[foo<p>bar]</p></div>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], - "<div><p>[foo</p><p>bar]</p></div>", + "<p>[foo</p><div><p>bar]</p></div>", [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[true,false,"",false,false,"p"]}], ["<div>[foo<p>bar]</p></div>", [["defaultparagraphseparator","p"],["formatblock","<p>"]], - "<div><p>[foo</p><p>bar]</p></div>", + "<p>[foo</p><div><p>bar]</p></div>", [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[true,false,"",false,false,"p"]}], ["<xmp>[foo]</xmp>", [["defaultparagraphseparator","div"],["formatblock","<p>"]], - "<p>[foo]</p>", + "<p><xmp>[foo]</xmp></p>", [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"p"]}], ["<xmp>[foo]</xmp>", [["defaultparagraphseparator","p"],["formatblock","<p>"]], - "<p>[foo]</p>", + "<p><xmp>[foo]</xmp></p>", [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"p"]}], ["<xmp>[foo]</xmp>", [["defaultparagraphseparator","div"],["formatblock","<div>"]], - "<div>[foo]</div>", + "<div><xmp>[foo]</xmp></div>", [true,true], {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"div"]}], ["<xmp>[foo]</xmp>", [["defaultparagraphseparator","p"],["formatblock","<div>"]], - "<div>[foo]</div>", + "<div><xmp>[foo]</xmp></div>", [true,true], {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"div"]}], ["<div><ol><li>[foo]</ol></div>", [["defaultparagraphseparator","div"],["formatblock","<div>"]], - "<div><ol><li><div>[foo]</div></li></ol></div>", + "<div><ol><li>[foo]</li></ol></div>", [true,true], - {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"div",false,false,"div"]}], ["<div><ol><li>[foo]</ol></div>", [["defaultparagraphseparator","p"],["formatblock","<div>"]], - "<div><ol><li><div>[foo]</div></li></ol></div>", + "<div><ol><li>[foo]</li></ol></div>", [true,true], - {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"",false,false,"div"]}], + {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"div",false,false,"div"]}], ["<div><table><tr><td>[foo]</table></div>", [["defaultparagraphseparator","div"],["formatblock","<div>"]], "<div><table><tbody><tr><td><div>[foo]</div></td></tr></tbody></table></div>", @@ -1752,22 +1830,22 @@ var browserTests = [ {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[true,false,"div",false,false,"div"]}], ["<div style=color:blue>[foo]</div>", [["stylewithcss","true"],["defaultparagraphseparator","div"],["formatblock","<p>"]], - "<p><span style=\"color:rgb(0, 0, 255)\">[foo]</span></p>", + "<p style=\"color:rgb(0, 0, 255)\">[foo]</p>", [true,true,true], {"stylewithcss":[false,false,"",false,true,""],"defaultparagraphseparator":[false,false,"p",false,false,"div"],"formatblock":[false,false,"div",false,false,"p"]}], ["<div style=color:blue>[foo]</div>", [["stylewithcss","false"],["defaultparagraphseparator","div"],["formatblock","<p>"]], - "<p><font color=\"#0000ff\">[foo]</font></p>", + "<p style=\"color:rgb(0, 0, 255)\">[foo]</p>", [true,true,true], {"stylewithcss":[false,true,"",false,false,""],"defaultparagraphseparator":[false,false,"div",false,false,"div"],"formatblock":[false,false,"div",false,false,"p"]}], ["<div style=color:blue>[foo]</div>", [["stylewithcss","true"],["defaultparagraphseparator","p"],["formatblock","<p>"]], - "<p><span style=\"color:rgb(0, 0, 255)\">[foo]</span></p>", + "<p style=\"color:rgb(0, 0, 255)\">[foo]</p>", [true,true,true], {"stylewithcss":[false,false,"",false,true,""],"defaultparagraphseparator":[false,false,"div",false,false,"p"],"formatblock":[false,false,"div",false,false,"p"]}], ["<div style=color:blue>[foo]</div>", [["stylewithcss","false"],["defaultparagraphseparator","p"],["formatblock","<p>"]], - "<p><font color=\"#0000ff\">[foo]</font></p>", + "<p style=\"color:rgb(0, 0, 255)\">[foo]</p>", [true,true,true], {"stylewithcss":[false,true,"",false,false,""],"defaultparagraphseparator":[false,false,"p",false,false,"p"],"formatblock":[false,false,"div",false,false,"p"]}], ["{<p>foo</p>ba]r", diff --git a/tests/wpt/tests/editing/edit-context/edit-context-input.tentative.html b/tests/wpt/tests/editing/edit-context/edit-context-input.tentative.html index 0f05606a356..f65dfbc915d 100644 --- a/tests/wpt/tests/editing/edit-context/edit-context-input.tentative.html +++ b/tests/wpt/tests/editing/edit-context/edit-context-input.tentative.html @@ -31,8 +31,6 @@ document.body.appendChild(test); test.editContext = editContext; test.focus(); - textInputController.setComposition("foo"); - assert_equals(test.innerHTML, ""); await test_driver.send_keys(test, 'a'); assert_equals(test.innerHTML, ""); test.remove(); diff --git a/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html new file mode 100644 index 00000000000..38eada4513c --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-no-referrer-when-downgrade.tentative.https.html @@ -0,0 +1,23 @@ +<!doctype html> +<html> +<head> +<title>FetchLater Referrer Header: No Referrer When Downgrade Policy</title> +<meta name='referrer' content='no-referrer-when-downgrade'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/fetch/fetch-later/resources/header-referrer-helper.js"></script> +</head> +<body> +<script> + +const { + HTTPS_ORIGIN, +} = get_host_info(); + +testReferrerHeader(token(), HTTPS_ORIGIN, REFERRER_URL); + +</script> +</body> +</html> diff --git a/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html new file mode 100644 index 00000000000..75e9ece7ba5 --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-no-referrer.tentative.https.html @@ -0,0 +1,19 @@ +<!doctype html> +<html> +<head> +<title>FetchLater Referrer Header: No Referrer Policy</title> +<meta name='referrer' content='no-referrer'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/fetch/fetch-later/resources/header-referrer-helper.js"></script> +</head> +<body> +<script> + +testReferrerHeader(token(), /*host=*/'', /*expectedReferer=*/""); + +</script> +</body> +</html> diff --git a/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html new file mode 100644 index 00000000000..b9f14171ba3 --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-origin-when-cross-origin.tentative.https.html @@ -0,0 +1,25 @@ +<!doctype html> +<html> +<head> +<title>FetchLater Referrer Header: Origin When Cross Origin Policy</title> +<meta name='referrer' content='origin-when-cross-origin'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/fetch/fetch-later/resources/header-referrer-helper.js"></script> +</head> +<body> +<script> + +const { + HTTPS_ORIGIN, + HTTPS_REMOTE_ORIGIN +} = get_host_info(); + +testReferrerHeader(token(), HTTPS_ORIGIN, REFERRER_URL); +testReferrerHeader(token(), HTTPS_REMOTE_ORIGIN, REFERRER_ORIGIN); + +</script> +</body> +</html> diff --git a/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html new file mode 100644 index 00000000000..ce7abf92039 --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-origin.tentative.https.html @@ -0,0 +1,23 @@ +<!doctype html> +<html> +<head> +<title>FetchLater Referrer Header: Origin Policy</title> +<meta name='referrer' content='origin'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/fetch/fetch-later/resources/header-referrer-helper.js"></script> +</head> +<body> +<script> + +const { + HTTPS_REMOTE_ORIGIN +} = get_host_info(); + +testReferrerHeader(token(), HTTPS_REMOTE_ORIGIN, REFERRER_ORIGIN); + +</script> +</body> +</html> diff --git a/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html new file mode 100644 index 00000000000..264beddc03a --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-same-origin.tentative.https.html @@ -0,0 +1,24 @@ +<!doctype html> +<html> +<head> +<title>FetchLater Referrer Header: Same Origin Policy</title> +<meta name='referrer' content='same-origin'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/fetch/fetch-later/resources/header-referrer-helper.js"></script> +</head> +<body> +<script> + +const { + HTTPS_REMOTE_ORIGIN +} = get_host_info(); + +testReferrerHeader(token(), /*host=*/'', REFERRER_URL); +testReferrerHeader(token(), HTTPS_REMOTE_ORIGIN, /*expectedReferrer=*/''); + +</script> +</body> +</html> diff --git a/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html new file mode 100644 index 00000000000..9133f2496fe --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-strict-origin-when-cross-origin.tentative.https.html @@ -0,0 +1,24 @@ +<!doctype html> +<html> +<head> +<title>FetchLater Referrer Header: Strict Origin Policy</title> +<meta name='referrer' content='strict-origin'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/fetch/fetch-later/resources/header-referrer-helper.js"></script> +</head> +<body> +<script> + +const { + HTTPS_REMOTE_ORIGIN +} = get_host_info(); + +testReferrerHeader(token(), HTTPS_REMOTE_ORIGIN, REFERRER_ORIGIN); +// Note: FetchLater cannot be used for non-secure URL. + +</script> +</body> +</html> diff --git a/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html new file mode 100644 index 00000000000..943d70bbc58 --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-strict-origin.tentative.https.html @@ -0,0 +1,24 @@ +<!doctype html> +<html> +<head> +<title>FetchLater Referrer Header: Strict Origin Policy</title> +<meta name='referrer' content='strict-origin'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/fetch/fetch-later/resources/header-referrer-helper.js"></script> +</head> +<body> +<script> + +const { + HTTPS_ORIGIN +} = get_host_info(); + +testReferrerHeader(token(), HTTPS_ORIGIN, REFERRER_ORIGIN); +// Note: FetchLater cannot be used for non-secure URL. + +</script> +</body> +</html> diff --git a/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html new file mode 100644 index 00000000000..a602e0003a4 --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/headers/header-referrer-unsafe-url.tentative.https.html @@ -0,0 +1,24 @@ +<!doctype html> +<html> +<head> +<title>FetchLater Referrer Header: Unsafe Url Policy</title> +<meta name='referrer' content='unsafe-url'> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/fetch/fetch-later/resources/header-referrer-helper.js"></script> +</head> +<body> +<script> + +const { + HTTPS_ORIGIN +} = get_host_info(); + +testReferrerHeader(token(), HTTPS_ORIGIN, REFERRER_URL); +// Note: FetchLater cannot be used for non-secure URL. + +</script> +</body> +</html> diff --git a/tests/wpt/tests/fetch/fetch-later/iframe.tentative.https.window.js b/tests/wpt/tests/fetch/fetch-later/iframe.tentative.https.window.js new file mode 100644 index 00000000000..62505bc81d9 --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/iframe.tentative.https.window.js @@ -0,0 +1,65 @@ +// META: script=/resources/testharness.js +// META: script=/resources/testharnessreport.js +// META: script=/common/utils.js +// META: script=/common/get-host-info.sub.js +// META: script=/pending-beacon/resources/pending_beacon-helper.js + +'use strict'; + +const { + HTTPS_ORIGIN, + HTTPS_NOTSAMESITE_ORIGIN, +} = get_host_info(); + +async function loadElement(el) { + const loaded = new Promise(resolve => el.onload = resolve); + document.body.appendChild(el); + await loaded; +} + +// `host` may be cross-origin +async function loadFetchLaterIframe(host, targetUrl) { + const url = `${host}/fetch/fetch-later/resources/fetch-later.html?url=${ + encodeURIComponent(targetUrl)}`; + const iframe = document.createElement('iframe'); + iframe.src = url; + await loadElement(iframe); + return iframe; +} + +parallelPromiseTest(async t => { + const uuid = token(); + const url = generateSetBeaconURL(uuid); + + // Loads a blank iframe that fires a fetchLater request. + const iframe = document.createElement('iframe'); + iframe.addEventListener('load', () => { + fetchLater(url, {activateAfter: 0}); + }); + await loadElement(iframe); + + // The iframe should have sent the request. + await expectBeacon(uuid, {count: 1}); +}, 'A blank iframe can trigger fetchLater.'); + +parallelPromiseTest(async t => { + const uuid = token(); + const url = generateSetBeaconURL(uuid); + + // Loads a same-origin iframe that fires a fetchLater request. + await loadFetchLaterIframe(HTTPS_ORIGIN, url); + + // The iframe should have sent the request. + await expectBeacon(uuid, {count: 1}); +}, 'A same-origin iframe can trigger fetchLater.'); + +parallelPromiseTest(async t => { + const uuid = token(); + const url = generateSetBeaconURL(uuid); + + // Loads a same-origin iframe that fires a fetchLater request. + await loadFetchLaterIframe(HTTPS_NOTSAMESITE_ORIGIN, url); + + // The iframe should have sent the request. + await expectBeacon(uuid, {count: 1}); +}, 'A cross-origin iframe can trigger fetchLater.'); diff --git a/tests/wpt/tests/fetch/fetch-later/new-window.tentative.https.window.js b/tests/wpt/tests/fetch/fetch-later/new-window.tentative.https.window.js new file mode 100644 index 00000000000..37b38d7f1dc --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/new-window.tentative.https.window.js @@ -0,0 +1,77 @@ +// META: script=/resources/testharness.js +// META: script=/resources/testharnessreport.js +// META: script=/common/utils.js +// META: script=/common/get-host-info.sub.js +// META: script=/pending-beacon/resources/pending_beacon-helper.js + +'use strict'; + +const { + HTTPS_ORIGIN, + HTTPS_NOTSAMESITE_ORIGIN, +} = get_host_info(); + +function fetchLaterPopupUrl(host, targetUrl) { + return `${host}/fetch/fetch-later/resources/fetch-later.html?url=${ + encodeURIComponent(targetUrl)}`; +} + +for (const target of ['', '_blank']) { + for (const features in ['', 'popup', 'popup,noopener']) { + parallelPromiseTest( + async t => { + const uuid = token(); + const url = + generateSetBeaconURL(uuid, {host: HTTPS_NOTSAMESITE_ORIGIN}); + + // Opens a blank popup window that fires a fetchLater request. + const w = window.open( + `javascript: fetchLater("${url}", {activateAfter: 0})`, target, + features); + await new Promise(resolve => w.addEventListener('load', resolve)); + + // The popup should have sent the request. + await expectBeacon(uuid, {count: 1}); + w.close(); + }, + `A blank window[target='${target}'][features='${ + features}'] can trigger fetchLater.`); + + parallelPromiseTest( + async t => { + const uuid = token(); + const popupUrl = + fetchLaterPopupUrl(HTTPS_ORIGIN, generateSetBeaconURL(uuid)); + + // Opens a same-origin popup that fires a fetchLater request. + const w = window.open(popupUrl, target, features); + await new Promise(resolve => w.addEventListener('load', resolve)); + + // The popup should have sent the request. + await expectBeacon(uuid, {count: 1}); + w.close(); + }, + `A same-origin window[target='${target}'][features='${ + features}'] can trigger fetchLater.`); + + parallelPromiseTest( + async t => { + const uuid = token(); + const popupUrl = fetchLaterPopupUrl( + HTTPS_NOTSAMESITE_ORIGIN, generateSetBeaconURL(uuid)); + + // Opens a cross-origin popup that fires a fetchLater request. + const w = window.open(popupUrl, target, features); + // As events from cross-origin window is not accessible, waiting for + // its message instead. + await new Promise( + resolve => window.addEventListener('message', resolve)); + + // The popup should have sent the request. + await expectBeacon(uuid, {count: 1}); + w.close(); + }, + `A cross-origin window[target='${target}'][features='${ + features}'] can trigger fetchLater.`); + } +} diff --git a/tests/wpt/tests/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js b/tests/wpt/tests/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js new file mode 100644 index 00000000000..5aa759c2346 --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js @@ -0,0 +1,28 @@ +// META: title=FetchLater: allowed by CSP +// META: script=/resources/testharness.js +// META: script=/resources/testharnessreport.js +// META: script=/common/utils.js +// META: script=/common/get-host-info.sub.js +// META: script=/pending-beacon/resources/pending_beacon-helper.js +'use strict'; + +const { + HTTPS_NOTSAMESITE_ORIGIN, +} = get_host_info(); + +// FetchLater requests allowed by Content Security Policy. +// https://w3c.github.io/webappsec-csp/#should-block-request + +const meta = document.createElement('meta'); +meta.setAttribute('http-equiv', 'Content-Security-Policy'); +meta.setAttribute('content', `connect-src 'self' ${HTTPS_NOTSAMESITE_ORIGIN}`); +document.head.appendChild(meta); + +promise_test(async t => { + const uuid = token(); + const url = generateSetBeaconURL(uuid, {host: HTTPS_NOTSAMESITE_ORIGIN}); + fetchLater(url, {activateAfter: 0}); + + await expectBeacon(uuid, {count: 1}); + t.done(); +}, 'FetchLater allowed by CSP should succeed'); diff --git a/tests/wpt/tests/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js b/tests/wpt/tests/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js new file mode 100644 index 00000000000..88490950d3a --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js @@ -0,0 +1,33 @@ +// META: title=FetchLater: blocked by CSP +// META: script=/resources/testharness.js +// META: script=/resources/testharnessreport.js +// META: script=/common/utils.js +// META: script=/common/get-host-info.sub.js +// META: script=/pending-beacon/resources/pending_beacon-helper.js +'use strict'; + +const { + HTTPS_NOTSAMESITE_ORIGIN, +} = get_host_info(); + +// FetchLater requests blocked by Content Security Policy are rejected. +// https://w3c.github.io/webappsec-csp/#should-block-request + +const meta = document.createElement('meta'); +meta.setAttribute('http-equiv', 'Content-Security-Policy'); +meta.setAttribute('content', 'connect-src \'self\''); +document.head.appendChild(meta); + +promise_test(async t => { + const uuid = token(); + const cspViolationUrl = + generateSetBeaconURL(uuid, {host: HTTPS_NOTSAMESITE_ORIGIN}); + fetchLater(cspViolationUrl, {activateAfter: 0}); + + await new Promise( + resolve => window.addEventListener('securitypolicyviolation', e => { + assert_equals(e.violatedDirective, 'connect-src'); + resolve(); + })); + t.done(); +}, 'FetchLater blocked by CSP should reject'); diff --git a/tests/wpt/tests/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js b/tests/wpt/tests/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js new file mode 100644 index 00000000000..c2019881cc2 --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js @@ -0,0 +1,33 @@ +// META: title=FetchLater: redirect blocked by CSP +// META: script=/resources/testharness.js +// META: script=/resources/testharnessreport.js +// META: script=/common/utils.js +// META: script=/common/get-host-info.sub.js +// META: script=/pending-beacon/resources/pending_beacon-helper.js +'use strict'; + +const { + HTTPS_NOTSAMESITE_ORIGIN, +} = get_host_info(); + +// FetchLater requests redirect to URL blocked by Content Security Policy. +// https://w3c.github.io/webappsec-csp/#should-block-request + +const meta = document.createElement('meta'); +meta.setAttribute('http-equiv', 'Content-Security-Policy'); +meta.setAttribute('content', 'connect-src \'self\''); +document.head.appendChild(meta); + +promise_test(async t => { + const uuid = token(); + const cspViolationUrl = + generateSetBeaconURL(uuid, {host: HTTPS_NOTSAMESITE_ORIGIN}); + const url = + `/common/redirect.py?location=${encodeURIComponent(cspViolationUrl)}`; + fetchLater(url, {activateAfter: 0}); + + // TODO(crbug.com/1465781): redirect csp check is handled in browser, of which + // result cannot be populated to renderer at this moment. + await expectBeacon(uuid, {count: 0}); + t.done(); +}, 'FetchLater redirect blocked by CSP should reject'); diff --git a/tests/wpt/tests/fetch/fetch-later/resources/fetch-later.html b/tests/wpt/tests/fetch/fetch-later/resources/fetch-later.html new file mode 100644 index 00000000000..b569e1a076a --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/resources/fetch-later.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<head> +</head> +<body> + <script> + const PARAMS = new URL(location.href).searchParams; + const TARGET_URL= decodeURIComponent(PARAMS.get('url')) || ''; + + fetchLater(TARGET_URL, {activateAfter: 0}); + if (window.opener) { + window.opener.postMessage("done", "*"); + } + </script> +</body> diff --git a/tests/wpt/tests/fetch/fetch-later/resources/header-referrer-helper.js b/tests/wpt/tests/fetch/fetch-later/resources/header-referrer-helper.js new file mode 100644 index 00000000000..374097614ae --- /dev/null +++ b/tests/wpt/tests/fetch/fetch-later/resources/header-referrer-helper.js @@ -0,0 +1,39 @@ +'use strict'; + +// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer +const REFERRER_ORIGIN = self.location.origin + '/'; +const REFERRER_URL = self.location.href; + +function testReferrerHeader(id, host, expectedReferrer) { + const url = `${ + host}/beacon/resources/inspect-header.py?header=referer&cmd=put&id=${id}`; + + promise_test(t => { + fetchLater(url, {activateAfter: 0}); + return pollResult(expectedReferrer, id).then(result => { + assert_equals(result, expectedReferrer, 'Correct referrer header result'); + }); + }, `Test referer header ${host}`); +} + +function pollResult(expectedReferrer, id) { + const checkUrl = + `/beacon/resources/inspect-header.py?header=referer&cmd=get&id=${id}`; + + return new Promise(resolve => { + function checkResult() { + fetch(checkUrl).then(response => { + assert_equals( + response.status, 200, 'Inspect header response\'s status is 200'); + let result = response.headers.get('x-request-referer'); + + if (result != undefined) { + resolve(result); + } else { + step_timeout(checkResult.bind(this), 100); + } + }); + } + checkResult(); + }); +} diff --git a/tests/wpt/tests/fetch/fetch-later/send-on-deactivate.tentative.https.window.js b/tests/wpt/tests/fetch/fetch-later/send-on-deactivate.tentative.https.window.js index 7a1ddc7ac3d..173c95ac120 100644 --- a/tests/wpt/tests/fetch/fetch-later/send-on-deactivate.tentative.https.window.js +++ b/tests/wpt/tests/fetch/fetch-later/send-on-deactivate.tentative.https.window.js @@ -101,3 +101,36 @@ parallelPromiseTest(async t => { await expectBeacon(uuid, {count: 1}); }, `fetchLater() sends on navigating away a page w/o BFCache.`); + +parallelPromiseTest(async t => { + const uuid = token(); + const url = generateSetBeaconURL(uuid); + // Sets no option to test the default behavior when a document gets discarded + // on navigated away. + const helper = new RemoteContextHelper(); + // Opens a window without BFCache. + const rc1 = await helper.addWindow(); + + // Creates 2 fetchLater requests in remote, and one of them is aborted + // immediately. The other one should only be sent right on navigating away. + await rc1.executeScript(url => { + const controller = new AbortController(); + fetchLater(url, {signal: controller.signal}); + fetchLater(url); + controller.abort(); + // Add a pageshow listener to stash the BFCache event. + window.addEventListener('pageshow', e => { + window.pageshowEvent = e; + }); + }, [url]); + // Navigates away to trigger request sending. + const rc2 = await rc1.navigateToNew(); + // Navigate back. + await rc2.historyBack(); + // Verify that the page was NOT BFCached. + assert_equals(undefined, await rc1.executeScript(() => { + return window.pageshowEvent; + })); + + await expectBeacon(uuid, {count: 1}); +}, `fetchLater() does not send aborted request on navigating away a page w/o BFCache.`); diff --git a/tests/wpt/tests/fetch/fetch-later/send-on-discard.tentative.https.window.js b/tests/wpt/tests/fetch/fetch-later/send-on-discard.tentative.https.window.js index c4911b11055..e1ff9b9e3a6 100644 --- a/tests/wpt/tests/fetch/fetch-later/send-on-discard.tentative.https.window.js +++ b/tests/wpt/tests/fetch/fetch-later/send-on-discard.tentative.https.window.js @@ -63,6 +63,5 @@ parallelPromiseTest(async t => { document.body.removeChild(iframe); // The iframe should not send the aborted request. - // TODO(crbug.com/1465781): Fix this after implementing abort function. await expectBeacon(uuid, {count: 1}); }, 'A discarded document does not send an already aborted fetchLater request.'); diff --git a/tests/wpt/tests/fledge/tentative/TODO b/tests/wpt/tests/fledge/tentative/TODO index 2b6a1dc3c2d..272a5e3ffb9 100644 --- a/tests/wpt/tests/fledge/tentative/TODO +++ b/tests/wpt/tests/fledge/tentative/TODO @@ -12,12 +12,11 @@ Need tests for (likely not a complete list): probably not worth covering all types, if we have coverage for the main renderURL). * Filtering/prioritization (including bidding signals influencing priorities) -* Size restrictions. +* Size restrictions / ad and component ad sizes. * additionalBids. * adCost. * bidCurrency. * modellingSignals. -* Ad and component ad sizes. * Updates (both after auction and triggered). * All auctionConfig parameters (including invalid auctionConfigs, and ones with no buyers). @@ -40,9 +39,8 @@ Need tests for (likely not a complete list): * Network timeouts. * Validate specific escaping behavior logic (still under discussion). There are a number of different rules for which characters are escaped, and - whether spacess are escaped as "%20" or "+". + whether spaces are escaped as "%20" or "+". * Reports not sent if ad not used. -* Ties. * Interactions with local network access API, which requires public networks to send CORS preflights for requests made over local networks. Needs testing with public publisher pages running auctions with @@ -50,10 +48,8 @@ Need tests for (likely not a complete list): * Calling FLEDGE APIs (or at least leaveAdInterestGroup() with no args) in a non-ad FencedFrame. * Test network requests in terms of fetch behavior - * No cookies. - * No referrer. * Redirects not followed. - * etc. + * Network partition (not yet specced). * Test that await is not needed for same-origin interest groups * Verify that's still in the spec/explainer first. * executionMode @@ -62,12 +58,13 @@ Need tests for (likely not a complete list): * Across scoreAd() / generateBid() calls, and with report calls. * In "group-by-origin" execution mode across IGs joined from different origins, and between generateBid() and reportWin(). -* Use AbortSignal to abort an auction. +* Test Content-Type headers allowed in responess for script/wasm/JSON fetches. If possible: * Aggregate reporting. * Join/leave permission delegation via .well-known files * Including tests for clearOriginJoinedInterestGroups(). + * Include tests for HTTP-y/fetch-y things (e.g., whether they have cookies) * k-anonymity. * Signals request batching. This is an optional feature, so can't require it, but maybe a test where batching could be used, and make sure things work, diff --git a/tests/wpt/tests/fledge/tentative/auction-config.https.window.js b/tests/wpt/tests/fledge/tentative/auction-config.https.window.js index e4811b96965..432be9cb10a 100644 --- a/tests/wpt/tests/fledge/tentative/auction-config.https.window.js +++ b/tests/wpt/tests/fledge/tentative/auction-config.https.window.js @@ -7,7 +7,8 @@ // META: variant=?6-10 // META: variant=?11-15 // META: variant=?16-20 -// META: variant=?21-last +// META: variant=?21-25 +// META: variant=?26-last "use strict;" @@ -276,3 +277,31 @@ makeTest({ ], }, }); + +makeTest({ + name: 'perBuyerCurrencies with invalid currency', + expect: EXPECT_PROMISE_ERROR, + expectPromiseError: EXPECT_EXCEPTION(TypeError), + auctionConfigOverrides: {perBuyerCurrencies: {'*': 'Dollars'}} +}); + +makeTest({ + name: 'perBuyerCurrencies with invalid currency map key', + expect: EXPECT_PROMISE_ERROR, + expectPromiseError: EXPECT_EXCEPTION(TypeError), + auctionConfigOverrides: {perBuyerCurrencies: {'example': 'USD'}} +}); + +makeTest({ + name: 'perBuyerCurrencies with non-https currency map key', + expect: EXPECT_PROMISE_ERROR, + expectPromiseError: EXPECT_EXCEPTION(TypeError), + auctionConfigOverrides: {perBuyerCurrencies: {'http://example.org/': 'USD'}} +}); + +makeTest({ + name: 'perBuyerCurrencies not convertible to dictionary', + expect: EXPECT_PROMISE_ERROR, + expectPromiseError: EXPECT_EXCEPTION(TypeError), + auctionConfigOverrides: {perBuyerCurrencies: 123} +}); diff --git a/tests/wpt/tests/fledge/tentative/currency.https.window.js b/tests/wpt/tests/fledge/tentative/currency.https.window.js new file mode 100644 index 00000000000..97802ce1379 --- /dev/null +++ b/tests/wpt/tests/fledge/tentative/currency.https.window.js @@ -0,0 +1,124 @@ +// META: script=/resources/testdriver.js +// META: script=/common/utils.js +// META: script=resources/fledge-util.sub.js +// META: script=/common/subset-tests.js +// META: timeout=long +// META: variant=?1-4 +// META: variant=?5-last + +'use strict;' + +// The tests in this file focus on calls to runAdAuction involving currency +// handling. + +// Joins an interest group that bids 9USD on window.location.origin, and one +// that bids 10CAD on OTHER_ORIGIN1, each with a reportWin() report. +async function joinTwoCurrencyGroups(test, uuid) { + const reportWinURL = createBidderReportURL(uuid, 'USD'); + const biddingURL = createBiddingScriptURL( + {bidCurrency: 'USD', reportWin: `sendReportTo('${reportWinURL}')`}); + await joinInterestGroup(test, uuid, {biddingLogicURL: biddingURL}); + + const otherReportWinURL = createBidderReportURL(uuid, 'CAD', OTHER_ORIGIN1); + const otherBiddingURL = createBiddingScriptURL({ + origin: OTHER_ORIGIN1, + bid: 10, + bidCurrency: 'CAD', + reportWin: `sendReportTo('${otherReportWinURL}')` + }); + await joinCrossOriginInterestGroup( + test, uuid, OTHER_ORIGIN1, {biddingLogicURL: otherBiddingURL}); +} + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await joinInterestGroup( + test, uuid, + {biddingLogicURL: createBiddingScriptURL({bidCurrency: 'usd'})}); + await runBasicFledgeTestExpectingNoWinner(test, uuid); +}, 'Returning bid with invalid currency.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await joinInterestGroup( + test, uuid, + {biddingLogicURL: createBiddingScriptURL({bidCurrency: 'USD'})}); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'Returning bid with currency, configuration w/o currency.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await joinInterestGroup(test, uuid); + await runBasicFledgeTestExpectingWinner( + test, uuid, {perBuyerCurrencies: {'*': 'USD'}}); +}, 'Returning bid w/o currency, configuration w/currency.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await joinInterestGroup( + test, uuid, + {biddingLogicURL: createBiddingScriptURL({bidCurrency: 'USD'})}); + await runBasicFledgeTestExpectingWinner( + test, uuid, {perBuyerCurrencies: {'*': 'USD'}}); +}, 'Returning bid w/currency, configuration w/matching currency.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await joinInterestGroup( + test, uuid, + {biddingLogicURL: createBiddingScriptURL({bidCurrency: 'USD'})}); + await runBasicFledgeTestExpectingNoWinner( + test, uuid, {perBuyerCurrencies: {'*': 'CAD'}}); +}, 'Returning bid w/currency, configuration w/different currency.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await joinTwoCurrencyGroups(test, uuid); + let auctionConfigOverrides = { + interestGroupBuyers: [window.location.origin, OTHER_ORIGIN1], + perBuyerCurrencies: {} + }; + auctionConfigOverrides.perBuyerCurrencies['*'] = 'USD'; + auctionConfigOverrides.perBuyerCurrencies[OTHER_ORIGIN1] = 'CAD'; + await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides); + + // Since the scoring script doesn't actually look at the currencies, + // We expect 10CAD to win because 10 > 9 + await waitForObservedRequests(uuid, [ + createBidderReportURL(uuid, 'CAD', OTHER_ORIGIN1), + createSellerReportURL(uuid) + ]); +}, 'Different currencies for different origins, all match.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await joinTwoCurrencyGroups(test, uuid); + let auctionConfigOverrides = { + interestGroupBuyers: [window.location.origin, OTHER_ORIGIN1], + perBuyerCurrencies: {} + }; + auctionConfigOverrides.perBuyerCurrencies[window.location.origin] = 'USD'; + auctionConfigOverrides.perBuyerCurrencies[OTHER_ORIGIN1] = 'EUR'; + await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides); + + // Since the configuration for CAD script expects EUR only the USD bid goes + // through. + await waitForObservedRequests( + uuid, [createBidderReportURL(uuid, 'USD'), createSellerReportURL(uuid)]); +}, 'Different currencies for different origins, USD one matches.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await joinTwoCurrencyGroups(test, uuid); + let auctionConfigOverrides = { + interestGroupBuyers: [window.location.origin, OTHER_ORIGIN1], + perBuyerCurrencies: {} + }; + auctionConfigOverrides.perBuyerCurrencies['*'] = 'EUR'; +}, 'Different currencies for different origins, none match.'); + +// TODO: look at currency passed in to scoring. +// Conversion to uniform currency (integrate private aggregation to check) +// --- also the passthrough and can't modify rule for things already in it. +// Basic sellerCurrency checks (requires component auctions; can be +// pass-through or modified bid). diff --git a/tests/wpt/tests/fledge/tentative/join-leave-ad-interest-group.https.window.js b/tests/wpt/tests/fledge/tentative/join-leave-ad-interest-group.https.window.js index 77da23a7a5b..107bd3b815a 100644 --- a/tests/wpt/tests/fledge/tentative/join-leave-ad-interest-group.https.window.js +++ b/tests/wpt/tests/fledge/tentative/join-leave-ad-interest-group.https.window.js @@ -637,14 +637,3 @@ subsetTest(promise_test, async test => { await joinInterestGroup(test, uuid, {}, -600); assert_true(await runBasicFledgeAuction(test, uuid) === null); }, 'Interest group test with overwritten duration of -600.'); - -subsetTest(promise_test, async test => { - try { - await navigator.leaveAdInterestGroup(); - } catch (e) { - assert_true(e instanceof TypeError, 'TypeError thrown'); - return; - } - - throw 'TypeError unexpectedly not thrown.' -}, 'leaveInterestGroup() with no parameters, outside of a fenced frame.'); diff --git a/tests/wpt/tests/fledge/tentative/network.https.window.js b/tests/wpt/tests/fledge/tentative/network.https.window.js new file mode 100644 index 00000000000..9c296105786 --- /dev/null +++ b/tests/wpt/tests/fledge/tentative/network.https.window.js @@ -0,0 +1,260 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/subset-tests.js +// META: script=/common/utils.js +// META: script=resources/fledge-util.sub.js +// META: timeout=long +// META: variant=?1-5 +// META: variant=?6-last + +"use strict"; + +// These tests focus on Protected Audience network requests - make sure they +// have no cookies, can set no cookies, and otherwise behave in the expected +// manner as related to the fetch spec. These tests don't cover additional +// request or response headers specific to Protected Audience API. + +// URL that sets a cookie named "cookie" with a value of "cookie". +const SET_COOKIE_URL = `${BASE_URL}resources/set-cookie.asis`; + +// Returns a URL that stores request headers. Headers can later be retrieved +// as a name-to-list-of-values mapping with +// "(await fetchTrackedData(uuid)).trackedHeaders" +function createHeaderTrackerURL(uuid) { + return createTrackerURL(window.location.origin, uuid, 'track_headers'); +} + +// Delete all cookies. Separate function so that can be replaced with +// something else for testing outside of a WPT environment. +async function deleteAllCookies() { + await test_driver.delete_all_cookies(); +} + +// Deletes all cookies (to avoid pre-existing cookies causing inconsistent +// output on failure) and sets a cookie with name "cookie" and a value of +// "cookie". Adds a cleanup task to delete all cookies again when the test +// is done. +async function setCookie(test) { + await deleteAllCookies(); + document.cookie = 'cookie=cookie; path=/' + test.add_cleanup(deleteAllCookies); +} + +// Assert that "headers" has a single header with "name", whose value is "value". +function assertHasHeader(headers, name, value) { + assert_equals(JSON.stringify(headers[name]), JSON.stringify([value]), + 'Header ' + name); +} + +// Assert that "headers" has no header with "name" +function assertDoesNotHaveHeader(headers, name) { + assert_equals(headers[name], undefined, 'Header ' + name); +} + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await setCookie(test); + + await joinGroupAndRunBasicFledgeTestExpectingNoWinner( + test, + { uuid: uuid, + interestGroupOverrides: { biddingLogicURL: createHeaderTrackerURL(uuid) } + }); + + let headers = (await fetchTrackedData(uuid)).trackedHeaders; + assertHasHeader(headers, 'accept', 'application/javascript'); + assertHasHeader(headers, 'sec-fetch-dest', 'empty'); + assertHasHeader(headers, 'sec-fetch-mode', 'no-cors'); + assertHasHeader(headers, 'sec-fetch-site', 'same-origin'); + assertDoesNotHaveHeader(headers, 'cookie'); + assertDoesNotHaveHeader(headers, 'referer'); +}, 'biddingLogicURL request headers.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await deleteAllCookies(); + + await joinGroupAndRunBasicFledgeTestExpectingNoWinner( + test, + { uuid: uuid, + interestGroupOverrides: { biddingLogicURL: SET_COOKIE_URL } + }); + + assert_equals(document.cookie, ''); + await deleteAllCookies(); +}, 'biddingLogicURL Set-Cookie.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await deleteAllCookies(); + + await joinGroupAndRunBasicFledgeTestExpectingNoWinner( + test, + { uuid: uuid, + interestGroupOverrides: { biddingLogicURL: SET_COOKIE_URL } + }); + + assert_equals(document.cookie, ''); + await deleteAllCookies(); +}, 'biddingLogicURL redirect.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await setCookie(test); + + await joinGroupAndRunBasicFledgeTestExpectingNoWinner( + test, + { uuid: uuid, + interestGroupOverrides: { biddingWasmHelperURL: createHeaderTrackerURL(uuid) } + }); + + let headers = (await fetchTrackedData(uuid)).trackedHeaders; + assertHasHeader(headers, 'accept', 'application/wasm'); + assertHasHeader(headers, 'sec-fetch-dest', 'empty'); + assertHasHeader(headers, 'sec-fetch-mode', 'no-cors'); + assertHasHeader(headers, 'sec-fetch-site', 'same-origin'); + assertDoesNotHaveHeader(headers, 'cookie'); + assertDoesNotHaveHeader(headers, 'referer'); +}, 'biddingWasmHelperURL request headers.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await deleteAllCookies(); + + await joinGroupAndRunBasicFledgeTestExpectingNoWinner( + test, + { uuid: uuid, + interestGroupOverrides: { biddingWasmHelperURL: SET_COOKIE_URL } + }); + + assert_equals(document.cookie, ''); + await deleteAllCookies(); +}, 'biddingWasmHelperURL Set-Cookie.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await setCookie(test); + + await joinGroupAndRunBasicFledgeTestExpectingNoWinner( + test, + { uuid: uuid, + auctionConfigOverrides: { decisionLogicURL: createHeaderTrackerURL(uuid) } + }); + + let headers = (await fetchTrackedData(uuid)).trackedHeaders; + assertHasHeader(headers, 'accept', 'application/javascript'); + assertHasHeader(headers, 'sec-fetch-dest', 'empty'); + assertHasHeader(headers, 'sec-fetch-mode', 'no-cors'); + assertHasHeader(headers, 'sec-fetch-site', 'same-origin'); + assertDoesNotHaveHeader(headers, 'cookie'); + assertDoesNotHaveHeader(headers, 'referer'); +}, 'decisionLogicURL request headers.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await deleteAllCookies(); + + await joinGroupAndRunBasicFledgeTestExpectingNoWinner( + test, + { uuid: uuid, + auctionConfigOverrides: { decisionLogicURL: SET_COOKIE_URL } + }); + + assert_equals(document.cookie, ''); + await deleteAllCookies(); +}, 'decisionLogicURL Set-Cookie.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await setCookie(test); + + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: { + trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL, + trustedBiddingSignalsKeys: ['headers'], + biddingLogicURL: createBiddingScriptURL({ + generateBid: + `let headers = trustedBiddingSignals.headers; + function checkHeader(name, value) { + jsonActualValue = JSON.stringify(headers[name]); + if (jsonActualValue !== JSON.stringify([value])) + throw "Unexpected " + name + ": " + jsonActualValue; + } + checkHeader("accept", "application/json"); + checkHeader("sec-fetch-dest", "empty"); + checkHeader("sec-fetch-mode", "no-cors"); + checkHeader("sec-fetch-site", "same-origin"); + if (headers.cookie !== undefined) + throw "Unexpected cookie: " + JSON.stringify(headers.cookie); + if (headers.referer !== undefined) + throw "Unexpected referer: " + JSON.stringify(headers.referer);`, + }) + } + }); +}, 'trustedBiddingSignalsURL request headers.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await deleteAllCookies(); + + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: { trustedBiddingSignalsURL: SET_COOKIE_URL } + }); + + assert_equals(document.cookie, ''); + await deleteAllCookies(); +}, 'trustedBiddingSignalsURL Set-Cookie.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await setCookie(test); + + let renderURL = createRenderURL(uuid, /*script=*/null, /*signalsParam=*/'headers'); + + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: { + ads: [{ renderURL: renderURL }] + }, + auctionConfigOverrides: { + trustedScoringSignalsURL: TRUSTED_SCORING_SIGNALS_URL, + decisionLogicURL: createDecisionScriptURL(uuid, + { + scoreAd: + `let headers = trustedScoringSignals.renderURL["${renderURL}"]; + function checkHeader(name, value) { + jsonActualValue = JSON.stringify(headers[name]); + if (jsonActualValue !== JSON.stringify([value])) + throw "Unexpected " + name + ": " + jsonActualValue; + } + checkHeader("accept", "application/json"); + checkHeader("sec-fetch-dest", "empty"); + checkHeader("sec-fetch-mode", "no-cors"); + checkHeader("sec-fetch-site", "same-origin"); + if (headers.cookie !== undefined) + throw "Unexpected cookie: " + JSON.stringify(headers.cookie); + if (headers.referer !== undefined) + throw "Unexpected referer: " + JSON.stringify(headers.referer);`, + }) + } + }); +}, 'trustedScoringSignalsURL request headers.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await deleteAllCookies(); + + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + auctionConfigOverrides: { trustedScoringSignalsURL: SET_COOKIE_URL } + }); + + assert_equals(document.cookie, ''); + await deleteAllCookies(); +}, 'trustedScoringSignalsURL Set-Cookie.'); diff --git a/tests/wpt/tests/fledge/tentative/resources/bidding-logic.sub.py b/tests/wpt/tests/fledge/tentative/resources/bidding-logic.sub.py index 58fe220880a..c0d6114ab2c 100644 --- a/tests/wpt/tests/fledge/tentative/resources/bidding-logic.sub.py +++ b/tests/wpt/tests/fledge/tentative/resources/bidding-logic.sub.py @@ -37,10 +37,15 @@ def main(request, response): # Use bid query param if present. Otherwise, use a bid of 9. bid = (request.GET.first(b"bid", None) or b"9").decode("ASCII") + bidCurrency = "" + bidCurrencyParam = request.GET.first(b"bidCurrency", None) + if bidCurrencyParam != None: + bidCurrency = "bidCurrency: '" + bidCurrencyParam.decode("ASCII") + "'," + allowComponentAuction = "" allowComponentAuctionParam = request.GET.first(b"allowComponentAuction", None) if allowComponentAuctionParam != None: - allowComponentAuction = f"allowComponentAuction: {allowComponentAuctionParam.decode('ASCII')}," + allowComponentAuction = f"allowComponentAuction: {allowComponentAuctionParam.decode('ASCII')}," body += f""" function generateBid(interestGroup, auctionSignals, perBuyerSignals, @@ -49,6 +54,7 @@ def main(request, response): {{{{GET[generateBid]}}}}; return {{ bid: {bid}, + {bidCurrency} {allowComponentAuction} render: interestGroup.ads[0].renderURL }}; diff --git a/tests/wpt/tests/fledge/tentative/resources/fledge-util.sub.js b/tests/wpt/tests/fledge/tentative/resources/fledge-util.sub.js index d500307a079..e19d85a558f 100644 --- a/tests/wpt/tests/fledge/tentative/resources/fledge-util.sub.js +++ b/tests/wpt/tests/fledge/tentative/resources/fledge-util.sub.js @@ -80,7 +80,31 @@ function generateUuid(test) { return uuid; } -// Repeatedly requests "request_list" URL until exactly the entries in +// Helper to fetch "tracked_data" URL to fetch all data recorded by the +// tracker URL associated with "uuid". Throws on error, including if +// the retrieved object's errors field is non-empty. +async function fetchTrackedData(uuid) { + let trackedRequestsURL = createTrackerURL(window.location.origin, uuid, + 'tracked_data'); + let response = await fetch(trackedRequestsURL, + {credentials: 'omit', mode: 'cors'}); + let trackedData = await response.json(); + + // Fail on fetch error. + if (trackedData.error) { + throw trackedRequestsURL + ' fetch failed:' + JSON.stringify(trackedData); + } + + // Fail on errors reported by the tracker script. + if (trackedData.errors.length > 0) { + throw 'Errors reported by request-tracker.py:' + + JSON.stringify(trackedData.errors); + } + + return trackedData; +} + +// Repeatedly requests "tracked_data" URL until exactly the entries in // "expectedRequests" have been observed by the request tracker script (in // any order, since report URLs are not guaranteed to be sent in any order). // @@ -90,36 +114,21 @@ function generateUuid(test) { // If any other strings are received from the tracking script, or the tracker // script reports an error, fails the test. async function waitForObservedRequests(uuid, expectedRequests) { - let trackedRequestsURL = createTrackerURL(window.location.origin, uuid, - 'request_list'); - // Sort array for easier comparison, since order doesn't matter. - expectedRequests.sort(); - while (true) { - let response = await fetch(trackedRequestsURL, - {credentials: 'omit', mode: 'cors'}); - let trackerData = await response.json(); + // Sort array for easier comparison, as observed request order does not + // matter, and replace UUID to print consistent errors on failure. + expectedRequests = expectedRequests.sort().map((url) => url.replace(uuid, '<uuid>')); - // Fail on fetch error. - if (trackerData.error) { - throw trackedRequestsURL + ' fetch failed:' + - JSON.stringify(trackerData); - } + while (true) { + let trackedData = await fetchTrackedData(uuid); - // Fail on errors reported by the tracker script. - if (trackerData.errors.length > 0) { - throw 'Errors reported by request-tracker.py:' + - JSON.stringify(trackerData.errors); - } + // Clean up "trackedRequests" in same manner as "expectedRequests". + let trackedRequests = trackedData.trackedRequests.sort().map( + (url) => url.replace(uuid, '<uuid>')); // If expected number of requests have been observed, compare with list of // all expected requests and exit. - let trackedRequests = trackerData.trackedRequests; if (trackedRequests.length == expectedRequests.length) { - // Hide the uuid content in order to have a static expected file. - assert_array_equals(trackedRequests.sort().map((url) => - url.replace(uuid, '<uuid>')), - expectedRequests.map((url) => - url.replace(uuid, '<uuid>'))); + assert_array_equals(trackedRequests, expectedRequests); break; } @@ -127,9 +136,7 @@ async function waitForObservedRequests(uuid, expectedRequests) { // compare what's been received so far, to have a greater chance to fail // rather than hang on error. for (const trackedRequest of trackedRequests) { - assert_in_array(trackedRequest.replace(uuid, '<uuid>'), - expectedRequests.sort().map((url) => - url.replace(uuid, '<uuid>'))); + assert_in_array(trackedRequest, expectedRequests); } } } @@ -151,6 +158,8 @@ function createBiddingScriptURL(params = {}) { url.searchParams.append('error', params.error); if (params.bid) url.searchParams.append('bid', params.bid); + if (params.bidCurrency) + url.searchParams.append('bidCurrency', params.bidCurrency); if (params.allowComponentAuction !== undefined) url.searchParams.append('allowComponentAuction', JSON.stringify(params.allowComponentAuction)) return url.toString(); diff --git a/tests/wpt/tests/fledge/tentative/resources/fledge_http_server_util.py b/tests/wpt/tests/fledge/tentative/resources/fledge_http_server_util.py new file mode 100644 index 00000000000..a5c9c9715aa --- /dev/null +++ b/tests/wpt/tests/fledge/tentative/resources/fledge_http_server_util.py @@ -0,0 +1,11 @@ +# Takes a map of header names to list of values that are all binary strings +# and returns an otherwise identical map where keys and values have both been +# converted to ASCII strings. +def headersToAscii(headers): + header_map = {} + for pair in headers.items(): + values = [] + for value in pair[1]: + values.append(value.decode("ASCII")) + header_map[pair[0].decode("ASCII")] = values + return header_map diff --git a/tests/wpt/tests/fledge/tentative/resources/request-tracker.py b/tests/wpt/tests/fledge/tentative/resources/request-tracker.py index 46da796f301..9fe20bf83ac 100644 --- a/tests/wpt/tests/fledge/tentative/resources/request-tracker.py +++ b/tests/wpt/tests/fledge/tentative/resources/request-tracker.py @@ -2,6 +2,7 @@ import mimetypes import os import json import wptserve.stash +from fledge.tentative.resources.fledge_http_server_util import headersToAscii from wptserve.utils import isomorphic_decode, isomorphic_encode @@ -12,14 +13,18 @@ from wptserve.utils import isomorphic_decode, isomorphic_encode # clean up after themselves, or that are running concurrently, from interfering # with other tests. # -# Each uuid has a stash entry with a dictionary with two entries: +# Each uuid has a stash entry with a dictionary with the following entries: # "trackedRequests" is a list of all observed requested URLs with a # dispatch of "track_get" or "track_post". POSTS are in the format # "<url>, body: <body>". +# "trackedHeaders" is an object mapping HTTP header names to lists +# of received HTTP header values for a single request with a +# dispatch of "track_headers". # "errors" is a list of an errors that occurred. # -# A dispatch of "request_list" will return the "trackedRequests" dictionary -# associated with the in uuid, as a JSON string. +# A dispatch of "tracked_data" will return all tracked information associated +# with the uuid, as a JSON string. The "errors" field should be checked by +# the caller before checking other fields. # # A dispatch of "clean_up" will delete all information associated with the uuid. def main(request, response): @@ -38,7 +43,7 @@ def main(request, response): with stash.lock: # Take ownership of stashed entry, if any. This removes the entry of the # stash. - server_state = stash.take(uuid) or {"trackedRequests": [], "errors": []} + server_state = stash.take(uuid) or {"trackedRequests": [], "errors": [], "trackedHeaders": None} # Clear the entire stash. No work to do, since stash entry was already # removed. @@ -48,7 +53,7 @@ def main(request, response): # Return the list of entries in the stash. Need to add data back to the # stash first. - if dispatch == b"request_list": + if dispatch == b"tracked_data": stash.put(uuid, server_state) return simple_response(request, response, 200, b"OK", json.dumps(server_state)) @@ -66,7 +71,7 @@ def main(request, response): # Tracks a request that's expected to be a POST. # In addition to the method, check the Content-Type, which is currently - # always text/plain, and compare the body against the expected body. + # always text/plain. The request body is stored in trackedRequests. if dispatch == b"track_post": contentType = request.headers.get(b"Content-Type", b"missing") if request.method != "POST": @@ -82,6 +87,16 @@ def main(request, response): stash.put(uuid, server_state) return simple_response(request, response, 200, b"OK", b"") + # Tracks request headers for a single request. + if dispatch == b"track_headers": + if server_state["trackedHeaders"] != None: + server_state["errors"].append("Second track_headers request received.") + else: + server_state["trackedHeaders"] = headersToAscii(request.headers) + + stash.put(uuid, server_state) + return simple_response(request, response, 200, b"OK", b"") + # Report unrecognized dispatch line. server_state["errors"].append( request.url + " request with unknown dispatch value received: " + diff --git a/tests/wpt/tests/fledge/tentative/resources/set-cookie.asis b/tests/wpt/tests/fledge/tentative/resources/set-cookie.asis new file mode 100644 index 00000000000..96d9f07c578 --- /dev/null +++ b/tests/wpt/tests/fledge/tentative/resources/set-cookie.asis @@ -0,0 +1,3 @@ +HTTP/1.1 200 Ok +Set-Cookie: cookie=cookie; path=/ + diff --git a/tests/wpt/tests/fledge/tentative/resources/trusted-bidding-signals.py b/tests/wpt/tests/fledge/tentative/resources/trusted-bidding-signals.py index 86e4db8ad44..16272afc71c 100644 --- a/tests/wpt/tests/fledge/tentative/resources/trusted-bidding-signals.py +++ b/tests/wpt/tests/fledge/tentative/resources/trusted-bidding-signals.py @@ -1,5 +1,6 @@ import json from urllib.parse import unquote_plus +from fledge.tentative.resources.fledge_http_server_util import headersToAscii # Script to generate trusted bidding signals. The responses depends on the # keys and interestGroupNames - some result in entire response failures, others @@ -99,6 +100,8 @@ def main(request, response): value = json.dumps(interestGroupNames) elif key == "hostname": value = request.GET.first(b"hostname", b"not-found").decode("ASCII") + elif key == "headers": + value = headersToAscii(request.headers) responseBody["keys"][key] = value if "data-version" in interestGroupNames: diff --git a/tests/wpt/tests/fledge/tentative/resources/trusted-scoring-signals.py b/tests/wpt/tests/fledge/tentative/resources/trusted-scoring-signals.py index 43ff772a0e3..fc6ec79096c 100644 --- a/tests/wpt/tests/fledge/tentative/resources/trusted-scoring-signals.py +++ b/tests/wpt/tests/fledge/tentative/resources/trusted-scoring-signals.py @@ -1,5 +1,6 @@ import json from urllib.parse import unquote_plus, urlparse +from fledge.tentative.resources.fledge_http_server_util import headersToAscii # Script to generate trusted scoring signals. The responses depends on the # query strings in the ads Urls - some result in entire response failures, @@ -117,6 +118,8 @@ def main(request, response): value = {"a":"b", "c":["d"]} elif signalsParam == "hostname": value = request.GET.first(b"hostname", b"not-found").decode("ASCII") + elif signalsParam == "headers": + value = headersToAscii(request.headers) if addValue: if urlList["type"] not in responseBody: responseBody[urlList["type"]] = {} diff --git a/tests/wpt/tests/fullscreen/api/fullscreen-reordering.html b/tests/wpt/tests/fullscreen/api/fullscreen-reordering.html index 4b394bc20fc..1aaf3c37c04 100644 --- a/tests/wpt/tests/fullscreen/api/fullscreen-reordering.html +++ b/tests/wpt/tests/fullscreen/api/fullscreen-reordering.html @@ -4,7 +4,7 @@ <script src="/resources/testharnessreport.js"></script> <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-vendor.js"></script> -<script src="../../html/semantics/popovers/resources/popover-utils.js"></script> +<script src="/common/top-layer.js"></script> <div class="elements"> <div id="A">Element A</div> diff --git a/tests/wpt/tests/generic-sensor/generic-sensor-iframe-tests.sub.js b/tests/wpt/tests/generic-sensor/generic-sensor-iframe-tests.sub.js index 7b816c01c74..8f13bd778e0 100644 --- a/tests/wpt/tests/generic-sensor/generic-sensor-iframe-tests.sub.js +++ b/tests/wpt/tests/generic-sensor/generic-sensor-iframe-tests.sub.js @@ -1,152 +1,295 @@ -function send_message_to_iframe(iframe, message, reply) { - if (reply === undefined) { - reply = 'success'; - } - +function send_message_to_iframe(iframe, message) { return new Promise((resolve, reject) => { window.addEventListener('message', (e) => { + // The usage of test_driver.set_test_context() in + // iframe_sensor_handler.html causes unrelated messages to be sent as + // well. We just need to ignore them here. + if (!e.data.command) { + return; + } + if (e.data.command !== message.command) { - reject(`Expected reply with command '${message.command}', got '${e.data.command}' instead`); + reject(`Expected reply with command '${message.command}', got '${ + e.data.command}' instead`); return; } - if (e.data.result === reply) { - resolve(); - } else { - reject(`Got unexpected reply '${e.data.result}' to command '${message.command}', expected '${reply}'`); + if (e.data.error) { + reject(e.data.error); + return; } - }, { once: true }); + resolve(e.data.result); + }); iframe.contentWindow.postMessage(message, '*'); }); } -function run_generic_sensor_iframe_tests(sensorName) { +function run_generic_sensor_iframe_tests(sensorData, readingData) { + validate_sensor_data(sensorData); + validate_reading_data(readingData); + + const {sensorName, permissionName, testDriverName} = sensorData; const sensorType = self[sensorName]; const featurePolicies = get_feature_policies_for_sensor(sensorName); - sensor_test(async t => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + // When comparing timestamps in the tests below, we need to account for small + // deviations coming from the way time is coarsened according to the High + // Resolution Time specification, even more so when we need to translate + // timestamps from different documents with different time origins. + // 0.5 is 500 microseconds, which is acceptable enough given that even a high + // sensor frequency beyond what is usually allowed like 100Hz has a period + // much larger than 0.5ms. + const ALLOWED_JITTER_IN_MS = 0.5; + + function sensor_test(func, name, properties) { + promise_test(async t => { + assert_implements(sensorName in self, `${sensorName} is not supported.`); + const readings = new RingBuffer(readingData.readings); + return func(t, readings); + }, name, properties); + } + + sensor_test(async (t, readings) => { + // This is a specialized EventWatcher that works with a sensor inside a + // cross-origin iframe. We cannot manipulate the sensor object there + // directly from this frame, so we need the iframe to send us a message + // when the "reading" event is fired, and we decide whether we were + // expecting for it or not. This should be instantiated early in the test + // to catch as many unexpected events as possible. + class IframeSensorReadingEventWatcher { + constructor(test_obj) { + this.resolve_ = null; + + window.onmessage = test_obj.step_func((ev) => { + // Unrelated message, ignore. + if (!ev.data.eventName) { + return; + } + + assert_equals( + ev.data.eventName, 'reading', 'Expecting a "reading" event'); + assert_true( + !!this.resolve_, + 'Received "reading" event from iframe but was not expecting one'); + const resolveFunc = this.resolve_; + this.resolve_ = null; + resolveFunc(ev.data.serializedSensor); + }); + } + + wait_for_reading() { + return new Promise(resolve => { + this.resolve_ = resolve; + }); + } + }; + + // Create main frame sensor. + await test_driver.set_permission({name: permissionName}, 'granted'); + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); + + // Create cross-origin iframe and a sensor inside it. const iframe = document.createElement('iframe'); iframe.allow = featurePolicies.join(';') + ';'; - iframe.src = 'https://{{domains[www1]}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; - - // Create sensor inside cross-origin nested browsing context. + iframe.src = + 'https://{{domains[www1]}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; const iframeLoadWatcher = new EventWatcher(t, iframe, 'load'); document.body.appendChild(iframe); t.add_cleanup(async () => { - await send_message_to_iframe(iframe, { command: 'reset_sensor_backend' }); + await send_message_to_iframe(iframe, {command: 'stop_sensor'}); iframe.parentNode.removeChild(iframe); }); await iframeLoadWatcher.wait_for('load'); - await send_message_to_iframe(iframe, {command: 'create_sensor', - type: sensorName}); + const iframeSensorWatcher = new IframeSensorReadingEventWatcher(t); + await send_message_to_iframe( + iframe, {command: 'create_sensor', sensorData}); - // Focus on the main frame and test that sensor receives readings. + // Start the test by focusing the main frame. It is already focused by + // default, but this makes the test easier to follow. + // When the main frame is focused, it sensor is expected to fire "reading" + // events and provide access to new reading values while the sensor in the + // cross-origin iframe is not. window.focus(); - const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ['reading', 'error']); + + // Start both sensors. They should both have the same state: active, but no + // readings have been provided to them yet. + await send_message_to_iframe(iframe, {command: 'start_sensor'}); sensor.start(); + await sensorWatcher.wait_for('activate'); + assert_false( + await send_message_to_iframe(iframe, {command: 'has_reading'})); + assert_false(sensor.hasReading); + + // We store `reading` here because we want to make sure the very same + // value is accepted later. + const reading = readings.next().value; + await Promise.all([ + sensorWatcher.wait_for('reading'), + test_driver.update_virtual_sensor(testDriverName, reading), + // Since we do not wait for the iframe sensor's "reading" event, it could + // arguably be delivered later. There are enough async calls happening + // that IframeSensorReadingEventWatcher would end up catching it and + // throwing an error. + ]); + assert_true(sensor.hasReading); + assert_false( + await send_message_to_iframe(iframe, {command: 'has_reading'})); - await sensorWatcher.wait_for('reading'); - const cachedTimeStamp = sensor.timestamp; + // Save sensor data for later before the sensor is stopped. + const savedMainFrameSensorReadings = serialize_sensor_data(sensor); - // Focus on the cross-origin frame and verify that sensor reading updates in - // the top level browsing context are suspended. + sensor.stop(); + await send_message_to_iframe(iframe, {command: 'stop_sensor'}); + + // Now focus the cross-origin iframe. The situation should be the opposite: + // the sensor in the main frame should not fire any "reading" events or + // provide access to updated readings, but the sensor in the iframe should. iframe.contentWindow.focus(); + + // Start both sensors. They should both have the same state: active, but no + // readings have been provided to them yet. await send_message_to_iframe(iframe, {command: 'start_sensor'}); + sensor.start(); + await sensorWatcher.wait_for('activate'); + assert_false( + await send_message_to_iframe(iframe, {command: 'has_reading'})); + assert_false(sensor.hasReading); - // Focus on the main frame, verify that sensor reading updates are resumed. - window.focus(); - await sensorWatcher.wait_for('reading'); - assert_greater_than(sensor.timestamp, cachedTimeStamp); - sensor.stop(); + const [serializedIframeSensor] = await Promise.all([ + iframeSensorWatcher.wait_for_reading(), + test_driver.update_virtual_sensor(testDriverName, reading), + ]); + assert_true(await send_message_to_iframe(iframe, {command: 'has_reading'})); + assert_false(sensor.hasReading); - // Verify that sensor in cross-origin frame is suspended. - await send_message_to_iframe(iframe, {command: 'is_sensor_suspended'}, true); - }, `${sensorName}: sensor is suspended and resumed when focus traverses from\ - to cross-origin frame`); + assert_sensor_reading_is_null(sensor); - sensor_test(async t => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + assert_sensor_reading_equals( + savedMainFrameSensorReadings, serializedIframeSensor, + {ignoreTimestamps: true}); + + // We could check that serializedIframeSensor.timestamp (adjusted to this + // frame by adding the iframe's timeOrigin and substracting + // performance.timeOrigin) is greater than + // savedMainFrameSensorReadings.timestamp (or other timestamps prior to the + // last test_driver.update_virtual_sensor() call), but this is surprisingly + // tricky and flaky due to the fact that we are using timestamps from + // cross-origin frames. + // + // On Chrome on Windows (M120 at the time of writing), for example, the + // difference between timeOrigin values is sometimes off by more than 10ms + // from the real difference, and allowing for this much jitter makes the + // test not test something meaningful. + }, `${sensorName}: unfocused sensors in cross-origin frames are not updated`); + + sensor_test(async (t, readings) => { + // Create main frame sensor. + await test_driver.set_permission({name: permissionName}, 'granted'); + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); + + // Create same-origin iframe and a sensor inside it. const iframe = document.createElement('iframe'); iframe.allow = featurePolicies.join(';') + ';'; - iframe.src = 'https://{{host}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; - + iframe.src = 'https://{{host}}:{{ports[https][0]}}/resources/blank.html'; // Create sensor inside same-origin nested browsing context. const iframeLoadWatcher = new EventWatcher(t, iframe, 'load'); document.body.appendChild(iframe); - t.add_cleanup(async () => { - await send_message_to_iframe(iframe, { command: 'reset_sensor_backend' }); + t.add_cleanup(() => { + if (iframeSensor) { + iframeSensor.stop(); + } iframe.parentNode.removeChild(iframe); }); await iframeLoadWatcher.wait_for('load'); - await send_message_to_iframe(iframe, {command: 'create_sensor', - type: sensorName}); + // We deliberately create the sensor here instead of using + // send_messge_to_iframe() because this is a same-origin iframe, and we can + // therefore use EventWatcher() to wait for "reading" events a lot more + // easily. + const iframeSensor = new iframe.contentWindow[sensorName](); + const iframeSensorWatcher = + new EventWatcher(t, iframeSensor, ['activate', 'error', 'reading']); - // Focus on main frame and test that sensor receives readings. - window.focus(); - const sensor = new sensorType({ - // generic_sensor_mocks.js uses a default frequency of 5Hz for sensors. - // We deliberately use a higher frequency here to make it easier to spot - // spurious, unexpected 'reading' events caused by the main frame's - // sensor not stopping early enough. - // TODO(rakuco): Create a constant with the 5Hz default frequency instead - // of using magic numbers. - frequency: 15 - }); - const sensorWatcher = new EventWatcher(t, sensor, ['reading', 'error']); - sensor.start(); - await sensorWatcher.wait_for('reading'); - let cachedTimeStamp = sensor.timestamp; - - // Stop sensor in main frame, so that sensorWatcher would not receive - // readings while sensor in iframe is started. Sensors that are active and - // belong to the same-origin context are not suspended automatically when - // focus changes to another same-origin iframe, so if we do not explicitly - // stop them we may receive extra 'reading' events that cause the test to - // fail (see e.g. https://crbug.com/857520). - sensor.stop(); + // Focus a different same-origin window each time and check that everything + // works the same. + for (const windowObject of [window, iframe.contentWindow]) { + windowObject.focus(); - iframe.contentWindow.focus(); - await send_message_to_iframe(iframe, {command: 'start_sensor'}); + iframeSensor.start(); + sensor.start(); + await Promise.all([ + iframeSensorWatcher.wait_for('activate'), + sensorWatcher.wait_for('activate') + ]); - // Start sensor on main frame, verify that readings are updated. - window.focus(); - sensor.start(); - await sensorWatcher.wait_for('reading'); - assert_greater_than(sensor.timestamp, cachedTimeStamp); - cachedTimeStamp = sensor.timestamp; - sensor.stop(); + assert_false(sensor.hasReading); + assert_false(iframeSensor.hasReading); - // Verify that sensor in nested browsing context is not suspended. - await send_message_to_iframe(iframe, {command: 'is_sensor_suspended'}, false); + // We store `reading` here because we want to make sure the very same + // value is accepted later. + const reading = readings.next().value; + await Promise.all([ + test_driver.update_virtual_sensor(testDriverName, reading), + iframeSensorWatcher.wait_for('reading'), + sensorWatcher.wait_for('reading') + ]); - // Verify that sensor in top level browsing context is receiving readings. - iframe.contentWindow.focus(); - sensor.start(); - await sensorWatcher.wait_for('reading'); - assert_greater_than(sensor.timestamp, cachedTimeStamp); - sensor.stop(); - }, `${sensorName}: sensor is not suspended when focus traverses from\ - to same-origin frame`); + assert_greater_than( + iframe.contentWindow.performance.timeOrigin, performance.timeOrigin, + 'iframe\'s time origin must be higher than the main window\'s'); + + // Check that the timestamps are similar enough to indicate that this is + // the same reading that was delivered to both sensors. + // The values are not identical due to how high resolution time is + // coarsened. + const translatedIframeSensorTimestamp = iframeSensor.timestamp + + iframe.contentWindow.performance.timeOrigin - performance.timeOrigin; + assert_approx_equals( + translatedIframeSensorTimestamp, sensor.timestamp, + ALLOWED_JITTER_IN_MS); - sensor_test(async t => { + // Do not compare timestamps here because of the reasons above. + assert_sensor_reading_equals( + sensor, iframeSensor, {ignoreTimestamps: true}); + + // Stop all sensors so we can use the same value in `reading` on every + // loop iteration. + iframeSensor.stop(); + sensor.stop(); + } + }, `${sensorName}: sensors in same-origin frames are updated if one of the frames is focused`); + + promise_test(async t => { assert_implements(sensorName in self, `${sensorName} is not supported.`); const iframe = document.createElement('iframe'); iframe.allow = featurePolicies.join(';') + ';'; - iframe.src = 'https://{{host}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; + iframe.src = + 'https://{{host}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; - // Create sensor in the iframe. const iframeLoadWatcher = new EventWatcher(t, iframe, 'load'); document.body.appendChild(iframe); await iframeLoadWatcher.wait_for('load'); - // This is required for the JS Mojo backend to be initialized in the - // iframe. - await send_message_to_iframe(iframe, {command: 'create_sensor', - type: sensorName}); + + // Create sensor in the iframe. + await test_driver.set_permission({name: permissionName}, 'granted'); + await test_driver.create_virtual_sensor(testDriverName); iframe.contentWindow.focus(); const iframeSensor = new iframe.contentWindow[sensorName](); - t.add_cleanup(() => { + t.add_cleanup(async () => { iframeSensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); }); const sensorWatcher = new EventWatcher(t, iframeSensor, ['activate']); iframeSensor.start(); @@ -161,24 +304,25 @@ function run_generic_sensor_iframe_tests(sensorName) { window.focus(); }, `${sensorName}: losing a document's frame with an active sensor does not crash`); - sensor_test(async t => { + promise_test(async t => { assert_implements(sensorName in self, `${sensorName} is not supported.`); const iframe = document.createElement('iframe'); iframe.allow = featurePolicies.join(';') + ';'; - iframe.src = 'https://{{host}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; + iframe.src = + 'https://{{host}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; - // Create sensor in the iframe (we do not care whether this is a - // cross-origin nested context in this test). const iframeLoadWatcher = new EventWatcher(t, iframe, 'load'); document.body.appendChild(iframe); await iframeLoadWatcher.wait_for('load'); - // The purpose of this message is to initialize the mock backend in the - // iframe. We are not going to use the sensor created there. - await send_message_to_iframe(iframe, {command: 'create_sensor', - type: sensorName}); - + // Create sensor in the iframe. + await test_driver.set_permission({name: permissionName}, 'granted'); + await test_driver.create_virtual_sensor(testDriverName); const iframeSensor = new iframe.contentWindow[sensorName](); + t.add_cleanup(async () => { + iframeSensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); assert_not_equals(iframeSensor, null); // Remove iframe from main document. |iframeSensor| no longer has a diff --git a/tests/wpt/tests/generic-sensor/generic-sensor-tests.js b/tests/wpt/tests/generic-sensor/generic-sensor-tests.js index 3c8f478c541..3b23fe89191 100644 --- a/tests/wpt/tests/generic-sensor/generic-sensor-tests.js +++ b/tests/wpt/tests/generic-sensor/generic-sensor-tests.js @@ -14,289 +14,344 @@ // |verificationFunction| is called to verify that a given reading matches a // value in |expectedReadings|. // |featurePolicies| represents |sensorName|'s associated sensor feature name. +function runGenericSensorTests(sensorData, readingData) { + validate_sensor_data(sensorData); + validate_reading_data(readingData); -function runGenericSensorTests(sensorName, - readingData, - verificationFunction, - featurePolicies) { + const {sensorName, permissionName, testDriverName, featurePolicyNames} = + sensorData; const sensorType = self[sensorName]; - function validateReadingFormat(data) { - return Array.isArray(data) && data.every(element => Array.isArray(element)); - } - - const { readings, expectedReadings, expectedRemappedReadings } = readingData; - if (!validateReadingFormat(readings)) { - throw new TypeError('readingData.readings must be an array of arrays.'); - } - if (!validateReadingFormat(expectedReadings)) { - throw new TypeError('readingData.expectedReadings must be an array of ' + - 'arrays.'); - } - if (readings.length < expectedReadings.length) { - throw new TypeError('readingData.readings\' length must be bigger than ' + - 'or equal to readingData.expectedReadings\' length.'); - } - if (expectedRemappedReadings && - !validateReadingFormat(expectedRemappedReadings)) { - throw new TypeError('readingData.expectedRemappedReadings must be an ' + - 'array of arrays.'); - } - if (expectedRemappedReadings && - expectedReadings.length != expectedRemappedReadings.length) { - throw new TypeError('readingData.expectedReadings and ' + - 'readingData.expectedRemappedReadings must have the same ' + - 'length.'); - } + function sensor_test(func, name, properties) { + promise_test(async t => { + assert_implements(sensorName in self, `${sensorName} is not supported.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); - sensorProvider.setGetSensorShouldFail(sensorName, true); - const sensor = new sensorType; - const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); - sensor.start(); + const readings = new RingBuffer(readingData.readings); + const expectedReadings = new RingBuffer(readingData.expectedReadings); + const expectedRemappedReadings = readingData.expectedRemappedReadings ? + new RingBuffer(readingData.expectedRemappedReadings) : + undefined; - const event = await sensorWatcher.wait_for("error"); + return func(t, readings, expectedReadings, expectedRemappedReadings); + }, name, properties); + } - assert_false(sensor.activated); - assert_equals(event.error.name, 'NotReadableError'); - }, `${sensorName}: Test that onerror is sent when sensor is not supported.`); + sensor_test(async t => { + await test_driver.set_permission({name: permissionName}, 'denied'); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); - sensorProvider.setPermissionsDenied(sensorName, true); + await test_driver.create_virtual_sensor(testDriverName); const sensor = new sensorType; - const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = new EventWatcher(t, sensor, ['reading', 'error']); sensor.start(); - const event = await sensorWatcher.wait_for("error"); + const event = await sensorWatcher.wait_for('error'); assert_false(sensor.activated); assert_equals(event.error.name, 'NotAllowedError'); }, `${sensorName}: Test that onerror is sent when permissions are not\ granted.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); - const sensor = new sensorType({frequency: 560}); - const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); - sensor.start(); + sensor_test(async t => { + await test_driver.set_permission({name: permissionName}, 'granted'); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - mockSensor.setStartShouldFail(true); + await test_driver.create_virtual_sensor(testDriverName, {connected: false}); + const sensor = new sensorType; + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = new EventWatcher(t, sensor, ['reading', 'error']); - const event = await sensorWatcher.wait_for("error"); + sensor.start(); + + const event = await sensorWatcher.wait_for('error'); assert_false(sensor.activated); assert_equals(event.error.name, 'NotReadableError'); }, `${sensorName}: Test that onerror is send when start() call has failed.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async t => { + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType({frequency: 560}); - const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = new EventWatcher(t, sensor, ['activate', 'error']); sensor.start(); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - - await sensorWatcher.wait_for("activate"); + await sensorWatcher.wait_for('activate'); + const mockSensorInfo = + await test_driver.get_virtual_sensor_information(testDriverName); - assert_less_than_equal(mockSensor.getSamplingFrequency(), 60); - sensor.stop(); - assert_false(sensor.activated); + assert_less_than_equal(mockSensorInfo.requestedSamplingFrequency, 60); }, `${sensorName}: Test that frequency is capped to allowed maximum.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async t => { + await test_driver.set_permission({name: permissionName}, 'granted'); + const maxSupportedFrequency = 5; - sensorProvider.setMaximumSupportedFrequency(maxSupportedFrequency); + await test_driver.create_virtual_sensor( + testDriverName, {maxSamplingFrequency: maxSupportedFrequency}); + const sensor = new sensorType({frequency: 50}); - const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = new EventWatcher(t, sensor, ['activate', 'error']); sensor.start(); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - - await sensorWatcher.wait_for("activate"); + await sensorWatcher.wait_for('activate'); + const mockSensorInfo = + await test_driver.get_virtual_sensor_information(testDriverName); - assert_equals(mockSensor.getSamplingFrequency(), maxSupportedFrequency); - sensor.stop(); - assert_false(sensor.activated); + assert_equals( + mockSensorInfo.requestedSamplingFrequency, maxSupportedFrequency); }, `${sensorName}: Test that frequency is capped to the maximum supported\ frequency.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async t => { + await test_driver.set_permission({name: permissionName}, 'granted'); + const minSupportedFrequency = 2; - sensorProvider.setMinimumSupportedFrequency(minSupportedFrequency); + await test_driver.create_virtual_sensor( + testDriverName, {minSamplingFrequency: minSupportedFrequency}); + const sensor = new sensorType({frequency: -1}); - const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = new EventWatcher(t, sensor, ['activate', 'error']); sensor.start(); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - - await sensorWatcher.wait_for("activate"); + await sensorWatcher.wait_for('activate'); + const mockSensorInfo = + await test_driver.get_virtual_sensor_information(testDriverName); - assert_equals(mockSensor.getSamplingFrequency(), minSupportedFrequency); - sensor.stop(); - assert_false(sensor.activated); + assert_equals( + mockSensorInfo.requestedSamplingFrequency, minSupportedFrequency); }, `${sensorName}: Test that frequency is limited to the minimum supported\ frequency.`); - promise_test(async t => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async t => { const iframe = document.createElement('iframe'); - iframe.allow = featurePolicies.join(' \'none\'; ') + ' \'none\';'; + iframe.allow = featurePolicyNames.join(' \'none\'; ') + ' \'none\';'; iframe.srcdoc = '<script>' + - ' window.onmessage = message => {' + - ' if (message.data === "LOADED") {' + - ' try {' + - ' new ' + sensorName + '();' + - ' parent.postMessage("FAIL", "*");' + - ' } catch (e) {' + - ' parent.postMessage("PASS", "*");' + - ' }' + - ' }' + - ' };' + - '<\/script>'; - const iframeWatcher = new EventWatcher(t, iframe, "load"); + ' window.onmessage = message => {' + + ' if (message.data === "LOADED") {' + + ' try {' + + ' new ' + sensorName + '();' + + ' parent.postMessage("FAIL", "*");' + + ' } catch (e) {' + + ' parent.postMessage(`PASS: got ${e.name}`, "*");' + + ' }' + + ' }' + + ' };' + + '<\/script>'; + const iframeWatcher = new EventWatcher(t, iframe, 'load'); document.body.appendChild(iframe); - await iframeWatcher.wait_for("load"); + await iframeWatcher.wait_for('load'); iframe.contentWindow.postMessage('LOADED', '*'); - const windowWatcher = new EventWatcher(t, window, "message"); - const message = await windowWatcher.wait_for("message"); - assert_equals(message.data, 'PASS'); + const windowWatcher = new EventWatcher(t, window, 'message'); + const message = await windowWatcher.wait_for('message'); + assert_equals(message.data, 'PASS: got SecurityError'); }, `${sensorName}: Test that sensor cannot be constructed within iframe\ disallowed to use feature policy.`); - promise_test(async t => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async t => { const iframe = document.createElement('iframe'); - iframe.allow = featurePolicies.join(';') + ';'; + iframe.allow = featurePolicyNames.join(';') + ';'; iframe.srcdoc = '<script>' + - ' window.onmessage = message => {' + - ' if (message.data === "LOADED") {' + - ' try {' + - ' new ' + sensorName + '();' + - ' parent.postMessage("PASS", "*");' + - ' } catch (e) {' + - ' parent.postMessage("FAIL", "*");' + - ' }' + - ' }' + - ' };' + - '<\/script>'; - const iframeWatcher = new EventWatcher(t, iframe, "load"); + ' window.onmessage = message => {' + + ' if (message.data === "LOADED") {' + + ' try {' + + ' new ' + sensorName + '();' + + ' parent.postMessage("PASS", "*");' + + ' } catch (e) {' + + ' parent.postMessage("FAIL", "*");' + + ' }' + + ' }' + + ' };' + + '<\/script>'; + const iframeWatcher = new EventWatcher(t, iframe, 'load'); document.body.appendChild(iframe); - await iframeWatcher.wait_for("load"); + await iframeWatcher.wait_for('load'); iframe.contentWindow.postMessage('LOADED', '*'); - const windowWatcher = new EventWatcher(t, window, "message"); - const message = await windowWatcher.wait_for("message"); + const windowWatcher = new EventWatcher(t, window, 'message'); + const message = await windowWatcher.wait_for('message'); assert_equals(message.data, 'PASS'); }, `${sensorName}: Test that sensor can be constructed within an iframe\ allowed to use feature policy.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); - const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); + sensor_test(async (t, readings, expectedReadings) => { + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + + const sensor = new sensorType; + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); + sensor.start(); assert_false(sensor.hasReading); + await sensorWatcher.wait_for('activate'); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - mockSensor.setSensorReading(readings); + await Promise.all([ + test_driver.update_virtual_sensor(testDriverName, readings.next().value), + sensorWatcher.wait_for('reading') + ]); + + assert_sensor_reading_equals(sensor, expectedReadings.next().value); - await sensorWatcher.wait_for("reading"); - const expected = new RingBuffer(expectedReadings).next().value; - assert_true(verificationFunction(expected, sensor)); assert_true(sensor.hasReading); sensor.stop(); - assert_true(verificationFunction(expected, sensor, /*isNull=*/true)); + + assert_sensor_reading_is_null(sensor); assert_false(sensor.hasReading); }, `${sensorName}: Test that 'onreading' is called and sensor reading is\ valid.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); - const sensor1 = new sensorType(); - const sensorWatcher1 = new EventWatcher(t, sensor1, ["reading", "error"]); - sensor1.start(); + sensor_test(async (t, readings, expectedReadings) => { + await test_driver.set_permission({name: permissionName}, 'granted'); + await test_driver.create_virtual_sensor(testDriverName); + + const sensor1 = new sensorType(); const sensor2 = new sensorType(); - const sensorWatcher2 = new EventWatcher(t, sensor2, ["reading", "error"]); + t.add_cleanup(async () => { + sensor1.stop(); + sensor2.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher1 = + new EventWatcher(t, sensor1, ['activate', 'reading', 'error']); + const sensorWatcher2 = + new EventWatcher(t, sensor2, ['activate', 'reading', 'error']); + sensor1.start(); sensor2.start(); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - mockSensor.setSensorReading(readings); + await Promise.all([ + sensorWatcher1.wait_for('activate'), sensorWatcher2.wait_for('activate') + ]); + + await Promise.all([ + test_driver.update_virtual_sensor(testDriverName, readings.next().value), + sensorWatcher1.wait_for('reading'), sensorWatcher2.wait_for('reading') + ]); - await Promise.all([sensorWatcher1.wait_for("reading"), - sensorWatcher2.wait_for("reading")]); - const expected = new RingBuffer(expectedReadings).next().value; // Reading values are correct for both sensors. - assert_true(verificationFunction(expected, sensor1)); - assert_true(verificationFunction(expected, sensor2)); + const expected = expectedReadings.next().value; + assert_sensor_reading_equals(sensor1, expected); + assert_sensor_reading_equals(sensor2, expected); // After first sensor stops its reading values are null, // reading values for the second sensor sensor remain. sensor1.stop(); - assert_true(verificationFunction(expected, sensor1, /*isNull=*/true)); - assert_true(verificationFunction(expected, sensor2)); + assert_sensor_reading_is_null(sensor1); + assert_sensor_reading_equals(sensor2, expected); sensor2.stop(); - assert_true(verificationFunction(expected, sensor2, /*isNull=*/true)); + assert_sensor_reading_is_null(sensor2); }, `${sensorName}: sensor reading is correct.`); // Tests that readings maps to expectedReadings correctly. Due to threshold // check and rounding some values might be discarded or changed. - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async (t, readings, expectedReadings) => { + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); sensor.start(); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - await mockSensor.setSensorReading(readings); + await sensorWatcher.wait_for('activate'); - for (let expectedReading of expectedReadings) { - await sensorWatcher.wait_for("reading"); - assert_true(sensor.hasReading, "hasReading"); - assert_true(verificationFunction(expectedReading, sensor), - "verification"); - } + const sensorInfo = + await test_driver.get_virtual_sensor_information(testDriverName); + const sensorPeriodInMs = (1 / sensorInfo.requestedSamplingFrequency) * 1000; - sensor.stop(); + for (let expectedReading of expectedReadings.data) { + await update_virtual_sensor_until_reading( + t, readings, sensorWatcher.wait_for('reading'), testDriverName, + sensorPeriodInMs * 3); + assert_true(sensor.hasReading, 'hasReading'); + assert_sensor_reading_equals(sensor, expectedReading); + } }, `${sensorName}: Test that readings are all mapped to expectedReadings\ correctly.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async (t, readings) => { + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); sensor.start(); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - mockSensor.setSensorReading(readings); + await sensorWatcher.wait_for('activate'); - await sensorWatcher.wait_for("reading"); + const sensorInfo = + await test_driver.get_virtual_sensor_information(testDriverName); + const sensorPeriodInMs = (1 / sensorInfo.requestedSamplingFrequency) * 1000; + + await Promise.all([ + test_driver.update_virtual_sensor(testDriverName, readings.next().value), + sensorWatcher.wait_for('reading') + ]); const cachedTimeStamp1 = sensor.timestamp; - await sensorWatcher.wait_for("reading"); + await update_virtual_sensor_until_reading( + t, readings, sensorWatcher.wait_for('reading'), testDriverName, + sensorPeriodInMs * 3); const cachedTimeStamp2 = sensor.timestamp; assert_greater_than(cachedTimeStamp2, cachedTimeStamp1); - sensor.stop(); }, `${sensorName}: sensor timestamp is updated when time passes.`); sensor_test(async t => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = new EventWatcher(t, sensor, ['activate', 'error']); assert_false(sensor.activated); sensor.start(); assert_false(sensor.activated); - await sensorWatcher.wait_for("activate"); + await sensorWatcher.wait_for('activate'); assert_true(sensor.activated); sensor.stop(); @@ -305,245 +360,331 @@ function runGenericSensorTests(sensorName, states are correct.`); sensor_test(async t => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = new EventWatcher(t, sensor, ['activate', 'error']); sensor.start(); sensor.start(); - await sensorWatcher.wait_for("activate"); + await sensorWatcher.wait_for('activate'); assert_true(sensor.activated); - sensor.stop(); }, `${sensorName}: no exception is thrown when calling start() on already\ started sensor.`); sensor_test(async t => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = new EventWatcher(t, sensor, ['activate', 'error']); sensor.start(); - await sensorWatcher.wait_for("activate"); + await sensorWatcher.wait_for('activate'); sensor.stop(); sensor.stop(); assert_false(sensor.activated); }, `${sensorName}: no exception is thrown when calling stop() on already\ stopped sensor.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async (t, readings, expectedReadings) => { + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); - const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); sensor.start(); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - mockSensor.setSensorReading(readings); + await sensorWatcher.wait_for('activate'); + + await Promise.all([ + test_driver.update_virtual_sensor(testDriverName, readings.next().value), + sensorWatcher.wait_for('reading') + ]); - const expectedBuffer = new RingBuffer(expectedReadings); - await sensorWatcher.wait_for("reading"); - const expected1 = expectedBuffer.next().value; assert_true(sensor.hasReading); - assert_true(verificationFunction(expected1, sensor)); + + const expected = expectedReadings.next().value; + assert_sensor_reading_equals(sensor, expected); + const timestamp = sensor.timestamp; sensor.stop(); assert_false(sensor.hasReading); + assert_false(sensor.activated); sensor.start(); - await sensorWatcher.wait_for("reading"); + + await sensorWatcher.wait_for('activate'); + assert_false(sensor.hasReading); + readings.reset(); + await Promise.all([ + test_driver.update_virtual_sensor(testDriverName, readings.next().value), + sensorWatcher.wait_for('reading') + ]); assert_true(sensor.hasReading); - // |readingData| may have a single reading/expectation value, and this - // is the second reading we are getting. For that case, make sure we - // also wrap around as if we had the same RingBuffer used in - // generic_sensor_mocks.js. - const expected2 = expectedBuffer.next().value; - assert_true(verificationFunction(expected2, sensor)); + + assert_sensor_reading_equals(sensor, expected); // Make sure that 'timestamp' is already initialized. assert_greater_than(timestamp, 0); // Check that the reading is updated. assert_greater_than(sensor.timestamp, timestamp); - sensor.stop(); }, `${sensorName}: Test that fresh reading is fetched on start().`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async (t, readings, expectedReadings) => { + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + const sensor = new sensorType(); - t.add_cleanup(() => { + t.add_cleanup(async () => { sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); }); - const sensorWatcher = new EventWatcher(t, sensor, ['reading', 'error']); - sensor.start(); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - mockSensor.setSensorReading(readings); + sensor.start(); + await sensorWatcher.wait_for('activate'); - const expectedBuffer = new RingBuffer(expectedReadings); - await sensorWatcher.wait_for('reading'); - const expected1 = expectedBuffer.next().value; - assert_true(verificationFunction(expected1, sensor)); - assert_true(mockSensor.isReadingData()); - const cachedTimestamp1 = sensor.timestamp; + assert_false(sensor.hasReading); + assert_sensor_reading_is_null(sensor); const {minimize, restore} = window_state_context(t); await minimize(); assert_true(document.hidden); - await t.step_wait( - () => !mockSensor.isReadingData(), 'readings must be suspended'); - const cachedTimestamp2 = sensor.timestamp; - assert_equals(cachedTimestamp1, cachedTimestamp2); + assert_true(sensor.activated); + assert_false(sensor.hasReading); + assert_sensor_reading_is_null(sensor); + + const reading = readings.next().value; + await test_driver.update_virtual_sensor(testDriverName, reading); await restore(); assert_false(document.hidden); - await t.step_wait( - () => mockSensor.isReadingData(), 'readings must be restored'); - await sensorWatcher.wait_for('reading'); - const expected2 = expectedBuffer.next().value; - assert_true(verificationFunction(expected2, sensor)); - assert_greater_than(sensor.timestamp, cachedTimestamp2); - }, `${sensorName}: Losing visibility must cause readings to be suspended.`); - - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); - - const fastSensor = new sensorType({ frequency: 60 }); - t.add_cleanup(() => { fastSensor.stop(); }); - let eventWatcher = new EventWatcher(t, fastSensor, "activate"); + assert_true(sensor.activated); + assert_false(sensor.hasReading); + assert_sensor_reading_is_null(sensor); + + const visiblePageTimestamp = performance.now(); + + const [readingEvent] = await Promise.all([ + sensorWatcher.wait_for('reading'), + test_driver.update_virtual_sensor(testDriverName, reading), + ]); + + const postReadingTimestamp = performance.now(); + + assert_sensor_reading_equals(sensor, expectedReadings.next().value); + + // Check that the only reading we received all this time was the one sent + // after the page was made visible again. This is done by verifying the + // timestamps of the event as well as the current reading's. + assert_greater_than_equal(sensor.timestamp, visiblePageTimestamp); + assert_greater_than(readingEvent.timeStamp, sensor.timestamp); + assert_greater_than_equal( + postReadingTimestamp, readingEvent.timeStamp, + 'No new reading events have been delivered'); + }, `${sensorName}: Readings are not delivered when the page has no visibility`); + + sensor_test(async t => { + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); + + const fastSensor = new sensorType({frequency: 60}); + t.add_cleanup(() => { + fastSensor.stop(); + }); + let eventWatcher = new EventWatcher(t, fastSensor, ['activate']); fastSensor.start(); // Wait for |fastSensor| to be activated so that the call to // getSamplingFrequency() below works. - await eventWatcher.wait_for("activate"); + await eventWatcher.wait_for('activate'); - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - mockSensor.setSensorReading(readings); + let mockSensorInfo = + await test_driver.get_virtual_sensor_information(testDriverName); // We need |fastSensorFrequency| because 60Hz might be higher than a sensor // type's maximum allowed frequency. - const fastSensorFrequency = mockSensor.getSamplingFrequency(); + const fastSensorFrequency = mockSensorInfo.requestedSamplingFrequency; const slowSensorFrequency = fastSensorFrequency * 0.25; - const slowSensor = new sensorType({ frequency: slowSensorFrequency }); - t.add_cleanup(() => { slowSensor.stop(); }); - eventWatcher = new EventWatcher(t, slowSensor, "activate"); + const slowSensor = new sensorType({frequency: slowSensorFrequency}); + t.add_cleanup(() => { + slowSensor.stop(); + }); + t.add_cleanup(async () => { + // Remove the virtual sensor only after calling stop() on both sensors. + await test_driver.remove_virtual_sensor(testDriverName); + }); + eventWatcher = new EventWatcher(t, slowSensor, 'activate'); slowSensor.start(); // Wait for |slowSensor| to be activated before we check if the mock // platform sensor's sampling frequency has changed. - await eventWatcher.wait_for("activate"); - assert_equals(mockSensor.getSamplingFrequency(), fastSensorFrequency); + await eventWatcher.wait_for('activate'); + mockSensorInfo = + await test_driver.get_virtual_sensor_information(testDriverName); + assert_equals( + mockSensorInfo.requestedSamplingFrequency, fastSensorFrequency); // Now stop |fastSensor| and verify that the sampling frequency has dropped // to the one |slowSensor| had requested. fastSensor.stop(); - return t.step_wait(() => { - return mockSensor.getSamplingFrequency() === slowSensorFrequency; - }, "Sampling frequency has dropped to slowSensor's requested frequency"); + await wait_for_virtual_sensor_state(testDriverName, (info) => { + return info.requestedSamplingFrequency === slowSensorFrequency; + }); }, `${sensorName}: frequency hint works.`); - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); + sensor_test(async (t, readings, expectedReadings) => { + await test_driver.set_permission({name: permissionName}, 'granted'); + + await test_driver.create_virtual_sensor(testDriverName); const sensor1 = new sensorType(); const sensor2 = new sensorType(); - return new Promise((resolve, reject) => { + t.add_cleanup(async () => { + sensor1.stop(); + sensor2.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + + return new Promise(async (resolve, reject) => { sensor1.addEventListener('reading', () => { sensor2.addEventListener('activate', () => { try { assert_true(sensor1.activated); assert_true(sensor1.hasReading); - assert_false(verificationFunction(null, sensor1, /*isNull=*/true)); - assert_not_equals(sensor1.timestamp, null); + + const expected = expectedReadings.next().value; + assert_sensor_reading_equals(sensor1, expected); assert_true(sensor2.activated); - assert_false(verificationFunction(null, sensor2, /*isNull=*/true)); - assert_not_equals(sensor2.timestamp, null); + assert_sensor_reading_equals(sensor2, expected); } catch (e) { reject(e); } - }, { once: true }); + }, {once: true}); sensor2.addEventListener('reading', () => { try { assert_true(sensor2.activated); assert_true(sensor2.hasReading); - assert_sensor_equals(sensor1, sensor2); + assert_sensor_reading_equals(sensor1, sensor2); + assert_equals(sensor1.timestamp, sensor2.timestamp); resolve(); } catch (e) { reject(e); } - }, { once: true }); + }, {once: true}); sensor2.start(); - }, { once: true }); + }, {once: true}); + + const eventWatcher = new EventWatcher(t, sensor1, ['activate']); sensor1.start(); + await eventWatcher.wait_for('activate'); + test_driver.update_virtual_sensor(testDriverName, readings.next().value); }); }, `${sensorName}: Readings delivered by shared platform sensor are\ immediately accessible to all sensors.`); -// Re-enable after https://github.com/w3c/sensors/issues/361 is fixed. -// test(() => { -// assert_throws_dom("NotSupportedError", -// () => { new sensorType({invalid: 1}) }); -// assert_throws_dom("NotSupportedError", -// () => { new sensorType({frequency: 60, invalid: 1}) }); -// if (!expectedRemappedReadings) { -// assert_throws_dom("NotSupportedError", -// () => { new sensorType({referenceFrame: "screen"}) }); -// } -// }, `${sensorName}: throw 'NotSupportedError' for an unsupported sensor\ -// option.`); + // Re-enable after https://github.com/w3c/sensors/issues/361 is fixed. + // test(() => { + // assert_throws_dom("NotSupportedError", + // () => { new sensorType({invalid: 1}) }); + // assert_throws_dom("NotSupportedError", + // () => { new sensorType({frequency: 60, invalid: 1}) }); + // if (!expectedRemappedReadings) { + // assert_throws_dom("NotSupportedError", + // () => { new sensorType({referenceFrame: "screen"}) }); + // } + // }, `${sensorName}: throw 'NotSupportedError' for an unsupported sensor\ + // option.`); test(() => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); - const invalidFreqs = [ - "invalid", - NaN, - Infinity, - -Infinity, - {} - ]; + const invalidFreqs = ['invalid', NaN, Infinity, -Infinity, {}]; invalidFreqs.map(freq => { - assert_throws_js(TypeError, - () => { new sensorType({frequency: freq}) }, - `when freq is ${freq}`); + assert_throws_js( + TypeError, () => {new sensorType({frequency: freq})}, + `when freq is ${freq}`); }); }, `${sensorName}: throw 'TypeError' if frequency is invalid.`); - if (!expectedRemappedReadings) { + if (!readingData.expectedRemappedReadings) { // The sensorType does not represent a spatial sensor. return; } - sensor_test(async (t, sensorProvider) => { - assert_implements(sensorName in self, `${sensorName} is not supported.`); - const sensor1 = new sensorType({frequency: 60}); - const sensor2 = new sensorType({frequency: 60, referenceFrame: "screen"}); - const sensorWatcher1 = new EventWatcher(t, sensor1, ["reading", "error"]); - const sensorWatcher2 = new EventWatcher(t, sensor1, ["reading", "error"]); - - sensor1.start(); - sensor2.start(); - - const mockSensor = await sensorProvider.getCreatedSensor(sensorName); - mockSensor.setSensorReading(readings); - - await Promise.all([sensorWatcher1.wait_for("reading"), - sensorWatcher2.wait_for("reading")]); - - const expected = new RingBuffer(expectedReadings).next().value; - const expectedRemapped = - new RingBuffer(expectedRemappedReadings).next().value; - assert_true(verificationFunction(expected, sensor1)); - assert_true(verificationFunction(expectedRemapped, sensor2)); - - sensor1.stop(); - assert_true(verificationFunction(expected, sensor1, /*isNull=*/true)); - assert_true(verificationFunction(expectedRemapped, sensor2)); - - sensor2.stop(); - assert_true(verificationFunction(expectedRemapped, sensor2, - /*isNull=*/true)); - }, `${sensorName}: sensor reading is correct when options.referenceFrame\ - is 'screen'.`); + // TODO(https://github.com/web-platform-tests/wpt/issues/42724): Re-enable + // when there is a cross-platform way to set an orientation angle. + // sensor_test( + // async (t, readings, expectedReadings, expectedRemappedReadings) => { + // assert_implements_optional(screen.orientation.angle == 270, + // 'Remapped values expect a specific screen rotation.'); + // await test_driver.set_permission({name: permissionName}, 'granted'); + + // await test_driver.create_virtual_sensor(testDriverName); + + // const sensor1 = new sensorType({frequency: 60}); + // const sensor2 = + // new sensorType({frequency: 60, referenceFrame: 'screen'}); + // t.add_cleanup(async () => { + // sensor1.stop(); + // sensor2.stop(); + // await test_driver.remove_virtual_sensor(testDriverName); + // }); + // const sensorWatcher1 = + // new EventWatcher(t, sensor1, ['activate', 'reading', 'error']); + // const sensorWatcher2 = + // new EventWatcher(t, sensor1, ['activate', 'reading', 'error']); + + // sensor1.start(); + // sensor2.start(); + + // await Promise.all([ + // sensorWatcher1.wait_for('activate'), + // sensorWatcher2.wait_for('activate') + // ]); + + // await Promise.all([ + // test_driver.update_virtual_sensor(testDriverName, + // readings.next().value), sensorWatcher1.wait_for('reading'), + // sensorWatcher2.wait_for('reading') + // ]); + + // const expected = expectedReadings.next().value; + // const expectedRemapped = expectedRemappedReadings.next().value; + // assert_sensor_reading_equals(sensor1, expected); + // assert_sensor_reading_equals(sensor2, expectedRemapped); + + // sensor1.stop(); + // assert_sensor_reading_is_null(sensor1); + // assert_sensor_reading_equals(sensor2, expectedRemapped); + + // sensor2.stop(); + // assert_sensor_reading_is_null(sensor2); + // }, + // `${sensorName}: sensor reading is correct when options.referenceFrame\ + // is 'screen'.`); } function runGenericSensorInsecureContext(sensorName) { diff --git a/tests/wpt/tests/generic-sensor/resources/generic-sensor-helpers.js b/tests/wpt/tests/generic-sensor/resources/generic-sensor-helpers.js index 9a51a591ce1..146f4292ade 100644 --- a/tests/wpt/tests/generic-sensor/resources/generic-sensor-helpers.js +++ b/tests/wpt/tests/generic-sensor/resources/generic-sensor-helpers.js @@ -1,142 +1,179 @@ 'use strict'; -// These tests rely on the User Agent providing an implementation of -// platform sensor backends. -// -// In Chromium-based browsers this implementation is provided by a polyfill -// in order to reduce the amount of test-only code shipped to users. To enable -// these tests the browser must be run with these options: -// -// --enable-blink-features=MojoJS,MojoJSTest -async function loadChromiumResources() { - await loadScript('/resources/testdriver.js'); - await loadScript('/resources/testdriver-vendor.js'); - await loadScript('/page-visibility/resources/window_state_context.js'); - await import('/resources/chromium/generic_sensor_mocks.js'); -} - -async function initialize_generic_sensor_tests() { - if (typeof GenericSensorTest === 'undefined') { - const script = document.createElement('script'); - script.src = '/resources/test-only-api.js'; - script.async = false; - const p = new Promise((resolve, reject) => { - script.onload = () => { resolve(); }; - script.onerror = e => { reject(e); }; - }) - document.head.appendChild(script); - await p; - - if (isChromiumBased) { - await loadChromiumResources(); +// If two doubles differ by less than this amount, we can consider them +// to be effectively equal. +const kEpsilon = 1e-8; + +class RingBuffer { + constructor(data) { + if (!Array.isArray(data)) { + throw new TypeError('`data` must be an array.'); } + + this.bufferPosition_ = 0; + this.data_ = Array.from(data); } - let sensorTest = new GenericSensorTest(); - await sensorTest.initialize(); - return sensorTest; -} + get data() { + return Array.from(this.data_); + } -function sensor_test(func, name, properties) { - promise_test(async (t) => { - t.add_cleanup(() => { - if (sensorTest) - return sensorTest.reset(); - }); + next() { + const value = this.data_[this.bufferPosition_]; + this.bufferPosition_ = (this.bufferPosition_ + 1) % this.data_.length; + return {done: false, value: value}; + } - let sensorTest = await initialize_generic_sensor_tests(); - return func(t, sensorTest.getSensorProvider()); - }, name, properties); -} + value() { + return this.data_[this.bufferPosition_]; + } -function verifySensorReading(pattern, values, timestamp, isNull) { - // If |val| cannot be converted to a float, we return the original value. - // This can happen when a value in |pattern| is not a number. - function round(val) { - const res = Number.parseFloat(val).toPrecision(6); - return res === "NaN" ? val : res; + [Symbol.iterator]() { + return this; } - if (isNull) { - return (values === null || values.every(r => r === null)) && - timestamp === null; + reset() { + this.bufferPosition_ = 0; + } +}; + +// Calls test_driver.update_virtual_sensor() until it results in a "reading" +// event. It waits |timeoutInMs| before considering that an event has not been +// delivered. +async function update_virtual_sensor_until_reading( + t, readings, readingPromise, testDriverName, timeoutInMs) { + while (true) { + await test_driver.update_virtual_sensor( + testDriverName, readings.next().value); + const value = await Promise.race([ + new Promise( + resolve => {t.step_timeout(() => resolve('TIMEOUT'), timeoutInMs)}), + readingPromise, + ]); + if (value !== 'TIMEOUT') { + break; + } } +} - return values.every((r, i) => round(r) === round(pattern[i])) && - timestamp !== null; +// This could be turned into a t.step_wait() call once +// https://github.com/web-platform-tests/wpt/pull/34289 is merged. +async function wait_for_virtual_sensor_state(testDriverName, predicate) { + const result = + await test_driver.get_virtual_sensor_information(testDriverName); + if (!predicate(result)) { + await wait_for_virtual_sensor_state(testDriverName, predicate); + } } -function verifyXyzSensorReading(pattern, {x, y, z, timestamp}, isNull) { - return verifySensorReading(pattern, [x, y, z], timestamp, isNull); +function validate_sensor_data(sensorData) { + if (!('sensorName' in sensorData)) { + throw new TypeError('sensorData.sensorName is missing'); + } + if (!('permissionName' in sensorData)) { + throw new TypeError('sensorData.permissionName is missing'); + } + if (!('testDriverName' in sensorData)) { + throw new TypeError('sensorData.testDriverName is missing'); + } + if (sensorData.featurePolicyNames !== undefined && + !Array.isArray(sensorData.featurePolicyNames)) { + throw new TypeError('sensorData.featurePolicyNames must be an array'); + } } -function verifyQuatSensorReading(pattern, {quaternion, timestamp}, isNull) { - return verifySensorReading(pattern, quaternion, timestamp, isNull); +function validate_reading_data(readingData) { + if (!Array.isArray(readingData.readings)) { + throw new TypeError('readingData.readings must be an array.'); + } + if (!Array.isArray(readingData.expectedReadings)) { + throw new TypeError('readingData.expectedReadings must be an array.'); + } + if (readingData.readings.length < readingData.expectedReadings.length) { + throw new TypeError( + 'readingData.readings\' length must be bigger than ' + + 'or equal to readingData.expectedReadings\' length.'); + } + if (readingData.expectedRemappedReadings && + !Array.isArray(readingData.expectedRemappedReadings)) { + throw new TypeError( + 'readingData.expectedRemappedReadings must be an ' + + 'array.'); + } + if (readingData.expectedRemappedReadings && + readingData.expectedReadings.length != + readingData.expectedRemappedReadings.length) { + throw new TypeError( + 'readingData.expectedReadings and ' + + 'readingData.expectedRemappedReadings must have the same ' + + 'length.'); + } } -function verifyAlsSensorReading(pattern, {illuminance, timestamp}, isNull) { - return verifySensorReading(pattern, [illuminance], timestamp, isNull); +function get_sensor_reading_properties(sensor) { + const className = sensor[Symbol.toStringTag]; + if ([ + 'Accelerometer', 'GravitySensor', 'Gyroscope', + 'LinearAccelerationSensor', 'Magnetometer', 'ProximitySensor' + ].includes(className)) { + return ['x', 'y', 'z']; + } else if (className == 'AmbientLightSensor') { + return ['illuminance']; + } else if ([ + 'AbsoluteOrientationSensor', 'RelativeOrientationSensor' + ].includes(className)) { + return ['quaternion']; + } else { + throw new TypeError(`Unexpected sensor '${className}'`); + } } -function verifyGeoSensorReading(pattern, {latitude, longitude, altitude, - accuracy, altitudeAccuracy, heading, speed, timestamp}, isNull) { - return verifySensorReading(pattern, [latitude, longitude, altitude, - accuracy, altitudeAccuracy, heading, speed], timestamp, isNull); +// Checks that `sensor` and `expectedSensorLike` have the same properties +// (except for timestamp) and they have the same values. +// +// Options allows configuring some aspects of the comparison: +// - ignoreTimestamps (boolean): If true, `sensor` and `expectedSensorLike`'s +// "timestamp" attribute will not be compared. If `expectedSensorLike` does +// not have a "timestamp" attribute, the values will not be compared either. +// This is particularly useful when comparing sensor objects from different +// origins (and consequently different time origins). +function assert_sensor_reading_equals( + sensor, expectedSensorLike, options = {}) { + for (const prop of get_sensor_reading_properties(sensor)) { + assert_true( + prop in expectedSensorLike, + `expectedSensorLike must have a property called '${prop}'`); + if (Array.isArray(sensor[prop])) + assert_array_approx_equals( + sensor[prop], expectedSensorLike[prop], kEpsilon); + else + assert_approx_equals(sensor[prop], expectedSensorLike[prop], kEpsilon); + } + assert_not_equals(sensor.timestamp, null); + + if ('timestamp' in expectedSensorLike && !options.ignoreTimestamps) { + assert_equals( + sensor.timestamp, expectedSensorLike.timestamp, + 'Sensor timestamps must be equal'); + } } -function verifyProximitySensorReading(pattern, {distance, max, near, timestamp}, isNull) { - return verifySensorReading(pattern, [distance, max, near], timestamp, isNull); +function assert_sensor_reading_is_null(sensor) { + for (const prop of get_sensor_reading_properties(sensor)) { + assert_equals(sensor[prop], null); + } + assert_equals(sensor.timestamp, null); } -// Assert that two Sensor objects have the same properties and values. -// -// Verifies that ``actual`` and ``expected`` have the same sensor properties -// and, if so, that their values are the same. -// -// @param {Sensor} actual - Test value. -// @param {Sensor} expected - Expected value. -function assert_sensor_equals(actual, expected) { - assert_true( - actual instanceof Sensor, - 'assert_sensor_equals: actual must be a Sensor'); - assert_true( - expected instanceof Sensor, - 'assert_sensor_equals: expected must be a Sensor'); - - // These properties vary per sensor type. - const CUSTOM_PROPERTIES = [ - ['illuminance'], ['quaternion'], ['x', 'y', 'z'], - [ - 'latitude', 'longitude', 'altitude', 'accuracy', 'altitudeAccuracy', - 'heading', 'speed' - ] - ]; - - // These properties are present on all objects derived from Sensor. - const GENERAL_PROPERTIES = ['timestamp']; - - for (let customProperties of CUSTOM_PROPERTIES) { - if (customProperties.every(p => p in actual) && - customProperties.every(p => p in expected)) { - customProperties.forEach(p => { - if (customProperties == 'quaternion') { - assert_array_equals( - actual[p], expected[p], - `assert_sensor_equals: property '${p}' does not match`); - } else { - assert_equals( - actual[p], expected[p], - `assert_sensor_equals: property '${p}' does not match`); - } - }); - GENERAL_PROPERTIES.forEach(p => { - assert_equals( - actual[p], expected[p], - `assert_sensor_equals: property '${p}' does not match`); - }); - return; - } +function serialize_sensor_data(sensor) { + const sensorData = {}; + for (const property of get_sensor_reading_properties(sensor)) { + sensorData[property] = sensor[property]; } + sensorData['timestamp'] = sensor.timestamp; + + // Note that this is not serialized by postMessage(). + sensorData[Symbol.toStringTag] = sensor[Symbol.toStringTag]; - assert_true(false, 'assert_sensor_equals: sensors have different attributes'); + return sensorData; } diff --git a/tests/wpt/tests/generic-sensor/resources/iframe_sensor_handler.html b/tests/wpt/tests/generic-sensor/resources/iframe_sensor_handler.html index 4528c57a6be..80cdcf7c0d0 100644 --- a/tests/wpt/tests/generic-sensor/resources/iframe_sensor_handler.html +++ b/tests/wpt/tests/generic-sensor/resources/iframe_sensor_handler.html @@ -1,63 +1,91 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>iframe sensor tester</title> +<title>cross-origin iframe sensor tester</title> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script> - let mockBackend = null; let sensor = null; - let sensorType = null; + + test_driver.set_test_context(window.parent); + + // This function is defined separately so that it is added only once + // regardless of how many times the 'start_sensor' command is received. + function sensorReadingEventHandler() { + window.parent.postMessage( + { + eventName: 'reading', + serializedSensor: serialize_sensor_data(sensor), + }, '*'); + } async function messageHandler(e) { - if (e.data.command === 'create_sensor') { - if (!sensor) { - mockBackend = await initialize_generic_sensor_tests(); - sensor = new self[e.data.type](); - sensorType = e.data.type; - } - - return Promise.resolve('success'); - } else if (e.data.command === 'start_sensor') { - if (!sensor) { - return Promise.reject('"create_sensor" must be called first'); - } - - return new Promise((resolve, reject) => { - sensor.addEventListener('reading', () => { - resolve('success'); - }, { once: true }); - sensor.addEventListener('error', e => { - reject(`${e.error.name}: ${e.error.message}`); - }, { once: true }); - sensor.start(); - }); - } else if (e.data.command === 'is_sensor_suspended') { - if (!mockBackend) { - return Promise.reject('"create_sensor" must be called first'); - } - - const mockPlatformSensor = await mockBackend.getSensorProvider().getCreatedSensor(sensorType); - return Promise.resolve(!mockPlatformSensor.isReadingData()); - } else if (e.data.command === 'reset_sensor_backend') { - if (sensor) { - sensor.stop(); - await mockBackend.reset(); - - sensor = null; - mockBackend = null; - } - return Promise.resolve('success'); - } else { - return Promise.reject(`unknown command "${e.data.command}"`); + switch (e.data.command) { + case 'create_sensor': + if (!sensor) { + const { sensorName, permissionName } = e.data.sensorData; + // TODO(https://github.com/w3c/permissions/issues/419): This does not + // work as expected: due to the set_test_context() call above, this + // call goes through the top-level frame, which has a different + // origin in cross-origin tests, meaning that cross-origin tests only + // really work when permissions are granted by default. This can only + // be fixed by testdriver.js allowing set_permission() to specify a + // different origin. + await test_driver.set_permission({ name: permissionName }, 'granted'); + sensor = new self[sensorName](); + } + return Promise.resolve(); + + case 'start_sensor': + return new Promise((resolve, reject) => { + // This event listener is different from the ones below, as it is + // supposed to be used together with IframeSensorReadingEventWatcher. + // It sends a message whenever there is an event, and window.parent + // decides whether it was expected or not. It is the only way to have + // something akin to EventWatcher in a cross-origin iframe. + sensor.addEventListener('reading', sensorReadingEventHandler); + + sensor.addEventListener('activate', () => { + resolve(); + }, { once: true }); + sensor.addEventListener('error', e => { + reject(`${e.error.name}: ${e.error.message}`); + }, { once: true }); + sensor.start(); + }); + + case 'has_reading': + return Promise.resolve(sensor.hasReading); + + case 'stop_sensor': + if (sensor) { + sensor.stop(); + } + return Promise.resolve(); + + default: + return Promise.reject(`unknown command "${e.data.command}"`); } } window.onmessage = async (e) => { - let reply; + // The call to test_driver.set_context() above makes messages other than + // those we are specifically waiting for to be delivered too. Ignore those + // here. + if (!e.data.command) { + return; + } + try { - reply = await messageHandler(e); + test_driver.message_test({ + command: e.data.command, + result: await messageHandler(e), + }); } catch (error) { - reply = error; + test_driver.message_test({ + command: e.data.command, + error, + }); } - e.source.postMessage({ command: e.data.command, result: reply }, '*'); } </script> diff --git a/tests/wpt/tests/geolocation-sensor/GeolocationSensor-iframe-access.https.html b/tests/wpt/tests/geolocation-sensor/GeolocationSensor-iframe-access.https.html index bb0541de32c..a3d39e3606f 100644 --- a/tests/wpt/tests/geolocation-sensor/GeolocationSensor-iframe-access.https.html +++ b/tests/wpt/tests/geolocation-sensor/GeolocationSensor-iframe-access.https.html @@ -5,10 +5,13 @@ <link rel="help" href="https://wicg.github.io/geolocation-sensor/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-iframe-tests.sub.js"></script> <script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script> +<script src="resources/sensor-data.js"></script> <div id="log"></div> <script> -run_generic_sensor_iframe_tests('GeolocationSensor'); +run_generic_sensor_iframe_tests(kGeolocationSensorData, kGeolocationReadings); </script> diff --git a/tests/wpt/tests/geolocation-sensor/GeolocationSensor.https.html b/tests/wpt/tests/geolocation-sensor/GeolocationSensor.https.html index b71f964b129..3b4b94e5bbb 100644 --- a/tests/wpt/tests/geolocation-sensor/GeolocationSensor.https.html +++ b/tests/wpt/tests/geolocation-sensor/GeolocationSensor.https.html @@ -5,25 +5,12 @@ <link rel="help" href="https://wicg.github.io/geolocation-sensor/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> - -'use strict'; - -const kReadings = { - readings: [ - [1.12345, 2.12345, 3.12345, 0.95, 0.96, 4.12345, 5.123] - ], - expectedReadings: [ - [1.12345, 2.12345, 3.12345, 0.95, 0.96, 4.12345, 5.123] - ] -}; - -runGenericSensorTests( - 'GeolocationSensor', - kReadings, - verifyXyzSensorReading, - ['geolocation']); - +runGenericSensorTests(kGeolocationSensorData, kGeolocationReadings); </script> diff --git a/tests/wpt/tests/geolocation-sensor/resources/sensor-data.js b/tests/wpt/tests/geolocation-sensor/resources/sensor-data.js new file mode 100644 index 00000000000..5bbad442929 --- /dev/null +++ b/tests/wpt/tests/geolocation-sensor/resources/sensor-data.js @@ -0,0 +1,17 @@ +'use strict'; + +const kGeolocationSensorData = { + sensorName: 'GeolocationSensor', + permissionName: 'geolocation', + testDriverName: 'geolocation', + featurePolicyNames: ['geolocation'] +}; + +const kGeolocationReadings = { + readings: [ + [1.12345, 2.12345, 3.12345, 0.95, 0.96, 4.12345, 5.123] + ], + expectedReadings: [ + [1.12345, 2.12345, 3.12345, 0.95, 0.96, 4.12345, 5.123] + ] +}; diff --git a/tests/wpt/tests/gyroscope/Gyroscope-iframe-access.https.html b/tests/wpt/tests/gyroscope/Gyroscope-iframe-access.https.html index ed0183bef9a..c94016764d5 100644 --- a/tests/wpt/tests/gyroscope/Gyroscope-iframe-access.https.html +++ b/tests/wpt/tests/gyroscope/Gyroscope-iframe-access.https.html @@ -5,11 +5,14 @@ <link rel="help" href="https://www.w3.org/TR/gyroscope/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-iframe-tests.sub.js"></script> <script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script> +<script src="resources/sensor-data.js"></script> <div id="log"></div> <script> -run_generic_sensor_iframe_tests('Gyroscope'); +run_generic_sensor_iframe_tests(kGyroscopeSensorData, kGyroscopeReadings); </script> diff --git a/tests/wpt/tests/gyroscope/Gyroscope.https.html b/tests/wpt/tests/gyroscope/Gyroscope.https.html index f85349f5315..8aab94693ab 100644 --- a/tests/wpt/tests/gyroscope/Gyroscope.https.html +++ b/tests/wpt/tests/gyroscope/Gyroscope.https.html @@ -6,28 +6,16 @@ <link rel="help" href="https://www.w3.org/TR/gyroscope/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> 'use strict'; -const kReadings = { - readings: [ - [1.12345, 2.12345, 3.12345] - ], - expectedReadings: [ - [1.12345, 2.12345, 3.12345] - ], - expectedRemappedReadings: [ - [-2.12345, 1.12345, 3.12345] - ] -}; - -runGenericSensorTests( - 'Gyroscope', - kReadings, - verifyXyzSensorReading, - ['gyroscope']); +runGenericSensorTests(kGyroscopeSensorData, kGyroscopeReadings); </script> diff --git a/tests/wpt/tests/gyroscope/resources/sensor-data.js b/tests/wpt/tests/gyroscope/resources/sensor-data.js new file mode 100644 index 00000000000..409ffef9a17 --- /dev/null +++ b/tests/wpt/tests/gyroscope/resources/sensor-data.js @@ -0,0 +1,23 @@ +'use strict'; + +const kGyroscopeSensorData = { + sensorName: 'Gyroscope', + permissionName: 'gyroscope', + testDriverName: 'gyroscope', + featurePolicyNames: ['gyroscope'] +}; + +// Due to the gyroscope input values being rounded using a precision of +// 0.1 deg/sec, the expectedReadings and expectedRemappedReadings contain +// a significant number of decimal places. +const kGyroscopeReadings = { + readings: [ + { x: 1, y: 2, z: 3 } + ], + expectedReadings: [ + { x: 1.00007366, y: 2.00014732, z: 3.00022098 } + ], + expectedRemappedReadings: [ + { x: -2.00014732, y: 1.00007366, z: 3.00022098 } + ] +}; diff --git a/tests/wpt/tests/hr-time/raf-coarsened-time.https.html b/tests/wpt/tests/hr-time/raf-coarsened-time.https.html new file mode 100644 index 00000000000..c7cc723da6f --- /dev/null +++ b/tests/wpt/tests/hr-time/raf-coarsened-time.https.html @@ -0,0 +1,33 @@ +<!doctype html> +<html> +<head> + <link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering"> + <script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + /* Coarsen to 5 microseconds or coarser */ + const COARSE_RESOLUTION = 0.005; + + const CUSTOM_TIMELINE_DELTA = 0.002; + const FLOATING_POINT_ERROR_EPSILON = 0.00001; + + // Note that this test would fail if the platform introduces a jitter. + // It is recommended that platforms that implement jitter run this test + // with a flag that turns jitter off, if possible. + + const customTimeline = new DocumentTimeline({originTime: CUSTOM_TIMELINE_DELTA}); + promise_test(async t => { + for (let i = 0; i < 32; ++i) { + const timestamp = await new Promise(resolve => requestAnimationFrame(ts => resolve(ts))); + const coarse_timestamp = Math.round(timestamp / COARSE_RESOLUTION) * COARSE_RESOLUTION; + assert_approx_equals(timestamp, coarse_timestamp, FLOATING_POINT_ERROR_EPSILON); + assert_approx_equals(timestamp, document.timeline.currentTime, FLOATING_POINT_ERROR_EPSILON); + assert_approx_equals(customTimeline.currentTime + CUSTOM_TIMELINE_DELTA, + timestamp, FLOATING_POINT_ERROR_EPSILON); + } + }); +</script> +</body> +</html> diff --git a/tests/wpt/tests/hr-time/raf-coarsened-time.https.html.headers b/tests/wpt/tests/hr-time/raf-coarsened-time.https.html.headers new file mode 100644 index 00000000000..5f8621ef836 --- /dev/null +++ b/tests/wpt/tests/hr-time/raf-coarsened-time.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Opener-Policy: same-origin diff --git a/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html b/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html new file mode 100644 index 00000000000..f453c80a2ae --- /dev/null +++ b/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-bfcache-restore.html @@ -0,0 +1,70 @@ +<!DOCTYPE html> +<title>pagereveal event fires and in correct order on restoration from BFCache</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/browsing-the-web.html#updating-the-document"> +<link rel="author" href="mailto:bokan@chromium.org"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script> +<script> +// runBfcacheTest opens a popup to pageA which navigates to pageB and then +// back, ensuring pageA is stored in the BFCache. +runBfcacheTest({ + funcBeforeNavigation: async () => { + // This function executes in pageA + + // Wait for an animation frame to ensure the the initial-load + // `pagereveal` has already been fired so it doesn't get recorded + // below. + const raf = new Promise(resolve => requestAnimationFrame(resolve)); + await raf; + + window.event_log = []; + let restored = false; + + function recordRafs() { + requestAnimationFrame( () => { + // Avoid recording animation frames until the page is restored from + // BFCache since it's currently uncached. This test is interested only + // in the behavior during restoration. + if (restored) + window.event_log.push('rAF'); + + recordRafs(); + }); + } + + recordRafs(); + + addEventListener('pageshow', (e) => { + window.event_log.push('pageshow' + (e.persisted ? '.persisted' : '')); + if (e.persisted) + restored = true; + }); + + addEventListener('pagereveal', () => { + window.event_log.push('pagereveal'); + }); + }, + funcAfterAssertion: async (pageA, pageB, t) => { + let event_log = await pageA.execute_script(async () => { + // Ensure at least one animation frame is produced to ensure + // pagereveal must have fired. + await new Promise(requestAnimationFrame); + return window.event_log; + }); + + // Expect that the events seen are: + // pageshow.persisted, pagereveal, rAF, rAF, rAF, ... + assert_equals(event_log.slice(0, 3).toString(), + 'pageshow.persisted,pagereveal,rAF'); + for (let i = 3; i < event_log.length; ++i) { + assert_equals(event_log[i], 'rAF', + 'All events following pagereveal should be animation frames'); + } + }, + targetOrigin: originSameOrigin, +}); +</script> diff --git a/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html b/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html new file mode 100644 index 00000000000..d2c44511d3a --- /dev/null +++ b/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-new-document-navigation.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>pagereveal event fires and in correct order on new-document navigation</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering"> +<link rel="author" href="mailto:bokan@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +const event_log = []; + +addEventListener('pageshow', () => event_log.push('pageshow')); +addEventListener('pagereveal', () => event_log.push('pagereveal')); +requestAnimationFrame(() => event_log.push('rAF')); + +promise_test(async () => { + await new Promise(resolve => requestAnimationFrame(resolve)); + assert_equals(event_log.toString(),'pageshow,pagereveal,rAF'); +}); +</script> diff --git a/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html b/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html new file mode 100644 index 00000000000..b281b2b0881 --- /dev/null +++ b/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/order-in-prerender-activation.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<title>pagereveal event fires and in correct order on prerender activation</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering"> +<link rel="author" href="mailto:bokan@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/speculation-rules/resources/utils.js"></script> +<script src="/speculation-rules/prerender/resources/utils.js"></script> +<script> +setup(() => assertSpeculationRulesIsSupported()); + +const uid = token(); +const initiator_url = `resources/order-in-prerender-activation-popup.html?uid=${uid}`; + +// This test opens a popup to an initiator page. That page then prerenders a +// "prerendering" version of itself (by adding a `prerendering` query param) +// and navigates itself to activate the prerender. The results are recorded and +// sent back to this test harness. +promise_test(async () => { + const channel = new PrerenderChannel('result', uid); + const test_done = new Promise(resolve => { + channel.addEventListener('message', e => resolve(e.data), { once: true }); + }); + + window.open(initiator_url, '_blank', 'noopener'); + + const result = await test_done; + + if (result.hasOwnProperty('fail')) { + assert_unreached(result.fail); + } + + // The test records relevant event occurrences up to the second animation + // frame. Ensure their order and apparance is as expected. + const events_in_order = result.events.join(','); + assert_equals(events_in_order, + 'pageshow,prerenderingchange,pagereveal,raf'); +}); +</script> diff --git a/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/resources/order-in-prerender-activation-popup.html b/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/resources/order-in-prerender-activation-popup.html new file mode 100644 index 00000000000..78989adc172 --- /dev/null +++ b/tests/wpt/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/tentative/resources/order-in-prerender-activation-popup.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<title>pagereveal event fires and in correct order on prerender activation (popup)</title> +<link rel="author" href="mailto:bokan@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/speculation-rules/prerender/resources/utils.js"></script> +<script> +const params = new URLSearchParams(location.search); +const uid = params.get('uid'); +const is_prerender_step = params.has('prerendering'); + +const ready_channel = new PrerenderChannel('ready-to-activate', uid); + +function finish(result) { + const result_channel = new PrerenderChannel('result', uid); + result_channel.postMessage(result); + result_channel.close(); + window.close(); +} + +// testharness.js assertions don't work inside this popup so this small helper +// sends a failure signal back to the test page which will cause test failure. +function assert(cond, desc) { + if (!cond) { + finish({fail: desc}); + } +} + +// The first load of this page should be without 'prerendering' and is used +// to setup the prerender and then activate it when it's ready. +if (!is_prerender_step) { + assert(!document.prerendering, 'initiator page must not be prerendered'); + + const ready_to_activate = new Promise(resolve => { + ready_channel.addEventListener('message', resolve, {once: true}); + }); + + const prerendering_url = location.href + '&prerendering'; + startPrerendering(prerendering_url); + + ready_to_activate.then(() => { + location.replace(prerendering_url); + }); +} else { + assert(document.prerendering, 'prerendering step must be initially prerendered'); + + const result = { + events: [] + }; + + document.addEventListener('prerenderingchange', () => { + result.events.push('prerenderingchange'); + }); + + addEventListener('pageshow', () => { + result.events.push('pageshow'); + }); + + // A second rAF will end the test. + requestAnimationFrame(() => { + result.events.push('raf'); + requestAnimationFrame(() => finish(result)); + }); + + addEventListener('pagereveal', () => { + result.events.push('pagereveal'); + }); + + addEventListener('load', () => { + ready_channel.postMessage('unused-readyToActivateMessage'); + ready_channel.close(); + }); +} +</script> diff --git a/tests/wpt/tests/html/dom/elements/global-attributes/dir-auto-form-associated.window.js b/tests/wpt/tests/html/dom/elements/global-attributes/dir-auto-form-associated.window.js new file mode 100644 index 00000000000..1777f75259b --- /dev/null +++ b/tests/wpt/tests/html/dom/elements/global-attributes/dir-auto-form-associated.window.js @@ -0,0 +1,61 @@ +// Keep this mostly synchronized with +// html/semantics/forms/attributes-common-to-form-controls/dirname-only-if-applies.html +// except that won't have "reset" and "button" as those don't submit their value +[ + "hidden", + "text", + "search", + "tel", + "url", + "email", + "password", + "submit", + "reset", + "button" +].forEach(type => { + test(t => { + const input = document.createElement("input"); + t.add_cleanup(() => input.remove()); + input.type = type; + assert_equals(input.type, type); + input.dir = "auto"; + input.value = "\u05D0"; // The Hebrew letter Alef (strongly RTL) + document.body.append(input); + assert_true(input.matches(":dir(rtl)")); + }, `<input dir=auto type=${type}> directionality`); +}); + +[ + "date", + "month", + "week", + "time", + "datetime-local", + "number", + "range", + "color", + "checkbox", + "radio", + // "file" // value setter throws + "image" +].forEach(type => { + test(t => { + const input = document.createElement("input"); + t.add_cleanup(() => input.remove()); + input.type = type; + assert_equals(input.type, type); + input.dir = "auto"; + input.value = "\u05D0"; // The Hebrew letter Alef (strongly RTL) + document.body.append(input); + assert_true(input.matches(":dir(ltr)")); + }, `<input dir=auto type=${type}> directionality`); +}); + +test(t => { + const input = document.createElement("textarea"); + t.add_cleanup(() => input.remove()); + input.dir = "auto"; + input.value = "\u05D0"; // The Hebrew letter Alef (strongly RTL) + document.body.append(input); + assert_true(input.matches(":dir(rtl)")); +}, `<textarea dir=auto> directionality`); diff --git a/tests/wpt/tests/html/dom/elements/global-attributes/lang-attribute.window.js b/tests/wpt/tests/html/dom/elements/global-attributes/lang-attribute.window.js new file mode 100644 index 00000000000..de0c03e6f85 --- /dev/null +++ b/tests/wpt/tests/html/dom/elements/global-attributes/lang-attribute.window.js @@ -0,0 +1,16 @@ +test(() => { + const container = document.createElement("div"); + document.body.append(container); + container.setAttribute("lang", "en-CA"); + + const child = document.createElementNS("div", "test"); + container.append(child); + child.setAttribute("lang", "en-NZ"); + + assert_true(container.matches(":lang(en-CA)"), "container matches en-CA"); + assert_true(child.matches(":lang(en-CA)"), "child matches en-CA"); + assert_false(container.matches(":lang(en-NZ)"), "container does not match en-NZ"); + assert_false(child.matches(":lang(en-NZ)"), "child does not match en-NZ"); + + container.remove(); +}, "unnamespaced lang attribute only works on elements in the HTML namespace"); diff --git a/tests/wpt/tests/html/dom/elements/global-attributes/lang-xmllang-01-ref.html b/tests/wpt/tests/html/dom/elements/global-attributes/lang-xmllang-01-ref.html index 1606bca2158..eacf73da16c 100644 --- a/tests/wpt/tests/html/dom/elements/global-attributes/lang-xmllang-01-ref.html +++ b/tests/wpt/tests/html/dom/elements/global-attributes/lang-xmllang-01-ref.html @@ -2,7 +2,7 @@ <title>Languages</title> <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes"> -<link tel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang"> +<link rel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang"> <meta name="flags" content="css21"> <style> #test > * { background: limegreen; } diff --git a/tests/wpt/tests/html/dom/elements/global-attributes/lang-xmllang-01.html b/tests/wpt/tests/html/dom/elements/global-attributes/lang-xmllang-01.html index 9538f15ca8c..04d8b74e2d1 100644 --- a/tests/wpt/tests/html/dom/elements/global-attributes/lang-xmllang-01.html +++ b/tests/wpt/tests/html/dom/elements/global-attributes/lang-xmllang-01.html @@ -3,7 +3,7 @@ <link rel="match" href="lang-xmllang-01-ref.html"> <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes"> -<link tel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang"> +<link rel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang"> <meta name="flags" content="css21"> <style> #test #a :lang(en) { background: limegreen; } diff --git a/tests/wpt/tests/html/dom/elements/global-attributes/lang-xyzzy.html b/tests/wpt/tests/html/dom/elements/global-attributes/lang-xyzzy.html index d6e6aeb6475..b950e1fac99 100644 --- a/tests/wpt/tests/html/dom/elements/global-attributes/lang-xyzzy.html +++ b/tests/wpt/tests/html/dom/elements/global-attributes/lang-xyzzy.html @@ -3,7 +3,7 @@ <link rel="match" href="lang-xyzzy-ref.html"> <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes"> -<link tel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang"> +<link rel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang"> <meta name="flags" content="css21"> <style>:lang(xyzzy) { color: green; }</style> <body> diff --git a/tests/wpt/tests/html/infrastructure/urls/base-url/document-base-uri-synthetic-document.html b/tests/wpt/tests/html/infrastructure/urls/base-url/document-base-uri-synthetic-document.html new file mode 100644 index 00000000000..bed090aac42 --- /dev/null +++ b/tests/wpt/tests/html/infrastructure/urls/base-url/document-base-uri-synthetic-document.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1486750"> +<link rel=help href="https://html.spec.whatwg.org/multipage/urls-and-fetching.html#document-base-url"> +<link rel=help href="https://html.spec.whatwg.org/multipage/urls-and-fetching.html#fallback-base-url"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> +test(() => { + const doc1 = document.implementation.createHTMLDocument(); + assert_equals(doc1.baseURI, 'about:blank', 'document.implementation.createHTMLDocument()'); + + const doc2 = document.implementation.createDocument('', ''); + assert_equals(doc2.baseURI, 'about:blank', 'document.implementation.createDocument("", "")'); + + const doc3 = new Document(); + assert_equals(doc3.baseURI, 'about:blank', 'new Document()'); +}, 'Synthetic documents should return about:blank for document.baseURI.'); + +test(() => { + const doc = document.implementation.createHTMLDocument(); + assert_equals(doc.baseURI, 'about:blank', 'baseURI should be about:blank without a <base>.'); + + const base = doc.createElement('base'); + base.href = '/foo'; + doc.head.appendChild(base); + assert_equals(doc.baseURI, 'about:blank', '<base> with relative URL should not change the about:blank baseURI.'); + + base.href = 'http://example.com/'; + assert_equals(doc.baseURI, 'http://example.com/', '<base> with complete URL should replace the about:blank baseURI.'); +}, 'Synthetic documents should incorporate <base> href URLs correctly.'); +</script> diff --git a/tests/wpt/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-viewport-001.html b/tests/wpt/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-viewport-001.html new file mode 100644 index 00000000000..408e5309e57 --- /dev/null +++ b/tests/wpt/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-viewport-001.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<head> + <meta charset="utf-8"> + <link rel="match" href="iframe-loading-lazy-in-viewport-ref.html"> + <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1860041"> +</head> +<body> + <iframe loading="lazy" src="data:text/html,PASS" onload="document.documentElement.className = ''"></iframe> + <script> + document.querySelector("iframe").getBoundingClientRect(); + </script> +</body> +</html> diff --git a/tests/wpt/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-viewport-ref.html b/tests/wpt/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-viewport-ref.html new file mode 100644 index 00000000000..067bfa19202 --- /dev/null +++ b/tests/wpt/tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-in-viewport-ref.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<iframe src="data:text/html,PASS"></iframe> diff --git a/tests/wpt/tests/html/semantics/embedded-content/the-img-element/img-src-in-synthetic-document.html b/tests/wpt/tests/html/semantics/embedded-content/the-img-element/img-src-in-synthetic-document.html new file mode 100644 index 00000000000..24c5567fb85 --- /dev/null +++ b/tests/wpt/tests/html/semantics/embedded-content/the-img-element/img-src-in-synthetic-document.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://github.com/whatwg/html/issues/9855"> +<link rel=help href="https://html.spec.whatwg.org/#reflecting-content-attributes-in-idl-attributes"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +test(() => { + const doc = document.implementation.createHTMLDocument(''); + const img = doc.createElement('img'); + img.setAttribute('src', '/test'); + doc.body.appendChild(img); + assert_equals(img.src, '/test'); +}, 'HTMLImageElement.src should return the string from the attribute in about:blank documents.'); +</script> diff --git a/tests/wpt/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-only-if-applies.html b/tests/wpt/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-only-if-applies.html index 1fd0476e314..8af6826fa13 100644 --- a/tests/wpt/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-only-if-applies.html +++ b/tests/wpt/tests/html/semantics/forms/attributes-common-to-form-controls/dirname-only-if-applies.html @@ -13,19 +13,24 @@ <div id="log"></div> <form action="resources/dirname-iframe.html" method=get target="iframe"> <textarea name="textarea" dirname="textarea.dir"></textarea> - <p><button id="btn-submit" type=submit>Submit</button></p> + <p><input id="btn-submit" type=submit name=submit dirname=submit.dir value=Submit></p> </form> <iframe name="iframe"></iframe> <script> - const types_applies = ["text", "search", "hidden", "tel", "url", "email"]; + const types_applies = [ + "hidden", "text", "search", "tel", "url", "email", "password", "submit" + ]; const types_not = [ - "password", "date", "month", "week", "time", "image", "reset", "button", - "datetime-local", "number", "range", "color", "checkbox", "radio", "file", "submit", + "date", "month", "week", "time", "datetime-local", "number", "range", "color", "checkbox", + "radio", "file", "image", "reset", "button" ]; const types = [...types_applies, ...types_not]; let form = document.querySelector("form"); for (const type of types) { + if (type === "submit") { + continue; + } let p = document.createElement("p"); let lbl = document.createElement("label"); let txt = document.createTextNode(type + ": "); @@ -52,7 +57,8 @@ } } - const data = new FormData(form); + const submitter = document.getElementById("btn-submit"); + const data = new FormData(form, submitter); test(function() { assertInputSubmission(data); }, "Submit input element directionality to FormData, if dirname applies."); @@ -60,7 +66,7 @@ assert_equals(data.get("textarea.dir"), "ltr", "Submit ltr for textarea"); }, "Submit textarea element directionality to FormData."); - document.getElementById("btn-submit").click(); + submitter.click(); const t_inp = async_test("Submit input element directionality, if dirname applies."); onIframeLoadedDone(t_inp, function(params) { assertInputSubmission(params); diff --git a/tests/wpt/tests/html/semantics/forms/the-input-element/input-disabled-fieldset-dynamic.html b/tests/wpt/tests/html/semantics/forms/the-input-element/input-disabled-fieldset-dynamic.html new file mode 100644 index 00000000000..eefcd972bf1 --- /dev/null +++ b/tests/wpt/tests/html/semantics/forms/the-input-element/input-disabled-fieldset-dynamic.html @@ -0,0 +1,38 @@ +<!doctype html> +<meta charset="utf-8"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1861027"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-actions.js></script> +<script src=/resources/testdriver-vendor.js></script> +<fieldset id="fieldset" disabled> + <input id="target"> +</fieldset> +<script> +const target = document.getElementById("target"); +const fieldset = document.getElementById("fieldset"); +promise_test(async function() { + await new Promise(r => window.addEventListener("load", r, { once: true })); + assert_true(target.matches(":disabled"), "Fieldset disables the input"); + assert_true(target.matches(":read-only"), "Disabled implies read-only"); + + // Try to focus, it shouldn't be focusable. + target.focus(); + + assert_not_equals(document.activeElement, target, "Should not be focusable"); + + fieldset.removeAttribute("disabled"); + + assert_false(target.matches(":disabled"), "Should go back to writable"); + assert_false(target.matches(":read-only"), "No longer read-only"); + + // Should be focusable now. + target.focus(); + + assert_equals(document.activeElement, target, "Should not be focusable"); + + await test_driver.send_keys(target, "A"); + assert_equals(target.value, "A", "Typing should work"); +}); +</script> diff --git a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-cancel-events.html b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-cancel-events.html index 7133ce3ca04..d583c4cd23c 100644 --- a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-cancel-events.html +++ b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-cancel-events.html @@ -1,70 +1,53 @@ <!DOCTYPE html> -<html> -<head> - <title>Test cancel event is fired when the dialog is closed by user interaction</title> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="/resources/testdriver.js"></script> - <script src="/resources/testdriver-vendor.js"></script> - <link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=227534"> - <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322947"> -</head> -<body> -<p>Test cancel event is fired when the dialog is closed by user interaction</p> +<meta charset="utf-8"> +<title>Test cancel event is fired when the dialog is closed by user close requests</title> +<link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=227534"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322947"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/common/top-layer.js"></script> +<script src="/close-watcher/resources/helpers.js"></script> + <dialog> <p>Hello World</p> </dialog> -<script> - setup({ single_test: true }); - var hasCancelEventFired = false; - var hasCloseEventFired = false; - var oncancelWasCalled = false; - var oncloseWasCalled = false; +<script type="module"> +setup({ single_test: true }); + +const dialog = document.querySelector("dialog"); +const events = []; + +dialog.addEventListener("cancel", event => { + assert_true(event.cancelable, "cancel event should be cancelable"); + assert_array_equals(events, []); + + events.push("addEventListener cancel"); +}); - function maybeDone() { - if (oncloseWasCalled && hasCloseEventFired) { - done(); - } - } +assert_equals(dialog.oncancel, null); +dialog.oncancel = () => { + assert_array_equals(events, ["addEventListener cancel"]); - const dialog = document.querySelector("dialog"); + events.push("oncancel"); +}; - dialog.addEventListener("cancel", function(event) { - assert_true(true, "cancel event is fired"); - assert_true(event.cancelable, "cancel event should be cancelable"); - assert_false(hasCancelEventFired, "cancel event should only be fired once"); - assert_false(hasCloseEventFired, "close event should be fired after cancel event"); - hasCancelEventFired = true; - }); +dialog.addEventListener("close", () => { + assert_array_equals(events, ["addEventListener cancel", "oncancel"]); - assert_equals(dialog.oncancel, null); - dialog.oncancel = function(event) { - assert_true(true, "oncancel event handler is called"); - assert_false(oncancelWasCalled, "oncancel handler should only be called once"); - assert_false(oncloseWasCalled, "onclose handler should be called after oncancel"); - oncancelWasCalled = true; - } + events.push("addEventListener close"); +}); - dialog.addEventListener("close", function() { - assert_true(true, "close event is fired"); - assert_false(hasCloseEventFired, "close event should only be fired once"); - assert_true(hasCancelEventFired, "cancel event should be fired before close event"); - hasCloseEventFired = true; - maybeDone(); - }); +assert_equals(dialog.onclose, null); +dialog.onclose = () => { + assert_array_equals(events, ["addEventListener cancel", "oncancel", "addEventListener close"]); - assert_equals(dialog.onclose, null); - dialog.onclose = function(event) { - assert_true(true, "onclose event handler is called"); - assert_false(oncloseWasCalled, "onclose handler should only be called once"); - assert_true(oncancelWasCalled, "oncancel handler should be called before onclose"); - oncloseWasCalled = true; - maybeDone(); - } + done(); +}; - dialog.showModal(); - test_driver.send_keys(document.documentElement, "\uE00C"); // ESC key +dialog.showModal(); +await blessTopLayer(dialog); +await sendCloseRequest(); </script> -</body> -</html> diff --git a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-cancel-preventDefault.html b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-cancel-preventDefault.html index 79728b649f4..4daffc09a46 100644 --- a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-cancel-preventDefault.html +++ b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-cancel-preventDefault.html @@ -6,6 +6,8 @@ <script src="/resources/testharnessreport.js"></script> <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-vendor.js"></script> + <script src="/common/top-layer.js"></script> + <script src="/close-watcher/resources/helpers.js"></script> <link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=227534"> <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322947"> </head> @@ -14,7 +16,7 @@ <dialog> <p>Hello World</p> </dialog> -<script> +<script type=module> setup({ single_test: true }); var hasCancelEventFired = false; @@ -39,7 +41,9 @@ }); dialog.showModal(); - test_driver.send_keys(document.documentElement, "\uE00C"); // ESC key + + await blessTopLayer(dialog); + await sendCloseRequest(); </script> </body> </html> diff --git a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html index fc003d29d19..e368bde6fb3 100644 --- a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html +++ b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/dialog-canceling.html @@ -8,6 +8,8 @@ <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-actions.js"></script> <script src="/resources/testdriver-vendor.js"></script> +<script src="/common/top-layer.js"></script> +<script src="/close-watcher/resources/helpers.js"></script> <!-- To test manually, hit Escape once to see the topmost dialog turn green @@ -44,13 +46,6 @@ then once again to close it. Repeat for the remaining dialog. </dialog> <script> -async function pressEscape() { - const actions = new test_driver.Actions() - .keyDown('\uE00C') - .keyUp('\uE00C'); - await actions.send(); -} - function handleCancel(event) { this.style.background = 'green'; this.querySelector('span').textContent = 'I blocked the cancel! Try again to close me.'; @@ -72,33 +67,36 @@ promise_test(async () => { }); bottomDialog.showModal(); + await blessTopLayer(bottomDialog); topDialog.showModal(); - await pressEscape(); + await blessTopLayer(topDialog); + await sendEscKey(); assert_true(topDialog.open, 'Top dialog event listener should prevent closing.'); assert_true(bottomDialog.open, 'Top dialog event listener should prevent closing.'); - await pressEscape(); + await blessTopLayer(topDialog); + await sendEscKey(); assert_false(topDialog.open, 'Top dialog should close.'); assert_true(bottomDialog.open, 'Top dialog should close.'); swallowInput.focus(); - await pressEscape(); - await pressEscape(); - await pressEscape(); + await sendEscKey(); + await sendEscKey(); + await sendEscKey(); assert_false(topDialog.open, 'Input should swallow Escape mechanism.'); assert_true(bottomDialog.open, 'Input should swallow Escape mechanism.'); normalInput.focus(); - await pressEscape(); + await sendEscKey(); assert_false(topDialog.open, 'Bottom dialog event listener should prevent closing.'); assert_true(bottomDialog.open, 'Bottom dialog event listener should prevent closing.'); - await pressEscape(); + await sendEscKey(); assert_false(topDialog.open, 'Bottom dialog should close.'); assert_false(bottomDialog.open, 'Bottom dialog should close.'); - await pressEscape(); + await sendEscKey(); assert_false(topDialog.open, 'Pressing Escape now should do nothing.'); assert_false(bottomDialog.open, 'Pressing Escape now should do nothing.'); diff --git a/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/focus-previous-iframe.tentative.html b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/focus-previous-iframe.tentative.html new file mode 100644 index 00000000000..c31daa48766 --- /dev/null +++ b/tests/wpt/tests/html/semantics/interactive-elements/the-dialog-element/focus-previous-iframe.tentative.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width,initial-scale=1"> +<title>Test focus is moved to the previously focused element when dialog is closed</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<body> +<dialog>Dialog in parent</dialog> + +<iframe srcdoc="<input><dialog> Dialog in child </dialog>"></iframe> + +<input> +<script> +test(() => { + window.onload = function() { + const iframe = document.querySelector("iframe"); + const input = iframe.contentDocument.querySelector("input"); + // <input> in the child document is focused + input.focus(); + + const dialog = document.querySelector("dialog"); + // <dialog> in the parent document is opened + dialog.showModal(); + dialog.close(); + + assert_equals(document.activeElement, iframe); + assert_equals(iframe.contentDocument.activeElement, input); + } +}, "Focus should move back from parent document to child document"); + +test(() => { + window.onload = function() { + const iframe = document.querySelector("iframe"); + const input = document.querySelector("input"); + // <input> in the parent document is focused + input.focus(); + + const dialog = iframe.contentDocument.querySelector("dialog"); + + // <dialog> in the child document is focused + dialog.showModal(); + dialog.close(); + + assert_equals(document.activeElement, input); + } +}, "Focus should move back from child document to parent document"); +</script> +</body> diff --git a/tests/wpt/tests/html/semantics/invokers/invokeelement-interface.tentative.html b/tests/wpt/tests/html/semantics/invokers/invokeelement-interface.tentative.html index 69cfd80fe56..b003daf20d4 100644 --- a/tests/wpt/tests/html/semantics/invokers/invokeelement-interface.tentative.html +++ b/tests/wpt/tests/html/semantics/invokers/invokeelement-interface.tentative.html @@ -17,8 +17,8 @@ const div = document.body.appendChild(document.createElement("div")); invoker.invokeTargetElement = div; assert_equals(invoker.invokeTargetElement, div); - assert_equals(invoker.getAttribute('invoketarget'), ''); - assert_false(invoker.hasAttribute('invokeaction')); + assert_equals(invoker.getAttribute("invoketarget"), ""); + assert_false(invoker.hasAttribute("invokeaction")); }, "invokeTargetElement reflects set value"); test(function () { @@ -27,8 +27,8 @@ const button = shadow.appendChild(document.createElement("button")); button.invokeTargetElement = invokee; assert_equals(button.invokeTargetElement, invokee); - assert_equals(invoker.getAttribute('invoketarget'), ''); - assert_false(invoker.hasAttribute('invokeaction')); + assert_equals(invoker.getAttribute("invoketarget"), ""); + assert_false(invoker.hasAttribute("invokeaction")); }, "invokeTargetElement reflects set value across shadow root into light dom"); test(function () { @@ -37,8 +37,8 @@ const div = shadow.appendChild(document.createElement("div")); invoker.invokeTargetElement = div; assert_equals(invoker.invokeTargetElement, null); - assert_equals(invoker.getAttribute('invoketarget'), ''); - assert_false(invoker.hasAttribute('invokeaction')); + assert_equals(invoker.getAttribute("invoketarget"), ""); + assert_false(invoker.hasAttribute("invokeaction")); }, "invokeTargetElement does not reflect set value inside shadowroot"); test(function () { @@ -52,7 +52,7 @@ }, "invokeTargetElement throws error on assignment of non Element"); test(function () { - assert_false(invoker.hasAttribute('invokeaction')); + assert_false(invoker.hasAttribute("invokeaction")); assert_equals(invoker.invokeAction, "auto"); }, "invokeAction reflects 'auto' when attribute not present"); @@ -64,6 +64,7 @@ test(function () { invoker.invokeAction = "fooBarBaz"; + assert_equals(invoker.getAttribute("invokeaction"), "fooBarBaz"); assert_equals(invoker.invokeAction, "fooBarBaz"); }, "invokeAction reflects same casing"); diff --git a/tests/wpt/tests/html/semantics/invokers/invokeevent-interface.tentative.html b/tests/wpt/tests/html/semantics/invokers/invokeevent-interface.tentative.html index 007c97e6fe5..82910b3d441 100644 --- a/tests/wpt/tests/html/semantics/invokers/invokeevent-interface.tentative.html +++ b/tests/wpt/tests/html/semantics/invokers/invokeevent-interface.tentative.html @@ -46,6 +46,11 @@ }, "action set to false"); test(function () { + const event = new InvokeEvent("test", { action: "" }); + assert_equals(event.action, ""); + }, "action explicitly set to empty string"); + + test(function () { const event = new InvokeEvent("test", { action: true }); assert_equals(event.action, "true"); }, "action set to true"); @@ -57,7 +62,7 @@ test(function () { const event = new InvokeEvent("test", { action: [] }); - assert_equals(event.action, "auto"); + assert_equals(event.action, ""); }, "action set to []"); test(function () { @@ -73,13 +78,13 @@ test(function () { const event = new InvokeEvent("test", { action: { - valueOf: function () { + toString() { return "sample"; }, }, }); - assert_equals(event.action, "[object Object]"); - }, "action set to an object with a valueOf function"); + assert_equals(event.action, "sample"); + }, "action set to an object with a toString function"); test(function () { const eventInit = { action: "sample", invoker: document.body }; diff --git a/tests/wpt/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html b/tests/wpt/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html new file mode 100644 index 00000000000..9d9bbaee721 --- /dev/null +++ b/tests/wpt/tests/html/semantics/invokers/invoketarget-on-popover-behavior.tentative.html @@ -0,0 +1,193 @@ +<!doctype html> +<meta charset="utf-8" /> +<meta name="author" title="Keith Cirkel" href="mailto:keithamus@github.com" /> +<link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="resources/invoker-utils.js"></script> + +<div id="invokee" popover> + <button id="invokerbutton2" invoketarget="invokee"></button> +</div> +<button id="invokerbutton" invoketarget="invokee"></button> + +<script> + // auto + + promise_test(async function (t) { + assert_false(invokee.matches(":popover-open")); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as auto) closed popover opens"); + + promise_test(async function (t) { + assert_false(invokee.matches(":popover-open")); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_false(invokee.matches(":popover-open")); + }, "invoking (as auto) closed popover with preventDefault does not open"); + + promise_test(async function (t) { + invokee.showPopover(); + assert_true(invokee.matches(":popover-open")); + await clickOn(invokerbutton2); + assert_false(invokee.matches(":popover-open")); + }, "invoking (as auto) open popover closes"); + + promise_test(async function (t) { + invokee.showPopover(); + t.add_cleanup(() => invokee.hidePopover()); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + assert_true(invokee.matches(":popover-open")); + await clickOn(invokerbutton2); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as auto) open popover with preventDefault does not close"); + + // togglepopover + + promise_test(async function (t) { + assert_false(invokee.matches(":popover-open")); + invokerbutton.setAttribute("invokeaction", "togglepopover"); + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as togglepopover) closed popover opens"); + + promise_test(async function (t) { + assert_false(invokee.matches(":popover-open")); + invokerbutton.setAttribute("invokeaction", "tOgGlEpOpOvEr"); + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as togglepopover - case insensitive) closed popover opens"); + + promise_test(async function (t) { + assert_false(invokee.matches(":popover-open")); + invokerbutton.setAttribute("invokeaction", "togglepopover"); + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_false(invokee.matches(":popover-open")); + }, "invoking (as togglepopover) closed popover with preventDefault does not open"); + + promise_test(async function (t) { + invokee.showPopover(); + invokerbutton2.setAttribute("invokeaction", "togglepopover"); + t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction")); + assert_true(invokee.matches(":popover-open")); + await clickOn(invokerbutton2); + assert_false(invokee.matches(":popover-open")); + }, "invoking (as togglepopover) open popover closes"); + + promise_test(async function (t) { + invokee.showPopover(); + t.add_cleanup(() => invokee.hidePopover()); + invokerbutton2.setAttribute("invokeaction", "togglepopover"); + t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction")); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + assert_true(invokee.matches(":popover-open")); + await clickOn(invokerbutton2); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as togglepopover) open popover with preventDefault does not close"); + + // showpopover + + promise_test(async function (t) { + invokerbutton.setAttribute("invokeaction", "showpopover"); + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + assert_false(invokee.matches(":popover-open")); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as showpopover) closed popover opens"); + + promise_test(async function (t) { + invokerbutton.setAttribute("invokeaction", "sHoWpOpOvEr"); + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + assert_false(invokee.matches(":popover-open")); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as showpopover - case insensitive) closed popover opens"); + + promise_test(async function (t) { + invokerbutton.setAttribute("invokeaction", "showpopover"); + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + invokee.showPopover(); + assert_true(invokee.matches(":popover-open")); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as showpopover) open popover is noop"); + + promise_test(async function (t) { + invokerbutton.setAttribute("invokeaction", "showpopover"); + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + assert_false(invokee.matches(":popover-open")); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + await clickOn(invokerbutton); + t.add_cleanup(() => invokee.hidePopover()); + assert_false(invokee.matches(":popover-open")); + }, "invoking (as showpopover) closed popover with preventDefault does not open"); + + // hidepopover + + promise_test(async function (t) { + invokerbutton.setAttribute("invokeaction", "hidepopover"); + t.add_cleanup(() => invokerbutton.removeAttribute("invokeaction")); + assert_false(invokee.matches(":popover-open")); + await clickOn(invokerbutton); + assert_false(invokee.matches(":popover-open")); + }, "invoking (as hidepopover) closed popover is noop"); + + promise_test(async function (t) { + invokerbutton2.setAttribute("invokeaction", "hidepopover"); + t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction")); + invokee.showPopover(); + assert_true(invokee.matches(":popover-open")); + await clickOn(invokerbutton2); + t.add_cleanup(() => invokee.hidePopover()); + assert_false(invokee.matches(":popover-open")); + }, "invoking (as hidepopover) open popover closes"); + + promise_test(async function (t) { + invokerbutton2.setAttribute("invokeaction", "hIdEpOpOvEr"); + t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction")); + invokee.showPopover(); + assert_true(invokee.matches(":popover-open")); + await clickOn(invokerbutton2); + t.add_cleanup(() => invokee.hidePopover()); + assert_false(invokee.matches(":popover-open")); + }, "invoking (as hidepopover - case insensitive) open popover closes"); + + promise_test(async function (t) { + invokerbutton2.setAttribute("invokeaction", "hidepopover"); + t.add_cleanup(() => invokerbutton2.removeAttribute("invokeaction")); + invokee.showPopover(); + t.add_cleanup(() => invokee.hidePopover()); + assert_true(invokee.matches(":popover-open")); + invokee.addEventListener("invoke", (e) => e.preventDefault(), { + once: true, + }); + await clickOn(invokerbutton2); + assert_true(invokee.matches(":popover-open")); + }, "invoking (as hidepopover) open popover with preventDefault does not close"); +</script> diff --git a/tests/wpt/tests/html/semantics/popovers/popover-close-request.html b/tests/wpt/tests/html/semantics/popovers/popover-close-request.html new file mode 100644 index 00000000000..830a40e0608 --- /dev/null +++ b/tests/wpt/tests/html/semantics/popovers/popover-close-request.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popover close request behavior</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/common/top-layer.js"></script> +<script src="/close-watcher/resources/helpers.js"></script> + +<div popover id=p1> + Inside popover 1 + <div popover id=p2>Inside popover 2</div> +</div> + +<script> +promise_test(async () => { + const popover1 = document.querySelector('#p1'); + const popover2 = document.querySelector('#p2'); + + popover1.showPopover(); + + // Bless the opening of popover2, so it doesn't get grouped with popover1 by + // the close watcher infrastructure. + await blessTopLayer(popover1); + popover2.showPopover(); + + assert_true(popover1.matches(':popover-open'), "Starting: popover1 must be open"); + assert_true(popover2.matches(':popover-open'), "Starting: popover2 must be open"); + + await sendCloseRequest(); + assert_true(popover1.matches(':popover-open'), "After one close request, popover1 must be open"); + assert_false(popover2.matches(':popover-open'), "After one close request, popover2 must be closed"); + + await sendCloseRequest(); + assert_false(popover1.matches(':popover-open'), "After two close requests, popover1 must be closed"); + assert_false(popover2.matches(':popover-open'), "After two close requests, popover2 must be closed"); +}); +</script> diff --git a/tests/wpt/tests/html/semantics/popovers/popover-top-layer-combinations.html b/tests/wpt/tests/html/semantics/popovers/popover-top-layer-combinations.html index c6fae283874..024794f5785 100644 --- a/tests/wpt/tests/html/semantics/popovers/popover-top-layer-combinations.html +++ b/tests/wpt/tests/html/semantics/popovers/popover-top-layer-combinations.html @@ -9,6 +9,7 @@ <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-actions.js"></script> <script src="/resources/testdriver-vendor.js"></script> +<script src="/common/top-layer.js"></script> <script src="resources/popover-utils.js"></script> <button id=visible>Visible button</button> diff --git a/tests/wpt/tests/html/semantics/popovers/popover-top-layer-interactions.html b/tests/wpt/tests/html/semantics/popovers/popover-top-layer-interactions.html index 95da47a5e20..6d050ed99bb 100644 --- a/tests/wpt/tests/html/semantics/popovers/popover-top-layer-interactions.html +++ b/tests/wpt/tests/html/semantics/popovers/popover-top-layer-interactions.html @@ -8,6 +8,7 @@ <script src="/resources/testharnessreport.js"></script> <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-vendor.js"></script> +<script src="/common/top-layer.js"></script> <script src="resources/popover-utils.js"></script> <body> diff --git a/tests/wpt/tests/html/semantics/popovers/resources/popover-utils.js b/tests/wpt/tests/html/semantics/popovers/resources/popover-utils.js index f11291e5c2f..bfc1f89ec10 100644 --- a/tests/wpt/tests/html/semantics/popovers/resources/popover-utils.js +++ b/tests/wpt/tests/html/semantics/popovers/resources/popover-utils.js @@ -46,22 +46,6 @@ async function sendEnter() { function isElementVisible(el) { return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length); } -function isTopLayer(el) { - // A bit of a hack. Just test a few properties of the ::backdrop pseudo - // element that change when in the top layer. - const properties = ['right','background']; - const testEl = document.createElement('div'); - document.body.appendChild(testEl); - const computedStyle = getComputedStyle(testEl, '::backdrop'); - const nonTopLayerValues = properties.map(p => computedStyle[p]); - testEl.remove(); - for(let i=0;i<properties.length;++i) { - if (getComputedStyle(el,'::backdrop')[properties[i]] !== nonTopLayerValues[i]) { - return true; - } - } - return false; -} async function finishAnimations(popover) { popover.getAnimations({subtree: true}).forEach(animation => animation.finish()); await waitForRender(); @@ -95,19 +79,6 @@ async function mouseHover(element,hoverWaitTimeMs) { assertMouseStillOver(element); } -async function blessTopLayer(visibleElement) { - // The normal "bless" function doesn't work well when there are top layer - // elements blocking clicks. Additionally, since the normal test_driver.bless - // function just adds a button to the main document and clicks it, we can't - // call that in the presence of open popovers, since that click will close them. - const button = document.createElement('button'); - button.innerHTML = "Click me to activate"; - visibleElement.appendChild(button); - let wait_click = new Promise(resolve => button.addEventListener("click", resolve, {once: true})); - await test_driver.click(button); - await wait_click; - button.remove(); -} // This is a "polyfill" of sorts for the `defaultopen` attribute. // It can be called before window.load is complete, and it will // show defaultopen popovers according to the rules previously part diff --git a/tests/wpt/tests/idle-detection/WEB_FEATURES.yml b/tests/wpt/tests/idle-detection/WEB_FEATURES.yml new file mode 100644 index 00000000000..1e208f268e3 --- /dev/null +++ b/tests/wpt/tests/idle-detection/WEB_FEATURES.yml @@ -0,0 +1,3 @@ +features: +- name: idle-detection + files: "**" diff --git a/tests/wpt/tests/infrastructure/metadata/infrastructure/webdriver/tests/test_load_file.py.ini b/tests/wpt/tests/infrastructure/metadata/infrastructure/webdriver/tests/test_load_file.py.ini new file mode 100644 index 00000000000..7e6ef522c9b --- /dev/null +++ b/tests/wpt/tests/infrastructure/metadata/infrastructure/webdriver/tests/test_load_file.py.ini @@ -0,0 +1,2 @@ +disabled: + if product == "firefox": @True diff --git a/tests/wpt/tests/interfaces/invokers.tentative.idl b/tests/wpt/tests/interfaces/invokers.tentative.idl index 67e2eb4ce19..62f7398b827 100644 --- a/tests/wpt/tests/interfaces/invokers.tentative.idl +++ b/tests/wpt/tests/interfaces/invokers.tentative.idl @@ -11,5 +11,5 @@ interface InvokeEvent : Event { dictionary InvokeEventInit : EventInit { Element? invoker = null; - DOMString action = ""; + DOMString action = "auto"; }; diff --git a/tests/wpt/tests/jpegxl/3x3_jpeg_recompression-ref.html b/tests/wpt/tests/jpegxl/3x3_jpeg_recompression-ref.html new file mode 100644 index 00000000000..070243d6a7e --- /dev/null +++ b/tests/wpt/tests/jpegxl/3x3_jpeg_recompression-ref.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<title>JPEG XL test reference</title> + +<img src="./resources/3x3_jpeg_recompression.png"> diff --git a/tests/wpt/tests/jpegxl/3x3_jpeg_recompression.html b/tests/wpt/tests/jpegxl/3x3_jpeg_recompression.html new file mode 100644 index 00000000000..f28fca8fdce --- /dev/null +++ b/tests/wpt/tests/jpegxl/3x3_jpeg_recompression.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>JPEG XL test</title> +<meta name=fuzzy content="0-1;0-9"> +<link rel="help" href="https://jpeg.org/jpegxl/"> +<link rel="match" href="3x3_jpeg_recompression-ref.html"> +<meta name="assert" content="JPEG XL image is rendered correctly"> + +<img src="./resources/3x3_jpeg_recompression.jxl"> diff --git a/tests/wpt/tests/jpegxl/3x3_srgb_lossless-ref.html b/tests/wpt/tests/jpegxl/3x3_srgb_lossless-ref.html new file mode 100644 index 00000000000..1bb50832409 --- /dev/null +++ b/tests/wpt/tests/jpegxl/3x3_srgb_lossless-ref.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<title>JPEG XL test reference</title> + +<img src="./resources/3x3_srgb_lossless.png"> diff --git a/tests/wpt/tests/jpegxl/3x3_srgb_lossless.html b/tests/wpt/tests/jpegxl/3x3_srgb_lossless.html new file mode 100644 index 00000000000..589f11c68c4 --- /dev/null +++ b/tests/wpt/tests/jpegxl/3x3_srgb_lossless.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>JPEG XL test</title> +<meta name=fuzzy content="0-4;0-9"> +<link rel="help" href="https://jpeg.org/jpegxl/"> +<link rel="match" href="3x3_srgb_lossless-ref.html"> +<meta name="assert" content="JPEG XL image is rendered correctly"> + +<img src="./resources/3x3_srgb_lossless.jxl"> diff --git a/tests/wpt/tests/jpegxl/srgb-ref.html b/tests/wpt/tests/jpegxl/3x3_srgb_lossy-ref.html index 634567e4303..a5e95baba3b 100644 --- a/tests/wpt/tests/jpegxl/srgb-ref.html +++ b/tests/wpt/tests/jpegxl/3x3_srgb_lossy-ref.html @@ -1,4 +1,4 @@ <!DOCTYPE html> <title>JPEG XL test reference</title> -<img src="./resources/3x3.png"> +<img src="./resources/3x3_srgb_lossy.png"> diff --git a/tests/wpt/tests/jpegxl/srgb.html b/tests/wpt/tests/jpegxl/3x3_srgb_lossy.html index 9d131787ec3..3a92b2b7301 100644 --- a/tests/wpt/tests/jpegxl/srgb.html +++ b/tests/wpt/tests/jpegxl/3x3_srgb_lossy.html @@ -1,7 +1,8 @@ <!DOCTYPE html> <title>JPEG XL test</title> +<meta name=fuzzy content="0-10;0-9"> <link rel="help" href="https://jpeg.org/jpegxl/"> -<link rel="match" href="srgb-ref.html"> +<link rel="match" href="3x3_srgb_lossy-ref.html"> <meta name="assert" content="JPEG XL image is rendered correctly"> -<img src="./resources/3x3_srgb.jxl"> +<img src="./resources/3x3_srgb_lossy.jxl"> diff --git a/tests/wpt/tests/jpegxl/3x3a_srgb_lossless-ref.html b/tests/wpt/tests/jpegxl/3x3a_srgb_lossless-ref.html new file mode 100644 index 00000000000..75d8ba7452e --- /dev/null +++ b/tests/wpt/tests/jpegxl/3x3a_srgb_lossless-ref.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<title>JPEG XL test reference</title> + +<img src="./resources/3x3a_srgb_lossless.png"> diff --git a/tests/wpt/tests/jpegxl/3x3a_srgb_lossless.html b/tests/wpt/tests/jpegxl/3x3a_srgb_lossless.html new file mode 100644 index 00000000000..1de61a5ba27 --- /dev/null +++ b/tests/wpt/tests/jpegxl/3x3a_srgb_lossless.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>JPEG XL test</title> +<meta name=fuzzy content="0-4;0-9"> +<link rel="help" href="https://jpeg.org/jpegxl/"> +<link rel="match" href="3x3a_srgb_lossless-ref.html"> +<meta name="assert" content="JPEG XL image is rendered correctly"> + +<img src="./resources/3x3a_srgb_lossless.jxl"> diff --git a/tests/wpt/tests/jpegxl/3x3a_srgb_lossy-ref.html b/tests/wpt/tests/jpegxl/3x3a_srgb_lossy-ref.html new file mode 100644 index 00000000000..3a1c22e8a27 --- /dev/null +++ b/tests/wpt/tests/jpegxl/3x3a_srgb_lossy-ref.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<title>JPEG XL test reference</title> + +<img src="./resources/3x3a_srgb_lossy.png"> diff --git a/tests/wpt/tests/jpegxl/3x3a_srgb_lossy.html b/tests/wpt/tests/jpegxl/3x3a_srgb_lossy.html new file mode 100644 index 00000000000..59583a11a9a --- /dev/null +++ b/tests/wpt/tests/jpegxl/3x3a_srgb_lossy.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>JPEG XL test</title> +<meta name=fuzzy content="0-10;0-9"> +<link rel="help" href="https://jpeg.org/jpegxl/"> +<link rel="match" href="3x3a_srgb_lossy-ref.html"> +<meta name="assert" content="JPEG XL image is rendered correctly"> + +<img src="./resources/3x3a_srgb_lossy.jxl"> diff --git a/tests/wpt/tests/jpegxl/resources/3x3.png b/tests/wpt/tests/jpegxl/resources/3x3.png Binary files differdeleted file mode 100644 index 96f86420a5f..00000000000 --- a/tests/wpt/tests/jpegxl/resources/3x3.png +++ /dev/null diff --git a/tests/wpt/tests/jpegxl/resources/3x3_jpeg_recompression.jxl b/tests/wpt/tests/jpegxl/resources/3x3_jpeg_recompression.jxl Binary files differnew file mode 100644 index 00000000000..deee4257ff6 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3_jpeg_recompression.jxl diff --git a/tests/wpt/tests/jpegxl/resources/3x3_jpeg_recompression.png b/tests/wpt/tests/jpegxl/resources/3x3_jpeg_recompression.png Binary files differnew file mode 100644 index 00000000000..b147cb57bd8 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3_jpeg_recompression.png diff --git a/tests/wpt/tests/jpegxl/resources/3x3_srgb.jxl b/tests/wpt/tests/jpegxl/resources/3x3_srgb.jxl Binary files differdeleted file mode 100644 index 5e52b33641e..00000000000 --- a/tests/wpt/tests/jpegxl/resources/3x3_srgb.jxl +++ /dev/null diff --git a/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossless.jxl b/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossless.jxl Binary files differnew file mode 100644 index 00000000000..bb9cf0bb2e4 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossless.jxl diff --git a/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossless.png b/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossless.png Binary files differnew file mode 100644 index 00000000000..f314145a139 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossless.png diff --git a/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossy.jxl b/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossy.jxl Binary files differnew file mode 100644 index 00000000000..a2d7a898e15 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossy.jxl diff --git a/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossy.png b/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossy.png Binary files differnew file mode 100644 index 00000000000..ad5ef8117f6 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3_srgb_lossy.png diff --git a/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossless.jxl b/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossless.jxl Binary files differnew file mode 100644 index 00000000000..6bbb43d8e72 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossless.jxl diff --git a/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossless.png b/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossless.png Binary files differnew file mode 100644 index 00000000000..3c5f9c4e6b1 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossless.png diff --git a/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossy.jxl b/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossy.jxl Binary files differnew file mode 100644 index 00000000000..0a4e952e3b8 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossy.jxl diff --git a/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossy.png b/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossy.png Binary files differnew file mode 100644 index 00000000000..885c5d03592 --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/3x3a_srgb_lossy.png diff --git a/tests/wpt/tests/jpegxl/resources/generate_resources.sh b/tests/wpt/tests/jpegxl/resources/generate_resources.sh new file mode 100755 index 00000000000..359b2afd9ea --- /dev/null +++ b/tests/wpt/tests/jpegxl/resources/generate_resources.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# This generates the png and jxl images needed. + +# Function to check if a command exists +command_exists() { + command -v "$1" &> /dev/null +} + +# Function to convert and compress an image +convert_and_compress() { + local input_image=$1 + local base_name=$2 + local color_space=$3 + + cjxl "$input_image" temp.jxl -d 0 + djxl temp.jxl "${base_name}_${color_space}_lossless.png" + cjxl "${base_name}_${color_space}_lossless.png" "${base_name}_${color_space}_lossy.jxl" -d 0.0001 -e 7 + djxl "${base_name}_${color_space}_lossy.jxl" "${base_name}_${color_space}_lossy.png" + cjxl "${base_name}_${color_space}_lossless.png" "${base_name}_${color_space}_lossless.jxl" -d 0 +} + +# Check for required tools +for tool in convert cjxl djxl; do + if ! command_exists "$tool"; then + echo "$tool could not be found. Please install it and run the script again." + exit 1 + fi +done + +# Create a 3x3 transparent image +convert -size 3x3 xc:none 3x3a.png + +# Draw colors with alpha values +convert 3x3a.png \ +-fill "rgba(255,0,0,0.5)" -draw "point 0,0" \ +-fill "rgba(0,255,0,0.5)" -draw "point 1,0" \ +-fill "rgba(0,0,255,0.5)" -draw "point 2,0" \ +-fill "rgba(128,64,64,0.5)" -draw "point 0,1" \ +-fill "rgba(64,128,64,0.5)" -draw "point 1,1" \ +-fill "rgba(64,64,128,0.5)" -draw "point 2,1" \ +-fill "rgba(255,255,255,0.5)" -draw "point 0,2" \ +-fill "rgba(128,128,128,0.5)" -draw "point 1,2" \ +-fill "rgba(0,0,0,0.5)" -draw "point 2,2" \ +3x3a.png + +# Generate initial image with alpha values +generate_image 3x3a.png + +# Generate a version without alpha channel +convert 3x3a.png -alpha off 3x3.png + +# Define color spaces +# TODO(firsching): add "RGB_D65_202_Rel_PeQ" and "RGB_D65_202_Rel_HLG" as color spaces here +color_spaces=("srgb") + +# Loop through color spaces and convert/compress images +for color_space in "${color_spaces[@]}"; do + convert_and_compress 3x3.png "3x3" "$color_space" + convert_and_compress 3x3a.png "3x3a" "$color_space" +done + +convert 3x3.png -quality 70 3x3.jpg +# lossless recompression +cjxl 3x3.jpg 3x3_jpeg_recompression.jxl +# checking that it was actually byte exact +djxl 3x3_jpeg_recompression.jxl 3x3_recovered.jpg +diff 3x3.jpg 3x3_recovered.jpg +if [ $? -ne 0 ]; then + echo "The recovery of the recompressed jpg failed: 3x3.png and 3x3_recovered.jpg differ" + exit 1 +fi +# generate reference png +djxl 3x3_jpeg_recompression.jxl 3x3_jpeg_recompression.png + +# Cleanup temporary file +rm -f temp.jxl 3x3.png 3x3a.png 3x3.jpg 3x3_recovered.jpg diff --git a/tests/wpt/tests/lint.ignore b/tests/wpt/tests/lint.ignore index 247d2950d55..5a16051bbd4 100644 --- a/tests/wpt/tests/lint.ignore +++ b/tests/wpt/tests/lint.ignore @@ -20,6 +20,7 @@ TRAILING WHITESPACE: html/syntax/xmldecl/support/no-version-or-space-or-trailing TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.adts TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.pdf TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.jpg +TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.jxl TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.png TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.gif TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.wav @@ -146,7 +147,6 @@ SET TIMEOUT: conformance-checkers/* SET TIMEOUT: content-security-policy/* SET TIMEOUT: css/compositing/opacity-and-transform-animation-crash.html SET TIMEOUT: css/css-contain/contain-body-overflow-002.html -SET TIMEOUT: css/css-lists/dynamic-counters-crash.html SET TIMEOUT: css/css-display/display-contents-shadow-dom-1.html SET TIMEOUT: css/CSS2/normal-flow/crashtests/block-in-inline-ax-crash.html SET TIMEOUT: css/selectors/selector-placeholder-shown-type-change-001.html @@ -311,8 +311,6 @@ GENERATE_TESTS: dom/ranges/Range-selectNode.html GENERATE_TESTS: dom/ranges/Range-set.html GENERATE_TESTS: dom/traversal/TreeWalker.html GENERATE_TESTS: domparsing/createContextualFragment.html -GENERATE_TESTS: domxpath/001.html -GENERATE_TESTS: domxpath/002.html GENERATE_TESTS: mediacapture-image/MediaStreamTrack-applyConstraints-reject.https.html GENERATE_TESTS: mediacapture-image/MediaStreamTrack-getCapabilities.https.html GENERATE_TESTS: mediacapture-image/MediaStreamTrack-getConstraints.https.html @@ -375,6 +373,7 @@ SET TIMEOUT: speculation-rules/prerender/resources/media-autoplay-attribute.html SET TIMEOUT: speculation-rules/prerender/resources/media-play.html SET TIMEOUT: html/browsers/browsing-the-web/back-forward-cache/timers.html SET TIMEOUT: dom/abort/crashtests/timeout-close.html +SET TIMEOUT: storage-access-api/storage-access-beyond-cookies.locks.tentative.sub.https.window.js # setTimeout use in reftests SET TIMEOUT: acid/acid3/test.html diff --git a/tests/wpt/tests/long-animation-frame/tentative/loaf-stream-source-location.html b/tests/wpt/tests/long-animation-frame/tentative/loaf-stream-source-location.html new file mode 100644 index 00000000000..3b6b2b31608 --- /dev/null +++ b/tests/wpt/tests/long-animation-frame/tentative/loaf-stream-source-location.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Long Animation Frame Timing: source location extraction for streams</title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/utils.js"></script> + +<body> +<h1>Long Animation Frame: source location extraction for streams</h1> +<div id="log"></div> +<script> + +const source_location_regex = /^([^@]+\@)?https?\:\/\/[^\/]+[^\:]+\:\d*$/; + +promise_test(async t => { + const scriptLocation = new URL("resources/stream-promise-generates-loaf.js", location.href); + const [entry, script] = await expect_long_frame_with_script(() => { + const scriptElement = document.createElement("script"); + scriptElement.src = scriptLocation; + document.body.appendChild(scriptElement); + }, script => script.name === "StreamPromise.resolve.then", t); + + assert_true(script.sourceLocation?.includes("stream-promise-generates-loaf.js")); +}, "Source location should be extracted for stream promises"); + +</script> +</body> diff --git a/tests/wpt/tests/long-animation-frame/tentative/resources/stream-promise-generates-loaf.js b/tests/wpt/tests/long-animation-frame/tentative/resources/stream-promise-generates-loaf.js new file mode 100644 index 00000000000..35e7920bb20 --- /dev/null +++ b/tests/wpt/tests/long-animation-frame/tentative/resources/stream-promise-generates-loaf.js @@ -0,0 +1,12 @@ +(async() => { + const response = await fetch("/common/dummy.xml"); + const {readable, writable} = new TransformStream({ + start() {}, + transform() { + const deadline = performance.now() + 360; + while (performance.now() < deadline) {} + } + }); + response.body.pipeTo(writable); + await readable.getReader().read(); +})(); diff --git a/tests/wpt/tests/magnetometer/Magnetometer-iframe-access.https.html b/tests/wpt/tests/magnetometer/Magnetometer-iframe-access.https.html index 3dc90e3dd7f..7aabd0eb61b 100644 --- a/tests/wpt/tests/magnetometer/Magnetometer-iframe-access.https.html +++ b/tests/wpt/tests/magnetometer/Magnetometer-iframe-access.https.html @@ -5,12 +5,15 @@ <link rel="help" href="https://www.w3.org/TR/magnetometer/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-iframe-tests.sub.js"></script> <script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script> +<script src="resources/sensor-data.js"></script> <div id="log"></div> <script> -run_generic_sensor_iframe_tests('Magnetometer'); -run_generic_sensor_iframe_tests('UncalibratedMagnetometer'); +run_generic_sensor_iframe_tests(kMagnetometerSensorData, kMagnetometerReadings); +run_generic_sensor_iframe_tests(kUncalibratedMagnetometerSensorData, kMagnetometerReadings); </script> diff --git a/tests/wpt/tests/magnetometer/Magnetometer.https.html b/tests/wpt/tests/magnetometer/Magnetometer.https.html index 0cc443784be..6beb534509d 100644 --- a/tests/wpt/tests/magnetometer/Magnetometer.https.html +++ b/tests/wpt/tests/magnetometer/Magnetometer.https.html @@ -6,34 +6,17 @@ <link rel="help" href="https://www.w3.org/TR/magnetometer/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> 'use strict'; -const kReadings = { - readings: [ - [-19.2, 12.1, -44.3] - ], - expectedReadings: [ - [-19.2, 12.1, -44.3] - ], - expectedRemappedReadings: [ - [-12.1, -19.2, -44.3] - ] -}; - -runGenericSensorTests( - 'Magnetometer', - kReadings, - verifyXyzSensorReading, - ['magnetometer']); - -runGenericSensorTests( - 'UncalibratedMagnetometer', - kReadings, - verifyXyzSensorReading, - ['magnetometer']); +runGenericSensorTests(kMagnetometerSensorData, kMagnetometerReadings); +runGenericSensorTests(kUncalibratedMagnetometerSensorData, kMagnetometerReadings); </script> diff --git a/tests/wpt/tests/magnetometer/resources/sensor-data.js b/tests/wpt/tests/magnetometer/resources/sensor-data.js new file mode 100644 index 00000000000..32c2b1e2895 --- /dev/null +++ b/tests/wpt/tests/magnetometer/resources/sensor-data.js @@ -0,0 +1,21 @@ +'use strict'; + +const kMagnetometerSensorData = { + sensorName: 'Magnetometer', + permissionName: 'magnetometer', + testDriverName: 'magnetometer', + featurePolicyNames: ['magnetometer'] +}; + +const kUncalibratedMagnetometerSensorData = { + sensorName: 'UncalibratedMagnetometer', + permissionName: 'magnetometer', + testDriverName: 'magnetometer', + featurePolicyNames: ['magnetometer'] +}; + +const kMagnetometerReadings = { + readings: [{x: -19.2, y: 12.1, z: -44.3}], + expectedReadings: [{x: -19.2, y: 12.1, z: -44.3}], + expectedRemappedReadings: [{x: -12.1, y: -19.2, z: -44.3}] +}; diff --git a/tests/wpt/tests/mediacapture-extensions/MediaStreamTrack-video-stats.https.html b/tests/wpt/tests/mediacapture-extensions/MediaStreamTrack-video-stats.https.html index 6901ed84e39..f1b6a2074a4 100644 --- a/tests/wpt/tests/mediacapture-extensions/MediaStreamTrack-video-stats.https.html +++ b/tests/wpt/tests/mediacapture-extensions/MediaStreamTrack-video-stats.https.html @@ -326,8 +326,8 @@ promise_test(async t => { const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); - assert_throws_dom('NotSupportedError', () => track.stats); -}, `track.stats throws on audio tracks`); + assert_equals(track.stats, null); +}, `track.stats is null on audio tracks`); promise_test(async t => { const canvas = document.createElement('canvas'); @@ -335,8 +335,8 @@ promise_test(async t => { const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); - assert_throws_dom('NotSupportedError', () => track.stats); -}, `track.stats throws on non-device tracks, such as canvas`); + assert_equals(track.stats, null); +}, `track.stats is null on non-device tracks, such as canvas`); promise_test(async t => { // getDisplayMedia() requires inducing a user gesture. diff --git a/tests/wpt/tests/orientation-sensor/AbsoluteOrientationSensor-iframe-access.https.html b/tests/wpt/tests/orientation-sensor/AbsoluteOrientationSensor-iframe-access.https.html index e99b5c6365d..4831b5e7192 100644 --- a/tests/wpt/tests/orientation-sensor/AbsoluteOrientationSensor-iframe-access.https.html +++ b/tests/wpt/tests/orientation-sensor/AbsoluteOrientationSensor-iframe-access.https.html @@ -5,11 +5,14 @@ <link rel="help" href="https://www.w3.org/TR/orientation-sensor/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-iframe-tests.sub.js"></script> <script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script> +<script src="resources/sensor-data.js"></script> <div id="log"></div> <script> -run_generic_sensor_iframe_tests('AbsoluteOrientationSensor'); +run_generic_sensor_iframe_tests(kAbsoluteOrientationSensorData, kOrientationReadings); </script> diff --git a/tests/wpt/tests/orientation-sensor/AbsoluteOrientationSensor.https.html b/tests/wpt/tests/orientation-sensor/AbsoluteOrientationSensor.https.html index e6f5dd91383..4c516da1451 100644 --- a/tests/wpt/tests/orientation-sensor/AbsoluteOrientationSensor.https.html +++ b/tests/wpt/tests/orientation-sensor/AbsoluteOrientationSensor.https.html @@ -7,17 +7,19 @@ <link rel="help" href="https://w3c.github.io/sensors/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> <script src="/orientation-sensor/orientation-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> -runGenericSensorTests( - 'AbsoluteOrientationSensor', - kReadings, - verifyQuatSensorReading, - ['accelerometer', 'gyroscope', 'magnetometer']); +'use strict'; -runOrientationSensorTests('AbsoluteOrientationSensor'); +runGenericSensorTests(kAbsoluteOrientationSensorData, kOrientationReadings); + +runOrientationSensorTests(kAbsoluteOrientationSensorData, kOrientationReadings); </script> diff --git a/tests/wpt/tests/orientation-sensor/RelativeOrientationSensor-iframe-access.https.html b/tests/wpt/tests/orientation-sensor/RelativeOrientationSensor-iframe-access.https.html index 5d30534841b..fe995e2d1b9 100644 --- a/tests/wpt/tests/orientation-sensor/RelativeOrientationSensor-iframe-access.https.html +++ b/tests/wpt/tests/orientation-sensor/RelativeOrientationSensor-iframe-access.https.html @@ -5,11 +5,14 @@ <link rel="help" href="https://www.w3.org/TR/orientation-sensor/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-iframe-tests.sub.js"></script> <script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script> +<script src="resources/sensor-data.js"></script> <div id="log"></div> <script> -run_generic_sensor_iframe_tests('RelativeOrientationSensor'); +run_generic_sensor_iframe_tests(kRelativeOrientationSensorData, kOrientationReadings); </script> diff --git a/tests/wpt/tests/orientation-sensor/RelativeOrientationSensor.https.html b/tests/wpt/tests/orientation-sensor/RelativeOrientationSensor.https.html index 499e7df8cea..35dc8c31113 100644 --- a/tests/wpt/tests/orientation-sensor/RelativeOrientationSensor.https.html +++ b/tests/wpt/tests/orientation-sensor/RelativeOrientationSensor.https.html @@ -7,17 +7,19 @@ <link rel="help" href="https://w3c.github.io/sensors/"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script> <script src="/generic-sensor/generic-sensor-tests.js"></script> <script src="/orientation-sensor/orientation-sensor-tests.js"></script> +<script src="resources/sensor-data.js"></script> <script> -runGenericSensorTests( - 'RelativeOrientationSensor', - kReadings, - verifyQuatSensorReading, - ['accelerometer', 'gyroscope']); +'use strict'; -runOrientationSensorTests('RelativeOrientationSensor'); +runGenericSensorTests(kRelativeOrientationSensorData, kOrientationReadings); + +runOrientationSensorTests(kRelativeOrientationSensorData, kOrientationReadings); </script> diff --git a/tests/wpt/tests/orientation-sensor/orientation-sensor-tests.js b/tests/wpt/tests/orientation-sensor/orientation-sensor-tests.js index 88fd432d470..d69fa3e54cd 100644 --- a/tests/wpt/tests/orientation-sensor/orientation-sensor-tests.js +++ b/tests/wpt/tests/orientation-sensor/orientation-sensor-tests.js @@ -1,89 +1,104 @@ 'use strict'; -const kDefaultReading = [ - [ 1, 0, 0, 0 ] // 180 degrees around X axis. -]; -const kRotationMatrix = [1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, -1, 0, - 0, 0, 0, 1]; -const kReadings = { - readings: kDefaultReading, - expectedReadings: kDefaultReading, - expectedRemappedReadings: [ - // For 'orientation.angle == 270', which is set for tests at - // at SensorProxy::GetScreenOrientationAngle(). - [-0.707107, 0.707107, 0, 0] - ] -}; - -async function checkQuaternion(t, sensorType) { +async function checkQuaternion( + t, sensorType, testDriverName, permissionName, readings) { + await test_driver.set_permission({name: permissionName}, 'granted'); + await test_driver.create_virtual_sensor(testDriverName); const sensor = new sensorType(); - const eventWatcher = new EventWatcher(t, sensor, ["reading", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); sensor.start(); - await eventWatcher.wait_for("reading"); - assert_equals(sensor.quaternion.length, 4); - assert_true(sensor.quaternion instanceof Array); - sensor.stop(); + await sensorWatcher.wait_for('activate'); + await Promise.all([ + test_driver.update_virtual_sensor(testDriverName, readings.next().value), + sensorWatcher.wait_for('reading') + ]); + assert_equals(sensor.quaternion.length, 4, 'Quaternion length must be 4'); + assert_true( + sensor.quaternion instanceof Array, 'Quaternion is must be array'); }; -async function checkPopulateMatrix(t, sensorProvider, sensorType) { +async function checkPopulateMatrix( + t, sensorProvider, sensorType, testDriverName, permissionName, readings) { + await test_driver.set_permission({name: permissionName}, 'granted'); + await test_driver.create_virtual_sensor(testDriverName); const sensor = new sensorType(); - const eventWatcher = new EventWatcher(t, sensor, ["reading", "error"]); + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor(testDriverName); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); // Throws with insufficient buffer space. - assert_throws_js(TypeError, - () => sensor.populateMatrix(new Float32Array(15))); + assert_throws_js( + TypeError, () => sensor.populateMatrix(new Float32Array(15))); // Throws if no orientation data available. - assert_throws_dom('NotReadableError', - () => sensor.populateMatrix(new Float32Array(16))); + assert_throws_dom( + 'NotReadableError', () => sensor.populateMatrix(new Float32Array(16))); // Throws if passed SharedArrayBuffer view. - assert_throws_js(TypeError, - // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()` - // WebAssembly.Memory's size is in multiples of 64 KiB - () => sensor.populateMatrix(new Float32Array(new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer))); + assert_throws_js( + TypeError, + // See https://github.com/whatwg/html/issues/5380 for why not `new + // SharedArrayBuffer()` WebAssembly.Memory's size is in multiples of 64KiB + () => sensor.populateMatrix(new Float32Array( + new WebAssembly.Memory({shared: true, initial: 1, maximum: 1}) + .buffer))); sensor.start(); + await sensorWatcher.wait_for('activate'); - const mockSensor = await sensorProvider.getCreatedSensor(sensorType.name); - await mockSensor.setSensorReading(kDefaultReading); - - await eventWatcher.wait_for("reading"); + await Promise.all([ + test_driver.update_virtual_sensor(testDriverName, readings.next().value), + sensorWatcher.wait_for('reading') + ]); // Works for all supported types. const rotationMatrix32 = new Float32Array(16); sensor.populateMatrix(rotationMatrix32); - assert_array_equals(rotationMatrix32, kRotationMatrix); + assert_array_approx_equals(rotationMatrix32, kRotationMatrix, kEpsilon); let rotationMatrix64 = new Float64Array(16); sensor.populateMatrix(rotationMatrix64); - assert_array_equals(rotationMatrix64, kRotationMatrix); + assert_array_approx_equals(rotationMatrix64, kRotationMatrix, kEpsilon); let rotationDOMMatrix = new DOMMatrix(); sensor.populateMatrix(rotationDOMMatrix); - assert_array_equals(rotationDOMMatrix.toFloat64Array(), kRotationMatrix); + assert_array_approx_equals( + rotationDOMMatrix.toFloat64Array(), kRotationMatrix, kEpsilon); // Sets every matrix element. rotationMatrix64.fill(123); sensor.populateMatrix(rotationMatrix64); - assert_array_equals(rotationMatrix64, kRotationMatrix); - - sensor.stop(); + assert_array_approx_equals(rotationMatrix64, kRotationMatrix, kEpsilon); } -function runOrientationSensorTests(sensorName) { +function runOrientationSensorTests(sensorData, readingData) { + validate_sensor_data(sensorData); + validate_reading_data(readingData); + + const {sensorName, permissionName, testDriverName} = sensorData; const sensorType = self[sensorName]; - sensor_test(async t => { - assert_true(sensorName in self); - return checkQuaternion(t, sensorType); + const readings = new RingBuffer(readingData.readings); + + promise_test(async t => { + assert_implements(sensorName in self, `${sensorName} is not supported.`); + return checkQuaternion( + t, sensorType, testDriverName, permissionName, readings); }, `${sensorName}.quaternion return a four-element FrozenArray.`); - sensor_test(async (t, sensorProvider) => { - assert_true(sensorName in self); - return checkPopulateMatrix(t, sensorProvider, sensorType); + promise_test(async (t, sensorProvider) => { + assert_implements(sensorName in self, `${sensorName} is not supported.`); + return checkPopulateMatrix( + t, sensorProvider, sensorType, testDriverName, permissionName, + readings); }, `${sensorName}.populateMatrix() method works correctly.`); } diff --git a/tests/wpt/tests/orientation-sensor/resources/sensor-data.js b/tests/wpt/tests/orientation-sensor/resources/sensor-data.js new file mode 100644 index 00000000000..d0b280fa6c4 --- /dev/null +++ b/tests/wpt/tests/orientation-sensor/resources/sensor-data.js @@ -0,0 +1,26 @@ +'use strict'; + +const kAbsoluteOrientationSensorData = { + sensorName: 'AbsoluteOrientationSensor', + permissionName: 'accelerometer', + testDriverName: 'absolute-orientation', + featurePolicyNames: ['accelerometer', 'gyroscope', 'magnetometer'] +}; + +const kRelativeOrientationSensorData = { + sensorName: 'RelativeOrientationSensor', + permissionName: 'accelerometer', + testDriverName: 'relative-orientation', + featurePolicyNames: ['accelerometer', 'gyroscope'] +}; + +const kOrientationReadings = { + readings: [{quaternion: [1, 0, 0, 0]}], + expectedReadings: [{quaternion: [1, 0, 0, 0]}], + expectedRemappedReadings: [{quaternion: [-0.70710678, 0.70710678, 0, 0]}] +}; + +const kRotationMatrix = [1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, -1, 0, + 0, 0, 0, 1]; diff --git a/tests/wpt/tests/pointerevents/pointerevent_after_target_removed.html b/tests/wpt/tests/pointerevents/pointerevent_after_target_removed.html index 5ab6040cc9c..2dcc94c2b23 100644 --- a/tests/wpt/tests/pointerevents/pointerevent_after_target_removed.html +++ b/tests/wpt/tests/pointerevents/pointerevent_after_target_removed.html @@ -106,27 +106,27 @@ // Tests for dispatched pointer events. addPromiseTest("pointerdown", "pointer", [ "pointerover@child", "pointerenter@parent", "pointerenter@child", - "pointerdown@child", "(child-removed)", "pointerup@parent", + "pointerdown@child", "(child-removed)", "pointerover@parent", "pointerup@parent", "pointerdown@parent", "pointerup@parent", "pointerout@parent", "pointerleave@parent" ]); addPromiseTest("pointerup", "pointer", [ "pointerover@child", "pointerenter@parent", "pointerenter@child", "pointerdown@child", "pointerup@child", "(child-removed)", - "pointerdown@parent", "pointerup@parent", + "pointerover@parent", "pointerdown@parent", "pointerup@parent", "pointerout@parent", "pointerleave@parent" ]); // Same tests for dispatched compatibility mouse events. addPromiseTest("pointerdown", "mouse", [ "mouseover@child", "mouseenter@parent", "mouseenter@child", - "(child-removed)", "mousedown@parent", "mouseup@parent", + "(child-removed)", "mouseover@parent", "mousedown@parent", "mouseup@parent", "mousedown@parent", "mouseup@parent", "mouseout@parent", "mouseleave@parent" ]); addPromiseTest("pointerup", "mouse", [ "mouseover@child", "mouseenter@parent", "mouseenter@child", - "mousedown@child", "(child-removed)", "mouseup@parent", + "mousedown@child", "(child-removed)", "mouseover@parent", "mouseup@parent", "mousedown@parent", "mouseup@parent", "mouseout@parent", "mouseleave@parent" ]); diff --git a/tests/wpt/tests/requestidlecallback/callback-timeRemaining-cross-realm-method.html b/tests/wpt/tests/requestidlecallback/callback-timeRemaining-cross-realm-method.html index 383479d64a0..078e2c9379c 100644 --- a/tests/wpt/tests/requestidlecallback/callback-timeRemaining-cross-realm-method.html +++ b/tests/wpt/tests/requestidlecallback/callback-timeRemaining-cross-realm-method.html @@ -1,4 +1,4 @@ -<!doctype html><!-- webkit-test-runner [ RequestIdleCallbackEnabled=true ] --> +<!doctype html> <meta charset="utf-8"> <meta name="timeout" content="long"> <title>IdleDeadline::timeRemaining() uses relevant global object as a high-res timestamp origin</title> diff --git a/tests/wpt/tests/service-workers/service-worker/resources/scope1/redirect.py b/tests/wpt/tests/service-workers/service-worker/resources/scope1/redirect.py index bb4c874aace..025ea671c50 100644 --- a/tests/wpt/tests/service-workers/service-worker/resources/scope1/redirect.py +++ b/tests/wpt/tests/service-workers/service-worker/resources/scope1/redirect.py @@ -1,6 +1,8 @@ import os -import imp + +from tools.wpt.utils import load_source + # Use the file from the parent directory. -mod = imp.load_source("_parent", os.path.join(os.path.dirname(os.path.dirname(__file__)), +mod = load_source("_parent", os.path.join(os.path.dirname(os.path.dirname(__file__)), os.path.basename(__file__))) main = mod.main diff --git a/tests/wpt/tests/service-workers/service-worker/resources/scope2/worker_interception_redirect_webworker.py b/tests/wpt/tests/service-workers/service-worker/resources/scope2/worker_interception_redirect_webworker.py index bb4c874aace..025ea671c50 100644 --- a/tests/wpt/tests/service-workers/service-worker/resources/scope2/worker_interception_redirect_webworker.py +++ b/tests/wpt/tests/service-workers/service-worker/resources/scope2/worker_interception_redirect_webworker.py @@ -1,6 +1,8 @@ import os -import imp + +from tools.wpt.utils import load_source + # Use the file from the parent directory. -mod = imp.load_source("_parent", os.path.join(os.path.dirname(os.path.dirname(__file__)), +mod = load_source("_parent", os.path.join(os.path.dirname(os.path.dirname(__file__)), os.path.basename(__file__))) main = mod.main diff --git a/tests/wpt/tests/service-workers/service-worker/resources/subdir/worker_interception_redirect_webworker.py b/tests/wpt/tests/service-workers/service-worker/resources/subdir/worker_interception_redirect_webworker.py index bb4c874aace..025ea671c50 100644 --- a/tests/wpt/tests/service-workers/service-worker/resources/subdir/worker_interception_redirect_webworker.py +++ b/tests/wpt/tests/service-workers/service-worker/resources/subdir/worker_interception_redirect_webworker.py @@ -1,6 +1,8 @@ import os -import imp + +from tools.wpt.utils import load_source + # Use the file from the parent directory. -mod = imp.load_source("_parent", os.path.join(os.path.dirname(os.path.dirname(__file__)), +mod = load_source("_parent", os.path.join(os.path.dirname(os.path.dirname(__file__)), os.path.basename(__file__))) main = mod.main diff --git a/tests/wpt/tests/storage-access-api/helpers.js b/tests/wpt/tests/storage-access-api/helpers.js index 7d259b21676..24ed21a976b 100644 --- a/tests/wpt/tests/storage-access-api/helpers.js +++ b/tests/wpt/tests/storage-access-api/helpers.js @@ -278,3 +278,15 @@ async function MaybeSetStorageAccess(origin, embedding_origin, value) { // in the test. } } + +// Starts a dedicated worker in the given frame. +function StartDedicatedWorker(frame) { + return PostMessageAndAwaitReply( + { command: "start_dedicated_worker" }, frame.contentWindow); +} + +// Sends a message to the dedicated worker in the given frame. +function MessageWorker(frame, message = {}) { + return PostMessageAndAwaitReply( + { command: "message_worker", message }, frame.contentWindow); +} diff --git a/tests/wpt/tests/storage-access-api/requestStorageAccess-dedicated-worker.tentative.sub.https.window.js b/tests/wpt/tests/storage-access-api/requestStorageAccess-dedicated-worker.tentative.sub.https.window.js new file mode 100644 index 00000000000..86caf819182 --- /dev/null +++ b/tests/wpt/tests/storage-access-api/requestStorageAccess-dedicated-worker.tentative.sub.https.window.js @@ -0,0 +1,67 @@ +// META: script=helpers.js +// META: script=/cookies/resources/cookie-helper.sub.js +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +'use strict'; + +(function() { + const altRoot = "https://{{hosts[alt][]}}:{{ports[https][0]}}"; + + const responderPath = "/storage-access-api/resources/script-with-cookie-header.py?script=embedded_responder.js"; + const echoCookiesPath = `/storage-access-api/resources/echo-cookie-header.py`; + + const altRootResponder = `${altRoot}${responderPath}`; + const altRootEchoCookies = `${altRoot}${echoCookiesPath}`; + + async function SetUpResponderFrame(t, url) { + const frame = await CreateFrame(url); + + await SetPermissionInFrame(frame, [{ name: 'storage-access' }, 'granted']); + t.add_cleanup(async () => { + await test_driver.delete_all_cookies(); + await SetPermissionInFrame(frame, [{ name: 'storage-access' }, 'prompt']); + await MaybeSetStorageAccess("*", "*", "allowed"); + }); + + return frame; + } + + promise_test(async (t) => { + await MaybeSetStorageAccess("*", "*", "blocked"); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(altRoot); + + const frame = await SetUpResponderFrame(t, altRootResponder); + assert_true(await RequestStorageAccessInFrame(frame), "requestStorageAccess resolves without requiring a gesture."); + assert_true(await FrameHasStorageAccess(frame), "frame has storage access after request."); + assert_true(await HasUnpartitionedCookie(frame), "frame has access to cookies after request."); + + await StartDedicatedWorker(frame); + + assert_equals( + await MessageWorker(frame, {command: "fetch", url: altRootEchoCookies}), + "cookie=unpartitioned", "Worker's fetch is credentialed."); + }, "Workers inherit storage access"); + + promise_test(async (t) => { + await MaybeSetStorageAccess("*", "*", "blocked"); + await SetFirstPartyCookieAndUnsetStorageAccessPermission(altRoot); + + const frame = await SetUpResponderFrame(t, altRootResponder); + + await StartDedicatedWorker(frame); + assert_equals( + await MessageWorker(frame, {command: "fetch", url: altRootEchoCookies}), + "", "Worker's first fetch is uncredentialed."); + + // Since the parent document obtains storage access *after* having created + // the worker, this should have no effect on the worker. + assert_true(await RequestStorageAccessInFrame(frame), "requestStorageAccess resolves without requiring a gesture."); + assert_true(await FrameHasStorageAccess(frame), "frame has storage access after request."); + assert_true(await HasUnpartitionedCookie(frame), "frame has access to cookies after request."); + + assert_equals( + await MessageWorker(frame, {command: "fetch", url: altRootEchoCookies}), + "", "Worker's second fetch is uncredentialed."); + }, "Workers don't observe parent's storage access"); + +}()); diff --git a/tests/wpt/tests/storage-access-api/resources/embedded_responder.js b/tests/wpt/tests/storage-access-api/resources/embedded_responder.js index 634079289b0..e9cc39bc71a 100644 --- a/tests/wpt/tests/storage-access-api/resources/embedded_responder.js +++ b/tests/wpt/tests/storage-access-api/resources/embedded_responder.js @@ -4,6 +4,18 @@ test_driver.set_test_context(window.top); +let worker; + +function waitForWorkerMessage(worker) { + return new Promise(resolve => { + const listener = (event) => { + worker.removeEventListener("message", listener); + resolve(event.data); + }; + worker.addEventListener("message", listener); + }); +} + window.addEventListener("message", async (event) => { function reply(data) { event.source.postMessage( @@ -51,6 +63,16 @@ window.addEventListener("message", async (event) => { case "cors fetch": reply(await fetch(event.data.url, {mode: 'cors', credentials: 'include'}).then((resp) => resp.text())); break; + case "start_dedicated_worker": + worker = new Worker("embedded_worker.js"); + reply(undefined); + break; + case "message_worker": { + const p = waitForWorkerMessage(worker); + worker.postMessage(event.data.message); + reply(await p.then(resp => resp.data)) + break; + } default: } }); diff --git a/tests/wpt/tests/storage-access-api/resources/embedded_worker.js b/tests/wpt/tests/storage-access-api/resources/embedded_worker.js new file mode 100644 index 00000000000..f3a0fb257ad --- /dev/null +++ b/tests/wpt/tests/storage-access-api/resources/embedded_worker.js @@ -0,0 +1,17 @@ +"use strict"; + +self.onmessage = async (message) => { + function reply(data) { + self.postMessage({data}); + } + + switch (message.data.command) { + case "fetch": { + const response = await fetch(message.data.url, {mode: 'cors', credentials: 'include'}) + .then((resp) => resp.text()); + reply(response); + break; + } + default: + } +}; diff --git a/tests/wpt/tests/storage-access-api/resources/storage-access-beyond-cookies-iframe-iframe.html b/tests/wpt/tests/storage-access-api/resources/storage-access-beyond-cookies-iframe-iframe.html new file mode 100644 index 00000000000..348efc5dec4 --- /dev/null +++ b/tests/wpt/tests/storage-access-api/resources/storage-access-beyond-cookies-iframe-iframe.html @@ -0,0 +1,75 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> +(async function() { + test_driver.set_test_context(window.top); + const type = (new URLSearchParams(window.location.search)).get("type"); + const id = (new URLSearchParams(window.location.search)).get("id"); + let message = "HasAccess for " + type; + // Step 6 (storage-access-api/storage-access-beyond-cookies.{}.tentative.sub.https.html) + try { + await test_driver.set_permission({ name: 'storage-access' }, 'granted'); + switch (type) { + case "sessionStorage": { + const handle = await document.requestStorageAccess({sessionStorage: true}); + if (id != handle.sessionStorage.getItem("test")) { + message = "No first-party Session Storage access"; + } + if (!!window.sessionStorage.getItem("test")) { + message = "Handle should not override window Session Storage"; + } + handle.sessionStorage.clear(); + break; + } + case "localStorage": { + const handle = await document.requestStorageAccess({localStorage: true}); + if (id != handle.localStorage.getItem("test")) { + message = "No first-party Local Storage access"; + } + if (!!window.localStorage.getItem("test")) { + message = "Handle should not override window Local Storage"; + } + handle.localStorage.clear(); + break; + } + case "indexedDB": { + const handle = await document.requestStorageAccess({indexedDB: true}); + const handle_dbs = await handle.indexedDB.databases(); + if (handle_dbs.length != 1 || handle_dbs[0].name != id) { + message = "No first-party IndexedDB access"; + } + const local_dbs = await window.indexedDB.databases(); + if (local_dbs.length != 0) { + message = "Handle should not override window IndexedDB"; + } + await handle.indexedDB.deleteDatabase(id); + break; + } + case "locks": { + const handle = await document.requestStorageAccess({locks: true}); + const handle_state = await handle.locks.query(); + if (handle_state.held.length != 1 || handle_state.held[0].name != id) { + message = "No first-party Web Lock access"; + } + const local_state = await window.navigator.locks.query(); + if (local_state.held.length != 0) { + message = "Handle should not override window Web Locks"; + } + await handle.locks.request(id, {steal: true}, async () => {}); + break; + } + default: { + message = "Unexpected type " + type; + break; + } + } + } catch (_) { + message = "Unable to load handle in same-origin context for " + type; + } + // Step 7 (storage-access-api/storage-access-beyond-cookies.{}.tentative.sub.https.html) + await test_driver.set_permission({ name: 'storage-access' }, 'prompt'); + window.top.postMessage(message, "*"); +})(); +</script> diff --git a/tests/wpt/tests/storage-access-api/resources/storage-access-beyond-cookies-iframe.sub.html b/tests/wpt/tests/storage-access-api/resources/storage-access-beyond-cookies-iframe.sub.html new file mode 100644 index 00000000000..fae51c2d547 --- /dev/null +++ b/tests/wpt/tests/storage-access-api/resources/storage-access-beyond-cookies-iframe.sub.html @@ -0,0 +1,62 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<body> +<script> +(async function() { + test_driver.set_test_context(window.top); + const type = (new URLSearchParams(window.location.search)).get("type"); + const id = (new URLSearchParams(window.location.search)).get("id"); + let message = ""; + // Step 4 (storage-access-api/storage-access-beyond-cookies.{}.tentative.sub.https.html) + try { + await test_driver.set_permission({ name: 'storage-access' }, 'granted'); + const handle = await document.requestStorageAccess({all: true}); + switch (type) { + case "sessionStorage": { + if (!!handle.sessionStorage.getItem("test")) { + message = "Cross-site first-party Session Storage should be empty"; + } + break; + } + case "localStorage": { + if (!!handle.localStorage.getItem("test")) { + message = "Cross-site first-party Local Storage should be empty"; + } + break; + } + case "indexedDB": { + const dbs = await handle.indexedDB.databases(); + if (dbs.length != 0) { + message = "Cross-site first-party IndexedDB should be empty"; + } + break; + } + case "locks": { + const state = await handle.locks.query(); + if (state.held.length != 0) { + message = "Cross-site first-party Web Locks should be empty"; + } + break; + } + default: { + message = "Unexpected type " + type; + break; + } + } + } catch (_) { + message = "Unable to load handle in cross-site context for all"; + } + await test_driver.set_permission({ name: 'storage-access' }, 'prompt'); + if (message) { + window.top.postMessage(message, "*"); + return; + } + // Step 5 (storage-access-api/storage-access-beyond-cookies.{}.tentative.sub.https.html) + let iframe = document.createElement("iframe"); + iframe.src = "https://{{hosts[][]}}:{{ports[https][0]}}/storage-access-api/resources/storage-access-beyond-cookies-iframe-iframe.html?type=" + type + "&id=" + id; + document.body.appendChild(iframe); +})(); +</script> +</body> diff --git a/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.indexedDB.tentative.sub.https.window.js b/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.indexedDB.tentative.sub.https.window.js new file mode 100644 index 00000000000..18c4317bbe9 --- /dev/null +++ b/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.indexedDB.tentative.sub.https.window.js @@ -0,0 +1,33 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (top-frame) Set up listener for "HasAccess" message. +// Step 2 (top-frame) Add data to first-party indexed db. +// Step 3 (top-frame) Embed an iframe that's cross-site with top-frame. +// Step 4 (sub-frame) Try to use storage access API and read first-party data. +// Step 5 (sub-frame) Embed an iframe that's same-origin with top-frame. +// Step 6 (sub-sub-frame) Try to use storage access API and read first-party data. +// Step 7 (sub-sub-frame) Send "HasAccess for indexedDB" message to top-frame. +// Step 8 (top-frame) Receive "HasAccess for indexedDB" message and cleanup. + +async_test(t => { + // Step 1 + window.addEventListener("message", t.step_func(e => { + // Step 8 + assert_equals(e.data, "HasAccess for indexedDB", "Storage Access API should be accessible and return first-party data"); + t.done(); + })); + + // Step 2 + const id = Date.now(); + let request = window.indexedDB.open(id); + request.onsuccess = () => { + // Step 3 + let iframe = document.createElement("iframe"); + iframe.src = "https://{{hosts[alt][]}}:{{ports[https][0]}}/storage-access-api/resources/storage-access-beyond-cookies-iframe.sub.html?type=indexedDB&id="+id; + document.body.appendChild(iframe); + }; +}, "Verify StorageAccessAPIBeyondCookies for IndexedDB"); diff --git a/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.localStorage.tentative.sub.https.window.js b/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.localStorage.tentative.sub.https.window.js new file mode 100644 index 00000000000..108e778766d --- /dev/null +++ b/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.localStorage.tentative.sub.https.window.js @@ -0,0 +1,32 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (top-frame) Set up listener for "HasAccess" message. +// Step 2 (top-frame) Add data to first-party local storage. +// Step 3 (top-frame) Embed an iframe that's cross-site with top-frame. +// Step 4 (sub-frame) Try to use storage access API and read first-party data. +// Step 5 (sub-frame) Embed an iframe that's same-origin with top-frame. +// Step 6 (sub-sub-frame) Try to use storage access API and read first-party data. +// Step 7 (sub-sub-frame) Send "HasAccess for localStorage" message to top-frame. +// Step 8 (top-frame) Receive "HasAccess for localStorage" message and cleanup. + +async_test(t => { + // Step 1 + window.addEventListener("message", t.step_func(e => { + // Step 8 + assert_equals(e.data, "HasAccess for localStorage", "Storage Access API should be accessible and return first-party data"); + t.done(); + })); + + // Step 2 + const id = Date.now(); + window.localStorage.setItem("test", id); + + // Step 3 + let iframe = document.createElement("iframe"); + iframe.src = "https://{{hosts[alt][]}}:{{ports[https][0]}}/storage-access-api/resources/storage-access-beyond-cookies-iframe.sub.html?type=localStorage&id="+id; + document.body.appendChild(iframe); +}, "Verify StorageAccessAPIBeyondCookies for Local Storage"); diff --git a/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.locks.tentative.sub.https.window.js b/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.locks.tentative.sub.https.window.js new file mode 100644 index 00000000000..83aa28c018e --- /dev/null +++ b/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.locks.tentative.sub.https.window.js @@ -0,0 +1,34 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (top-frame) Set up listener for "HasAccess" message. +// Step 2 (top-frame) Secure first-party web lock. +// Step 3 (top-frame) Embed an iframe that's cross-site with top-frame. +// Step 4 (sub-frame) Try to use storage access API and read first-party data. +// Step 5 (sub-frame) Embed an iframe that's same-origin with top-frame. +// Step 6 (sub-sub-frame) Try to use storage access API and read first-party data. +// Step 7 (sub-sub-frame) Send "HasAccess for locks" message to top-frame. +// Step 8 (top-frame) Receive "HasAccess for locks" message and cleanup. + +async_test(t => { + // Step 1 + window.addEventListener("message", t.step_func(e => { + // Step 8 + assert_equals(e.data, "HasAccess for locks", "Storage Access API should be accessible and return first-party data"); + t.done(); + })); + + // Step 2 + const id = Date.now(); + window.navigator.locks.request(id, async () => { + // Step 3 + let iframe = document.createElement("iframe"); + iframe.src = "https://{{hosts[alt][]}}:{{ports[https][0]}}/storage-access-api/resources/storage-access-beyond-cookies-iframe.sub.html?type=locks&id="+id; + document.body.appendChild(iframe); + // We need to sleep so this locks stays engaged until the test succeeds or times out. + await new Promise(r => setTimeout(r, 30000)) + }).catch (() => {/*We expect this lock to be stolen if the test runs correctly.*/}); +}, "Verify StorageAccessAPIBeyondCookies for Web Locks"); diff --git a/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.sessionStorage.tentative.sub.https.window.js b/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.sessionStorage.tentative.sub.https.window.js new file mode 100644 index 00000000000..2e504851c22 --- /dev/null +++ b/tests/wpt/tests/storage-access-api/storage-access-beyond-cookies.sessionStorage.tentative.sub.https.window.js @@ -0,0 +1,32 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +// Here's the set-up for this test: +// Step 1 (top-frame) Set up listener for "HasAccess" message. +// Step 2 (top-frame) Add data to first-party session storage. +// Step 3 (top-frame) Embed an iframe that's cross-site with top-frame. +// Step 4 (sub-frame) Try to use storage access API and read first-party data. +// Step 5 (sub-frame) Embed an iframe that's same-origin with top-frame. +// Step 6 (sub-sub-frame) Try to use storage access API and read first-party data. +// Step 7 (sub-sub-frame) Send "HasAccess for sessionStorage" message to top-frame. +// Step 8 (top-frame) Receive "HasAccess for sessionStorage" message and cleanup. + +async_test(t => { + // Step 1 + window.addEventListener("message", t.step_func(e => { + // Step 8 + assert_equals(e.data, "HasAccess for sessionStorage", "Storage Access API should be accessible and return first-party data"); + t.done(); + })); + + // Step 2 + const id = Date.now(); + window.sessionStorage.setItem("test", id); + + // Step 3 + let iframe = document.createElement("iframe"); + iframe.src = "https://{{hosts[alt][]}}:{{ports[https][0]}}/storage-access-api/resources/storage-access-beyond-cookies-iframe.sub.html?type=sessionStorage&id=" + id; + document.body.appendChild(iframe); +}, "Verify StorageAccessAPIBeyondCookies for Session Storage"); diff --git a/tests/wpt/tests/storage/estimate-indexeddb.https.any.js b/tests/wpt/tests/storage/estimate-indexeddb.https.any.js index f0b82b9fa09..6577b021ad5 100644 --- a/tests/wpt/tests/storage/estimate-indexeddb.https.any.js +++ b/tests/wpt/tests/storage/estimate-indexeddb.https.any.js @@ -1,21 +1,8 @@ // META: title=StorageManager: estimate() for indexeddb // META: script=/storage/buckets/resources/util.js -test(t => { - assert_true('estimate' in navigator.storage); - assert_equals(typeof navigator.storage.estimate, 'function'); - assert_true(navigator.storage.estimate() instanceof Promise); -}, 'estimate() method exists and returns a Promise'); - -promise_test(async t => { - const estimate = await navigator.storage.estimate(); - assert_equals(typeof estimate, 'object'); - assert_true('usage' in estimate); - assert_equals(typeof estimate.usage, 'number'); - assert_true('quota' in estimate); - assert_equals(typeof estimate.quota, 'number'); -}, 'estimate() resolves to dictionary with members'); - +// Technically, this verifies unspecced behavior. See +// https://github.com/whatwg/storage/issues/110 for defining this behavior. promise_test(async t => { const arraySize = 1e6; const objectStoreName = "storageManager"; diff --git a/tests/wpt/tests/storage/storagemanager-estimate.https.any.js b/tests/wpt/tests/storage/storagemanager-estimate.https.any.js index c2f5c569dc5..3b6f4d8edc4 100644 --- a/tests/wpt/tests/storage/storagemanager-estimate.https.any.js +++ b/tests/wpt/tests/storage/storagemanager-estimate.https.any.js @@ -1,60 +1,16 @@ // META: title=StorageManager: estimate() -test(function(t) { - assert_true(navigator.storage.estimate() instanceof Promise); -}, 'estimate() method returns a Promise'); +test(t => { + assert_true('estimate' in navigator.storage); + assert_equals(typeof navigator.storage.estimate, 'function'); + assert_true(navigator.storage.estimate() instanceof Promise); +}, 'estimate() method exists and returns a Promise'); -promise_test(function(t) { - return navigator.storage.estimate().then(function(result) { - assert_equals(typeof result, 'object'); - assert_true('usage' in result); - assert_equals(typeof result.usage, 'number'); - assert_true('quota' in result); - assert_equals(typeof result.quota, 'number'); - }); +promise_test(async t => { + const result = await navigator.storage.estimate(); + assert_equals(typeof result, 'object'); + assert_true('usage' in result); + assert_equals(typeof result.usage, 'number'); + assert_true('quota' in result); + assert_equals(typeof result.quota, 'number'); }, 'estimate() resolves to dictionary with members'); - -promise_test(function(t) { - const large_value = new Uint8Array(1e6); - const dbname = `db-${location}-${t.name}`; - let db, before, after; - - indexedDB.deleteDatabase(dbname); - return new Promise((resolve, reject) => { - const open = indexedDB.open(dbname); - open.onerror = () => { reject(open.error); }; - open.onupgradeneeded = () => { - const connection = open.result; - connection.createObjectStore('store'); - }; - open.onsuccess = () => { - const connection = open.result; - t.add_cleanup(() => { - connection.close(); - indexedDB.deleteDatabase(dbname); - }); - resolve(connection); - }; - }) - .then(connection => { - db = connection; - return navigator.storage.estimate(); - }) - .then(estimate => { - before = estimate.usage; - return new Promise((resolve, reject) => { - const tx = db.transaction('store', 'readwrite'); - tx.objectStore('store').put(large_value, 'key'); - tx.onabort = () => { reject(tx.error); }; - tx.oncomplete = () => { resolve(); }; - }); - }) - .then(() => { - return navigator.storage.estimate(); - }) - .then(estimate => { - after = estimate.usage; - assert_greater_than(after, before, - 'estimated usage should increase'); - }); -}, 'estimate() shows usage increase after 1MB IndexedDB record is stored'); diff --git a/tests/wpt/tests/svg/extensibility/foreignObject/masked.html b/tests/wpt/tests/svg/extensibility/foreignObject/masked.html index 1c7a332d7f9..a4ca2fd8521 100644 --- a/tests/wpt/tests/svg/extensibility/foreignObject/masked.html +++ b/tests/wpt/tests/svg/extensibility/foreignObject/masked.html @@ -3,7 +3,7 @@ <link rel="match" href="masked-ref.html"> <link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org"> <link rel="help" href="https://svgwg.org/svg2-draft/single-page.html#embedded-ForeignObjectElement"/> -<meta name="fuzzy" content="maxDifference=0-37; totalPixels=0-124"> +<meta name="fuzzy" content="maxDifference=0-138; totalPixels=0-124"> <svg style="display: block"> <foreignObject x="0" y="0" width="32" height="32" mask="url(#circle)"> <div style="width: 32px; height: 32px; background: green"></div> diff --git a/tests/wpt/tests/svg/pservers/scripted/pattern-transform-clear.svg b/tests/wpt/tests/svg/pservers/scripted/pattern-transform-clear.svg new file mode 100644 index 00000000000..6800fd8d20d --- /dev/null +++ b/tests/wpt/tests/svg/pservers/scripted/pattern-transform-clear.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"> + <title>SVG Paint Servers: Clear should cause patternTransform to be ignored.</title> + <metadata> + <h:link rel="help" href="https://svgwg.org/svg2-draft/pservers.html#PatternElementPatternTransformAttribute"/> + <h:link rel="match" href="../reftests/reference/green-100x100.svg"/> + </metadata> + <pattern id="p1" patternTransform="scale(2)"/> + <pattern id="p" href="#p1" viewBox="0 0 50 50" patternTransform="scale(1)" width="100%" height="100%"> + <rect fill="red" width="50" height="50"/> + <rect fill="green" width="25" height="25"/> + </pattern> + <rect fill="url(#p)" width="100" height="100"/> + <script><![CDATA[ + document.getElementById("p").patternTransform.baseVal.clear(); + ]]></script> +</svg> diff --git a/tests/wpt/tests/tools/ci/ci_wptrunner_infrastructure.sh b/tests/wpt/tests/tools/ci/ci_wptrunner_infrastructure.sh index ebe7870afa8..fc6907f8de6 100755 --- a/tests/wpt/tests/tools/ci/ci_wptrunner_infrastructure.sh +++ b/tests/wpt/tests/tools/ci/ci_wptrunner_infrastructure.sh @@ -1,19 +1,19 @@ #!/bin/bash set -ex -SCRIPT_DIR=$(cd $(dirname "$0") && pwd -P) +REL_DIR_NAME=$(dirname "$0") +SCRIPT_DIR=$(cd "$REL_DIR_NAME" && pwd -P) WPT_ROOT=$SCRIPT_DIR/../.. -cd $WPT_ROOT +cd "$WPT_ROOT" run_infra_test() { - TERM=dumb ./wpt run --log-mach - --yes --manifest ~/meta/MANIFEST.json --metadata infrastructure/metadata/ --install-fonts --install-webdriver --log-wptreport="/home/test/artifacts/wptreport-$1.json" $2 $1 infrastructure/ + ./tools/ci/taskcluster-run.py "$1" "$2" -- --metadata=infrastructure/metadata/ --log-wptreport="../artifacts/wptreport-$1.json" --include=infrastructure/ } main() { - ./wpt manifest --rebuild -p ~/meta/MANIFEST.json - run_infra_test "chrome" "--binary=$(which google-chrome-unstable) --enable-swiftshader --channel dev $1" - run_infra_test "firefox" "--binary=~/build/firefox/firefox $1" - run_infra_test "firefox_android" "--install-browser --logcat-dir=/home/test/artifacts/ $1" + run_infra_test "chrome" "dev" + run_infra_test "firefox" "nightly" + run_infra_test "firefox_android" "nightly" } -main $1 +main diff --git a/tests/wpt/tests/tools/ci/taskcluster-run.py b/tests/wpt/tests/tools/ci/taskcluster-run.py index c801f61e8e8..2917d8f3402 100755 --- a/tests/wpt/tests/tools/ci/taskcluster-run.py +++ b/tests/wpt/tests/tools/ci/taskcluster-run.py @@ -10,13 +10,15 @@ import subprocess import sys -def get_browser_args(product, channel): +def get_browser_args(product, channel, artifact_path): if product == "firefox": local_binary = os.path.expanduser(os.path.join("~", "build", "firefox", "firefox")) if os.path.exists(local_binary): return ["--binary=%s" % local_binary] print("WARNING: Local firefox binary not found") return ["--install-browser", "--install-webdriver"] + if product == "firefox_android": + return ["--install-browser", "--install-webdriver", "--logcat-dir", artifact_path] if product == "servo": return ["--install-browser", "--processes=12"] if product == "chrome" or product == "chromium": @@ -52,7 +54,7 @@ def gzip_file(filename, delete_original=True): os.unlink(filename) -def main(product, channel, commit_range, wpt_args): +def main(product, channel, commit_range, artifact_path, wpt_args): """Invoke the `wpt run` command according to the needs of the Taskcluster continuous integration service.""" @@ -84,16 +86,18 @@ def main(product, channel, commit_range, wpt_args): "--no-headless", "--verify-log-full" ] - wpt_args += get_browser_args(product, channel) + wpt_args += get_browser_args(product, channel, artifact_path) # Hack to run servo with one process only for wdspec if product == "servo" and "--test-type=wdspec" in wpt_args: wpt_args = [item for item in wpt_args if not item.startswith("--processes")] - command = ["python3", "./wpt", "run"] + wpt_args + [product] + wpt_args.append(product) + + command = ["python3", "./wpt", "run"] + wpt_args logger.info("Executing command: %s" % " ".join(command)) - with open("/home/test/artifacts/checkrun.md", "a") as f: + with open(os.path.join(artifact_path, "checkrun.md"), "a") as f: f.write("\n**WPT Command:** `%s`\n\n" % " ".join(command)) retcode = subprocess.call(command, env=dict(os.environ, TERM="dumb")) @@ -114,6 +118,9 @@ if __name__ == "__main__": help="""Git commit range. If specified, this will be supplied to the `wpt tests-affected` command to determine the list of test to execute""") + parser.add_argument("--artifact-path", action="store", + default="/home/test/artifacts/", + help="Path to store output files") parser.add_argument("product", action="store", help="Browser to run tests in") parser.add_argument("channel", action="store", diff --git a/tests/wpt/tests/tools/ci/tc/tasks/test.yml b/tests/wpt/tests/tools/ci/tc/tasks/test.yml index 598a3395def..7c1a4df994c 100644 --- a/tests/wpt/tests/tools/ci/tc/tasks/test.yml +++ b/tests/wpt/tests/tools/ci/tc/tasks/test.yml @@ -296,12 +296,6 @@ tasks: use: - trigger-daily - trigger-push - - vars: - browser: firefox_android - channel: nightly - use: - - trigger-daily - - trigger-push do: - ${vars.browser}-${vars.channel}-${vars.suite}: use: diff --git a/tests/wpt/tests/tools/ci/tc/tests/test_valid.py b/tests/wpt/tests/tools/ci/tc/tests/test_valid.py index 1d50115f91d..36c2d0a986c 100644 --- a/tests/wpt/tests/tools/ci/tc/tests/test_valid.py +++ b/tests/wpt/tests/tools/ci/tc/tests/test_valid.py @@ -325,8 +325,7 @@ def test_verify_payload(): 'wpt-firefox_android-nightly-crashtest-1', 'wpt-firefox-stable-print-reftest-1', 'wpt-chromium-nightly-print-reftest-1', - 'wpt-chrome-stable-print-reftest-1', - 'wpt-firefox_android-nightly-print-reftest-1']) + 'wpt-chrome-stable-print-reftest-1']) ]) def test_schedule_tasks(event_path, is_pr, files_changed, expected): with mock.patch("tools.ci.tc.decision.get_fetch_rev", return_value=(None, None, None)): diff --git a/tests/wpt/tests/tools/runner/update_manifest.py b/tests/wpt/tests/tools/runner/update_manifest.py index a7f72b35b33..58b9ac4d84b 100644 --- a/tests/wpt/tests/tools/runner/update_manifest.py +++ b/tests/wpt/tests/tools/runner/update_manifest.py @@ -1,16 +1,18 @@ # mypy: ignore-errors -import imp import json import os +from tools.wpt.utils import load_source + here = os.path.dirname(__file__) -localpaths = imp.load_source("localpaths", os.path.abspath(os.path.join(here, os.pardir, "localpaths.py"))) +localpaths = load_source("localpaths", os.path.abspath(os.path.join(here, os.pardir, "localpaths.py"))) root = localpaths.repo_root from manifest import manifest + def main(request, response): path = os.path.join(root, "MANIFEST.json") diff --git a/tests/wpt/tests/tools/webdriver/webdriver/__init__.py b/tests/wpt/tests/tools/webdriver/webdriver/__init__.py index a81751407e7..dfd264f8b29 100644 --- a/tests/wpt/tests/tools/webdriver/webdriver/__init__.py +++ b/tests/wpt/tests/tools/webdriver/webdriver/__init__.py @@ -2,13 +2,14 @@ from .client import ( Cookies, - Element, Find, - Frame, Session, ShadowRoot, Timeouts, - Window) + WebElement, + WebFrame, + WebWindow, +) from .error import ( ElementNotSelectableException, ElementNotVisibleException, diff --git a/tests/wpt/tests/tools/webdriver/webdriver/client.py b/tests/wpt/tests/tools/webdriver/webdriver/client.py index f33fc34dac9..e41df7f5764 100644 --- a/tests/wpt/tests/tools/webdriver/webdriver/client.py +++ b/tests/wpt/tests/tools/webdriver/webdriver/client.py @@ -295,9 +295,7 @@ class Actions: return ActionSequence(self.session, *args, **kwargs) -class Window: - identifier = "window-fcc6-11e5-b4f8-330a88ab9d7f" - +class BrowserWindow: def __init__(self, session): self.session = session @@ -372,59 +370,6 @@ class Window: def fullscreen(self): return self.session.send_session_command("POST", "window/fullscreen") - @classmethod - def from_json(cls, json, session): - uuid = json[Window.identifier] - return cls(uuid, session) - - -class Frame: - identifier = "frame-075b-4da1-b6ba-e579c2d3230a" - - def __init__(self, session): - self.session = session - - @classmethod - def from_json(cls, json, session): - uuid = json[Frame.identifier] - return cls(uuid, session) - - -class ShadowRoot: - identifier = "shadow-6066-11e4-a52e-4f735466cecf" - - def __init__(self, session, id): - """ - Construct a new shadow root representation. - - :param id: Shadow root UUID which must be unique across - all browsing contexts. - :param session: Current ``webdriver.Session``. - """ - self.id = id - self.session = session - - @classmethod - def from_json(cls, json, session): - uuid = json[ShadowRoot.identifier] - return cls(session, uuid) - - def send_shadow_command(self, method, uri, body=None): - url = f"shadow/{self.id}/{uri}" - return self.session.send_session_command(method, url, body) - - @command - def find_element(self, strategy, selector): - body = {"using": strategy, - "value": selector} - return self.send_shadow_command("POST", "element", body) - - @command - def find_elements(self, strategy, selector): - body = {"using": strategy, - "value": selector} - return self.send_shadow_command("POST", "elements", body) - class Find: def __init__(self, session): @@ -512,7 +457,7 @@ class Session: self.extension_cls = extension self.timeouts = Timeouts(self) - self.window = Window(self) + self.window = BrowserWindow(self) self.find = Find(self) self.alert = UserPrompt(self) self.actions = Actions(self) @@ -795,7 +740,44 @@ class Session: def screenshot(self): return self.send_session_command("GET", "screenshot") -class Element: + +class ShadowRoot: + identifier = "shadow-6066-11e4-a52e-4f735466cecf" + + def __init__(self, session, id): + """ + Construct a new shadow root representation. + + :param id: Shadow root UUID which must be unique across + all browsing contexts. + :param session: Current ``webdriver.Session``. + """ + self.id = id + self.session = session + + @classmethod + def from_json(cls, json, session): + uuid = json[ShadowRoot.identifier] + return cls(session, uuid) + + def send_shadow_command(self, method, uri, body=None): + url = f"shadow/{self.id}/{uri}" + return self.session.send_session_command(method, url, body) + + @command + def find_element(self, strategy, selector): + body = {"using": strategy, + "value": selector} + return self.send_shadow_command("POST", "element", body) + + @command + def find_elements(self, strategy, selector): + body = {"using": strategy, + "value": selector} + return self.send_shadow_command("POST", "elements", body) + + +class WebElement: """ Representation of a web element. @@ -818,12 +800,12 @@ class Element: return "<%s %s>" % (self.__class__.__name__, self.id) def __eq__(self, other): - return (isinstance(other, Element) and self.id == other.id and + return (isinstance(other, WebElement) and self.id == other.id and self.session == other.session) @classmethod def from_json(cls, json, session): - uuid = json[Element.identifier] + uuid = json[WebElement.identifier] return cls(session, uuid) def send_element_command(self, method, uri, body=None): @@ -902,3 +884,42 @@ class Element: @command def property(self, name): return self.send_element_command("GET", "property/%s" % name) + +class WebFrame: + identifier = "frame-075b-4da1-b6ba-e579c2d3230a" + + def __init__(self, session, id): + self.id = id + self.session = session + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, self.id) + + def __eq__(self, other): + return (isinstance(other, WebFrame) and self.id == other.id and + self.session == other.session) + + @classmethod + def from_json(cls, json, session): + uuid = json[WebFrame.identifier] + return cls(session, uuid) + + +class WebWindow: + identifier = "window-fcc6-11e5-b4f8-330a88ab9d7f" + + def __init__(self, session, id): + self.id = id + self.session = session + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, self.id) + + def __eq__(self, other): + return (isinstance(other, WebWindow) and self.id == other.id and + self.session == other.session) + + @classmethod + def from_json(cls, json, session): + uuid = json[WebWindow.identifier] + return cls(session, uuid) diff --git a/tests/wpt/tests/tools/webdriver/webdriver/protocol.py b/tests/wpt/tests/tools/webdriver/webdriver/protocol.py index 1972c3fce21..d6c89af22be 100644 --- a/tests/wpt/tests/tools/webdriver/webdriver/protocol.py +++ b/tests/wpt/tests/tools/webdriver/webdriver/protocol.py @@ -16,14 +16,14 @@ class Encoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, (list, tuple)): return [self.default(x) for x in obj] - elif isinstance(obj, webdriver.Element): - return {webdriver.Element.identifier: obj.id} - elif isinstance(obj, webdriver.Frame): - return {webdriver.Frame.identifier: obj.id} - elif isinstance(obj, webdriver.Window): - return {webdriver.Frame.identifier: obj.id} + elif isinstance(obj, webdriver.WebElement): + return {webdriver.WebElement.identifier: obj.id} + elif isinstance(obj, webdriver.WebFrame): + return {webdriver.WebFrame.identifier: obj.id} elif isinstance(obj, webdriver.ShadowRoot): return {webdriver.ShadowRoot.identifier: obj.id} + elif isinstance(obj, webdriver.WebWindow): + return {webdriver.WebWindow.identifier: obj.id} return super().default(obj) @@ -36,14 +36,14 @@ class Decoder(json.JSONDecoder): def object_hook(self, payload): if isinstance(payload, (list, tuple)): return [self.object_hook(x) for x in payload] - elif isinstance(payload, dict) and webdriver.Element.identifier in payload: - return webdriver.Element.from_json(payload, self.session) - elif isinstance(payload, dict) and webdriver.Frame.identifier in payload: - return webdriver.Frame.from_json(payload, self.session) - elif isinstance(payload, dict) and webdriver.Window.identifier in payload: - return webdriver.Window.from_json(payload, self.session) + elif isinstance(payload, dict) and webdriver.WebElement.identifier in payload: + return webdriver.WebElement.from_json(payload, self.session) + elif isinstance(payload, dict) and webdriver.WebFrame.identifier in payload: + return webdriver.WebFrame.from_json(payload, self.session) elif isinstance(payload, dict) and webdriver.ShadowRoot.identifier in payload: return webdriver.ShadowRoot.from_json(payload, self.session) + elif isinstance(payload, dict) and webdriver.WebWindow.identifier in payload: + return webdriver.WebWindow.from_json(payload, self.session) elif isinstance(payload, dict): return {k: self.object_hook(v) for k, v in payload.items()} return payload diff --git a/tests/wpt/tests/tools/webdriver/webdriver/transport.py b/tests/wpt/tests/tools/webdriver/webdriver/transport.py index e1e16bdebad..ca1ff74ef96 100644 --- a/tests/wpt/tests/tools/webdriver/webdriver/transport.py +++ b/tests/wpt/tests/tools/webdriver/webdriver/transport.py @@ -102,9 +102,9 @@ class HTTPWireProtocol: Transports messages (commands and responses) over the WebDriver wire protocol. - Complex objects, such as ``webdriver.Element``, ``webdriver.Frame``, - and ``webdriver.Window`` are by default not marshaled to enable - use of `session.transport.send` in WPT tests:: + Complex objects, such as ``webdriver.ShadowRoot``, ``webdriver.WebElement``, + ``webdriver.WebFrame``, and ``webdriver.WebWindow`` are by default not + marshaled to enable use of `session.transport.send` in WPT tests:: session = webdriver.Session("127.0.0.1", 4444) response = transport.send("GET", "element/active", None) @@ -180,17 +180,17 @@ class HTTPWireProtocol: """ Send a command to the remote. - The request `body` must be JSON serialisable unless a + The request `body` must be JSON serializable unless a custom `encoder` has been provided. This means complex - objects such as ``webdriver.Element``, ``webdriver.Frame``, - and `webdriver.Window`` are not automatically made - into JSON. This behaviour is, however, provided by + objects such as ``webdriver.ShadowRoot``, ``webdriver.WebElement``, + ``webdriver.WebFrame``, and `webdriver.Window`` are not automatically + made into JSON. This behavior is, however, provided by ``webdriver.protocol.Encoder``, should you want it. Similarly, the response body is returned au natural as plain JSON unless a `decoder` that converts web element references to ``webdriver.Element`` is provided. - Use ``webdriver.protocol.Decoder`` to achieve this behaviour. + Use ``webdriver.protocol.Decoder`` to achieve this behavior. The client will attempt to use persistent HTTP connections. @@ -211,7 +211,7 @@ class HTTPWireProtocol: describing the HTTP response received from the remote end. :raises ValueError: If `body` or the response body are not - JSON serialisable. + JSON serializable. """ if body is None and method == "POST": body = {} diff --git a/tests/wpt/tests/tools/wpt/utils.py b/tests/wpt/tests/tools/wpt/utils.py index b015b95e1ae..5899dc3f3a9 100644 --- a/tests/wpt/tests/tools/wpt/utils.py +++ b/tests/wpt/tests/tools/wpt/utils.py @@ -3,10 +3,10 @@ import errno import logging import os -import sys import shutil import stat import subprocess +import sys import tarfile import time import zipfile @@ -166,3 +166,16 @@ def sha256sum(file_path): for chunk in iter(lambda: f.read(4096), b''): hash.update(chunk) return hash.hexdigest() + + +# see https://docs.python.org/3/whatsnew/3.12.html#imp +def load_source(modname, filename): + import importlib.machinery + import importlib.util + + loader = importlib.machinery.SourceFileLoader(modname, filename) + spec = importlib.util.spec_from_file_location(modname, filename, loader=loader) + module = importlib.util.module_from_spec(spec) + sys.modules[module.__name__] = module + loader.exec_module(module) + return module diff --git a/tests/wpt/tests/tools/wptrunner/requirements.txt b/tests/wpt/tests/tools/wptrunner/requirements.txt index 1c4316a9f86..93c17bf3bff 100644 --- a/tests/wpt/tests/tools/wptrunner/requirements.txt +++ b/tests/wpt/tests/tools/wptrunner/requirements.txt @@ -7,4 +7,4 @@ packaging==23.1 pillow==9.5.0 requests==2.31.0 six==1.16.0 -urllib3==2.0.6 +urllib3==2.0.7 diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/content_shell.py b/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/content_shell.py index 14956eeb786..23f4e99da62 100644 --- a/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/content_shell.py +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/browsers/content_shell.py @@ -5,6 +5,7 @@ import os import subprocess from multiprocessing import Queue, Event from threading import Thread +from urllib.parse import urljoin from . import chrome_spki_certs from .base import ( @@ -16,6 +17,7 @@ from .base import ( from .base import get_timeout_multiplier # noqa: F401 from .chrome import debug_args from ..executors import executor_kwargs as base_executor_kwargs +from ..executors.base import server_url from ..executors.executorcontentshell import ( # noqa: F401 ContentShellCrashtestExecutor, ContentShellPrintRefTestExecutor, @@ -82,7 +84,8 @@ def browser_kwargs(logger, test_type, run_info_data, config, subsuite, **kwargs) return {"binary": kwargs["binary"], "binary_args": args, - "debug_info": kwargs["debug_info"]} + "debug_info": kwargs["debug_info"], + "pac_origin": server_url(config, "http")} def executor_kwargs(logger, test_type, test_environment, run_info_data, @@ -127,21 +130,27 @@ class ContentShellBrowser(Browser): termination_timeout: float = 3 def __init__(self, logger, binary="content_shell", binary_args=None, - debug_info=None, **kwargs): + debug_info=None, pac_origin=None, **kwargs): super().__init__(logger) - debug_cmd_prefix, browser_cmd = browser_command(binary, binary_args or [], debug_info) - self._args = [*debug_cmd_prefix, *browser_cmd] + self._debug_cmd_prefix, self._browser_cmd = browser_command( + binary, binary_args or [], debug_info) self._output_handler = None self._proc = None - - def start(self, group_metadata, **kwargs): - self.logger.debug("Starting content shell: %s..." % self._args[0]) - self._output_handler = OutputHandler(self.logger, self._args) + self._pac_origin = pac_origin + self._pac = None + + def start(self, group_metadata, **settings): + browser_cmd, pac = list(self._browser_cmd), settings.get("pac") + if pac: + browser_cmd.insert(1, f"--proxy-pac-url={pac}") + self.logger.debug(f"Starting content shell: {browser_cmd[0]}...") + args = [*self._debug_cmd_prefix, *browser_cmd] + self._output_handler = OutputHandler(self.logger, args) if os.name == "posix": close_fds, preexec_fn = True, lambda: os.setpgid(0, 0) else: close_fds, preexec_fn = False, None - self._proc = subprocess.Popen(self._args, + self._proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -169,7 +178,7 @@ class ContentShellBrowser(Browser): # Content shell is likely still in the process of initializing. The actual waiting # for the startup to finish is done in the ContentShellProtocol. self.logger.debug("Content shell has been started.") - self._output_handler.start(group_metadata=group_metadata, **kwargs) + self._output_handler.start(group_metadata=group_metadata, **settings) def stop(self, force=False): self.logger.debug("Stopping content shell...") @@ -239,6 +248,13 @@ class ContentShellBrowser(Browser): def check_crash(self, process, test): return not self.is_alive() + def settings(self, test): + pac_path = test.environment.get("pac") + if self._pac_origin and pac_path: + self._pac = urljoin(self._pac_origin, pac_path) + return {"pac": self._pac} + return {} + def _create_reader_thread(self, name, stream, queue, prefix=b""): """This creates (and starts) a background thread which reads lines from `stream` and puts them into `queue` until `stream` reports EOF. diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/executors/base.py b/tests/wpt/tests/tools/wptrunner/wptrunner/executors/base.py index 1e66e60890e..e89b57b57ac 100644 --- a/tests/wpt/tests/tools/wptrunner/wptrunner/executors/base.py +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/executors/base.py @@ -64,6 +64,16 @@ def strip_server(url): return urlunsplit(url_parts) +def server_url(server_config, protocol, subdomain=False): + scheme = "https" if protocol == "h2" else protocol + host = server_config["browser_host"] + if subdomain: + # The only supported subdomain filename flag is "www". + host = "{subdomain}.{host}".format(subdomain="www", host=host) + return "{scheme}://{host}:{port}".format(scheme=scheme, host=host, + port=server_config["ports"][protocol][0]) + + class TestharnessResultConverter: harness_codes = {0: "OK", 1: "ERROR", @@ -317,13 +327,7 @@ class TestExecutor: self.runner.send_message("test_ended", test, result) def server_url(self, protocol, subdomain=False): - scheme = "https" if protocol == "h2" else protocol - host = self.server_config["browser_host"] - if subdomain: - # The only supported subdomain filename flag is "www". - host = "{subdomain}.{host}".format(subdomain="www", host=host) - return "{scheme}://{host}:{port}".format(scheme=scheme, host=host, - port=self.server_config["ports"][protocol][0]) + return server_url(self.server_config, protocol, subdomain) def test_url(self, test): return urljoin(self.server_url(test.environment["protocol"], diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/stability.py b/tests/wpt/tests/tools/wptrunner/wptrunner/stability.py index 9ac6249c44c..029b237f988 100644 --- a/tests/wpt/tests/tools/wptrunner/wptrunner/stability.py +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/stability.py @@ -2,7 +2,6 @@ import copy import functools -import imp import io import os from collections import OrderedDict, defaultdict @@ -10,16 +9,17 @@ from datetime import datetime from mozlog import reader from mozlog.formatters import JSONFormatter -from mozlog.handlers import BaseHandler, StreamHandler, LogLevelFilter +from mozlog.handlers import BaseHandler, LogLevelFilter, StreamHandler + +from tools.wpt.utils import load_source from . import wptrunner here = os.path.dirname(__file__) -localpaths = imp.load_source("localpaths", os.path.abspath(os.path.join(here, os.pardir, os.pardir, "localpaths.py"))) +localpaths = load_source("localpaths", os.path.abspath(os.path.join(here, os.pardir, os.pardir, "localpaths.py"))) # type: ignore from ci.tc.github_checks_output import get_gh_checks_outputter # type: ignore from wpt.markdown import markdown_adjust, table # type: ignore - # If a test takes more than (FLAKY_THRESHOLD*timeout) and does not consistently # time out, it is considered slow (potentially flaky). FLAKY_THRESHOLD = 0.8 diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/testrunner.py b/tests/wpt/tests/tools/wptrunner/wptrunner/testrunner.py index b84f1a52be3..a4f759c42a7 100644 --- a/tests/wpt/tests/tools/wptrunner/wptrunner/testrunner.py +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/testrunner.py @@ -701,7 +701,7 @@ class TestRunnerManager(threading.Thread): # change result to unexpected if expected_fail_message does not # match expected_fail_message = test.expected_fail_message(result.name) - if expected_fail_message is not None and result.message != expected_fail_message: + if expected_fail_message is not None and result.message.strip() != expected_fail_message: is_unexpected = True if is_unexpected: diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/tests/test_wptrunner.py b/tests/wpt/tests/tools/wptrunner/wptrunner/tests/test_wptrunner.py new file mode 100644 index 00000000000..3c9a0bc1fd4 --- /dev/null +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/tests/test_wptrunner.py @@ -0,0 +1,79 @@ +from ..wptrunner import get_pause_after_test +from .test_testloader import Subsuite, TestFilter, TestLoader, WPTManifest + +def test_get_pause_after_test(): # type: ignore + manifest_json = { + "items": { + "testharness": { + "a": { + "foo.html": [ + "abcdef123456", + [None, {}], + ], + "bar.h2.html": [ + "uvwxyz987654", + [None, {}], + ], + } + }, + "reftest": { + "a": { + "reffoo.html": [ + "abcdef654321", + [None, [["/common/some-ref.html", "=="]], {}] + ], + } + } + }, + "url_base": "/", + "version": 8, + } + + kwargs = { + "pause_after_test": None, + "repeat_until_unexpected": False, + "headless": False, + "debug_test": False, + "repeat": 1, + "rerun": 1 + } + + manifest = WPTManifest.from_json("/", manifest_json) + test_manifests = {manifest: {"metadata_path": ""}} + + manifest_filters = [TestFilter(test_manifests, include=["/a/foo.html", "/a/reffoo.html"])] + + subsuites = {} + subsuites[""] = Subsuite("", config={}) + + # This has two testharness tests, so shouldn't set pause_after_test + loader = TestLoader(test_manifests, ["testharness"], None, subsuites) + + assert get_pause_after_test(loader, **kwargs) is False + + # This has one testharness test, so should set pause_after_test + loader = TestLoader(test_manifests, ["testharness"], None, subsuites, + manifest_filters=manifest_filters) + + assert get_pause_after_test(loader, **kwargs) is True + + # This has one testharness test, and one reftest so shouldn't set pause_after_test + loader = TestLoader(test_manifests, ["testharness", "reftest"], None, subsuites, + manifest_filters=manifest_filters) + + assert get_pause_after_test(loader, **kwargs) is False + + # This has one reftest so shouldn't set pause_after_test + loader = TestLoader(test_manifests, ["reftest"], None, subsuites) + + assert get_pause_after_test(loader, **kwargs) is False + + multi_subsuites = {} + multi_subsuites[""] = Subsuite("", config={}) + multi_subsuites["extra"] = Subsuite("extra", config={}, include=["/a/foo.html"]) + + # This has one testharness test per subsuite, so shouldn't set pause_after_test + loader = TestLoader(test_manifests, ["testharness"], None, multi_subsuites, + manifest_filters=manifest_filters) + print(loader.tests) + assert get_pause_after_test(loader, **kwargs) is False diff --git a/tests/wpt/tests/tools/wptrunner/wptrunner/wptrunner.py b/tests/wpt/tests/tools/wptrunner/wptrunner/wptrunner.py index a4ad268dce1..b9e5190105c 100644 --- a/tests/wpt/tests/tools/wptrunner/wptrunner/wptrunner.py +++ b/tests/wpt/tests/tools/wptrunner/wptrunner/wptrunner.py @@ -159,20 +159,30 @@ def list_tests(test_paths, product, **kwargs): def get_pause_after_test(test_loader, **kwargs): - if kwargs["pause_after_test"] is None: - if kwargs["repeat_until_unexpected"]: - return False - if kwargs["headless"]: - return False - if kwargs["debug_test"]: - return True - tests = test_loader.tests - is_single_testharness = (sum(len(item) for item in tests.values()) == 1 and - len(tests.get("testharness", [])) == 1) - if kwargs["repeat"] == 1 and kwargs["rerun"] == 1 and is_single_testharness: - return True + if kwargs["pause_after_test"] is not None: + return kwargs["pause_after_test"] + if kwargs["repeat_until_unexpected"]: return False - return kwargs["pause_after_test"] + if kwargs["headless"]: + return False + if kwargs["debug_test"]: + return True + tests = test_loader.tests + is_single_testharness = True + testharness_count = 0 + for tests_by_type in tests.values(): + for test_type, tests in tests_by_type.items(): + if test_type != "testharness" and len(tests): + is_single_testharness = False + break + elif test_type == "testharness": + testharness_count += len(tests) + if testharness_count > 1: + is_single_testharness = False + break + return kwargs["repeat"] == 1 and kwargs["rerun"] == 1 and is_single_testharness + + def log_suite_start(tests_by_group, base_run_info, subsuites, run_by_dir): diff --git a/tests/wpt/tests/wai-aria/role/invalid-roles.html b/tests/wpt/tests/wai-aria/role/invalid-roles.html index e16fb677044..3f4255083e1 100644 --- a/tests/wpt/tests/wai-aria/role/invalid-roles.html +++ b/tests/wpt/tests/wai-aria/role/invalid-roles.html @@ -39,7 +39,7 @@ <nav role="​" data-testname="nav with zero-width space as role (should be treated as whitespace)" data-expectedrole="navigation" class="ex">x</nav> <nav role="⠀" data-testname="nav with braille space (10240) as role" data-expectedrole="navigation" class="ex">x</nav> <nav role="⠀" data-testname="nav with braille space (x2800) as role" data-expectedrole="navigation" class="ex">x</nav> -<nav role=" " data-testname="nav with non-breaking space (nbsp) as role" data-expectedrole="navigation" class="ex">x</nav> +<nav role=" " data-testname="nav with non-breaking space (nbsp) as role" data-expectedrole="navigation" class="ex">x</nav> <nav role="" data-testname="nav with standard space (nbsp) as role" data-expectedrole="navigation" class="ex">x</nav> <!-- Escaped whitespace tests with <span> (including line breaks, tabs, zero-width space, braille space, non-breaking space, standard space) --> @@ -49,7 +49,7 @@ <span role="​" data-testname="span with escaped zero-width space as role (should be treated as whitespace)" class="ex-generic">x</span> <span role="⠀" data-testname="span with escaped braille space (10240) as role" class="ex-generic">x</span> <span role="⠀" data-testname="span with escaped braille space (x2800) as role" class="ex-generic">x</span> -<span role=" " data-testname="span with escaped non-breaking space (nbsp) as role" class="ex-generic">x</span> +<span role=" " data-testname="span with escaped non-breaking space (nbsp) as role" class="ex-generic">x</span> <span role="" data-testname="span with escaped standard space (nbsp) as role" class="ex-generic">x</span> <!-- Unescaped whitespace tests with <span> (including line breaks, tabs, zero-width space, braille space, non-breaking space, standard space) --> diff --git a/tests/wpt/tests/wasm/jsapi/exception/basic.tentative.any.js b/tests/wpt/tests/wasm/jsapi/exception/basic.tentative.any.js index 869c64b6d30..cacce99d9cb 100644 --- a/tests/wpt/tests/wasm/jsapi/exception/basic.tentative.any.js +++ b/tests/wpt/tests/wasm/jsapi/exception/basic.tentative.any.js @@ -11,8 +11,7 @@ function assert_throws_wasm(fn, message) { } promise_test(async () => { - const kWasmAnyRef = 0x6f; - const kSig_v_r = makeSig([kWasmAnyRef], []); + const kSig_v_r = makeSig([kWasmExternRef], []); const builder = new WasmModuleBuilder(); const tagIndex = builder.addTag(kSig_v_r); builder.addFunction("throw_param", kSig_v_r) @@ -48,7 +47,7 @@ promise_test(async () => { const tagIndex = builder.addTag(kSig_v_a); builder.addFunction("throw_null", kSig_v_v) .addBody([ - kExprRefNull, kWasmAnyFunc, + kExprRefNull, kAnyFuncCode, kExprThrow, tagIndex, ]) .exportFunc(); @@ -82,7 +81,7 @@ promise_test(async () => { kExprCatch, tagIndex, kExprReturn, kExprEnd, - kExprRefNull, kWasmAnyRef, + kExprRefNull, kExternRefCode, ]) .exportFunc(); @@ -106,7 +105,7 @@ promise_test(async () => { kExprCatchAll, kExprRethrow, 0x00, kExprEnd, - kExprRefNull, kWasmAnyRef, + kExprRefNull, kExternRefCode, ]) .exportFunc(); diff --git a/tests/wpt/tests/wasm/jsapi/gc/casts.tentative.any.js b/tests/wpt/tests/wasm/jsapi/gc/casts.tentative.any.js new file mode 100644 index 00000000000..cce06224fd4 --- /dev/null +++ b/tests/wpt/tests/wasm/jsapi/gc/casts.tentative.any.js @@ -0,0 +1,332 @@ +// META: global=window,dedicatedworker,jsshell +// META: script=/wasm/jsapi/wasm-module-builder.js + +let exports = {}; +setup(() => { + const builder = new WasmModuleBuilder(); + const structIndex = builder.addStruct([makeField(kWasmI32, true)]); + const arrayIndex = builder.addArray(kWasmI32, true); + const structIndex2 = builder.addStruct([makeField(kWasmF32, true)]); + const arrayIndex2 = builder.addArray(kWasmF32, true); + const funcIndex = builder.addType({ params: [], results: [] }); + const funcIndex2 = builder.addType({ params: [], results: [kWasmI32] }); + + const argFunctions = [ + { name: "any", code: kWasmAnyRef }, + { name: "eq", code: kWasmEqRef }, + { name: "struct", code: kWasmStructRef }, + { name: "array", code: kWasmArrayRef }, + { name: "i31", code: kWasmI31Ref }, + { name: "func", code: kWasmFuncRef }, + { name: "extern", code: kWasmExternRef }, + { name: "none", code: kWasmNullRef }, + { name: "nofunc", code: kWasmNullFuncRef }, + { name: "noextern", code: kWasmNullExternRef }, + { name: "concreteStruct", code: structIndex }, + { name: "concreteArray", code: arrayIndex }, + { name: "concreteFunc", code: funcIndex }, + ]; + + for (const desc of argFunctions) { + builder + .addFunction(desc.name + "Arg", makeSig_v_x(wasmRefType(desc.code))) + .addBody([]) + .exportFunc(); + + builder + .addFunction(desc.name + "NullableArg", makeSig_v_x(wasmRefNullType(desc.code))) + .addBody([]) + .exportFunc(); + } + + builder + .addFunction("makeStruct", makeSig_r_v(wasmRefType(structIndex))) + .addBody([...wasmI32Const(42), + ...GCInstr(kExprStructNew), structIndex]) + .exportFunc(); + + builder + .addFunction("makeArray", makeSig_r_v(wasmRefType(arrayIndex))) + .addBody([...wasmI32Const(5), ...wasmI32Const(42), + ...GCInstr(kExprArrayNew), arrayIndex]) + .exportFunc(); + + builder + .addFunction("makeStruct2", makeSig_r_v(wasmRefType(structIndex2))) + .addBody([...wasmF32Const(42), + ...GCInstr(kExprStructNew), structIndex2]) + .exportFunc(); + + builder + .addFunction("makeArray2", makeSig_r_v(wasmRefType(arrayIndex2))) + .addBody([...wasmF32Const(42), ...wasmI32Const(5), + ...GCInstr(kExprArrayNew), arrayIndex2]) + .exportFunc(); + + builder + .addFunction("testFunc", funcIndex) + .addBody([]) + .exportFunc(); + + builder + .addFunction("testFunc2", funcIndex2) + .addBody([...wasmI32Const(42)]) + .exportFunc(); + + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + const instance = new WebAssembly.Instance(module, {}); + exports = instance.exports; +}); + +test(() => { + exports.anyArg(exports.makeStruct()); + exports.anyArg(exports.makeArray()); + exports.anyArg(42); + exports.anyArg(42n); + exports.anyArg("foo"); + exports.anyArg({}); + exports.anyArg(() => {}); + exports.anyArg(exports.testFunc); + assert_throws_js(TypeError, () => exports.anyArg(null)); + + exports.anyNullableArg(null); + exports.anyNullableArg(exports.makeStruct()); + exports.anyNullableArg(exports.makeArray()); + exports.anyNullableArg(42); + exports.anyNullableArg(42n); + exports.anyNullableArg("foo"); + exports.anyNullableArg({}); + exports.anyNullableArg(() => {}); + exports.anyNullableArg(exports.testFunc); +}, "anyref casts"); + +test(() => { + exports.eqArg(exports.makeStruct()); + exports.eqArg(exports.makeArray()); + exports.eqArg(42); + assert_throws_js(TypeError, () => exports.eqArg(42n)); + assert_throws_js(TypeError, () => exports.eqArg("foo")); + assert_throws_js(TypeError, () => exports.eqArg({})); + assert_throws_js(TypeError, () => exports.eqArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.eqArg(() => {})); + assert_throws_js(TypeError, () => exports.eqArg(null)); + + exports.eqNullableArg(null); + exports.eqNullableArg(exports.makeStruct()); + exports.eqNullableArg(exports.makeArray()); + exports.eqNullableArg(42); + assert_throws_js(TypeError, () => exports.eqNullableArg(42n)); + assert_throws_js(TypeError, () => exports.eqNullableArg("foo")); + assert_throws_js(TypeError, () => exports.eqNullableArg({})); + assert_throws_js(TypeError, () => exports.eqNullableArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.eqNullableArg(() => {})); +}, "eqref casts"); + +test(() => { + exports.structArg(exports.makeStruct()); + assert_throws_js(TypeError, () => exports.structArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.structArg(42)); + assert_throws_js(TypeError, () => exports.structArg(42n)); + assert_throws_js(TypeError, () => exports.structArg("foo")); + assert_throws_js(TypeError, () => exports.structArg({})); + assert_throws_js(TypeError, () => exports.structArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.structArg(() => {})); + assert_throws_js(TypeError, () => exports.structArg(null)); + + exports.structNullableArg(null); + exports.structNullableArg(exports.makeStruct()); + assert_throws_js(TypeError, () => exports.structNullableArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.structNullableArg(42)); + assert_throws_js(TypeError, () => exports.structNullableArg(42n)); + assert_throws_js(TypeError, () => exports.structNullableArg("foo")); + assert_throws_js(TypeError, () => exports.structNullableArg({})); + assert_throws_js(TypeError, () => exports.structNullableArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.structNullableArg(() => {})); +}, "structref casts"); + +test(() => { + exports.arrayArg(exports.makeArray()); + assert_throws_js(TypeError, () => exports.arrayArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.arrayArg(42)); + assert_throws_js(TypeError, () => exports.arrayArg(42n)); + assert_throws_js(TypeError, () => exports.arrayArg("foo")); + assert_throws_js(TypeError, () => exports.arrayArg({})); + assert_throws_js(TypeError, () => exports.arrayArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.arrayArg(() => {})); + assert_throws_js(TypeError, () => exports.arrayArg(null)); + + exports.arrayNullableArg(null); + exports.arrayNullableArg(exports.makeArray()); + assert_throws_js(TypeError, () => exports.arrayNullableArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.arrayNullableArg(42)); + assert_throws_js(TypeError, () => exports.arrayNullableArg(42n)); + assert_throws_js(TypeError, () => exports.arrayNullableArg("foo")); + assert_throws_js(TypeError, () => exports.arrayNullableArg({})); + assert_throws_js(TypeError, () => exports.arrayNullableArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.arrayNullableArg(() => {})); +}, "arrayref casts"); + +test(() => { + exports.i31Arg(42); + assert_throws_js(TypeError, () => exports.i31Arg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.i31Arg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.i31Arg(42n)); + assert_throws_js(TypeError, () => exports.i31Arg("foo")); + assert_throws_js(TypeError, () => exports.i31Arg({})); + assert_throws_js(TypeError, () => exports.i31Arg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.i31Arg(() => {})); + assert_throws_js(TypeError, () => exports.i31Arg(null)); + + exports.i31NullableArg(null); + exports.i31NullableArg(42); + assert_throws_js(TypeError, () => exports.i31NullableArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.i31NullableArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.i31NullableArg(42n)); + assert_throws_js(TypeError, () => exports.i31NullableArg("foo")); + assert_throws_js(TypeError, () => exports.i31NullableArg({})); + assert_throws_js(TypeError, () => exports.i31NullableArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.i31NullableArg(() => {})); +}, "i31ref casts"); + +test(() => { + exports.funcArg(exports.testFunc); + assert_throws_js(TypeError, () => exports.funcArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.funcArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.funcArg(42)); + assert_throws_js(TypeError, () => exports.funcArg(42n)); + assert_throws_js(TypeError, () => exports.funcArg("foo")); + assert_throws_js(TypeError, () => exports.funcArg({})); + assert_throws_js(TypeError, () => exports.funcArg(() => {})); + assert_throws_js(TypeError, () => exports.funcArg(null)); + + exports.funcNullableArg(null); + exports.funcNullableArg(exports.testFunc); + assert_throws_js(TypeError, () => exports.funcNullableArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.funcNullableArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.funcNullableArg(42)); + assert_throws_js(TypeError, () => exports.funcNullableArg(42n)); + assert_throws_js(TypeError, () => exports.funcNullableArg("foo")); + assert_throws_js(TypeError, () => exports.funcNullableArg({})); + assert_throws_js(TypeError, () => exports.funcNullableArg(() => {})); +}, "funcref casts"); + +test(() => { + exports.externArg(exports.makeArray()); + exports.externArg(exports.makeStruct()); + exports.externArg(42); + exports.externArg(42n); + exports.externArg("foo"); + exports.externArg({}); + exports.externArg(exports.testFunc); + exports.externArg(() => {}); + assert_throws_js(TypeError, () => exports.externArg(null)); + + exports.externNullableArg(null); + exports.externNullableArg(exports.makeArray()); + exports.externNullableArg(exports.makeStruct()); + exports.externNullableArg(42); + exports.externNullableArg(42n); + exports.externNullableArg("foo"); + exports.externNullableArg({}); + exports.externNullableArg(exports.testFunc); + exports.externNullableArg(() => {}); +}, "externref casts"); + +test(() => { + for (const nullfunc of [exports.noneArg, exports.nofuncArg, exports.noexternArg]) { + assert_throws_js(TypeError, () => nullfunc(exports.makeStruct())); + assert_throws_js(TypeError, () => nullfunc(exports.makeArray())); + assert_throws_js(TypeError, () => nullfunc(42)); + assert_throws_js(TypeError, () => nullfunc(42n)); + assert_throws_js(TypeError, () => nullfunc("foo")); + assert_throws_js(TypeError, () => nullfunc({})); + assert_throws_js(TypeError, () => nullfunc(exports.testFunc)); + assert_throws_js(TypeError, () => nullfunc(() => {})); + assert_throws_js(TypeError, () => nullfunc(null)); + } + + for (const nullfunc of [exports.noneNullableArg, exports.nofuncNullableArg, exports.noexternNullableArg]) { + nullfunc(null); + assert_throws_js(TypeError, () => nullfunc(exports.makeStruct())); + assert_throws_js(TypeError, () => nullfunc(exports.makeArray())); + assert_throws_js(TypeError, () => nullfunc(42)); + assert_throws_js(TypeError, () => nullfunc(42n)); + assert_throws_js(TypeError, () => nullfunc("foo")); + assert_throws_js(TypeError, () => nullfunc({})); + assert_throws_js(TypeError, () => nullfunc(exports.testFunc)); + assert_throws_js(TypeError, () => nullfunc(() => {})); + } +}, "null casts"); + +test(() => { + exports.concreteStructArg(exports.makeStruct()); + assert_throws_js(TypeError, () => exports.concreteStructArg(exports.makeStruct2())); + assert_throws_js(TypeError, () => exports.concreteStructArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.concreteStructArg(42)); + assert_throws_js(TypeError, () => exports.concreteStructArg(42n)); + assert_throws_js(TypeError, () => exports.concreteStructArg("foo")); + assert_throws_js(TypeError, () => exports.concreteStructArg({})); + assert_throws_js(TypeError, () => exports.concreteStructArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.concreteStructArg(() => {})); + assert_throws_js(TypeError, () => exports.concreteStructArg(null)); + + exports.concreteStructNullableArg(null); + exports.concreteStructNullableArg(exports.makeStruct()); + assert_throws_js(TypeError, () => exports.concreteStructNullableArg(exports.makeStruct2())); + assert_throws_js(TypeError, () => exports.concreteStructNullableArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.concreteStructNullableArg(42)); + assert_throws_js(TypeError, () => exports.concreteStructNullableArg(42n)); + assert_throws_js(TypeError, () => exports.concreteStructNullableArg("foo")); + assert_throws_js(TypeError, () => exports.concreteStructNullableArg({})); + assert_throws_js(TypeError, () => exports.concreteStructNullableArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.concreteStructNullableArg(() => {})); +}, "concrete struct casts"); + +test(() => { + exports.concreteArrayArg(exports.makeArray()); + assert_throws_js(TypeError, () => exports.concreteArrayArg(exports.makeArray2())); + assert_throws_js(TypeError, () => exports.concreteArrayArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.concreteArrayArg(42)); + assert_throws_js(TypeError, () => exports.concreteArrayArg(42n)); + assert_throws_js(TypeError, () => exports.concreteArrayArg("foo")); + assert_throws_js(TypeError, () => exports.concreteArrayArg({})); + assert_throws_js(TypeError, () => exports.concreteArrayArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.concreteArrayArg(() => {})); + assert_throws_js(TypeError, () => exports.concreteArrayArg(null)); + + exports.concreteArrayNullableArg(null); + exports.concreteArrayNullableArg(exports.makeArray()); + assert_throws_js(TypeError, () => exports.concreteArrayNullableArg(exports.makeArray2())); + assert_throws_js(TypeError, () => exports.concreteArrayNullableArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.concreteArrayNullableArg(42)); + assert_throws_js(TypeError, () => exports.concreteArrayNullableArg(42n)); + assert_throws_js(TypeError, () => exports.concreteArrayNullableArg("foo")); + assert_throws_js(TypeError, () => exports.concreteArrayNullableArg({})); + assert_throws_js(TypeError, () => exports.concreteArrayNullableArg(exports.testFunc)); + assert_throws_js(TypeError, () => exports.concreteArrayNullableArg(() => {})); +}, "concrete array casts"); + +test(() => { + exports.concreteFuncArg(exports.testFunc); + assert_throws_js(TypeError, () => exports.concreteFuncArg(exports.testFunc2)); + assert_throws_js(TypeError, () => exports.concreteFuncArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.concreteFuncArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.concreteFuncArg(42)); + assert_throws_js(TypeError, () => exports.concreteFuncArg(42n)); + assert_throws_js(TypeError, () => exports.concreteFuncArg("foo")); + assert_throws_js(TypeError, () => exports.concreteFuncArg({})); + assert_throws_js(TypeError, () => exports.concreteFuncArg(() => {})); + assert_throws_js(TypeError, () => exports.concreteFuncArg(null)); + + exports.concreteFuncNullableArg(null); + exports.concreteFuncNullableArg(exports.testFunc); + assert_throws_js(TypeError, () => exports.concreteFuncNullableArg(exports.testFunc2)); + assert_throws_js(TypeError, () => exports.concreteFuncNullableArg(exports.makeArray())); + assert_throws_js(TypeError, () => exports.concreteFuncNullableArg(exports.makeStruct())); + assert_throws_js(TypeError, () => exports.concreteFuncNullableArg(42)); + assert_throws_js(TypeError, () => exports.concreteFuncNullableArg(42n)); + assert_throws_js(TypeError, () => exports.concreteFuncNullableArg("foo")); + assert_throws_js(TypeError, () => exports.concreteFuncNullableArg({})); + assert_throws_js(TypeError, () => exports.concreteFuncNullableArg(() => {})); +}, "concrete func casts"); diff --git a/tests/wpt/tests/wasm/jsapi/gc/exported-object.tentative.any.js b/tests/wpt/tests/wasm/jsapi/gc/exported-object.tentative.any.js new file mode 100644 index 00000000000..b572f140067 --- /dev/null +++ b/tests/wpt/tests/wasm/jsapi/gc/exported-object.tentative.any.js @@ -0,0 +1,190 @@ +// META: global=window,dedicatedworker,jsshell +// META: script=/wasm/jsapi/wasm-module-builder.js + +let functions = {}; +setup(() => { + const builder = new WasmModuleBuilder(); + + const structIndex = builder.addStruct([makeField(kWasmI32, true)]); + const arrayIndex = builder.addArray(kWasmI32, true); + const structRef = wasmRefType(structIndex); + const arrayRef = wasmRefType(arrayIndex); + + builder + .addFunction("makeStruct", makeSig_r_v(structRef)) + .addBody([...wasmI32Const(42), + ...GCInstr(kExprStructNew), structIndex]) + .exportFunc(); + + builder + .addFunction("makeArray", makeSig_r_v(arrayRef)) + .addBody([...wasmI32Const(5), ...wasmI32Const(42), + ...GCInstr(kExprArrayNew), arrayIndex]) + .exportFunc(); + + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + const instance = new WebAssembly.Instance(module, {}); + functions = instance.exports; +}); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_equals(struct.foo, undefined); + assert_equals(struct[0], undefined); + assert_equals(array.foo, undefined); + assert_equals(array[0], undefined); +}, "property access"); + +test(() => { + "use strict"; + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => { struct.foo = 5; }); + assert_throws_js(TypeError, () => { array.foo = 5; }); + assert_throws_js(TypeError, () => { struct[0] = 5; }); + assert_throws_js(TypeError, () => { array[0] = 5; }); +}, "property assignment (strict mode)"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => { struct.foo = 5; }); + assert_throws_js(TypeError, () => { array.foo = 5; }); + assert_throws_js(TypeError, () => { struct[0] = 5; }); + assert_throws_js(TypeError, () => { array[0] = 5; }); +}, "property assignment (non-strict mode)"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_equals(Object.getOwnPropertyNames(struct).length, 0); + assert_equals(Object.getOwnPropertyNames(array).length, 0); +}, "ownPropertyNames"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => Object.defineProperty(struct, "foo", { value: 1 })); + assert_throws_js(TypeError, () => Object.defineProperty(array, "foo", { value: 1 })); +}, "defineProperty"); + +test(() => { + "use strict"; + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => delete struct.foo); + assert_throws_js(TypeError, () => delete struct[0]); + assert_throws_js(TypeError, () => delete array.foo); + assert_throws_js(TypeError, () => delete array[0]); +}, "delete (strict mode)"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => delete struct.foo); + assert_throws_js(TypeError, () => delete struct[0]); + assert_throws_js(TypeError, () => delete array.foo); + assert_throws_js(TypeError, () => delete array[0]); +}, "delete (non-strict mode)"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_equals(Object.getPrototypeOf(struct), null); + assert_equals(Object.getPrototypeOf(array), null); +}, "getPrototypeOf"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => Object.setPrototypeOf(struct, {})); + assert_throws_js(TypeError, () => Object.setPrototypeOf(array, {})); +}, "setPrototypeOf"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_false(Object.isExtensible(struct)); + assert_false(Object.isExtensible(array)); +}, "isExtensible"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => Object.preventExtensions(struct)); + assert_throws_js(TypeError, () => Object.preventExtensions(array)); +}, "preventExtensions"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => Object.seal(struct)); + assert_throws_js(TypeError, () => Object.seal(array)); +}, "sealing"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_equals(typeof struct, "object"); + assert_equals(typeof array, "object"); +}, "typeof"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => struct.toString()); + assert_equals(Object.prototype.toString.call(struct), "[object Object]"); + assert_throws_js(TypeError, () => array.toString()); + assert_equals(Object.prototype.toString.call(array), "[object Object]"); +}, "toString"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + assert_throws_js(TypeError, () => struct.valueOf()); + assert_equals(Object.prototype.valueOf.call(struct), struct); + assert_throws_js(TypeError, () => array.valueOf()); + assert_equals(Object.prototype.valueOf.call(array), array); +}, "valueOf"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + const map = new Map(); + map.set(struct, "struct"); + map.set(array, "array"); + assert_equals(map.get(struct), "struct"); + assert_equals(map.get(array), "array"); +}, "GC objects as map keys"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + const set = new Set(); + set.add(struct); + set.add(array); + assert_true(set.has(struct)); + assert_true(set.has(array)); +}, "GC objects as set element"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + const map = new WeakMap(); + map.set(struct, "struct"); + map.set(array, "array"); + assert_equals(map.get(struct), "struct"); + assert_equals(map.get(array), "array"); +}, "GC objects as weak map keys"); + +test(() => { + const struct = functions.makeStruct(); + const array = functions.makeArray(); + const set = new WeakSet(); + set.add(struct); + set.add(array); + assert_true(set.has(struct)); + assert_true(set.has(array)); +}, "GC objects as weak set element"); diff --git a/tests/wpt/tests/wasm/jsapi/gc/i31.tentative.any.js b/tests/wpt/tests/wasm/jsapi/gc/i31.tentative.any.js new file mode 100644 index 00000000000..17fd82440cc --- /dev/null +++ b/tests/wpt/tests/wasm/jsapi/gc/i31.tentative.any.js @@ -0,0 +1,98 @@ +// META: global=window,dedicatedworker,jsshell +// META: script=/wasm/jsapi/wasm-module-builder.js + +let exports = {}; +setup(() => { + const builder = new WasmModuleBuilder(); + const i31Ref = wasmRefType(kWasmI31Ref); + const i31NullableRef = wasmRefNullType(kWasmI31Ref); + const anyRef = wasmRefType(kWasmAnyRef); + + builder + .addFunction("makeI31", makeSig_r_x(i31Ref, kWasmI32)) + .addBody([kExprLocalGet, 0, + ...GCInstr(kExprI31New)]) + .exportFunc(); + + builder + .addFunction("castI31", makeSig_r_x(kWasmI32, anyRef)) + .addBody([kExprLocalGet, 0, + ...GCInstr(kExprRefCast), kI31RefCode, + ...GCInstr(kExprI31GetU)]) + .exportFunc(); + + builder + .addFunction("getI31", makeSig_r_x(kWasmI32, i31Ref)) + .addBody([kExprLocalGet, 0, + ...GCInstr(kExprI31GetS)]) + .exportFunc(); + + builder + .addFunction("argI31", makeSig_v_x(i31NullableRef)) + .addBody([]) + .exportFunc(); + + builder + .addGlobal(i31NullableRef, true, [...wasmI32Const(0), ...GCInstr(kExprI31New)]) + builder + .addExportOfKind("i31Global", kExternalGlobal, 0); + + builder + .addTable(i31NullableRef, 10) + builder + .addExportOfKind("i31Table", kExternalTable, 0); + + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + const instance = new WebAssembly.Instance(module, {}); + exports = instance.exports; +}); + +test(() => { + assert_equals(exports.makeI31(42), 42); + assert_equals(exports.makeI31(2 ** 30 - 1), 2 ** 30 - 1); + assert_equals(exports.makeI31(2 ** 30), -(2 ** 30)); + assert_equals(exports.makeI31(-(2 ** 30)), -(2 ** 30)); + assert_equals(exports.makeI31(2 ** 31 - 1), -1); + assert_equals(exports.makeI31(2 ** 31), 0); +}, "i31ref conversion to Number"); + +test(() => { + assert_equals(exports.getI31(exports.makeI31(42)), 42); + assert_equals(exports.getI31(42), 42); + assert_equals(exports.getI31(2.0 ** 30 - 1), 2 ** 30 - 1); + assert_equals(exports.getI31(-(2 ** 30)), -(2 ** 30)); +}, "Number conversion to i31ref"); + +test(() => { + exports.argI31(null); + assert_throws_js(TypeError, () => exports.argI31(2 ** 30)); + assert_throws_js(TypeError, () => exports.argI31(-(2 ** 30) - 1)); + assert_throws_js(TypeError, () => exports.argI31(2n)); + assert_throws_js(TypeError, () => exports.argI31(() => 3)); + assert_throws_js(TypeError, () => exports.argI31(exports.getI31)); +}, "Check i31ref argument type"); + +test(() => { + assert_equals(exports.castI31(42), 42); + assert_equals(exports.castI31(2 ** 30 - 1), 2 ** 30 - 1); + assert_throws_js(WebAssembly.RuntimeError, () => { exports.castI31(2 ** 30); }); + assert_throws_js(WebAssembly.RuntimeError, () => { exports.castI31(-(2 ** 30) - 1); }); + assert_throws_js(WebAssembly.RuntimeError, () => { exports.castI31(2 ** 32); }); +}, "Numbers in i31 range are i31ref, not hostref"); + +test(() => { + assert_equals(exports.i31Global.value, 0); + exports.i31Global.value = 42; + assert_throws_js(TypeError, () => exports.i31Global.value = 2 ** 30); + assert_throws_js(TypeError, () => exports.i31Global.value = -(2 ** 30) - 1); + assert_equals(exports.i31Global.value, 42); +}, "i31ref global"); + +test(() => { + assert_equals(exports.i31Table.get(0), null); + exports.i31Table.set(0, 42); + assert_throws_js(TypeError, () => exports.i31Table.set(0, 2 ** 30)); + assert_throws_js(TypeError, () => exports.i31Table.set(0, -(2 ** 30) - 1)); + assert_equals(exports.i31Table.get(0), 42); +}, "i31ref table"); diff --git a/tests/wpt/tests/wasm/jsapi/instanceTestFactory.js b/tests/wpt/tests/wasm/jsapi/instanceTestFactory.js index 6e6ec875bda..2e015af8198 100644 --- a/tests/wpt/tests/wasm/jsapi/instanceTestFactory.js +++ b/tests/wpt/tests/wasm/jsapi/instanceTestFactory.js @@ -237,7 +237,7 @@ const instanceTestFactory = [ builder.addGlobal(kWasmI32, true) .exportAs("") - .init = 7; + .init = wasmI32Const(7); const buffer = builder.toBuffer(); @@ -273,10 +273,10 @@ const instanceTestFactory = [ builder.addGlobal(kWasmI32, true) .exportAs("global") - .init = 7; + .init = wasmI32Const(7); builder.addGlobal(kWasmF64, true) .exportAs("global2") - .init = 1.2; + .init = wasmF64Const(1.2); builder.addMemory(4, 8, true); diff --git a/tests/wpt/tests/wasm/jsapi/module/exports.any.js b/tests/wpt/tests/wasm/jsapi/module/exports.any.js index 499a2649b17..0c32e984a2c 100644 --- a/tests/wpt/tests/wasm/jsapi/module/exports.any.js +++ b/tests/wpt/tests/wasm/jsapi/module/exports.any.js @@ -109,10 +109,10 @@ test(() => { builder.addGlobal(kWasmI32, true) .exportAs("global") - .init = 7; + .init = wasmI32Const(7); builder.addGlobal(kWasmF64, true) .exportAs("global2") - .init = 1.2; + .init = wasmF64Const(1.2); builder.addMemory(0, 256, true); @@ -167,7 +167,7 @@ test(() => { builder.addGlobal(kWasmI32, true) .exportAs("") - .init = 7; + .init = wasmI32Const(7); const buffer = builder.toBuffer() const module = new WebAssembly.Module(buffer); diff --git a/tests/wpt/tests/wasm/jsapi/wasm-module-builder.js b/tests/wpt/tests/wasm/jsapi/wasm-module-builder.js index 3545c3a8da7..1d8db0a6e6f 100644 --- a/tests/wpt/tests/wasm/jsapi/wasm-module-builder.js +++ b/tests/wpt/tests/wasm/jsapi/wasm-module-builder.js @@ -74,6 +74,13 @@ let kLocalNamesCode = 2; let kWasmFunctionTypeForm = 0x60; let kWasmAnyFunctionTypeForm = 0x70; +let kWasmStructTypeForm = 0x5f; +let kWasmArrayTypeForm = 0x5e; +let kWasmSubtypeForm = 0x50; +let kWasmSubtypeFinalForm = 0x4f; +let kWasmRecursiveTypeGroupForm = 0x4e; + +let kNoSuperType = 0xFFFFFFFF; let kHasMaximumFlag = 1; let kSharedHasMaximumFlag = 3; @@ -97,8 +104,43 @@ let kWasmI64 = 0x7e; let kWasmF32 = 0x7d; let kWasmF64 = 0x7c; let kWasmS128 = 0x7b; -let kWasmAnyRef = 0x6f; -let kWasmAnyFunc = 0x70; + +// These are defined as negative integers to distinguish them from positive type +// indices. +let kWasmNullFuncRef = -0x0d; +let kWasmNullExternRef = -0x0e; +let kWasmNullRef = -0x0f; +let kWasmFuncRef = -0x10; +let kWasmAnyFunc = kWasmFuncRef; // Alias named as in the JS API spec +let kWasmExternRef = -0x11; +let kWasmAnyRef = -0x12; +let kWasmEqRef = -0x13; +let kWasmI31Ref = -0x14; +let kWasmStructRef = -0x15; +let kWasmArrayRef = -0x16; + +// Use the positive-byte versions inside function bodies. +let kLeb128Mask = 0x7f; +let kFuncRefCode = kWasmFuncRef & kLeb128Mask; +let kAnyFuncCode = kFuncRefCode; // Alias named as in the JS API spec +let kExternRefCode = kWasmExternRef & kLeb128Mask; +let kAnyRefCode = kWasmAnyRef & kLeb128Mask; +let kEqRefCode = kWasmEqRef & kLeb128Mask; +let kI31RefCode = kWasmI31Ref & kLeb128Mask; +let kNullExternRefCode = kWasmNullExternRef & kLeb128Mask; +let kNullFuncRefCode = kWasmNullFuncRef & kLeb128Mask; +let kStructRefCode = kWasmStructRef & kLeb128Mask; +let kArrayRefCode = kWasmArrayRef & kLeb128Mask; +let kNullRefCode = kWasmNullRef & kLeb128Mask; + +let kWasmRefNull = 0x63; +let kWasmRef = 0x64; +function wasmRefNullType(heap_type) { + return {opcode: kWasmRefNull, heap_type: heap_type}; +} +function wasmRefType(heap_type) { + return {opcode: kWasmRef, heap_type: heap_type}; +} let kExternalFunction = 0; let kExternalTable = 1; @@ -146,14 +188,14 @@ let kSig_v_f = makeSig([kWasmF32], []); let kSig_f_f = makeSig([kWasmF32], [kWasmF32]); let kSig_f_d = makeSig([kWasmF64], [kWasmF32]); let kSig_d_d = makeSig([kWasmF64], [kWasmF64]); -let kSig_r_r = makeSig([kWasmAnyRef], [kWasmAnyRef]); +let kSig_r_r = makeSig([kWasmExternRef], [kWasmExternRef]); let kSig_a_a = makeSig([kWasmAnyFunc], [kWasmAnyFunc]); -let kSig_i_r = makeSig([kWasmAnyRef], [kWasmI32]); -let kSig_v_r = makeSig([kWasmAnyRef], []); +let kSig_i_r = makeSig([kWasmExternRef], [kWasmI32]); +let kSig_v_r = makeSig([kWasmExternRef], []); let kSig_v_a = makeSig([kWasmAnyFunc], []); -let kSig_v_rr = makeSig([kWasmAnyRef, kWasmAnyRef], []); +let kSig_v_rr = makeSig([kWasmExternRef, kWasmExternRef], []); let kSig_v_aa = makeSig([kWasmAnyFunc, kWasmAnyFunc], []); -let kSig_r_v = makeSig([], [kWasmAnyRef]); +let kSig_r_v = makeSig([], [kWasmExternRef]); let kSig_a_v = makeSig([], [kWasmAnyFunc]); let kSig_a_i = makeSig([kWasmI32], [kWasmAnyFunc]); @@ -374,10 +416,50 @@ let kExprRefIsNull = 0xd1; let kExprRefFunc = 0xd2; // Prefix opcodes +let kGCPrefix = 0xfb; let kNumericPrefix = 0xfc; let kSimdPrefix = 0xfd; let kAtomicPrefix = 0xfe; +// Use these for multi-byte instructions (opcode > 0x7F needing two LEB bytes): +function GCInstr(opcode) { + if (opcode <= 0x7F) return [kGCPrefix, opcode]; + return [kGCPrefix, 0x80 | (opcode & 0x7F), opcode >> 7]; +} + +// GC opcodes +let kExprStructNew = 0x00; +let kExprStructNewDefault = 0x01; +let kExprStructGet = 0x02; +let kExprStructGetS = 0x03; +let kExprStructGetU = 0x04; +let kExprStructSet = 0x05; +let kExprArrayNew = 0x06; +let kExprArrayNewDefault = 0x07; +let kExprArrayNewFixed = 0x08; +let kExprArrayNewData = 0x09; +let kExprArrayNewElem = 0x0a; +let kExprArrayGet = 0x0b; +let kExprArrayGetS = 0x0c; +let kExprArrayGetU = 0x0d; +let kExprArraySet = 0x0e; +let kExprArrayLen = 0x0f; +let kExprArrayFill = 0x10; +let kExprArrayCopy = 0x11; +let kExprArrayInitData = 0x12; +let kExprArrayInitElem = 0x13; +let kExprRefTest = 0x14; +let kExprRefTestNull = 0x15; +let kExprRefCast = 0x16; +let kExprRefCastNull = 0x17; +let kExprBrOnCast = 0x18; +let kExprBrOnCastFail = 0x19; +let kExprExternInternalize = 0x1a; +let kExprExternExternalize = 0x1b; +let kExprI31New = 0x1c; +let kExprI31GetS = 0x1d; +let kExprI31GetU = 0x1e; + // Numeric opcodes. let kExprMemoryInit = 0x08; let kExprDataDrop = 0x09; @@ -554,6 +636,25 @@ class Binary { } } + emit_heap_type(heap_type) { + this.emit_bytes(wasmSignedLeb(heap_type, kMaxVarInt32Size)); + } + + emit_type(type) { + if ((typeof type) == 'number') { + this.emit_u8(type >= 0 ? type : type & kLeb128Mask); + } else { + this.emit_u8(type.opcode); + if ('depth' in type) this.emit_u8(type.depth); + this.emit_heap_type(type.heap_type); + } + } + + emit_init_expr(expr) { + this.emit_bytes(expr); + this.emit_u8(kExprEnd); + } + emit_header() { this.emit_bytes([ kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3 @@ -644,11 +745,11 @@ class WasmFunctionBuilder { } class WasmGlobalBuilder { - constructor(module, type, mutable) { + constructor(module, type, mutable, init) { this.module = module; this.type = type; this.mutable = mutable; - this.init = 0; + this.init = init; } exportAs(name) { @@ -658,13 +759,24 @@ class WasmGlobalBuilder { } } +function checkExpr(expr) { + for (let b of expr) { + if (typeof b !== 'number' || (b & (~0xFF)) !== 0) { + throw new Error( + 'invalid body (entries must be 8 bit numbers): ' + expr); + } + } +} + class WasmTableBuilder { - constructor(module, type, initial_size, max_size) { + constructor(module, type, initial_size, max_size, init_expr) { this.module = module; this.type = type; this.initial_size = initial_size; this.has_max = max_size != undefined; this.max_size = max_size; + this.init_expr = init_expr; + this.has_init = init_expr !== undefined; } exportAs(name) { @@ -674,6 +786,35 @@ class WasmTableBuilder { } } +function makeField(type, mutability) { + if ((typeof mutability) != 'boolean') { + throw new Error('field mutability must be boolean'); + } + return {type: type, mutability: mutability}; +} + +class WasmStruct { + constructor(fields, is_final, supertype_idx) { + if (!Array.isArray(fields)) { + throw new Error('struct fields must be an array'); + } + this.fields = fields; + this.type_form = kWasmStructTypeForm; + this.is_final = is_final; + this.supertype = supertype_idx; + } +} + +class WasmArray { + constructor(type, mutability, is_final, supertype_idx) { + this.type = type; + this.mutability = mutability; + this.type_form = kWasmArrayTypeForm; + this.is_final = is_final; + this.supertype = supertype_idx; + } +} + class WasmModuleBuilder { constructor() { this.types = []; @@ -686,6 +827,7 @@ class WasmModuleBuilder { this.element_segments = []; this.data_segments = []; this.explicit = []; + this.rec_groups = []; this.num_imported_funcs = 0; this.num_imported_globals = 0; this.num_imported_tables = 0; @@ -728,25 +870,65 @@ class WasmModuleBuilder { this.explicit.push(this.createCustomSection(name, bytes)); } - addType(type) { - this.types.push(type); - var pl = type.params.length; // should have params - var rl = type.results.length; // should have results + // We use {is_final = true} so that the MVP syntax is generated for + // signatures. + addType(type, supertype_idx = kNoSuperType, is_final = true) { + var pl = type.params.length; // should have params + var rl = type.results.length; // should have results + var type_copy = {params: type.params, results: type.results, + is_final: is_final, supertype: supertype_idx}; + this.types.push(type_copy); + return this.types.length - 1; + } + + addStruct(fields, supertype_idx = kNoSuperType, is_final = false) { + this.types.push(new WasmStruct(fields, is_final, supertype_idx)); return this.types.length - 1; } - addGlobal(local_type, mutable) { - let glob = new WasmGlobalBuilder(this, local_type, mutable); + addArray(type, mutability, supertype_idx = kNoSuperType, is_final = false) { + this.types.push(new WasmArray(type, mutability, is_final, supertype_idx)); + return this.types.length - 1; + } + + static defaultFor(type) { + switch (type) { + case kWasmI32: + return wasmI32Const(0); + case kWasmI64: + return wasmI64Const(0); + case kWasmF32: + return wasmF32Const(0.0); + case kWasmF64: + return wasmF64Const(0.0); + case kWasmS128: + return [kSimdPrefix, kExprS128Const, ...(new Array(16).fill(0))]; + default: + if ((typeof type) != 'number' && type.opcode != kWasmRefNull) { + throw new Error("Non-defaultable type"); + } + let heap_type = (typeof type) == 'number' ? type : type.heap_type; + return [kExprRefNull, ...wasmSignedLeb(heap_type, kMaxVarInt32Size)]; + } + } + + addGlobal(type, mutable, init) { + if (init === undefined) init = WasmModuleBuilder.defaultFor(type); + checkExpr(init); + let glob = new WasmGlobalBuilder(this, type, mutable, init); glob.index = this.globals.length + this.num_imported_globals; this.globals.push(glob); return glob; } - addTable(type, initial_size, max_size = undefined) { - if (type != kWasmAnyRef && type != kWasmAnyFunc) { - throw new Error('Tables must be of type kWasmAnyRef or kWasmAnyFunc'); + addTable(type, initial_size, max_size = undefined, init_expr = undefined) { + if (type == kWasmI32 || type == kWasmI64 || type == kWasmF32 || + type == kWasmF64 || type == kWasmS128 || type == kWasmStmt) { + throw new Error('Tables must be of a reference type'); } - let table = new WasmTableBuilder(this, type, initial_size, max_size); + if (init_expr != undefined) checkExpr(init_expr); + let table = new WasmTableBuilder( + this, type, initial_size, max_size, init_expr); table.index = this.tables.length + this.num_imported_tables; this.tables.push(table); return table; @@ -754,9 +936,9 @@ class WasmModuleBuilder { addTag(type) { let type_index = (typeof type) == "number" ? type : this.addType(type); - let except_index = this.tags.length + this.num_imported_tags; + let tag_index = this.tags.length + this.num_imported_tags; this.tags.push(type_index); - return except_index; + return tag_index; } addFunction(name, type) { @@ -877,6 +1059,21 @@ class WasmModuleBuilder { return this; } + startRecGroup() { + this.rec_groups.push({start: this.types.length, size: 0}); + } + + endRecGroup() { + if (this.rec_groups.length == 0) { + throw new Error("Did not start a recursive group before ending one") + } + let last_element = this.rec_groups[this.rec_groups.length - 1] + if (last_element.size != 0) { + throw new Error("Did not start a recursive group before ending one") + } + last_element.size = this.types.length - last_element.start; + } + setName(name) { this.name = name; return this; @@ -891,18 +1088,55 @@ class WasmModuleBuilder { // Add type section if (wasm.types.length > 0) { - if (debug) print("emitting types @ " + binary.length); + if (debug) print('emitting types @ ' + binary.length); binary.emit_section(kTypeSectionCode, section => { - section.emit_u32v(wasm.types.length); - for (let type of wasm.types) { - section.emit_u8(kWasmFunctionTypeForm); - section.emit_u32v(type.params.length); - for (let param of type.params) { - section.emit_u8(param); + let length_with_groups = wasm.types.length; + for (let group of wasm.rec_groups) { + length_with_groups -= group.size - 1; + } + section.emit_u32v(length_with_groups); + + let rec_group_index = 0; + + for (let i = 0; i < wasm.types.length; i++) { + if (rec_group_index < wasm.rec_groups.length && + wasm.rec_groups[rec_group_index].start == i) { + section.emit_u8(kWasmRecursiveTypeGroupForm); + section.emit_u32v(wasm.rec_groups[rec_group_index].size); + rec_group_index++; } - section.emit_u32v(type.results.length); - for (let result of type.results) { - section.emit_u8(result); + + let type = wasm.types[i]; + if (type.supertype != kNoSuperType) { + section.emit_u8(type.is_final ? kWasmSubtypeFinalForm + : kWasmSubtypeForm); + section.emit_u8(1); // supertype count + section.emit_u32v(type.supertype); + } else if (!type.is_final) { + section.emit_u8(kWasmSubtypeForm); + section.emit_u8(0); // no supertypes + } + if (type instanceof WasmStruct) { + section.emit_u8(kWasmStructTypeForm); + section.emit_u32v(type.fields.length); + for (let field of type.fields) { + section.emit_type(field.type); + section.emit_u8(field.mutability ? 1 : 0); + } + } else if (type instanceof WasmArray) { + section.emit_u8(kWasmArrayTypeForm); + section.emit_type(type.type); + section.emit_u8(type.mutability ? 1 : 0); + } else { + section.emit_u8(kWasmFunctionTypeForm); + section.emit_u32v(type.params.length); + for (let param of type.params) { + section.emit_type(param); + } + section.emit_u32v(type.results.length); + for (let result of type.results) { + section.emit_type(result); + } } } }); @@ -918,9 +1152,9 @@ class WasmModuleBuilder { section.emit_string(imp.name || ''); section.emit_u8(imp.kind); if (imp.kind == kExternalFunction) { - section.emit_u32v(imp.type); + section.emit_u32v(imp.type_index); } else if (imp.kind == kExternalGlobal) { - section.emit_u32v(imp.type); + section.emit_type(imp.type); section.emit_u8(imp.mutable); } else if (imp.kind == kExternalMemory) { var has_max = (typeof imp.maximum) != "undefined"; @@ -933,7 +1167,7 @@ class WasmModuleBuilder { section.emit_u32v(imp.initial); // initial if (has_max) section.emit_u32v(imp.maximum); // maximum } else if (imp.kind == kExternalTable) { - section.emit_u8(imp.type); + section.emit_type(imp.type); var has_max = (typeof imp.maximum) != "undefined"; section.emit_u8(has_max ? 1 : 0); // flags section.emit_u32v(imp.initial); // initial @@ -965,10 +1199,11 @@ class WasmModuleBuilder { binary.emit_section(kTableSectionCode, section => { section.emit_u32v(wasm.tables.length); for (let table of wasm.tables) { - section.emit_u8(table.type); + section.emit_type(table.type); section.emit_u8(table.has_max); section.emit_u32v(table.initial_size); if (table.has_max) section.emit_u32v(table.max_size); + if (table.has_init) section.emit_init_expr(table.init_expr); } }); } @@ -997,41 +1232,9 @@ class WasmModuleBuilder { binary.emit_section(kGlobalSectionCode, section => { section.emit_u32v(wasm.globals.length); for (let global of wasm.globals) { - section.emit_u8(global.type); + section.emit_type(global.type); section.emit_u8(global.mutable); - if ((typeof global.init_index) == "undefined") { - // Emit a constant initializer. - switch (global.type) { - case kWasmI32: - section.emit_u8(kExprI32Const); - section.emit_u32v(global.init); - break; - case kWasmI64: - section.emit_u8(kExprI64Const); - section.emit_u64v(global.init); - break; - case kWasmF32: - section.emit_bytes(wasmF32Const(global.init)); - break; - case kWasmF64: - section.emit_bytes(wasmF64Const(global.init)); - break; - case kWasmAnyFunc: - case kWasmAnyRef: - if (global.function_index !== undefined) { - section.emit_u8(kExprRefFunc); - section.emit_u32v(global.function_index); - } else { - section.emit_u8(kExprRefNull); - } - break; - } - } else { - // Emit a global-index initializer. - section.emit_u8(kExprGlobalGet); - section.emit_u32v(global.init_index); - } - section.emit_u8(kExprEnd); // end of init expression + section.emit_init_expr(global.init); } }); } @@ -1161,7 +1364,7 @@ class WasmModuleBuilder { local_decls.push({count: l.s128_count, type: kWasmS128}); } if (l.anyref_count > 0) { - local_decls.push({count: l.anyref_count, type: kWasmAnyRef}); + local_decls.push({count: l.anyref_count, type: kWasmExternRef}); } if (l.anyfunc_count > 0) { local_decls.push({count: l.anyfunc_count, type: kWasmAnyFunc}); @@ -1171,7 +1374,7 @@ class WasmModuleBuilder { header.emit_u32v(local_decls.length); for (let decl of local_decls) { header.emit_u32v(decl.count); - header.emit_u8(decl.type); + header.emit_type(decl.type); } section.emit_u32v(header.length + func.body.length); diff --git a/tests/wpt/tests/web-animations/animation-model/animation-types/scrollbar-interpolation.html b/tests/wpt/tests/web-animations/animation-model/animation-types/scrollbar-interpolation.html new file mode 100644 index 00000000000..bc02dd00b97 --- /dev/null +++ b/tests/wpt/tests/web-animations/animation-model/animation-types/scrollbar-interpolation.html @@ -0,0 +1,91 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<link rel="help" href="https://drafts.csswg.org/web-animations/#animation-types"> +<title>Scrollbar interpolation</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +</head> +<style type="text/css"> + #container { + height: 100px; + width: 100px; + overflow: scroll; + } + #contents { + height: 200px; + width: 200px; + } +</style> +<body> + <div id="container"> + <div id="contents"></div> + </div> +</body> +<!-- Extend coverage in interpolation-per-property-002 to include testing + if named and system colors +--> +<script type="text/javascript"> + function interpolate(keyframes, property) { + const anim = container.animate(keyframes, { + duration: 1000, + easing: 'linear' + }); + anim.pause(); + anim.currentTime = 500; + const result = getComputedStyle(container)[property]; + anim.cancel(); + return result; + } + + function test_scrollbar_interpolation(from, to) { + let fromKeyframe =`${from.thumb} ${from.track}`; + let toKeyframe = `${to.thumb} ${to.track}`; + let keyframes = { scrollbarColor: [ fromKeyframe, toKeyframe ] }; + const scrollbarColors = interpolate(keyframes, 'scrollbarColor'); + + // As the colors may be system dependent, we use the container as a + // color swatch and resolve the color blend via background-color. + // The scrollbar colors are expected to match the blend on the thumb + // and track colors respectively. + keyframes = { + backgroundColor: [`${from.thumb}`, `${to.thumb}` ] + } + const expectedThumbColor = interpolate(keyframes, 'backgroundColor'); + keyframes = { + backgroundColor: [ `${from.track}`, `${to.track}` ] + } + const expectedTrackColor = interpolate(keyframes, 'backgroundColor'); + assert_equals(scrollbarColors, + `${expectedThumbColor} ${expectedTrackColor}`, + `${fromKeyframe} to ${toKeyframe}`); + } + + test(() => { + const data = [ + { + from: { thumb: 'black', track: 'white' }, + to: { thumb: 'lime', track: 'darkgreen' } + }, + { + from: { thumb: '#000', track: 'pink' }, + to: { thumb: 'canvas', track: 'buttontext' } + }, + { + from: { thumb: 'rgba(255,255,255,0)', track: 'rgba(128,128,128,0)'}, + to: { thumb: 'rgba(255,255,255,1)', track: 'rgba(128,128,128,1)'} + }, + { + from: { thumb: 'transparent', track: 'transparent' }, + to: { thumb: 'rgba(255,255,255,1)', track: 'rgba(128,128,128,1)'} + } + ]; + data.forEach((test) => { + test_scrollbar_interpolation(test.from, test.to); + }); + }, 'Verify scrollbar-color-interpolation'); +</script> +</html> diff --git a/tests/wpt/tests/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.html b/tests/wpt/tests/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.html deleted file mode 100644 index fe0cf15b43d..00000000000 --- a/tests/wpt/tests/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.html +++ /dev/null @@ -1,28 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title> - audioparam-default-value.html - </title> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="/webaudio/resources/audit.js"></script> - </head> - <body> - <script id="layout-test-code"> - const audit = Audit.createTaskRunner(); - - audit.define('test', function(task, should) { - const context = new OfflineAudioContext(1, 1, 44100); - const defaultValue = -1; - const gainNode = new GainNode(context, { gain: defaultValue }); - - should(gainNode.gain.defaultValue, "AudioParam's defaultValue").beEqualTo(defaultValue); - - task.done(); - }); - - audit.run(); - </script> - </body> -</html> diff --git a/tests/wpt/tests/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.window.js b/tests/wpt/tests/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.window.js new file mode 100644 index 00000000000..359df111846 --- /dev/null +++ b/tests/wpt/tests/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.window.js @@ -0,0 +1,12 @@ +// META: script=/resources/testharness.js +// META: script=/resources/testharnessreport.js + +'use strict'; + +test(() => { + const context = new OfflineAudioContext(1, 1, 44100); + const defaultValue = -1; + const gainNode = new GainNode(context, { gain: defaultValue }); + + assert_equals(gainNode.gain.defaultValue, defaultValue, "AudioParam's defaultValue is not correct."); +}, "AudioParam's defaultValue"); diff --git a/tests/wpt/tests/webauthn/storecredential.https.html b/tests/wpt/tests/webauthn/storecredential.https.html new file mode 100644 index 00000000000..726b289fbd1 --- /dev/null +++ b/tests/wpt/tests/webauthn/storecredential.https.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src=helpers.js></script> +<script> + "use strict"; + + virtualAuthenticatorPromiseTest(async t => { + const cred = await navigator.credentials.get({publicKey: { + challenge: new Uint8Array(), + allowCredentials: [{ + id: (await createCredential()).rawId, + type: "public-key", + }], + }}); + return promise_rejects_dom(t, "NotSupportedError", navigator.credentials.store(cred)); + }, {}, "navigator.credentials.store() throws NotAllowedError with a public key credential"); + +</script> diff --git a/tests/wpt/tests/webcodecs/META.yml b/tests/wpt/tests/webcodecs/META.yml index 8570ee05e5a..071ef88121b 100644 --- a/tests/wpt/tests/webcodecs/META.yml +++ b/tests/wpt/tests/webcodecs/META.yml @@ -3,3 +3,5 @@ suggested_reviewers: - Djuffin - sandersdan - youennf + - padenot + - ChunMinChang diff --git a/tests/wpt/tests/webcodecs/audio-decoder.https.any.js b/tests/wpt/tests/webcodecs/audio-decoder.https.any.js index 606b052edc8..79ba22157ab 100644 --- a/tests/wpt/tests/webcodecs/audio-decoder.https.any.js +++ b/tests/wpt/tests/webcodecs/audio-decoder.https.any.js @@ -135,20 +135,23 @@ validButUnsupportedConfigs.forEach(entry => { }); validButUnsupportedConfigs.forEach(entry => { - async_test( + promise_test( t => { + let isErrorCallbackCalled = false; let codec = new AudioDecoder({ output: t.unreached_func('unexpected output'), error: t.step_func_done(e => { + isErrorCallbackCalled = true; assert_true(e instanceof DOMException); assert_equals(e.name, 'NotSupportedError'); assert_equals(codec.state, 'closed', 'state'); }) }); codec.configure(entry.config); - codec.flush() + return codec.flush() .then(t.unreached_func('flush succeeded unexpectedly')) .catch(t.step_func(e => { + assert_true(isErrorCallbackCalled, "isErrorCallbackCalled"); assert_true(e instanceof DOMException); assert_equals(e.name, 'NotSupportedError'); assert_equals(codec.state, 'closed', 'state'); diff --git a/tests/wpt/tests/webcodecs/audio-encoder-config.https.any.js b/tests/wpt/tests/webcodecs/audio-encoder-config.https.any.js index 98a9513b7dc..3be8eb3f6d3 100644 --- a/tests/wpt/tests/webcodecs/audio-encoder-config.https.any.js +++ b/tests/wpt/tests/webcodecs/audio-encoder-config.https.any.js @@ -213,20 +213,23 @@ validButUnsupportedConfigs.forEach(entry => { }); validButUnsupportedConfigs.forEach(entry => { - async_test( + promise_test( t => { + let isErrorCallbackCalled = false; let codec = new AudioEncoder({ output: t.unreached_func('unexpected output'), error: t.step_func_done(e => { + isErrorCallbackCalled = true; assert_true(e instanceof DOMException); assert_equals(e.name, 'NotSupportedError'); assert_equals(codec.state, 'closed', 'state'); }) }); codec.configure(entry.config); - codec.flush() + return codec.flush() .then(t.unreached_func('flush succeeded unexpectedly')) .catch(t.step_func(e => { + assert_true(isErrorCallbackCalled, "isErrorCallbackCalled"); assert_true(e instanceof DOMException); assert_equals(e.name, 'NotSupportedError'); assert_equals(codec.state, 'closed', 'state'); diff --git a/tests/wpt/tests/webcodecs/video-decoder.https.any.js b/tests/wpt/tests/webcodecs/video-decoder.https.any.js index 190a524dd6c..77a610bd4ea 100644 --- a/tests/wpt/tests/webcodecs/video-decoder.https.any.js +++ b/tests/wpt/tests/webcodecs/video-decoder.https.any.js @@ -96,20 +96,23 @@ validButUnsupportedConfigs.forEach(entry => { }); validButUnsupportedConfigs.forEach(entry => { - async_test( + promise_test( t => { + let isErrorCallbackCalled = false; let codec = new VideoDecoder({ output: t.unreached_func('unexpected output'), - error: t.step_func_done(e => { + error: t.step_func(e => { + isErrorCallbackCalled = true; assert_true(e instanceof DOMException); assert_equals(e.name, 'NotSupportedError'); assert_equals(codec.state, 'closed', 'state'); }) }); codec.configure(entry.config); - codec.flush() + return codec.flush() .then(t.unreached_func('flush succeeded unexpectedly')) .catch(t.step_func(e => { + assert_true(isErrorCallbackCalled, "isErrorCallbackCalled"); assert_true(e instanceof DOMException); assert_equals(e.name, 'NotSupportedError'); assert_equals(codec.state, 'closed', 'state'); diff --git a/tests/wpt/tests/webcodecs/video-encoder-config.https.any.js b/tests/wpt/tests/webcodecs/video-encoder-config.https.any.js index e4807361fca..5011bfdd0a8 100644 --- a/tests/wpt/tests/webcodecs/video-encoder-config.https.any.js +++ b/tests/wpt/tests/webcodecs/video-encoder-config.https.any.js @@ -189,20 +189,23 @@ validButUnsupportedConfigs.forEach(entry => { }); validButUnsupportedConfigs.forEach(entry => { - async_test( + promise_test( t => { + let isErrorCallbackCalled = false; let codec = new VideoEncoder({ output: t.unreached_func('unexpected output'), error: t.step_func_done(e => { + isErrorCallbackCalled = true; assert_true(e instanceof DOMException); assert_equals(e.name, 'NotSupportedError'); assert_equals(codec.state, 'closed', 'state'); }) }); codec.configure(entry.config); - codec.flush() + return codec.flush() .then(t.unreached_func('flush succeeded unexpectedly')) .catch(t.step_func(e => { + assert_true(isErrorCallbackCalled, "isErrorCallbackCalled"); assert_true(e instanceof DOMException); assert_equals(e.name, 'NotSupportedError'); assert_equals(codec.state, 'closed', 'state'); diff --git a/tests/wpt/tests/webdriver/tests/bidi/browsing_context/context_destroyed/__init__.py b/tests/wpt/tests/webdriver/tests/bidi/browsing_context/context_destroyed/__init__.py new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/tests/wpt/tests/webdriver/tests/bidi/browsing_context/context_destroyed/__init__.py diff --git a/tests/wpt/tests/webdriver/tests/bidi/browsing_context/context_destroyed/context_destroyed.py b/tests/wpt/tests/webdriver/tests/bidi/browsing_context/context_destroyed/context_destroyed.py new file mode 100644 index 00000000000..5baac7abd2d --- /dev/null +++ b/tests/wpt/tests/webdriver/tests/bidi/browsing_context/context_destroyed/context_destroyed.py @@ -0,0 +1,248 @@ +import pytest +from webdriver.bidi.modules.script import ContextTarget +from webdriver.error import TimeoutException + +from tests.support.sync import AsyncPoll +from .. import assert_browsing_context + +pytestmark = pytest.mark.asyncio + +CONTEXT_DESTROYED_EVENT = "browsingContext.contextDestroyed" + + +async def test_unsubscribe(bidi_session, new_tab): + await bidi_session.session.subscribe(events=[CONTEXT_DESTROYED_EVENT]) + await bidi_session.session.unsubscribe(events=[CONTEXT_DESTROYED_EVENT]) + + # Track all received browsingContext.contextDestroyed events in the events array + events = [] + + async def on_event(_, data): + events.append(data) + + remove_listener = bidi_session.add_event_listener(CONTEXT_DESTROYED_EVENT, on_event) + + await bidi_session.browsing_context.close(context=new_tab["context"]) + + wait = AsyncPoll(bidi_session, timeout=0.5) + with pytest.raises(TimeoutException): + await wait.until(lambda _: len(events) > 0) + + remove_listener() + + +@pytest.mark.parametrize("type_hint", ["tab", "window"]) +async def test_new_context(bidi_session, wait_for_event, subscribe_events, type_hint): + await subscribe_events([CONTEXT_DESTROYED_EVENT]) + + on_entry = wait_for_event(CONTEXT_DESTROYED_EVENT) + new_context = await bidi_session.browsing_context.create(type_hint=type_hint) + + await bidi_session.browsing_context.close(context=new_context["context"]) + + context_info = await on_entry + + assert_browsing_context( + context_info, + new_context["context"], + children=None, + url="about:blank", + parent=None, + ) + + +@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"]) +async def test_navigate(bidi_session, subscribe_events, new_tab, inline, domain): + await subscribe_events([CONTEXT_DESTROYED_EVENT]) + + # Track all received browsingContext.contextDestroyed events in the events array + events = [] + + async def on_event(_, data): + events.append(data) + + remove_listener = bidi_session.add_event_listener(CONTEXT_DESTROYED_EVENT, on_event) + + url = inline(f"<div>test</div>", domain=domain) + await bidi_session.browsing_context.navigate( + url=url, context=new_tab["context"], wait="complete" + ) + + # Make sure navigation doesn't cause the context to be destroyed + wait = AsyncPoll(bidi_session, timeout=0.5) + with pytest.raises(TimeoutException): + await wait.until(lambda _: len(events) > 0) + + remove_listener() + + +@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"]) +async def test_navigate_iframe( + bidi_session, wait_for_event, subscribe_events, new_tab, inline, domain +): + await subscribe_events([CONTEXT_DESTROYED_EVENT]) + + on_entry = wait_for_event(CONTEXT_DESTROYED_EVENT) + + frame_url = inline("<div>foo</div>") + url = inline(f"<iframe src='{frame_url}'></iframe>") + await bidi_session.browsing_context.navigate( + url=url, context=new_tab["context"], wait="complete" + ) + + contexts = await bidi_session.browsing_context.get_tree(root=new_tab["context"]) + frame = contexts[0]["children"][0] + + # Navigate to destroy iframes + url = inline(f"<iframe src='{frame_url}'></iframe>", domain=domain) + await bidi_session.browsing_context.navigate( + url=url, context=new_tab["context"], wait="complete" + ) + + context_info = await on_entry + + assert_browsing_context( + context_info, + frame["context"], + children=None, + url=frame_url, + parent=new_tab["context"], + ) + + +async def test_delete_iframe( + bidi_session, wait_for_event, subscribe_events, new_tab, inline +): + await subscribe_events([CONTEXT_DESTROYED_EVENT]) + + on_entry = wait_for_event(CONTEXT_DESTROYED_EVENT) + + frame_url = inline("<div>foo</div>") + url = inline(f"<iframe src='{frame_url}'></iframe>") + await bidi_session.browsing_context.navigate( + url=url, context=new_tab["context"], wait="complete" + ) + + contexts = await bidi_session.browsing_context.get_tree(root=new_tab["context"]) + iframe = contexts[0]["children"][0] + + # Delete the iframe + await bidi_session.script.evaluate( + expression="""document.querySelector('iframe').remove()""", + target=ContextTarget(new_tab["context"]), + await_promise=False, + ) + + context_info = await on_entry + + assert_browsing_context( + context_info, + iframe["context"], + children=None, + url=frame_url, + parent=new_tab["context"], + ) + + +async def test_delete_nested_iframes( + bidi_session, + subscribe_events, + new_tab, + test_page_nested_frames, + test_page_same_origin_frame, +): + await subscribe_events([CONTEXT_DESTROYED_EVENT]) + # Track all received browsingContext.contextDestroyed events in the events array + events = [] + + async def on_event(_, data): + events.append(data) + + remove_listener = bidi_session.add_event_listener(CONTEXT_DESTROYED_EVENT, on_event) + + await bidi_session.browsing_context.navigate( + url=test_page_nested_frames, context=new_tab["context"], wait="complete" + ) + + contexts = await bidi_session.browsing_context.get_tree(root=new_tab["context"]) + top_iframe = contexts[0]["children"][0] + + # Delete top iframe + await bidi_session.script.evaluate( + expression="""document.querySelector('iframe').remove()""", + target=ContextTarget(new_tab["context"]), + await_promise=False, + ) + + assert len(events) == 1 + assert_browsing_context( + events[0], + top_iframe["context"], + children=None, + url=test_page_same_origin_frame, + parent=new_tab["context"], + ) + + remove_listener() + + +async def test_iframe_destroy_parent( + bidi_session, subscribe_events, new_tab, test_page_nested_frames +): + await subscribe_events([CONTEXT_DESTROYED_EVENT]) + # Track all received browsingContext.contextDestroyed events in the events array + events = [] + + async def on_event(_, data): + events.append(data) + + remove_listener = bidi_session.add_event_listener(CONTEXT_DESTROYED_EVENT, on_event) + + await bidi_session.browsing_context.navigate( + url=test_page_nested_frames, context=new_tab["context"], wait="complete" + ) + + # Destroy top context + await bidi_session.browsing_context.close(context=new_tab["context"]) + + assert len(events) == 1 + assert_browsing_context( + events[0], + new_tab["context"], + children=None, + url=test_page_nested_frames, + parent=None, + ) + + remove_listener() + + +async def test_subscribe_to_one_context(bidi_session, subscribe_events, new_tab): + # Subscribe to a specific context + await subscribe_events( + events=[CONTEXT_DESTROYED_EVENT], contexts=[new_tab["context"]] + ) + + # Track all received browsingContext.contextDestroyed events in the events array + events = [] + + async def on_event(_, data): + events.append(data) + + remove_listener = bidi_session.add_event_listener(CONTEXT_DESTROYED_EVENT, on_event) + + another_new_tab = await bidi_session.browsing_context.create(type_hint="tab") + await bidi_session.browsing_context.close(context=another_new_tab["context"]) + + # Make sure we didn't receive the event for the new tab + wait = AsyncPoll(bidi_session, timeout=0.5) + with pytest.raises(TimeoutException): + await wait.until(lambda _: len(events) > 0) + + await bidi_session.browsing_context.close(context=new_tab["context"]) + + # Make sure we received the event + await wait.until(lambda _: len(events) >= 1) + assert len(events) == 1 + + remove_listener() diff --git a/tests/wpt/tests/webdriver/tests/bidi/browsing_context/user_prompt_opened/user_prompt_opened.py b/tests/wpt/tests/webdriver/tests/bidi/browsing_context/user_prompt_opened/user_prompt_opened.py index a24a1e86aba..a2d5d840a49 100644 --- a/tests/wpt/tests/webdriver/tests/bidi/browsing_context/user_prompt_opened/user_prompt_opened.py +++ b/tests/wpt/tests/webdriver/tests/bidi/browsing_context/user_prompt_opened/user_prompt_opened.py @@ -56,29 +56,40 @@ async def test_prompt_type( } +@pytest.mark.parametrize( + "default", [None, "", "default"], ids=["null", "empty string", "non empty string"] +) async def test_prompt_default_value( - bidi_session, inline, new_tab, subscribe_events, wait_for_event + bidi_session, inline, new_tab, subscribe_events, wait_for_event, default ): await subscribe_events(events=[USER_PROMPT_OPENED_EVENT]) on_entry = wait_for_event(USER_PROMPT_OPENED_EVENT) text = "test" - default = "default" + + if default is None: + script = f"<script>window.prompt('{text}', null)</script>" + else: + script = f"<script>window.prompt('{text}', '{default}')</script>" await bidi_session.browsing_context.navigate( context=new_tab["context"], - url=inline(f"<script>window.prompt('{text}', '{default}')</script>"), + url=inline(script), ) event = await on_entry - assert event == { + expected_event = { "context": new_tab["context"], "type": "prompt", "message": text, - "defaultValue": default, } + if default is not None: + expected_event["defaultValue"] = default + + assert event == expected_event + @pytest.mark.parametrize("type_hint", ["tab", "window"]) async def test_subscribe_to_one_context( diff --git a/tests/wpt/tests/webdriver/tests/bidi/script/call_function/result_node.py b/tests/wpt/tests/webdriver/tests/bidi/script/call_function/result_node.py index 9d09b9fc04a..47cbd42d22d 100644 --- a/tests/wpt/tests/webdriver/tests/bidi/script/call_function/result_node.py +++ b/tests/wpt/tests/webdriver/tests/bidi/script/call_function/result_node.py @@ -506,34 +506,147 @@ async def test_document_fragment_node( @pytest.mark.asyncio -async def test_node_within_object(bidi_session, get_test_page, top_context): +@pytest.mark.parametrize( + "function_declaration, expected", + [ + ( + """ + () => [document.querySelector("img")] + """, + { + "type": "array", + "value": [ + { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1, + }, + }, + ], + }, + ), + ( + """ + () => { + const map = new Map(); + map.set(document.querySelector("img"), "elem"); + return map; + } + """, + { + "type": "map", + "value": [[ + { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1 + } + }, + { + "type": "string", + "value": "elem" + } + ]] + } + ), + ( + """ + () => { + const map = new Map(); + map.set("elem", document.querySelector("img")); + return map; + } + """, + { + "type": "map", + "value": [[ + "elem", { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1 + } + } + ]] + } + ), + ( + """ + () => ({"elem": document.querySelector("img")}) + """, + { + "type": "object", + "value": [ + ["elem", { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1 + } + }] + ] + } + ), + ( + """ + () => { + const set = new Set(); + set.add(document.querySelector("img")); + return set; + } + """, + { + "type": "set", + "value": [ + { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1, + }, + }, + ], + }, + ), + ], ids=[ + "array", "map-key", "map-value", "object", "set" + ] +) +async def test_node_embedded_within( + bidi_session, get_test_page, top_context, function_declaration, expected +): await bidi_session.browsing_context.navigate( context=top_context['context'], url=get_test_page(), wait="complete" ) result = await bidi_session.script.call_function( - function_declaration="""() => ({"elem": document.querySelector("img")})""", + function_declaration=function_declaration, target=ContextTarget(top_context["context"]), await_promise=False, ) - expected = { - "type": "object", - "value": [ - ["elem", { - "type": "node", - "sharedId": any_string, - "value": { - "attributes": {}, - "childNodeCount": 0, - "localName": "img", - "namespaceURI": "http://www.w3.org/1999/xhtml", - "nodeType": 1 - } - }] - ] - } - recursive_compare(expected, result) diff --git a/tests/wpt/tests/webdriver/tests/bidi/script/classic_interop/node_shared_id.py b/tests/wpt/tests/webdriver/tests/bidi/script/classic_interop/node_shared_id.py index 82b39b42e1c..aeb2bc45978 100644 --- a/tests/wpt/tests/webdriver/tests/bidi/script/classic_interop/node_shared_id.py +++ b/tests/wpt/tests/webdriver/tests/bidi/script/classic_interop/node_shared_id.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element, ShadowRoot +from webdriver import ShadowRoot, WebElement from webdriver.bidi.modules.script import ContextTarget pytestmark = pytest.mark.asyncio @@ -51,7 +51,7 @@ async def test_web_element_reference_created_in_bidi( assert nodeType == ELEMENT_NODE # Use element reference from WebDriver BiDi in WebDriver classic - node = Element(current_session, result["sharedId"]) + node = WebElement(current_session, result["sharedId"]) nodeType = current_session.execute_script( """return arguments[0].nodeType""", args=(node,) ) diff --git a/tests/wpt/tests/webdriver/tests/bidi/script/evaluate/result_node.py b/tests/wpt/tests/webdriver/tests/bidi/script/evaluate/result_node.py index a3ca316d027..a0bfd0d4c02 100644 --- a/tests/wpt/tests/webdriver/tests/bidi/script/evaluate/result_node.py +++ b/tests/wpt/tests/webdriver/tests/bidi/script/evaluate/result_node.py @@ -494,34 +494,141 @@ async def test_document_fragment_node( @pytest.mark.asyncio -async def test_node_within_object(bidi_session, get_test_page, top_context): +@pytest.mark.parametrize( + "expression, expected", + [ + ( + """ + [document.querySelector("img")] + """, + { + "type": "array", + "value": [ + { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1, + }, + }, + ], + }, + ), + ( + """ + const map = new Map(); + map.set(document.querySelector("img"), "elem"); + map + """, + { + "type": "map", + "value": [[ + { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1 + } + }, + { + "type": "string", + "value": "elem" + } + ]] + } + ), + ( + """ + const map = new Map(); + map.set("elem", document.querySelector("img")); + map + """, + { + "type": "map", + "value": [[ + "elem", { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1 + } + } + ]] + } + ), + ( + """ + ({"elem": document.querySelector("img")}) + """, + { + "type": "object", + "value": [ + ["elem", { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1 + } + }] + ] + } + ), + ( + """ + const set = new Set(); + set.add(document.querySelector("img")); + set + """, + { + "type": "set", + "value": [ + { + "type": "node", + "sharedId": any_string, + "value": { + "attributes": {}, + "childNodeCount": 0, + "localName": "img", + "namespaceURI": "http://www.w3.org/1999/xhtml", + "nodeType": 1, + }, + }, + ], + }, + ), + ], ids=[ + "array", "map-key", "map-value", "object", "set" + ] +) +async def test_node_embedded_within( + bidi_session, get_test_page, top_context, expression, expected +): await bidi_session.browsing_context.navigate( context=top_context['context'], url=get_test_page(), wait="complete" ) result = await bidi_session.script.evaluate( - expression="""({"elem": document.querySelector("img")})""", + expression=expression, target=ContextTarget(top_context["context"]), await_promise=False, ) - expected = { - "type": "object", - "value": [ - ["elem", { - "type": "node", - "sharedId": any_string, - "value": { - "attributes": {}, - "childNodeCount": 0, - "localName": "img", - "namespaceURI": "http://www.w3.org/1999/xhtml", - "nodeType": 1 - } - }] - ] - } - recursive_compare(expected, result) diff --git a/tests/wpt/tests/webdriver/tests/classic/element_clear/clear.py b/tests/wpt/tests/webdriver/tests/classic/element_clear/clear.py index 9b0d7f2133f..22c07b6a8ce 100644 --- a/tests/wpt/tests/webdriver/tests/classic/element_clear/clear.py +++ b/tests/wpt/tests/webdriver/tests/classic/element_clear/clear.py @@ -1,7 +1,7 @@ # META: timeout=long import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import ( assert_element_has_focus, @@ -45,7 +45,7 @@ def test_null_response_value(session, inline): def test_no_top_browsing_context(session, closed_window): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_clear(session, element) assert_error(response, "no such window") @@ -59,14 +59,14 @@ def test_no_top_browsing_context(session, closed_window): def test_no_browsing_context(session, closed_frame): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_clear(session, element) assert_error(response, "no such window") def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_clear(session, element) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/element_click/click.py b/tests/wpt/tests/webdriver/tests/classic/element_click/click.py index 3c3f7d70e6c..61acc923e8e 100644 --- a/tests/wpt/tests/webdriver/tests/classic/element_click/click.py +++ b/tests/wpt/tests/webdriver/tests/classic/element_click/click.py @@ -1,5 +1,5 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success @@ -21,7 +21,7 @@ def test_null_response_value(session, inline): def test_no_top_browsing_context(session, closed_window): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_click(session, element) assert_error(response, "no such window") @@ -35,14 +35,14 @@ def test_no_top_browsing_context(session, closed_window): def test_no_browsing_context(session, closed_frame): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_click(session, element) assert_error(response, "no such window") def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_click(session, element) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/element_click/events.py b/tests/wpt/tests/webdriver/tests/classic/element_click/events.py index 30f2dfa0a4a..5e80b52e879 100644 --- a/tests/wpt/tests/webdriver/tests/classic/element_click/events.py +++ b/tests/wpt/tests/webdriver/tests/classic/element_click/events.py @@ -1,4 +1,4 @@ -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_success from tests.support.helpers import filter_dict diff --git a/tests/wpt/tests/webdriver/tests/classic/element_send_keys/send_keys.py b/tests/wpt/tests/webdriver/tests/classic/element_send_keys/send_keys.py index 281c7ad719d..92002f29457 100644 --- a/tests/wpt/tests/webdriver/tests/classic/element_send_keys/send_keys.py +++ b/tests/wpt/tests/webdriver/tests/classic/element_send_keys/send_keys.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from webdriver.transport import Response from tests.support.asserts import assert_error, assert_success @@ -34,7 +34,7 @@ def test_null_response_value(session, inline): def test_no_top_browsing_context(session, closed_window): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_send_keys(session, element, "foo") assert_error(response, "no such window") @@ -48,14 +48,14 @@ def test_no_top_browsing_context(session, closed_window): def test_no_browsing_context(session, closed_frame): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_send_keys(session, element, "foo") assert_error(response, "no such window") def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = element_send_keys(session, element, "foo") assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_async_script/arguments.py b/tests/wpt/tests/webdriver/tests/classic/execute_async_script/arguments.py index ead6e0c186e..81b30de2678 100644 --- a/tests/wpt/tests/webdriver/tests/classic/execute_async_script/arguments.py +++ b/tests/wpt/tests/webdriver/tests/classic/execute_async_script/arguments.py @@ -1,6 +1,6 @@ import pytest -from webdriver.client import Element, Frame, ShadowRoot, Window +from webdriver.client import ShadowRoot, WebElement, WebFrame, WebWindow from tests.support.asserts import assert_error, assert_success from . import execute_async_script @@ -54,8 +54,8 @@ def test_object(session): assert actual[1] == value -def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") +def test_no_such_element_with_unknown_id(session): + element = WebElement(session, "foo") result = execute_async_script(session, """ arguments[1](true); @@ -101,7 +101,7 @@ def test_no_such_element_from_other_frame(session, get_test_page, closed): assert_error(result, "no such element") -def test_no_such_shadow_root_with_unknown_shadow_root(session): +def test_no_such_shadow_root_with_unknown_id(session): shadow_root = ShadowRoot(session, "foo") result = execute_async_script(session, """ @@ -159,18 +159,47 @@ def test_stale_element_reference(session, stale_element, as_frame): assert_error(result, "stale element reference") -@pytest.mark.parametrize("expression, expected_type, expected_class", [ - ("window.frames[0]", Frame, "Frame"), - ("document.querySelector('div')", Element, "HTMLDivElement"), - ("document.querySelector('custom-element').shadowRoot", ShadowRoot, "ShadowRoot"), - ("window", Window, "Window") +@pytest.mark.parametrize("type", [WebFrame, WebWindow], ids=["frame", "window"]) +@pytest.mark.parametrize("value", [None, False, 42, [], {}]) +def test_invalid_argument_for_window_with_invalid_type(session, type, value): + reference = type(session, value) + + result = execute_async_script(session, "arguments[1](true)", args=(reference,)) + assert_error(result, "invalid argument") + + +def test_no_such_window_for_window_with_invalid_value(session, get_test_page): + session.url = get_test_page() + + result = execute_async_script(session, "arguments[0]([window, window.frames[0]]);") + [window, frame] = assert_success(result) + + assert isinstance(window, WebWindow) + assert isinstance(frame, WebFrame) + + window_reference = WebWindow(session, frame.id) + frame_reference = WebFrame(session, window.id) + + for reference in [window_reference, frame_reference]: + result = execute_async_script(session, "arguments[1](true)", args=(reference,)) + assert_error(result, "no such window") + + +@pytest.mark.parametrize("expression, expected_type", [ + ("window.frames[0]", WebFrame), + ("document.querySelector('div')", WebElement), + ("document.querySelector('custom-element').shadowRoot", ShadowRoot), + ("window", WebWindow) ], ids=["frame", "node", "shadow-root", "window"]) -def test_element_reference(session, get_test_page, expression, expected_type, expected_class): +def test_element_reference(session, get_test_page, expression, expected_type): session.url = get_test_page(as_frame=False) result = execute_async_script(session, f"arguments[0]({expression})") reference = assert_success(result) assert isinstance(reference, expected_type) - result = execute_async_script(session, "arguments[1](arguments[0].constructor.name)", [reference]) - assert_success(result, expected_class) + result = execute_async_script(session, f""" + let resolve = arguments[1]; + resolve(arguments[0] == {expression}) + """, [reference]) + assert_success(result, True) diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_async_script/execute_async.py b/tests/wpt/tests/webdriver/tests/classic/execute_async_script/execute_async.py index 42cf4aacee8..3c8cc6210d4 100644 --- a/tests/wpt/tests/webdriver/tests/classic/execute_async_script/execute_async.py +++ b/tests/wpt/tests/webdriver/tests/classic/execute_async_script/execute_async.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from webdriver.error import NoSuchAlertException from webdriver.transport import Response @@ -16,12 +16,12 @@ def test_null_parameter_value(session, http): def test_no_top_browsing_context(session, closed_window): - response = execute_async_script(session, "argument[0](1);") + response = execute_async_script(session, "arguments[0](1);") assert_error(response, "no such window") def test_no_browsing_context(session, closed_frame): - response = execute_async_script(session, "argument[0](1);") + response = execute_async_script(session, "arguments[0](1);") assert_error(response, "no such window") diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_async_script/node.py b/tests/wpt/tests/webdriver/tests/classic/execute_async_script/node.py index 53abda4b300..2f1bf75e83c 100644 --- a/tests/wpt/tests/webdriver/tests/classic/execute_async_script/node.py +++ b/tests/wpt/tests/webdriver/tests/classic/execute_async_script/node.py @@ -1,6 +1,6 @@ import pytest -from webdriver.client import Element, Frame, ShadowRoot, Window +from webdriver.client import ShadowRoot, WebElement from tests.support.asserts import assert_error, assert_success from . import execute_async_script @@ -59,11 +59,9 @@ def test_stale_element(session, get_test_page, as_frame): @pytest.mark.parametrize("expression, expected_type", [ - ("window.frames[0]", Frame), - ("document.querySelector('div')", Element), + ("document.querySelector('div')", WebElement), ("document.querySelector('custom-element').shadowRoot", ShadowRoot), - ("window", Window), -], ids=["frame", "node", "shadow-root", "window"]) +], ids=["element", "shadow-root"]) def test_element_reference(session, get_test_page, expression, expected_type): session.url = get_test_page() @@ -81,7 +79,7 @@ def test_element_reference(session, get_test_page, expression, expected_type): (""" document"""), (""" document.doctype"""), ], ids=["attribute", "text", "cdata", "processing_instruction", "comment", "document", "doctype"]) -def test_non_element_nodes(session, inline, expression): +def test_not_supported_nodes(session, inline, expression): session.url = inline(PAGE_DATA) result = execute_async_script(session, f"arguments[0]({expression})") diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_async_script/window.py b/tests/wpt/tests/webdriver/tests/classic/execute_async_script/window.py new file mode 100644 index 00000000000..f79bfdf49d9 --- /dev/null +++ b/tests/wpt/tests/webdriver/tests/classic/execute_async_script/window.py @@ -0,0 +1,33 @@ +import pytest + +from webdriver.client import WebFrame, WebWindow + +from tests.support.asserts import assert_success +from . import execute_async_script + + +@pytest.mark.parametrize("expression, expected_type", [ + ("window.frames[0]", WebFrame), + ("window", WebWindow), +], ids=["frame", "window"]) +def test_web_reference(session, get_test_page, expression, expected_type): + session.url = get_test_page() + + result = execute_async_script(session, f"arguments[0]({expression})") + reference = assert_success(result) + + assert isinstance(reference, expected_type) + + if isinstance(reference, WebWindow): + assert reference.id in session.handles + else: + assert reference.id not in session.handles + + +def test_window_open(session): + result = execute_async_script( + session, "window.foo = window.open(); arguments[0](window.foo);") + reference = assert_success(result) + + assert isinstance(reference, WebWindow) + assert reference.id in session.handles diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_script/arguments.py b/tests/wpt/tests/webdriver/tests/classic/execute_script/arguments.py index b8657ce0efa..ab5c5234ba1 100644 --- a/tests/wpt/tests/webdriver/tests/classic/execute_script/arguments.py +++ b/tests/wpt/tests/webdriver/tests/classic/execute_script/arguments.py @@ -1,6 +1,6 @@ import pytest -from webdriver.client import Element, Frame, ShadowRoot, Window +from webdriver.client import ShadowRoot, WebElement, WebFrame, WebWindow from tests.support.asserts import assert_error, assert_success from . import execute_script @@ -46,8 +46,8 @@ def test_object(session): assert actual[1] == value -def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") +def test_no_such_element_with_unknown_id(session): + element = WebElement(session, "foo") result = execute_script(session, "return true;", args=[element]) assert_error(result, "no such element") @@ -87,7 +87,7 @@ def test_no_such_element_from_other_frame(session, get_test_page, closed): assert_error(result, "no such element") -def test_no_such_shadow_root_with_unknown_shadow_root(session): +def test_no_such_shadow_root_with_unknown_id(session): shadow_root = ShadowRoot(session, "foo") result = execute_script(session, "return true;", args=[shadow_root]) @@ -147,18 +147,44 @@ def test_stale_element_reference(session, stale_element, as_frame): assert_error(result, "stale element reference") -@pytest.mark.parametrize("expression, expected_type, expected_class", [ - ("window.frames[0]", Frame, "Frame"), - ("document.querySelector('div')", Element, "HTMLDivElement"), - ("document.querySelector('custom-element').shadowRoot", ShadowRoot, "ShadowRoot"), - ("window", Window, "Window") +@pytest.mark.parametrize("type", [WebFrame, WebWindow], ids=["frame", "window"]) +@pytest.mark.parametrize("value", [None, False, 42, [], {}]) +def test_invalid_argument_for_window_with_invalid_type(session, type, value): + reference = type(session, value) + + result = execute_script(session, "return true", args=(reference,)) + assert_error(result, "invalid argument") + + +def test_no_such_window_for_window_with_invalid_value(session, get_test_page): + session.url = get_test_page() + + result = execute_script(session, "return [window, window.frames[0]];") + [window, frame] = assert_success(result) + + assert isinstance(window, WebWindow) + assert isinstance(frame, WebFrame) + + window_reference = WebWindow(session, frame.id) + frame_reference = WebFrame(session, window.id) + + for reference in [window_reference, frame_reference]: + result = execute_script(session, "return true", args=(reference,)) + assert_error(result, "no such window") + + +@pytest.mark.parametrize("expression, expected_type", [ + ("window.frames[0]", WebFrame), + ("document.querySelector('div')", WebElement), + ("document.querySelector('custom-element').shadowRoot", ShadowRoot), + ("window", WebWindow) ], ids=["frame", "node", "shadow-root", "window"]) -def test_element_reference(session, get_test_page, expression, expected_type, expected_class): +def test_element_reference(session, get_test_page, expression, expected_type): session.url = get_test_page(as_frame=False) result = execute_script(session, f"return {expression}") reference = assert_success(result) assert isinstance(reference, expected_type) - result = execute_script(session, "return arguments[0].constructor.name", [reference]) - assert_success(result, expected_class) + result = execute_script(session, f"return arguments[0] == {expression}", [reference]) + assert_success(result, True) diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_script/execute.py b/tests/wpt/tests/webdriver/tests/classic/execute_script/execute.py index fbccc986338..15ac1d0132a 100644 --- a/tests/wpt/tests/webdriver/tests/classic/execute_script/execute.py +++ b/tests/wpt/tests/webdriver/tests/classic/execute_script/execute.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from webdriver.error import NoSuchAlertException from webdriver.transport import Response diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_script/json_serialize_windowproxy.py b/tests/wpt/tests/webdriver/tests/classic/execute_script/json_serialize_windowproxy.py deleted file mode 100644 index 8e76feda238..00000000000 --- a/tests/wpt/tests/webdriver/tests/classic/execute_script/json_serialize_windowproxy.py +++ /dev/null @@ -1,51 +0,0 @@ -import json - -from tests.support.asserts import assert_success -from . import execute_script - -_window_id = "window-fcc6-11e5-b4f8-330a88ab9d7f" -_frame_id = "frame-075b-4da1-b6ba-e579c2d3230a" - - -def test_initial_window(session): - # non-auxiliary top-level browsing context - response = execute_script(session, "return window;") - raw_json = assert_success(response) - - obj = json.loads(raw_json) - assert len(obj) == 1 - assert _window_id in obj - handle = obj[_window_id] - assert handle in session.window_handles - - -def test_window_open(session): - # auxiliary browsing context - session.execute_script("window.foo = window.open()") - - response = execute_script(session, "return window.foo;") - raw_json = assert_success(response) - - obj = json.loads(raw_json) - assert len(obj) == 1 - assert _window_id in obj - handle = obj[_window_id] - assert handle in session.window_handles - - -def test_frame(session): - # nested browsing context - append = """ - window.frame = document.createElement('iframe'); - document.body.appendChild(frame); - """ - session.execute_script(append) - - response = execute_script(session, "return frame.contentWindow;") - raw_json = assert_success(response) - - obj = json.loads(raw_json) - assert len(obj) == 1 - assert _frame_id in obj - handle = obj[_frame_id] - assert handle not in session.window_handles diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_script/node.py b/tests/wpt/tests/webdriver/tests/classic/execute_script/node.py index caf85988f15..61cf3463dcb 100644 --- a/tests/wpt/tests/webdriver/tests/classic/execute_script/node.py +++ b/tests/wpt/tests/webdriver/tests/classic/execute_script/node.py @@ -1,6 +1,6 @@ import pytest -from webdriver.client import Element, Frame, ShadowRoot, Window +from webdriver.client import WebElement, ShadowRoot from tests.support.asserts import assert_error, assert_success from . import execute_script @@ -58,12 +58,10 @@ def test_stale_element(session, get_test_page, as_frame): @pytest.mark.parametrize("expression, expected_type", [ - ("window.frames[0]", Frame), - ("document.querySelector('div')", Element), + ("document.querySelector('div')", WebElement), ("document.querySelector('custom-element').shadowRoot", ShadowRoot), - ("window", Window), -], ids=["frame", "node", "shadow-root", "window"]) -def test_element_reference(session, get_test_page, expression, expected_type): +], ids=["element", "shadow-root"]) +def test_web_reference(session, get_test_page, expression, expected_type): session.url = get_test_page() result = execute_script(session, f"return {expression}") @@ -80,7 +78,7 @@ def test_element_reference(session, get_test_page, expression, expected_type): (""" document"""), (""" document.doctype"""), ], ids=["attribute", "text", "cdata", "processing_instruction", "comment", "document", "doctype"]) -def test_non_element_nodes(session, inline, expression): +def test_not_supported_nodes(session, inline, expression): session.url = inline(PAGE_DATA) result = execute_script(session, f"return {expression}") diff --git a/tests/wpt/tests/webdriver/tests/classic/execute_script/window.py b/tests/wpt/tests/webdriver/tests/classic/execute_script/window.py new file mode 100644 index 00000000000..9ab45d7cb78 --- /dev/null +++ b/tests/wpt/tests/webdriver/tests/classic/execute_script/window.py @@ -0,0 +1,87 @@ +import pytest + +from webdriver.client import WebFrame, WebWindow + +from tests.support.asserts import assert_success +from . import execute_script + + +@pytest.mark.parametrize("expression, expected_type", [ + ("window.frames[0]", WebFrame), + ("window", WebWindow), +], ids=["frame", "window"]) +def test_web_reference(session, get_test_page, expression, expected_type): + session.url = get_test_page() + + result = execute_script(session, f"return {expression}") + reference = assert_success(result) + + assert isinstance(reference, expected_type) + + if isinstance(reference, WebWindow): + assert reference.id in session.handles + else: + assert reference.id not in session.handles + + +@pytest.mark.parametrize("expression, expected_type", [ + ("window.frames[0]", WebFrame), + ("window", WebWindow), +], ids=["frame", "window"]) +def test_web_reference_in_array(session, get_test_page, expression, expected_type): + session.url = get_test_page() + + result = execute_script(session, f"return [{expression}]") + value = assert_success(result) + + assert isinstance(value[0], expected_type) + + if isinstance(value[0], WebWindow): + assert value[0].id in session.handles + else: + assert value[0].id not in session.handles + + +@pytest.mark.parametrize("expression, expected_type", [ + ("window.frames[0]", WebFrame), + ("window", WebWindow), +], ids=["frame", "window"]) +def test_web_reference_in_object(session, get_test_page, expression, expected_type): + session.url = get_test_page() + + result = execute_script(session, f"""return {{"ref": {expression}}}""") + reference = assert_success(result) + + assert isinstance(reference["ref"], expected_type) + + if isinstance(reference["ref"], WebWindow): + assert reference["ref"].id in session.handles + else: + assert reference["ref"].id not in session.handles + + +def test_window_open(session): + result = execute_script(session, "window.foo = window.open(); return window.foo;") + reference = assert_success(result) + + assert isinstance(reference, WebWindow) + assert reference.id in session.handles + + +def test_same_id_after_cross_origin_navigation(session, get_test_page): + params = {"pipe": "header(Cross-Origin-Opener-Policy,same-origin)"} + + first_page = get_test_page(parameters=params, protocol="https") + second_page = get_test_page(parameters=params, protocol="https", domain="alt") + + session.url = first_page + + result = execute_script(session, "return window") + window_before = assert_success(result) + + session.url = second_page + + result = execute_script(session, "return window") + window_after = assert_success(result) + + assert window_before == window_after diff --git a/tests/wpt/tests/webdriver/tests/classic/find_element_from_shadow_root/find.py b/tests/wpt/tests/webdriver/tests/classic/find_element_from_shadow_root/find.py index 3f1b64a61c5..c658152ee69 100644 --- a/tests/wpt/tests/webdriver/tests/classic/find_element_from_shadow_root/find.py +++ b/tests/wpt/tests/webdriver/tests/classic/find_element_from_shadow_root/find.py @@ -1,5 +1,5 @@ import pytest -from webdriver.client import Element, ShadowRoot +from webdriver.client import WebElement, ShadowRoot from webdriver.transport import Response from tests.support.asserts import assert_error, assert_same_element, assert_success @@ -174,7 +174,7 @@ def test_find_element(session, get_test_page, using, value, mode): result = find_element(session, shadow_root.id, using, value) value = assert_success(result) - element = Element.from_json(value, session) + element = WebElement.from_json(value, session) assert element.text == expected_text @@ -243,5 +243,5 @@ def test_find_element_in_nested_shadow_root(session, get_test_page, mode): result = find_element(session, nested_shadow_root.id, "css selector", "#linkText") value = assert_success(result) - element = Element.from_json(value, session) + element = WebElement.from_json(value, session) assert element.text == expected_text diff --git a/tests/wpt/tests/webdriver/tests/classic/find_elements_from_shadow_root/find.py b/tests/wpt/tests/webdriver/tests/classic/find_elements_from_shadow_root/find.py index ffdaa7e84b0..188fff29212 100644 --- a/tests/wpt/tests/webdriver/tests/classic/find_elements_from_shadow_root/find.py +++ b/tests/wpt/tests/webdriver/tests/classic/find_elements_from_shadow_root/find.py @@ -1,5 +1,5 @@ import pytest -from webdriver.client import Element, ShadowRoot +from webdriver.client import WebElement, ShadowRoot from webdriver.transport import Response from tests.support.asserts import assert_error, assert_same_element, assert_success @@ -177,7 +177,7 @@ def test_find_elements(session, get_test_page, using, value, mode): assert len(value) == 1 - element = Element.from_json(value[0], session) + element = WebElement.from_json(value[0], session) assert element.text == expected_text @@ -256,5 +256,5 @@ def test_find_elements_in_nested_shadow_root( assert len(value) == 1 - element = Element.from_json(value[0], session) + element = WebElement.from_json(value[0], session) assert element.text == expected_text diff --git a/tests/wpt/tests/webdriver/tests/classic/get_computed_label/get.py b/tests/wpt/tests/webdriver/tests/classic/get_computed_label/get.py index 0dc00a471a9..e023b79cea5 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_computed_label/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_computed_label/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from webdriver.error import NoSuchAlertException from tests.support.asserts import assert_error, assert_success @@ -19,7 +19,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") result = get_computed_label(session, element.id) assert_error(result, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/get_computed_role/get.py b/tests/wpt/tests/webdriver/tests/classic/get_computed_role/get.py index 51b6a8b3b6d..1b8489675ce 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_computed_role/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_computed_role/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from webdriver.error import NoSuchAlertException from tests.support.asserts import assert_error, assert_success @@ -19,7 +19,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") result = get_computed_role(session, element.id) assert_error(result, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/get_element_attribute/get.py b/tests/wpt/tests/webdriver/tests/classic/get_element_attribute/get.py index 375f25032c0..0fcfd00c97c 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_element_attribute/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_element_attribute/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success @@ -30,7 +30,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = get_element_attribute(session, element.id, "id") assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/get_element_css_value/get.py b/tests/wpt/tests/webdriver/tests/classic/get_element_css_value/get.py index 6f0a8a56395..1f6f571149b 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_element_css_value/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_element_css_value/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success @@ -34,7 +34,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = get_element_css_value(session, element.id, "display") assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/get_element_property/get.py b/tests/wpt/tests/webdriver/tests/classic/get_element_property/get.py index bb63481dfca..12d48a3abb5 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_element_property/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_element_property/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element, Frame, ShadowRoot, Window +from webdriver import WebElement, WebFrame, ShadowRoot, WebWindow from tests.support.asserts import assert_error, assert_same_element, assert_success @@ -31,7 +31,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = get_element_property(session, element.id, "id") assert_error(response, "no such element") @@ -165,10 +165,10 @@ def test_primitives_set_by_execute_script(session, inline, js_primitive, py_prim @pytest.mark.parametrize("js_web_reference,py_web_reference", [ - ("element", Element), - ("frame", Frame), + ("element", WebElement), + ("frame", WebFrame), ("shadowRoot", ShadowRoot), - ("window", Window), + ("window", WebWindow), ]) def test_web_reference(session, get_test_page, js_web_reference, py_web_reference): session.url = get_test_page() diff --git a/tests/wpt/tests/webdriver/tests/classic/get_element_rect/get.py b/tests/wpt/tests/webdriver/tests/classic/get_element_rect/get.py index 942f119f43c..959ccc455ec 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_element_rect/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_element_rect/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success from tests.support.helpers import element_rect @@ -34,7 +34,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = get_element_rect(session, element.id) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/get_element_shadow_root/get.py b/tests/wpt/tests/webdriver/tests/classic/get_element_shadow_root/get.py index d9adde0b9e3..25e68c1bbac 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_element_shadow_root/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_element_shadow_root/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_same_element, assert_success @@ -30,7 +30,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = get_shadow_root(session, element.id) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/get_element_tag_name/get.py b/tests/wpt/tests/webdriver/tests/classic/get_element_tag_name/get.py index 3bb03d79886..d8bb3acc500 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_element_tag_name/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_element_tag_name/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success @@ -30,7 +30,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = get_element_tag_name(session, element.id) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/get_element_text/get.py b/tests/wpt/tests/webdriver/tests/classic/get_element_text/get.py index e8d559cf661..2a2363c0528 100644 --- a/tests/wpt/tests/webdriver/tests/classic/get_element_text/get.py +++ b/tests/wpt/tests/webdriver/tests/classic/get_element_text/get.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success @@ -30,7 +30,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = get_element_text(session, element.id) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/is_element_enabled/enabled.py b/tests/wpt/tests/webdriver/tests/classic/is_element_enabled/enabled.py index fccff383a55..24fc85fdad2 100644 --- a/tests/wpt/tests/webdriver/tests/classic/is_element_enabled/enabled.py +++ b/tests/wpt/tests/webdriver/tests/classic/is_element_enabled/enabled.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success @@ -33,7 +33,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = is_element_enabled(session, element.id) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/is_element_selected/selected.py b/tests/wpt/tests/webdriver/tests/classic/is_element_selected/selected.py index 1fb5b9ce86b..bf650de3e23 100644 --- a/tests/wpt/tests/webdriver/tests/classic/is_element_selected/selected.py +++ b/tests/wpt/tests/webdriver/tests/classic/is_element_selected/selected.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success @@ -49,7 +49,7 @@ def test_no_browsing_context(session, closed_frame): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = is_element_selected(session, element.id) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/classic/perform_actions/pointer_mouse.py b/tests/wpt/tests/webdriver/tests/classic/perform_actions/pointer_mouse.py index 97295f56f41..6ccb7c404e0 100644 --- a/tests/wpt/tests/webdriver/tests/classic/perform_actions/pointer_mouse.py +++ b/tests/wpt/tests/webdriver/tests/classic/perform_actions/pointer_mouse.py @@ -188,6 +188,24 @@ def test_click_navigation(session, url, inline): Poll(session, message=error_message).until(lambda s: s.url == destination) +@pytest.mark.parametrize("x, y, event_count", [ + (0, 0, 0), + (1, 0, 1), + (0, 1, 1), +], ids=["default value", "x", "y"]) +def test_move_to_position_in_viewport( + session, test_actions_page, mouse_chain, x, y, event_count +): + mouse_chain.pointer_move(x, y).perform() + events = get_events(session) + assert len(events) == event_count + + # Move again to check that no further mouse move event is emitted. + mouse_chain.pointer_move(x, y).perform() + events = get_events(session) + assert len(events) == event_count + + @pytest.mark.parametrize("drag_duration", [0, 300, 800]) @pytest.mark.parametrize("dx, dy", [ (20, 0), (0, 15), (10, 15), (-20, 0), (10, -15), (-10, -15) diff --git a/tests/wpt/tests/webdriver/tests/classic/take_element_screenshot/screenshot.py b/tests/wpt/tests/webdriver/tests/classic/take_element_screenshot/screenshot.py index ea4cc290db4..fdc0d65b1d9 100644 --- a/tests/wpt/tests/webdriver/tests/classic/take_element_screenshot/screenshot.py +++ b/tests/wpt/tests/webdriver/tests/classic/take_element_screenshot/screenshot.py @@ -1,6 +1,6 @@ import pytest -from webdriver import Element +from webdriver import WebElement from tests.support.asserts import assert_error, assert_success from tests.support.image import png_dimensions @@ -33,7 +33,7 @@ def test_no_browsing_context(session, closed_frame, inline): def test_no_such_element_with_invalid_value(session): - element = Element(session, "foo") + element = WebElement(session, "foo") response = take_element_screenshot(session, element.id) assert_error(response, "no such element") diff --git a/tests/wpt/tests/webdriver/tests/support/asserts.py b/tests/wpt/tests/webdriver/tests/support/asserts.py index 04bd1993316..9d31ff7b124 100644 --- a/tests/wpt/tests/webdriver/tests/support/asserts.py +++ b/tests/wpt/tests/webdriver/tests/support/asserts.py @@ -1,7 +1,7 @@ import imghdr from base64 import decodebytes -from webdriver import Element, NoSuchAlertException, WebDriverException +from webdriver import NoSuchAlertException, WebDriverException, WebElement # WebDriver specification ID: dfn-error-response-data @@ -148,17 +148,17 @@ def assert_is_active_element(session, element): def assert_same_element(session, a, b): """Verify that two element references describe the same element.""" if isinstance(a, dict): - assert Element.identifier in a, "Actual value does not describe an element" - a_id = a[Element.identifier] - elif isinstance(a, Element): + assert WebElement.identifier in a, "Actual value does not describe an element" + a_id = a[WebElement.identifier] + elif isinstance(a, WebElement): a_id = a.id else: raise AssertionError("Actual value is not a dictionary or web element") if isinstance(b, dict): - assert Element.identifier in b, "Expected value does not describe an element" - b_id = b[Element.identifier] - elif isinstance(b, Element): + assert WebElement.identifier in b, "Expected value does not describe an element" + b_id = b[WebElement.identifier] + elif isinstance(b, WebElement): b_id = b.id else: raise AssertionError("Expected value is not a dictionary or web element") diff --git a/tests/wpt/tests/webtransport/echo-large-bidirectional-streams.https.html b/tests/wpt/tests/webtransport/echo-large-bidirectional-streams.https.any.js index daa7c1b9b36..3f46530327e 100644 --- a/tests/wpt/tests/webtransport/echo-large-bidirectional-streams.https.html +++ b/tests/wpt/tests/webtransport/echo-large-bidirectional-streams.https.any.js @@ -1,10 +1,7 @@ -<!DOCTYPE html> -<meta charset="utf-8"/> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/common/get-host-info.sub.js"></script> -<script src="resources/webtransport-test-helpers.sub.js"></script> -<script> +// META: global=window,worker +// META: script=/common/get-host-info.sub.js +// META: script=resources/webtransport-test-helpers.sub.js + // A test that aims to reproduce https://crbug.com/1369030 -- note that since // the bug in question is a race condition, this test will probably be flaky if // this is actually broken. @@ -23,5 +20,3 @@ promise_test(async t => { assert_equals(response.byteLength, numBytes); } }, 'Ensure large bidirectional streams does not cause race condition'); - -</script> diff --git a/tests/wpt/tests/xhr/resources/auth1/auth.py b/tests/wpt/tests/xhr/resources/auth1/auth.py index db4f7bc4c9f..3797aaa52e9 100644 --- a/tests/wpt/tests/xhr/resources/auth1/auth.py +++ b/tests/wpt/tests/xhr/resources/auth1/auth.py @@ -1,12 +1,13 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(os.path.abspath(isomorphic_decode(__file__))) def main(request, response): - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, u"..", u"authentication.py")) return auth.main(request, response) diff --git a/tests/wpt/tests/xhr/resources/auth10/auth.py b/tests/wpt/tests/xhr/resources/auth10/auth.py index db4f7bc4c9f..568d31e9068 100644 --- a/tests/wpt/tests/xhr/resources/auth10/auth.py +++ b/tests/wpt/tests/xhr/resources/auth10/auth.py @@ -1,12 +1,14 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(os.path.abspath(isomorphic_decode(__file__))) + def main(request, response): - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, u"..", u"authentication.py")) return auth.main(request, response) diff --git a/tests/wpt/tests/xhr/resources/auth11/auth.py b/tests/wpt/tests/xhr/resources/auth11/auth.py index db4f7bc4c9f..3797aaa52e9 100644 --- a/tests/wpt/tests/xhr/resources/auth11/auth.py +++ b/tests/wpt/tests/xhr/resources/auth11/auth.py @@ -1,12 +1,13 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(os.path.abspath(isomorphic_decode(__file__))) def main(request, response): - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, u"..", u"authentication.py")) return auth.main(request, response) diff --git a/tests/wpt/tests/xhr/resources/auth2/auth.py b/tests/wpt/tests/xhr/resources/auth2/auth.py index db4f7bc4c9f..568d31e9068 100644 --- a/tests/wpt/tests/xhr/resources/auth2/auth.py +++ b/tests/wpt/tests/xhr/resources/auth2/auth.py @@ -1,12 +1,14 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(os.path.abspath(isomorphic_decode(__file__))) + def main(request, response): - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, u"..", u"authentication.py")) return auth.main(request, response) diff --git a/tests/wpt/tests/xhr/resources/auth2/corsenabled.py b/tests/wpt/tests/xhr/resources/auth2/corsenabled.py index bec6687dbe9..7b9d3b65aba 100644 --- a/tests/wpt/tests/xhr/resources/auth2/corsenabled.py +++ b/tests/wpt/tests/xhr/resources/auth2/corsenabled.py @@ -1,8 +1,9 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(isomorphic_decode(__file__)) def main(request, response): @@ -11,7 +12,7 @@ def main(request, response): response.headers.set(b'Access-Control-Allow-Methods', b'GET') response.headers.set(b'Access-Control-Allow-Headers', b'authorization, x-user, x-pass') response.headers.set(b'Access-Control-Expose-Headers', b'x-challenge, xhr-user, ses-user') - auth = imp.load_source(u"", os.path.abspath(os.path.join(here, os.pardir, u"authentication.py"))) + auth = load_source(u"", os.path.abspath(os.path.join(here, os.pardir, u"authentication.py"))) if request.method == u"OPTIONS": return b"" else: diff --git a/tests/wpt/tests/xhr/resources/auth3/auth.py b/tests/wpt/tests/xhr/resources/auth3/auth.py index db4f7bc4c9f..3797aaa52e9 100644 --- a/tests/wpt/tests/xhr/resources/auth3/auth.py +++ b/tests/wpt/tests/xhr/resources/auth3/auth.py @@ -1,12 +1,13 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(os.path.abspath(isomorphic_decode(__file__))) def main(request, response): - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, u"..", u"authentication.py")) return auth.main(request, response) diff --git a/tests/wpt/tests/xhr/resources/auth4/auth.py b/tests/wpt/tests/xhr/resources/auth4/auth.py index db4f7bc4c9f..3797aaa52e9 100644 --- a/tests/wpt/tests/xhr/resources/auth4/auth.py +++ b/tests/wpt/tests/xhr/resources/auth4/auth.py @@ -1,12 +1,13 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(os.path.abspath(isomorphic_decode(__file__))) def main(request, response): - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, u"..", u"authentication.py")) return auth.main(request, response) diff --git a/tests/wpt/tests/xhr/resources/auth7/corsenabled.py b/tests/wpt/tests/xhr/resources/auth7/corsenabled.py index 7a060627b70..c82ba4e6bc4 100644 --- a/tests/wpt/tests/xhr/resources/auth7/corsenabled.py +++ b/tests/wpt/tests/xhr/resources/auth7/corsenabled.py @@ -1,8 +1,9 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(isomorphic_decode(__file__)) def main(request, response): @@ -11,7 +12,7 @@ def main(request, response): response.headers.set(b'Access-Control-Allow-Methods', b'GET') response.headers.set(b'Access-Control-Allow-Headers', b'authorization, x-user, x-pass') response.headers.set(b'Access-Control-Expose-Headers', b'x-challenge, xhr-user, ses-user') - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, os.pardir, u"authentication.py")) if request.method == u"OPTIONS": diff --git a/tests/wpt/tests/xhr/resources/auth8/corsenabled-no-authorize.py b/tests/wpt/tests/xhr/resources/auth8/corsenabled-no-authorize.py index af8e7c4c170..4fdf99e2658 100644 --- a/tests/wpt/tests/xhr/resources/auth8/corsenabled-no-authorize.py +++ b/tests/wpt/tests/xhr/resources/auth8/corsenabled-no-authorize.py @@ -1,8 +1,9 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(isomorphic_decode(__file__)) def main(request, response): @@ -11,7 +12,7 @@ def main(request, response): response.headers.set(b'Access-Control-Allow-Methods', b'GET') response.headers.set(b'Access-Control-Allow-Headers', b'x-user, x-pass') response.headers.set(b'Access-Control-Expose-Headers', b'x-challenge, xhr-user, ses-user') - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, os.pardir, u"authentication.py")) if request.method == u"OPTIONS": diff --git a/tests/wpt/tests/xhr/resources/auth9/auth.py b/tests/wpt/tests/xhr/resources/auth9/auth.py index db4f7bc4c9f..3797aaa52e9 100644 --- a/tests/wpt/tests/xhr/resources/auth9/auth.py +++ b/tests/wpt/tests/xhr/resources/auth9/auth.py @@ -1,12 +1,13 @@ -import imp import os from wptserve.utils import isomorphic_decode +from tools.wpt.utils import load_source + here = os.path.dirname(os.path.abspath(isomorphic_decode(__file__))) def main(request, response): - auth = imp.load_source(u"", os.path.join(here, + auth = load_source(u"", os.path.join(here, u"..", u"authentication.py")) return auth.main(request, response) |