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 + + + 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 @@ + + 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 @@ + + + + + + + + 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 @@
-

+

+ + + + +
+ +
+ 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 @@ - - - Test cancel event is fired when the dialog is closed by user interaction - - - - - - - - -

Test cancel event is fired when the dialog is closed by user interaction

+ +Test cancel event is fired when the dialog is closed by user close requests + + + + + + + + +

Hello World

- - - 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 @@ + + @@ -14,7 +16,7 @@

Hello World

- 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 @@ + + + IdleDeadline::timeRemaining() uses relevant global object as a high-res timestamp origin 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 @@ + + + + + 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 @@ + + + + + + + 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 @@ - +
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 @@ + + + SVG Paint Servers: Clear should cause patternTransform to be ignored. + + + + + + + + + + + + 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 + self._pac_origin = pac_origin + self._pac = 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) + 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 @@ - + @@ -49,7 +49,7 @@ x x x -x +x x 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; } - addGlobal(local_type, mutable) { - let glob = new WasmGlobalBuilder(this, local_type, mutable); + addStruct(fields, supertype_idx = kNoSuperType, is_final = false) { + this.types.push(new WasmStruct(fields, is_final, supertype_idx)); + return this.types.length - 1; + } + + 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 @@ + + + + + + +Scrollbar interpolation + + + + + + +
+
+
+ + + + 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 @@ - - - - - audioparam-default-value.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 @@ + + + + + + + + + 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 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"
test
", 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("
foo
") + url = inline(f"") + 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"", 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("
foo
") + url = inline(f"") + 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"" + else: + script = f"" await bidi_session.browsing_context.navigate( context=new_tab["context"], - url=inline(f""), + 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 similarity index 72% rename from tests/wpt/tests/webtransport/echo-large-bidirectional-streams.https.html rename to 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 @@ - - - - - - - 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)