diff --git a/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini b/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini index 76b398963ae..dd4ffcf4345 100644 --- a/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini +++ b/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini @@ -1,5 +1,4 @@ [url-in-tags-revoke.window.html] - expected: TIMEOUT [Fetching a blob URL immediately before revoking it works in an iframe.] expected: FAIL @@ -15,6 +14,3 @@ [Opening a blob URL in a new window by clicking an tag works immediately before revoking the URL.] expected: FAIL - [Fetching a blob URL immediately before revoking it works in - - -
- - - - - - diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/registered-property-type.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/registered-property-type.https.html new file mode 100644 index 00000000000..6ff7ce4e0af --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-paint-api/registered-property-type.https.html @@ -0,0 +1,148 @@ + + + + + + + + +
+ + + + diff --git a/tests/wpt/web-platform-tests/css/css-scrollbars/textarea-scrollbar-width-none-ref.html b/tests/wpt/web-platform-tests/css/css-scrollbars/textarea-scrollbar-width-none-ref.html new file mode 100644 index 00000000000..9f505dd7f1d --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-scrollbars/textarea-scrollbar-width-none-ref.html @@ -0,0 +1,16 @@ + + +CSS Reference + + + + + diff --git a/tests/wpt/web-platform-tests/css/css-scrollbars/textarea-scrollbar-width-none.html b/tests/wpt/web-platform-tests/css/css-scrollbars/textarea-scrollbar-width-none.html new file mode 100644 index 00000000000..dcfaf5b6270 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-scrollbars/textarea-scrollbar-width-none.html @@ -0,0 +1,18 @@ + + +CSS Test: scrollbar-width should apply on <textarea> + + + + + + + diff --git a/tests/wpt/web-platform-tests/css/motion/parsing/offset-parsing-valid.html b/tests/wpt/web-platform-tests/css/motion/parsing/offset-parsing-valid.html index 75c93e5475f..b93091b2088 100644 --- a/tests/wpt/web-platform-tests/css/motion/parsing/offset-parsing-valid.html +++ b/tests/wpt/web-platform-tests/css/motion/parsing/offset-parsing-valid.html @@ -16,25 +16,25 @@ test_valid_value("offset", "100px none auto 90deg", "100px center none auto 90de test_valid_value("offset", "100px", "100px center"); test_valid_value("offset", "auto none reverse"); test_valid_value("offset", "auto"); -test_valid_value("offset", "center bottom path('M 1 2 V 3 Z')"); -test_valid_value("offset", "center center path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z') 100% 90deg / left bottom"); +test_valid_value("offset", "center bottom path(\"M 1 2 V 3 Z\")"); +test_valid_value("offset", "center center path(\"M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z\") 100% 90deg / left bottom"); test_valid_value("offset", "left bottom ray(0rad closest-side) 10px auto 30deg / right bottom"); test_valid_value("offset", "left top"); test_valid_value("offset", "none 30deg reverse", "none reverse 30deg"); test_valid_value("offset", "none 50px reverse 30deg"); test_valid_value("offset", "none calc(10px + 20%) auto"); test_valid_value("offset", "none reverse"); -test_valid_value("offset", "path('M 0 0 H 1') -200% auto"); -test_valid_value("offset", "path('M 0 0 H 1') -200%"); -test_valid_value("offset", "path('M 0 0 H 1') 50px"); -test_valid_value("offset", "path('M 0 0 H 1') auto"); -test_valid_value("offset", "path('M 0 0 H 1') reverse 30deg 50px", "path('M 0 0 H 1') 50px reverse 30deg"); -test_valid_value("offset", "path('M 0 0 H 1')"); -test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px / auto", "path('m 0 0 h 100') 8px -7rad / auto"); -test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px / left top", "path('m 0 0 h 100') 8px -7rad / left top"); -test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px", "path('m 0 0 h 100') 8px -7rad"); -test_valid_value("offset", "path('m 0 0 h 100') 100px 0deg"); -test_valid_value("offset", "path('m 1 2 v 3 Z')"); +test_valid_value("offset", "path(\"M 0 0 H 1\") -200% auto"); +test_valid_value("offset", "path(\"M 0 0 H 1\") -200%"); +test_valid_value("offset", "path('M 0 0 H 1') 50px", "path(\"M 0 0 H 1\") 50px"); +test_valid_value("offset", "path(\"M 0 0 H 1\") auto"); +test_valid_value("offset", "path('M 0 0 H 1') reverse 30deg 50px", "path(\"M 0 0 H 1\") 50px reverse 30deg"); +test_valid_value("offset", "path(\"M 0 0 H 1\")"); +test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px / auto", "path(\"m 0 0 h 100\") 8px -7rad / auto"); +test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px / left top", "path(\"m 0 0 h 100\") 8px -7rad / left top"); +test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px", "path(\"m 0 0 h 100\") 8px -7rad"); +test_valid_value("offset", "path(\"m 0 0 h 100\") 100px 0deg"); +test_valid_value("offset", "path('m 1 2 v 3 Z')", "path(\"m 1 2 v 3 Z\")"); test_valid_value("offset", "ray(farthest-corner 90deg) 1%", "ray(90deg farthest-corner) 1%"); test_valid_value("offset", "ray(sides 0deg) 50% 90deg auto", "ray(0deg sides) 50% auto 90deg"); test_valid_value("offset", "right bottom / left top"); diff --git a/tests/wpt/web-platform-tests/html/editing/focus/composed.window.js b/tests/wpt/web-platform-tests/html/interaction/focus/composed.window.js similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/composed.window.js rename to tests/wpt/web-platform-tests/html/interaction/focus/composed.window.js diff --git a/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/document-level-apis.html b/tests/wpt/web-platform-tests/html/interaction/focus/document-level-focus-apis/document-level-apis.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/document-level-apis.html rename to tests/wpt/web-platform-tests/html/interaction/focus/document-level-focus-apis/document-level-apis.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/test.html b/tests/wpt/web-platform-tests/html/interaction/focus/document-level-focus-apis/test.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/test.html rename to tests/wpt/web-platform-tests/html/interaction/focus/document-level-focus-apis/test.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/focus-01.html b/tests/wpt/web-platform-tests/html/interaction/focus/focus-01.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/focus-01.html rename to tests/wpt/web-platform-tests/html/interaction/focus/focus-01.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/focus-02.html b/tests/wpt/web-platform-tests/html/interaction/focus/focus-02.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/focus-02.html rename to tests/wpt/web-platform-tests/html/interaction/focus/focus-02.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/focus-management/focus-event-targets-simple.html b/tests/wpt/web-platform-tests/html/interaction/focus/focus-management/focus-event-targets-simple.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/focus-management/focus-event-targets-simple.html rename to tests/wpt/web-platform-tests/html/interaction/focus/focus-management/focus-event-targets-simple.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/focus-management/focus-events.html b/tests/wpt/web-platform-tests/html/interaction/focus/focus-management/focus-events.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/focus-management/focus-events.html rename to tests/wpt/web-platform-tests/html/interaction/focus/focus-management/focus-events.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/processing-model/focus-fixup-rule-one-no-dialogs.html b/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/focus-fixup-rule-one-no-dialogs.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/processing-model/focus-fixup-rule-one-no-dialogs.html rename to tests/wpt/web-platform-tests/html/interaction/focus/processing-model/focus-fixup-rule-one-no-dialogs.html diff --git a/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/legend-focusable.html b/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/legend-focusable.html new file mode 100644 index 00000000000..c9209d3cf62 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/legend-focusable.html @@ -0,0 +1,17 @@ + +legend focusable + + + +
+ + legend + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/legend.html b/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/legend.html new file mode 100644 index 00000000000..b53839374df --- /dev/null +++ b/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/legend.html @@ -0,0 +1,20 @@ + +legend + + + +
+ + legend + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/editing/focus/processing-model/preventScroll.html b/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/preventScroll.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/processing-model/preventScroll.html rename to tests/wpt/web-platform-tests/html/interaction/focus/processing-model/preventScroll.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/processing-model/support/preventScroll-helper.html b/tests/wpt/web-platform-tests/html/interaction/focus/processing-model/support/preventScroll-helper.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/processing-model/support/preventScroll-helper.html rename to tests/wpt/web-platform-tests/html/interaction/focus/processing-model/support/preventScroll-helper.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html b/tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html rename to tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative.html b/tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative.html rename to tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-order.html b/tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-order.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-order.html rename to tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-order.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive.html b/tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive.html rename to tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-zero.html b/tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-zero.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-zero.html rename to tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-zero.html diff --git a/tests/wpt/web-platform-tests/html/editing/focus/tabindex-focus-flag.html b/tests/wpt/web-platform-tests/html/interaction/focus/tabindex-focus-flag.html similarity index 100% rename from tests/wpt/web-platform-tests/html/editing/focus/tabindex-focus-flag.html rename to tests/wpt/web-platform-tests/html/interaction/focus/tabindex-focus-flag.html diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-text-align.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-text-align.html new file mode 100644 index 00000000000..01483bf8ad3 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-text-align.html @@ -0,0 +1,27 @@ + +legend align does not map to text-align + + + + +
foo bar abcdefghijklmnopqrstuvwxyz
+
foo bar abcdefghijklmnopqrstuvwxyz
+
foo bar abcdefghijklmnopqrstuvwxyz
+
foo bar abcdefghijklmnopqrstuvwxyz
+
foo bar abcdefghijklmnopqrstuvwxyz
+ diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align.html index f7511c9e4c9..e7745998194 100644 --- a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align.html +++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align.html @@ -5,6 +5,7 @@
x
x
x
+
x
x
@@ -14,6 +15,9 @@
x
+
+
x
+
x
@@ -33,12 +37,12 @@ function test_align(selectorTest, selectorRef) { }, selectorTest); } -for (const val of ['left', 'center', 'right']) { - test_align(`div[align=${val}] legend`, `legend[align=${val}]`); +for (const val of ['left', 'center', 'right', 'justify']) { + test_align(`div[align=${val}] legend`, `legend[align=left]`); } test_align(`div[style="text-align: center"] legend`, `legend[align=left]`); -test_align(`div[style="text-align: center"][align=center] legend`, `legend[align=center]`); +test_align(`div[style="text-align: center"][align=center] legend`, `legend[align=left]`); test_align(`legend[style="margin: 0 auto"]`, `legend[align=center]`); test_align(`legend[style="margin: 0 0 0 auto"]`, `legend[align=right]`); test_align(`fieldset[dir=rtl] legend`, `legend[align=right]`); diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/common/accesskey.js b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/common/accesskey.js new file mode 100644 index 00000000000..f08761be8c1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/common/accesskey.js @@ -0,0 +1,36 @@ +setup({explicit_done: true, explicit_timeout: true}); + +const NOTRUN = 3; +let status = NOTRUN; +function notrun() { + return status === NOTRUN; +} +add_completion_callback(tests => { + status = tests[0].status; +}); + +function pass() { + // Wait a couple of frames in case fail() is also called. + requestAnimationFrame(() => { + requestAnimationFrame(() => { + if (notrun()) { + test(() => {}); + done(); + } + }); + }); +} + +function fail(msg) { + if (notrun()) { + test(() => { assert_unreached(msg); }); + done(); + } +} + +document.addEventListener('DOMContentLoaded', () => { + const accessKeyElement = document.querySelector('[accesskey]'); + if (accessKeyElement.accessKeyLabel) { + document.querySelector('kbd').textContent = accessKeyElement.accessKeyLabel; + } +}); diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-after-legend-manual.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-after-legend-manual.html new file mode 100644 index 00000000000..521b4bb9755 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-after-legend-manual.html @@ -0,0 +1,10 @@ + +First input after the legend + + + +

Press the access key combination for "a".

+
+ legend + +
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-before-legend-manual.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-before-legend-manual.html new file mode 100644 index 00000000000..1c40cc7b81e --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-before-legend-manual.html @@ -0,0 +1,13 @@ + +First input before the legend + + + +

Press the access key combination for "a".

+
+ + legend + + + +
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-inside-legend-manual.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-inside-legend-manual.html new file mode 100644 index 00000000000..abd3a3b2dfe --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/first-input-inside-legend-manual.html @@ -0,0 +1,12 @@ + +First input inside the legend + + + +

Press the access key combination for "a".

+
+ legend + + + +
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/focusable-legend-manual.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/focusable-legend-manual.html new file mode 100644 index 00000000000..e2880a77bf9 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/focusable-legend-manual.html @@ -0,0 +1,14 @@ + +Focusable legend + + + +

Press the access key combination for "a".

+
+ + legend + + + +
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/focusable-legend-sibling-manual.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/focusable-legend-sibling-manual.html new file mode 100644 index 00000000000..49dcaaf7d54 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/focusable-legend-sibling-manual.html @@ -0,0 +1,17 @@ + +Focusable legend sibling + + + +

Press the access key combination for "a".

+
+ first legend + second legend +
+ diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/input-outside-fieldset-manual.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/input-outside-fieldset-manual.html new file mode 100644 index 00000000000..dc6af48323e --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/input-outside-fieldset-manual.html @@ -0,0 +1,17 @@ + +Input outside fieldset + + + +

Press the access key combination for "a".

+
+ legend +
+ + diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/label-sibling-manual.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/label-sibling-manual.html new file mode 100644 index 00000000000..8a7b20565f7 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/label-sibling-manual.html @@ -0,0 +1,18 @@ + +Label sibling + + + +

Press the access key combination for "a".

+ +
+ legend + +
+ diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/no-fieldset-parent-manual.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/no-fieldset-parent-manual.html new file mode 100644 index 00000000000..e7abb71454a --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/legend/no-fieldset-parent-manual.html @@ -0,0 +1,18 @@ + +No fieldset parent + + + +

Press the access key combination for "a".

+ + legend + + + + diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-referrer-policy.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-referrer-policy.https.html index 9b67faccac8..73ae123ae4e 100644 --- a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-referrer-policy.https.html +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-referrer-policy.https.html @@ -7,12 +7,19 @@ diff --git a/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-relative-absolute.svg b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-relative-absolute.svg index 65d2f3b2eb6..09d4c70712f 100644 --- a/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-relative-absolute.svg +++ b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-relative-absolute.svg @@ -17,106 +17,106 @@ // Mix relative and non-relative test_interpolation({ property: 'd', - from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')", - to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z')" + from: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")', + to: 'path("M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z")' }, [ - {at: -1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 0 -100 Z')"}, - {at: 0, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"}, - {at: 0.125, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 225 125 Z')"}, - {at: 0.875, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 375 275 Z')"}, - {at: 1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 400 300 Z')"}, - {at: 2, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 600 500 Z')"}, + {at: -1, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 0 -100 Z")'}, + {at: 0, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'}, + {at: 0.125, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 225 125 Z")'}, + {at: 0.875, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 375 275 Z")'}, + {at: 1, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 400 300 Z")'}, + {at: 2, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 600 500 Z")'}, ]); test_interpolation({ property: 'd', - from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')", - to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z')" + from: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")', + to: 'path("M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z")' }, [ - {at: -1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"}, - {at: 0, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"}, - {at: 0.125, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"}, - {at: 0.875, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"}, - {at: 1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"}, - {at: 2, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"}, + {at: -1, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'}, + {at: 0, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'}, + {at: 0.125, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'}, + {at: 0.875, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'}, + {at: 1, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'}, + {at: 2, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'}, ]); test_interpolation({ property: 'd', - from: "path('m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130')", - to: "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')" + from: 'path("m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130")', + to: 'path("M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220")' }, [ - {at: -1, expect: "path('M -190 -180 L -70 -50 Z L 10 40 Z M 30 50 L 120 70 Z T 60 220')"}, - {at: 0, expect: "path('M 10 20 L 50 70 Z L 50 80 Z M 70 90 L 160 150 Z T 140 220')"}, - {at: 0.125, expect: "path('M 35 45 L 65 85 Z L 55 85 Z M 75 95 L 165 160 Z T 150 220')"}, - {at: 0.875, expect: "path('M 185 195 L 155 175 Z L 85 115 Z M 105 125 L 195 220 Z T 210 220')"}, - {at: 1, expect: "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')"}, - {at: 2, expect: "path('M 410 420 L 290 310 Z L 130 160 Z M 150 170 L 240 310 Z T 300 220')"} + {at: -1, expect: 'path("M -190 -180 L -70 -50 Z L 10 40 Z M 30 50 L 120 70 Z T 60 220")'}, + {at: 0, expect: 'path("M 10 20 L 50 70 Z L 50 80 Z M 70 90 L 160 150 Z T 140 220")'}, + {at: 0.125, expect: 'path("M 35 45 L 65 85 Z L 55 85 Z M 75 95 L 165 160 Z T 150 220")'}, + {at: 0.875, expect: 'path("M 185 195 L 155 175 Z L 85 115 Z M 105 125 L 195 220 Z T 210 220")'}, + {at: 1, expect: 'path("M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220")'}, + {at: 2, expect: 'path("M 410 420 L 290 310 Z L 130 160 Z M 150 170 L 240 310 Z T 300 220")'} ]); test_interpolation({ property: 'd', - from: "path('m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160')", - to: "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')" + from: 'path("m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160")', + to: 'path("M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330")' }, [ - {at: -1, expect: "path('M -110 -60 C -30 -10 -40 0 -30 10 C 130 140 180 150 80 170')"}, - {at: 0, expect: "path('M 10 20 C 50 70 40 80 90 90 C 210 220 260 230 200 250')"}, - {at: 0.125, expect: "path('M 25 30 C 60 80 50 90 105 100 C 220 230 270 240 215 260')"}, - {at: 0.875, expect: "path('M 115 90 C 120 140 110 150 195 160 C 280 290 330 300 305 320')"}, - {at: 1, expect: "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')"}, - {at: 2, expect: "path('M 250 180 C 210 230 200 240 330 250 C 370 380 420 390 440 410')"} + {at: -1, expect: 'path("M -110 -60 C -30 -10 -40 0 -30 10 C 130 140 180 150 80 170")'}, + {at: 0, expect: 'path("M 10 20 C 50 70 40 80 90 90 C 210 220 260 230 200 250")'}, + {at: 0.125, expect: 'path("M 25 30 C 60 80 50 90 105 100 C 220 230 270 240 215 260")'}, + {at: 0.875, expect: 'path("M 115 90 C 120 140 110 150 195 160 C 280 290 330 300 305 320")'}, + {at: 1, expect: 'path("M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330")'}, + {at: 2, expect: 'path("M 250 180 C 210 230 200 240 330 250 C 370 380 420 390 440 410")'} ]); test_interpolation({ property: 'd', - from: "path('m 10 20 q 30 60 40 50 q 110 80 90 80')", - to: "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')" + from: 'path("m 10 20 q 30 60 40 50 q 110 80 90 80")', + to: 'path("M 130 100 Q 120 160 130 150 Q 200 150 180 190")' }, [ - {at: -1, expect: "path('M -110 -60 Q -40 0 -30 -10 Q 120 150 100 110')"}, - {at: 0, expect: "path('M 10 20 Q 40 80 50 70 Q 160 150 140 150')"}, - {at: 0.125, expect: "path('M 25 30 Q 50 90 60 80 Q 165 150 145 155')"}, - {at: 0.875, expect: "path('M 115 90 Q 110 150 120 140 Q 195 150 175 185')"}, - {at: 1, expect: "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')"}, - {at: 2, expect: "path('M 250 180 Q 200 240 210 230 Q 240 150 220 230')"} + {at: -1, expect: 'path("M -110 -60 Q -40 0 -30 -10 Q 120 150 100 110")'}, + {at: 0, expect: 'path("M 10 20 Q 40 80 50 70 Q 160 150 140 150")'}, + {at: 0.125, expect: 'path("M 25 30 Q 50 90 60 80 Q 165 150 145 155")'}, + {at: 0.875, expect: 'path("M 115 90 Q 110 150 120 140 Q 195 150 175 185")'}, + {at: 1, expect: 'path("M 130 100 Q 120 160 130 150 Q 200 150 180 190")'}, + {at: 2, expect: 'path("M 250 180 Q 200 240 210 230 Q 240 150 220 230")'} ]); test_interpolation({ property: 'd', - from: "path('m 10 20 s 30 60 40 50 s 110 60 90 70')", - to: "path('M 130 140 S 120 160 130 150 S 200 170 140 180')" + from: 'path("m 10 20 s 30 60 40 50 s 110 60 90 70")', + to: 'path("M 130 140 S 120 160 130 150 S 200 170 140 180")' }, [ - {at: -1, expect: "path('M -110 -100 S -40 0 -30 -10 S 120 90 140 100')"}, - {at: 0, expect: "path('M 10 20 S 40 80 50 70 S 160 130 140 140')"}, - {at: 0.125, expect: "path('M 25 35 S 50 90 60 80 S 165 135 140 145')"}, - {at: 0.875, expect: "path('M 115 125 S 110 150 120 140 S 195 165 140 175')"}, - {at: 1, expect: "path('M 130 140 S 120 160 130 150 S 200 170 140 180')"}, - {at: 2, expect: "path('M 250 260 S 200 240 210 230 S 240 210 140 220')"} + {at: -1, expect: 'path("M -110 -100 S -40 0 -30 -10 S 120 90 140 100")'}, + {at: 0, expect: 'path("M 10 20 S 40 80 50 70 S 160 130 140 140")'}, + {at: 0.125, expect: 'path("M 25 35 S 50 90 60 80 S 165 135 140 145")'}, + {at: 0.875, expect: 'path("M 115 125 S 110 150 120 140 S 195 165 140 175")'}, + {at: 1, expect: 'path("M 130 140 S 120 160 130 150 S 200 170 140 180")'}, + {at: 2, expect: 'path("M 250 260 S 200 240 210 230 S 240 210 140 220")'} ]); test_interpolation({ property: 'd', - from: "path('m 10 20 h 30 v 60 h 10 v -10 l 110 60 Z')", - to: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z')" + from: 'path("m 10 20 h 30 v 60 h 10 v -10 l 110 60 Z")', + to: 'path("M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z")' }, [ - {at: -1, expect: "path('M -110 -100 H -40 V 0 H -30 V -10 L 120 90 Z')"}, - {at: 0, expect: "path('M 10 20 H 40 V 80 H 50 V 70 L 160 130 Z')"}, - {at: 0.125, expect: "path('M 25 35 H 50 V 90 H 60 V 80 L 165 135 Z')"}, - {at: 0.875, expect: "path('M 115 125 H 110 V 150 H 120 V 140 L 195 165 Z')"}, - {at: 1, expect: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z')"}, - {at: 2, expect: "path('M 250 260 H 200 V 240 H 210 V 230 L 240 210 Z')"} + {at: -1, expect: 'path("M -110 -100 H -40 V 0 H -30 V -10 L 120 90 Z")'}, + {at: 0, expect: 'path("M 10 20 H 40 V 80 H 50 V 70 L 160 130 Z")'}, + {at: 0.125, expect: 'path("M 25 35 H 50 V 90 H 60 V 80 L 165 135 Z")'}, + {at: 0.875, expect: 'path("M 115 125 H 110 V 150 H 120 V 140 L 195 165 Z")'}, + {at: 1, expect: 'path("M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z")'}, + {at: 2, expect: 'path("M 250 260 H 200 V 240 H 210 V 230 L 240 210 Z")'} ]); test_interpolation({ property: 'd', - from: "path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')", - to: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')" + from: 'path("m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50")', + to: 'path("M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80")' }, [ - {at: -1, expect: "path('M 2 28 A -30 -60 -10 1 0 10 30 A 70 80 -10 1 1 310 160')"}, - {at: 0, expect: "path('M 10 20 A 10 20 30 1 0 50 70 A 110 120 30 1 1 190 120')"}, - {at: 0.125, expect: "path('M 11 19 A 15 30 35 1 0 55 75 A 115 125 35 1 1 175 115')"}, - {at: 0.875, expect: "path('M 17 13 A 45 90 65 0 1 85 105 A 145 155 65 0 1 85 85')"}, - {at: 1, expect: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')"}, - {at: 2, expect: "path('M 26 4 A 90 180 110 0 1 130 150 A 190 200 110 0 1 -50 40')"} + {at: -1, expect: 'path("M 2 28 A -30 -60 -10 1 0 10 30 A 70 80 -10 1 1 310 160")'}, + {at: 0, expect: 'path("M 10 20 A 10 20 30 1 0 50 70 A 110 120 30 1 1 190 120")'}, + {at: 0.125, expect: 'path("M 11 19 A 15 30 35 1 0 55 75 A 115 125 35 1 1 175 115")'}, + {at: 0.875, expect: 'path("M 17 13 A 45 90 65 0 1 85 105 A 145 155 65 0 1 85 85")'}, + {at: 1, expect: 'path("M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80")'}, + {at: 2, expect: 'path("M 26 4 A 90 180 110 0 1 130 150 A 190 200 110 0 1 -50 40")'} ]); ]]> diff --git a/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-single.svg b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-single.svg index 25c523168a7..107b607beca 100644 --- a/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-single.svg +++ b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-single.svg @@ -17,229 +17,229 @@ // Exercise each segment type test_interpolation({ property: 'd', - from: "path('M 20 70')", - to: "path('M 100 30')" + from: 'path("M 20 70")', + to: 'path("M 100 30")' }, [ - {at: -1, expect: "path('M -60 110')"}, - {at: 0, expect: "path('M 20 70')"}, - {at: 0.125, expect: "path('M 30 65')"}, - {at: 0.875, expect: "path('M 90 35')"}, - {at: 1, expect: "path('M 100 30')"}, - {at: 2, expect: "path('M 180 -10')"} + {at: -1, expect: 'path("M -60 110")'}, + {at: 0, expect: 'path("M 20 70")'}, + {at: 0.125, expect: 'path("M 30 65")'}, + {at: 0.875, expect: 'path("M 90 35")'}, + {at: 1, expect: 'path("M 100 30")'}, + {at: 2, expect: 'path("M 180 -10")'} ]); test_interpolation({ property: 'd', - from: "path('m 20 70')", - to: "path('m 100 30')" + from: 'path("m 20 70")', + to: 'path("m 100 30")' }, [ - {at: -1, expect: "path('M -60 110')"}, - {at: 0, expect: "path('M 20 70')"}, - {at: 0.125, expect: "path('M 30 65')"}, - {at: 0.875, expect: "path('M 90 35')"}, - {at: 1, expect: "path('M 100 30')"}, - {at: 2, expect: "path('M 180 -10')"} + {at: -1, expect: 'path("M -60 110")'}, + {at: 0, expect: 'path("M 20 70")'}, + {at: 0.125, expect: 'path("M 30 65")'}, + {at: 0.875, expect: 'path("M 90 35")'}, + {at: 1, expect: 'path("M 100 30")'}, + {at: 2, expect: 'path("M 180 -10")'} ]); test_interpolation({ property: 'd', - from: "path('m 100 200 L 120 270')", - to: "path('m 100 200 L 200 230')" + from: 'path("m 100 200 L 120 270")', + to: 'path("m 100 200 L 200 230")' }, [ - {at: -1, expect: "path('M 100 200 L 40 310')"}, - {at: 0, expect: "path('M 100 200 L 120 270')"}, - {at: 0.125, expect: "path('M 100 200 L 130 265')"}, - {at: 0.875, expect: "path('M 100 200 L 190 235')"}, - {at: 1, expect: "path('M 100 200 L 200 230')"}, - {at: 2, expect: "path('M 100 200 L 280 190')"} + {at: -1, expect: 'path("M 100 200 L 40 310")'}, + {at: 0, expect: 'path("M 100 200 L 120 270")'}, + {at: 0.125, expect: 'path("M 100 200 L 130 265")'}, + {at: 0.875, expect: 'path("M 100 200 L 190 235")'}, + {at: 1, expect: 'path("M 100 200 L 200 230")'}, + {at: 2, expect: 'path("M 100 200 L 280 190")'} ]); test_interpolation({ property: 'd', - from: "path('m 100 200 l 20 70')", - to: "path('m 100 200 l 100 30')" + from: 'path("m 100 200 l 20 70")', + to: 'path("m 100 200 l 100 30")' }, [ - {at: -1, expect: "path('M 100 200 L 40 310')"}, - {at: 0, expect: "path('M 100 200 L 120 270')"}, - {at: 0.125, expect: "path('M 100 200 L 130 265')"}, - {at: 0.875, expect: "path('M 100 200 L 190 235')"}, - {at: 1, expect: "path('M 100 200 L 200 230')"}, - {at: 2, expect: "path('M 100 200 L 280 190')"} + {at: -1, expect: 'path("M 100 200 L 40 310")'}, + {at: 0, expect: 'path("M 100 200 L 120 270")'}, + {at: 0.125, expect: 'path("M 100 200 L 130 265")'}, + {at: 0.875, expect: 'path("M 100 200 L 190 235")'}, + {at: 1, expect: 'path("M 100 200 L 200 230")'}, + {at: 2, expect: 'path("M 100 200 L 280 190")'} ]); test_interpolation({ property: 'd', - from: "path('M 20 10 C 32 42 52 62 120 2200')", - to: "path('M 20 10 C 40 50 60 70 200 3000')", + from: 'path("M 20 10 C 32 42 52 62 120 2200")', + to: 'path("M 20 10 C 40 50 60 70 200 3000")', }, [ - {at: -1, expect: "path('M 20 10 C 24 34 44 54 40 1400')"}, - {at: 0, expect: "path('M 20 10 C 32 42 52 62 120 2200')"}, - {at: 0.125, expect: "path('M 20 10 C 33 43 53 63 130 2300')"}, - {at: 0.875, expect: "path('M 20 10 C 39 49 59 69 190 2900')"}, - {at: 1, expect: "path('M 20 10 C 40 50 60 70 200 3000')"}, - {at: 2, expect: "path('M 20 10 C 48 58 68 78 280 3800')"} + {at: -1, expect: 'path("M 20 10 C 24 34 44 54 40 1400")'}, + {at: 0, expect: 'path("M 20 10 C 32 42 52 62 120 2200")'}, + {at: 0.125, expect: 'path("M 20 10 C 33 43 53 63 130 2300")'}, + {at: 0.875, expect: 'path("M 20 10 C 39 49 59 69 190 2900")'}, + {at: 1, expect: 'path("M 20 10 C 40 50 60 70 200 3000")'}, + {at: 2, expect: 'path("M 20 10 C 48 58 68 78 280 3800")'} ]); test_interpolation({ property: 'd', - from: "path('m 20 10 c 12 32 32 52 100 2190')", - to: "path('m 20 10 c 20 40 40 60 180 2990')" + from: 'path("m 20 10 c 12 32 32 52 100 2190")', + to: 'path("m 20 10 c 20 40 40 60 180 2990")' }, [ - {at: -1, expect: "path('M 20 10 C 24 34 44 54 40 1400')"}, - {at: 0, expect: "path('M 20 10 C 32 42 52 62 120 2200')"}, - {at: 0.125, expect: "path('M 20 10 C 33 43 53 63 130 2300')"}, - {at: 0.875, expect: "path('M 20 10 C 39 49 59 69 190 2900')"}, - {at: 1, expect: "path('M 20 10 C 40 50 60 70 200 3000')"}, - {at: 2, expect: "path('M 20 10 C 48 58 68 78 280 3800')"} + {at: -1, expect: 'path("M 20 10 C 24 34 44 54 40 1400")'}, + {at: 0, expect: 'path("M 20 10 C 32 42 52 62 120 2200")'}, + {at: 0.125, expect: 'path("M 20 10 C 33 43 53 63 130 2300")'}, + {at: 0.875, expect: 'path("M 20 10 C 39 49 59 69 190 2900")'}, + {at: 1, expect: 'path("M 20 10 C 40 50 60 70 200 3000")'}, + {at: 2, expect: 'path("M 20 10 C 48 58 68 78 280 3800")'} ]); test_interpolation({ property: 'd', - from: "path('M 20 10 Q 32 42 120 2200')", - to: "path('M 20 10 Q 40 50 200 3000')" + from: 'path("M 20 10 Q 32 42 120 2200")', + to: 'path("M 20 10 Q 40 50 200 3000")' }, [ - {at: -1, expect: "path('M 20 10 Q 24 34 40 1400')"}, - {at: 0, expect: "path('M 20 10 Q 32 42 120 2200')"}, - {at: 0.125, expect: "path('M 20 10 Q 33 43 130 2300')"}, - {at: 0.875, expect: "path('M 20 10 Q 39 49 190 2900')"}, - {at: 1, expect: "path('M 20 10 Q 40 50 200 3000')"}, - {at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"} + {at: -1, expect: 'path("M 20 10 Q 24 34 40 1400")'}, + {at: 0, expect: 'path("M 20 10 Q 32 42 120 2200")'}, + {at: 0.125, expect: 'path("M 20 10 Q 33 43 130 2300")'}, + {at: 0.875, expect: 'path("M 20 10 Q 39 49 190 2900")'}, + {at: 1, expect: 'path("M 20 10 Q 40 50 200 3000")'}, + {at: 2, expect: 'path("M 20 10 Q 48 58 280 3800")'} ]); test_interpolation({ property: 'd', - from: "path('m 20 10 q 12 32 100 2190')", - to: "path('m 20 10 q 20 40 180 2990')" + from: 'path("m 20 10 q 12 32 100 2190")', + to: 'path("m 20 10 q 20 40 180 2990")' }, [ - {at: -1, expect: "path('M 20 10 Q 24 34 40 1400')"}, - {at: 0, expect: "path('M 20 10 Q 32 42 120 2200')"}, - {at: 0.125, expect: "path('M 20 10 Q 33 43 130 2300')"}, - {at: 0.875, expect: "path('M 20 10 Q 39 49 190 2900')"}, - {at: 1, expect: "path('M 20 10 Q 40 50 200 3000')"}, - {at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"} + {at: -1, expect: 'path("M 20 10 Q 24 34 40 1400")'}, + {at: 0, expect: 'path("M 20 10 Q 32 42 120 2200")'}, + {at: 0.125, expect: 'path("M 20 10 Q 33 43 130 2300")'}, + {at: 0.875, expect: 'path("M 20 10 Q 39 49 190 2900")'}, + {at: 1, expect: 'path("M 20 10 Q 40 50 200 3000")'}, + {at: 2, expect: 'path("M 20 10 Q 48 58 280 3800")'} ]); test_interpolation({ property: 'd', - from: "path('M 100 400 A 10 20 30 1 0 140 450')", - to: "path('M 300 200 A 50 60 70 0 1 380 290')" + from: 'path("M 100 400 A 10 20 30 1 0 140 450")', + to: 'path("M 300 200 A 50 60 70 0 1 380 290")' }, [ - {at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"}, - {at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"}, - {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"}, - {at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"}, - {at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"}, - {at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"} + {at: -1, expect: 'path("M -100 600 A -30 -20 -10 1 0 -100 610")'}, + {at: 0, expect: 'path("M 100 400 A 10 20 30 1 0 140 450")'}, + {at: 0.125, expect: 'path("M 125 375 A 15 25 35 1 0 170 430")'}, + {at: 0.875, expect: 'path("M 275 225 A 45 55 65 0 1 350 310")'}, + {at: 1, expect: 'path("M 300 200 A 50 60 70 0 1 380 290")'}, + {at: 2, expect: 'path("M 500 0 A 90 100 110 0 1 620 130")'} ]); test_interpolation({ property: 'd', - from: "path('m 100 400 a 10 20 30 1 0 40 50')", - to: "path('m 300 200 a 50 60 70 0 1 80 90')" + from: 'path("m 100 400 a 10 20 30 1 0 40 50")', + to: 'path("m 300 200 a 50 60 70 0 1 80 90")' }, [ - {at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"}, - {at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"}, - {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"}, - {at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"}, - {at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"}, - {at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"} + {at: -1, expect: 'path("M -100 600 A -30 -20 -10 1 0 -100 610")'}, + {at: 0, expect: 'path("M 100 400 A 10 20 30 1 0 140 450")'}, + {at: 0.125, expect: 'path("M 125 375 A 15 25 35 1 0 170 430")'}, + {at: 0.875, expect: 'path("M 275 225 A 45 55 65 0 1 350 310")'}, + {at: 1, expect: 'path("M 300 200 A 50 60 70 0 1 380 290")'}, + {at: 2, expect: 'path("M 500 0 A 90 100 110 0 1 620 130")'} ]); test_interpolation({ property: 'd', - from: "path('M 50 60 H 70')", - to: "path('M 10 140 H 270')" + from: 'path("M 50 60 H 70")', + to: 'path("M 10 140 H 270")' }, [ - {at: -1, expect: "path('M 90 -20 H -130')"}, - {at: 0, expect: "path('M 50 60 H 70')"}, - {at: 0.125, expect: "path('M 45 70 H 95')"}, - {at: 0.875, expect: "path('M 15 130 H 245')"}, - {at: 1, expect: "path('M 10 140 H 270')"}, - {at: 2, expect: "path('M -30 220 H 470')"} + {at: -1, expect: 'path("M 90 -20 H -130")'}, + {at: 0, expect: 'path("M 50 60 H 70")'}, + {at: 0.125, expect: 'path("M 45 70 H 95")'}, + {at: 0.875, expect: 'path("M 15 130 H 245")'}, + {at: 1, expect: 'path("M 10 140 H 270")'}, + {at: 2, expect: 'path("M -30 220 H 470")'} ]); test_interpolation({ property: 'd', - from: "path('m 50 60 h 20')", - to: "path('m 10 140 h 260')" + from: 'path("m 50 60 h 20")', + to: 'path("m 10 140 h 260")' }, [ - {at: -1, expect: "path('M 90 -20 H -130')"}, - {at: 0, expect: "path('M 50 60 H 70')"}, - {at: 0.125, expect: "path('M 45 70 H 95')"}, - {at: 0.875, expect: "path('M 15 130 H 245')"}, - {at: 1, expect: "path('M 10 140 H 270')"}, - {at: 2, expect: "path('M -30 220 H 470')"} + {at: -1, expect: 'path("M 90 -20 H -130")'}, + {at: 0, expect: 'path("M 50 60 H 70")'}, + {at: 0.125, expect: 'path("M 45 70 H 95")'}, + {at: 0.875, expect: 'path("M 15 130 H 245")'}, + {at: 1, expect: 'path("M 10 140 H 270")'}, + {at: 2, expect: 'path("M -30 220 H 470")'} ]); test_interpolation({ property: 'd', - from: "path('M 50 60 V 70')", - to: "path('M 10 140 V 270')" + from: 'path("M 50 60 V 70")', + to: 'path("M 10 140 V 270")' }, [ - {at: -1, expect: "path('M 90 -20 V -130')"}, - {at: 0, expect: "path('M 50 60 V 70')"}, - {at: 0.125, expect: "path('M 45 70 V 95')"}, - {at: 0.875, expect: "path('M 15 130 V 245')"}, - {at: 1, expect: "path('M 10 140 V 270')"}, - {at: 2, expect: "path('M -30 220 V 470')"} + {at: -1, expect: 'path("M 90 -20 V -130")'}, + {at: 0, expect: 'path("M 50 60 V 70")'}, + {at: 0.125, expect: 'path("M 45 70 V 95")'}, + {at: 0.875, expect: 'path("M 15 130 V 245")'}, + {at: 1, expect: 'path("M 10 140 V 270")'}, + {at: 2, expect: 'path("M -30 220 V 470")'} ]); test_interpolation({ property: 'd', - from: "path('m 50 60 v 10')", - to: "path('m 10 140 v 130')" + from: 'path("m 50 60 v 10")', + to: 'path("m 10 140 v 130")' }, [ - {at: -1, expect: "path('M 90 -20 V -130')"}, - {at: 0, expect: "path('M 50 60 V 70')"}, - {at: 0.125, expect: "path('M 45 70 V 95')"}, - {at: 0.875, expect: "path('M 15 130 V 245')"}, - {at: 1, expect: "path('M 10 140 V 270')"}, - {at: 2, expect: "path('M -30 220 V 470')"} + {at: -1, expect: 'path("M 90 -20 V -130")'}, + {at: 0, expect: 'path("M 50 60 V 70")'}, + {at: 0.125, expect: 'path("M 45 70 V 95")'}, + {at: 0.875, expect: 'path("M 15 130 V 245")'}, + {at: 1, expect: 'path("M 10 140 V 270")'}, + {at: 2, expect: 'path("M -30 220 V 470")'} ]); test_interpolation({ property: 'd', - from: "path('M 12 34 S 45 67 89 123')", - to: "path('M 20 26 S 61 51 113 99')" + from: 'path("M 12 34 S 45 67 89 123")', + to: 'path("M 20 26 S 61 51 113 99")' }, [ - {at: -1, expect: "path('M 4 42 S 29 83 65 147')"}, - {at: 0, expect: "path('M 12 34 S 45 67 89 123')"}, - {at: 0.125, expect: "path('M 13 33 S 47 65 92 120')"}, - {at: 0.875, expect: "path('M 19 27 S 59 53 110 102')"}, - {at: 1, expect: "path('M 20 26 S 61 51 113 99')"}, - {at: 2, expect: "path('M 28 18 S 77 35 137 75')"}, + {at: -1, expect: 'path("M 4 42 S 29 83 65 147")'}, + {at: 0, expect: 'path("M 12 34 S 45 67 89 123")'}, + {at: 0.125, expect: 'path("M 13 33 S 47 65 92 120")'}, + {at: 0.875, expect: 'path("M 19 27 S 59 53 110 102")'}, + {at: 1, expect: 'path("M 20 26 S 61 51 113 99")'}, + {at: 2, expect: 'path("M 28 18 S 77 35 137 75")'}, ]); test_interpolation({ property: 'd', - from: "path('m 12 34 s 33 33 77 89')", - to: "path('m 20 26 s 41 25 93 73')" + from: 'path("m 12 34 s 33 33 77 89")', + to: 'path("m 20 26 s 41 25 93 73")' }, [ - {at: -1, expect: "path('M 4 42 S 29 83 65 147')"}, - {at: 0, expect: "path('M 12 34 S 45 67 89 123')"}, - {at: 0.125, expect: "path('M 13 33 S 47 65 92 120')"}, - {at: 0.875, expect: "path('M 19 27 S 59 53 110 102')"}, - {at: 1, expect: "path('M 20 26 S 61 51 113 99')"}, - {at: 2, expect: "path('M 28 18 S 77 35 137 75')"}, + {at: -1, expect: 'path("M 4 42 S 29 83 65 147")'}, + {at: 0, expect: 'path("M 12 34 S 45 67 89 123")'}, + {at: 0.125, expect: 'path("M 13 33 S 47 65 92 120")'}, + {at: 0.875, expect: 'path("M 19 27 S 59 53 110 102")'}, + {at: 1, expect: 'path("M 20 26 S 61 51 113 99")'}, + {at: 2, expect: 'path("M 28 18 S 77 35 137 75")'}, ]); test_interpolation({ property: 'd', - from: "path('M 12 34 T 45 67')", - to: "path('M 20 26 T 61 51')" + from: 'path("M 12 34 T 45 67")', + to: 'path("M 20 26 T 61 51")' }, [ - {at: -1, expect: "path('M 4 42 T 29 83')"}, - {at: 0, expect: "path('M 12 34 T 45 67')"}, - {at: 0.125, expect: "path('M 13 33 T 47 65')"}, - {at: 0.875, expect: "path('M 19 27 T 59 53')"}, - {at: 1, expect: "path('M 20 26 T 61 51')"}, - {at: 2, expect: "path('M 28 18 T 77 35')"}, + {at: -1, expect: 'path("M 4 42 T 29 83")'}, + {at: 0, expect: 'path("M 12 34 T 45 67")'}, + {at: 0.125, expect: 'path("M 13 33 T 47 65")'}, + {at: 0.875, expect: 'path("M 19 27 T 59 53")'}, + {at: 1, expect: 'path("M 20 26 T 61 51")'}, + {at: 2, expect: 'path("M 28 18 T 77 35")'}, ]); test_interpolation({ property: 'd', - from: "path('m 12 34 t 33 33')", - to: "path('m 20 26 t 41 25')" + from: 'path("m 12 34 t 33 33")', + to: 'path("m 20 26 t 41 25")' }, [ - {at: -1, expect: "path('M 4 42 T 29 83')"}, - {at: 0, expect: "path('M 12 34 T 45 67')"}, - {at: 0.125, expect: "path('M 13 33 T 47 65')"}, - {at: 0.875, expect: "path('M 19 27 T 59 53')"}, - {at: 1, expect: "path('M 20 26 T 61 51')"}, - {at: 2, expect: "path('M 28 18 T 77 35')"}, + {at: -1, expect: 'path("M 4 42 T 29 83")'}, + {at: 0, expect: 'path("M 12 34 T 45 67")'}, + {at: 0.125, expect: 'path("M 13 33 T 47 65")'}, + {at: 0.875, expect: 'path("M 19 27 T 59 53")'}, + {at: 1, expect: 'path("M 20 26 T 61 51")'}, + {at: 2, expect: 'path("M 28 18 T 77 35")'}, ]); ]]> diff --git a/tests/wpt/web-platform-tests/svg/path/property/getComputedStyle.svg b/tests/wpt/web-platform-tests/svg/path/property/getComputedStyle.svg index af30862781a..5830191931f 100644 --- a/tests/wpt/web-platform-tests/svg/path/property/getComputedStyle.svg +++ b/tests/wpt/web-platform-tests/svg/path/property/getComputedStyle.svg @@ -39,14 +39,14 @@ var p6 = document.getElementById('p6'); var p7 = document.getElementById('p7'); - assert_equals(getComputedStyle(g0).d, "none"); - assert_equals(getComputedStyle(p1).d, "none"); - assert_equals(getComputedStyle(p2).d, "path('M 10 2 H 20')"); - assert_equals(getComputedStyle(p3).d, "path('M 10 3 H 30')"); - assert_equals(getComputedStyle(p4).d, "path('M 10 4 H 40')"); - assert_equals(getComputedStyle(g5).d, "path('M 10 5 H 50')"); - assert_equals(getComputedStyle(p6).d, "path('M 10 5 H 50')"); - assert_equals(getComputedStyle(p7).d, "none"); + assert_equals(getComputedStyle(g0).d, 'none'); + assert_equals(getComputedStyle(p1).d, 'none'); + assert_equals(getComputedStyle(p2).d, 'path("M 10 2 H 20")'); + assert_equals(getComputedStyle(p3).d, 'path("M 10 3 H 30")'); + assert_equals(getComputedStyle(p4).d, 'path("M 10 4 H 40")'); + assert_equals(getComputedStyle(g5).d, 'path("M 10 5 H 50")'); + assert_equals(getComputedStyle(p6).d, 'path("M 10 5 H 50")'); + assert_equals(getComputedStyle(p7).d, 'none'); }); ]]> diff --git a/tests/wpt/web-platform-tests/tools/ci/ci_taskcluster.sh b/tests/wpt/web-platform-tests/tools/ci/ci_taskcluster.sh index 546055293d7..901ae520c7f 100755 --- a/tests/wpt/web-platform-tests/tools/ci/ci_taskcluster.sh +++ b/tests/wpt/web-platform-tests/tools/ci/ci_taskcluster.sh @@ -1,6 +1,8 @@ #!/bin/bash +set -ex -./wpt manifest-download +# This is allowed to fail +./wpt manifest-download || echo if [ $1 == "firefox" ]; then ./wpt run firefox --log-tbpl=../artifacts/log_tbpl.log --log-tbpl-level=info --log-wptreport=../artifacts/wpt_report.json --log-mach=- --this-chunk=$4 --total-chunks=$5 --test-type=$3 -y --install-browser --channel=$2 --no-pause --no-restart-on-unexpected --reftest-internal --install-fonts --no-fail-on-unexpected diff --git a/tests/wpt/web-platform-tests/tools/ci/ci_wptrunner_infrastructure.sh b/tests/wpt/web-platform-tests/tools/ci/ci_wptrunner_infrastructure.sh index d6d6803974f..c32c9438703 100755 --- a/tests/wpt/web-platform-tests/tools/ci/ci_wptrunner_infrastructure.sh +++ b/tests/wpt/web-platform-tests/tools/ci/ci_wptrunner_infrastructure.sh @@ -18,14 +18,14 @@ test_infrastructure() { } main() { - PRODUCTS=( "firefox" "chrome" ) + PRODUCTS=( "firefox" "chrome" "chrome_webdriver" ) for PRODUCT in "${PRODUCTS[@]}"; do if [ "$PRODUCT" != "firefox" ]; then # Firefox is expected to work using pref settings for DNS # Don't adjust the hostnames in that case to ensure this keeps working hosts_fixup fi - if [ "$PRODUCT" == "chrome" ]; then + if [[ "$PRODUCT" == "chrome"* ]]; then install_chrome unstable test_infrastructure "--binary=$(which google-chrome-unstable)" else diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py index e148e8fe800..23ffc40b31f 100644 --- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py +++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py @@ -6,8 +6,10 @@ class WebDriverException(Exception): http_status = None status_code = None - def __init__(self, message=None, stacktrace=None): + def __init__(self, http_status=None, status_code=None, message=None, stacktrace=None): super(WebDriverException, self) + self.http_status = http_status + self.status_code = status_code self.message = message self.stacktrace = stacktrace @@ -171,6 +173,8 @@ def from_response(response): """ if response.status == 200: raise UnknownErrorException( + response.status, + None, "Response is not an error:\n" "%s" % json.dumps(response.body)) @@ -178,6 +182,8 @@ def from_response(response): value = response.body["value"] else: raise UnknownErrorException( + response.status, + None, "Expected 'value' key in response body:\n" "%s" % json.dumps(response.body)) @@ -187,7 +193,7 @@ def from_response(response): stack = value["stacktrace"] or None cls = get(code) - return cls(message, stacktrace=stack) + return cls(response.status, code, message, stacktrace=stack) def get(error_code): diff --git a/tests/wpt/web-platform-tests/tools/wpt/browser.py b/tests/wpt/web-platform-tests/tools/wpt/browser.py index 65752a25f12..7b943c2e73c 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/browser.py +++ b/tests/wpt/web-platform-tests/tools/wpt/browser.py @@ -486,6 +486,12 @@ class ChromeAndroid(Browser): def version(self, binary): return None +class ChromeWebDriver(Chrome): + """Chrome-specific interface for chrome without using selenium. + + Includes webdriver installation. + """ + product = "chrome_webdriver" class Opera(Browser): """Opera-specific interface. @@ -582,6 +588,10 @@ class Edge(Browser): return None +class EdgeWebDriver(Edge): + product = "edge_webdriver" + + class InternetExplorer(Browser): """Internet Explorer-specific interface.""" @@ -629,6 +639,10 @@ class Safari(Browser): return None +class SafariWebDriver(Safari): + product = "safari_webdriver" + + class Servo(Browser): """Servo-specific interface.""" diff --git a/tests/wpt/web-platform-tests/tools/wpt/run.py b/tests/wpt/web-platform-tests/tools/wpt/run.py index 036c38f2586..a1e5637bf1d 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/run.py +++ b/tests/wpt/web-platform-tests/tools/wpt/run.py @@ -273,6 +273,10 @@ class ChromeAndroid(BrowserSetup): else: raise WptrunError("Unable to locate or install chromedriver binary") +class ChromeWebDriver(Chrome): + name = "chrome_webdriver" + browser_cls = browser.ChromeWebDriver + class Opera(BrowserSetup): name = "opera" @@ -318,6 +322,11 @@ https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ kwargs["webdriver_binary"] = webdriver_binary +class EdgeWebDriver(Edge): + name = "edge_webdriver" + browser_cls = browser.EdgeWebDriver + + class InternetExplorer(BrowserSetup): name = "ie" browser_cls = browser.InternetExplorer @@ -356,6 +365,11 @@ class Safari(BrowserSetup): kwargs["webdriver_binary"] = webdriver_binary +class SafariWebDriver(Safari): + name = "safari_webdriver" + browser_cls = browser.SafariWebDriver + + class Sauce(BrowserSetup): name = "sauce" browser_cls = browser.Sauce @@ -402,9 +416,12 @@ product_setup = { "firefox": Firefox, "chrome": Chrome, "chrome_android": ChromeAndroid, + "chrome_webdriver": ChromeWebDriver, "edge": Edge, + "edge_webdriver": EdgeWebDriver, "ie": InternetExplorer, "safari": Safari, + "safari_webdriver": SafariWebDriver, "servo": Servo, "sauce": Sauce, "opera": Opera, diff --git a/tests/wpt/web-platform-tests/tools/wpt/wpt.py b/tests/wpt/web-platform-tests/tools/wpt/wpt.py index f4eecce22cf..55802461553 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/wpt.py +++ b/tests/wpt/web-platform-tests/tools/wpt/wpt.py @@ -101,9 +101,6 @@ def main(prog=None, argv=None): main_args, command_args = parse_args(argv, commands) - if not(len(argv) and argv[0] in commands): - sys.exit(1) - command = main_args.command props = commands[command] venv = None diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/__init__.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/__init__.py index d8682e16a55..08949f79483 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/__init__.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/__init__.py @@ -24,11 +24,14 @@ module global scope. product_list = ["chrome", "chrome_android", + "chrome_webdriver", "edge", + "edge_webdriver", "fennec", "firefox", "ie", "safari", + "safari_webdriver", "sauce", "servo", "servodriver", diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py index dc03ef711b6..70324bec31f 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py @@ -2,12 +2,32 @@ import os import platform import socket from abc import ABCMeta, abstractmethod +from copy import deepcopy from ..wptcommandline import require_arg # noqa: F401 here = os.path.split(__file__)[0] +def inherit(super_module, child_globals, product_name): + super_wptrunner = super_module.__wptrunner__ + child_globals["__wptrunner__"] = child_wptrunner = deepcopy(super_wptrunner) + + child_wptrunner["product"] = product_name + + for k in ("check_args", "browser", "browser_kwargs", "executor_kwargs", + "env_extras", "env_options"): + attr = super_wptrunner[k] + child_globals[attr] = getattr(super_module, attr) + + for v in super_module.__wptrunner__["executor"].values(): + child_globals[v] = getattr(super_module, v) + + if "run_info_extras" in super_wptrunner: + attr = super_wptrunner["run_info_extras"] + child_globals[attr] = getattr(super_module, attr) + + def cmd_arg(name, value=None): prefix = "-" if platform.system() == "Windows" else "--" rv = prefix + name diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome_webdriver.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome_webdriver.py new file mode 100644 index 00000000000..a63460f4544 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome_webdriver.py @@ -0,0 +1,50 @@ +from .base import inherit +from . import chrome + +from ..executors import executor_kwargs as base_executor_kwargs +from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401 + WebDriverRefTestExecutor) # noqa: F401 + + +inherit(chrome, globals(), "chrome_webdriver") + +# __wptrunner__ magically appears from inherit, F821 is undefined name +__wptrunner__["executor_kwargs"] = "executor_kwargs" # noqa: F821 +__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821 +__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821 + + +def executor_kwargs(test_type, server_config, cache_manager, run_info_data, + **kwargs): + executor_kwargs = base_executor_kwargs(test_type, server_config, + cache_manager, run_info_data, + **kwargs) + executor_kwargs["close_after_done"] = True + + capabilities = { + "browserName": "chrome", + "platform": "ANY", + "version": "", + "goog:chromeOptions": { + "prefs": { + "profile": { + "default_content_setting_values": { + "popups": 1 + } + } + }, + "w3c": True + } + } + + for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]: + if kwargs[kwarg] is not None: + capabilities["goog:chromeOptions"][capability] = kwargs[kwarg] + + if test_type == "testharness": + capabilities["goog:chromeOptions"]["useAutomationExtension"] = False + capabilities["goog:chromeOptions"]["excludeSwitches"] = ["enable-automation"] + + executor_kwargs["capabilities"] = capabilities + + return executor_kwargs diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/edge_webdriver.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/edge_webdriver.py new file mode 100644 index 00000000000..c2545de46f0 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/edge_webdriver.py @@ -0,0 +1,12 @@ +from .base import inherit +from . import edge + +from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401 + WebDriverRefTestExecutor) # noqa: F401 + + +inherit(edge, globals(), "edge_webdriver") + +# __wptrunner__ magically appears from inherit, F821 is undefined name +__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821 +__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/safari_webdriver.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/safari_webdriver.py new file mode 100644 index 00000000000..12735c141b3 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/safari_webdriver.py @@ -0,0 +1,12 @@ +from .base import inherit +from . import safari + +from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401 + WebDriverRefTestExecutor) # noqa: F401 + + +inherit(safari, globals(), "safari_webdriver") + +# __wptrunner__ magically appears from inherit, F821 is undefined name +__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821 +__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executorselenium.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executorselenium.py index d9b67968ddf..0675461d5d8 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executorselenium.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executorselenium.py @@ -95,14 +95,14 @@ class SeleniumTestharnessProtocolPart(TestharnessProtocolPart): def get_test_window(self, window_id, parent): test_window = None - if window_id: - try: - # Try this, it's in Level 1 but nothing supports it yet - win_s = self.webdriver.execute_script("return window['%s'];" % self.window_id) - win_obj = json.loads(win_s) - test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"] - except Exception: - pass + try: + # Try using the JSON serialization of the WindowProxy object, + # it's in Level 1 but nothing supports it yet + win_s = self.webdriver.execute_script("return window['%s'];" % window_id) + win_obj = json.loads(win_s) + test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"] + except Exception: + pass if test_window is None: after = self.webdriver.window_handles @@ -296,7 +296,7 @@ class SeleniumTestharnessExecutor(TestharnessExecutor): parent_window = protocol.testharness.close_old_windows() # Now start the test harness protocol.base.execute_script(self.script % format_map) - test_window = protocol.testharness.get_test_window(webdriver, parent_window) + test_window = protocol.testharness.get_test_window(self.window_id, parent_window) handler = CallbackHandler(self.logger, protocol, test_window) while True: diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executorwebdriver.py new file mode 100644 index 00000000000..127c909e810 --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executorwebdriver.py @@ -0,0 +1,373 @@ +import json +import os +import socket +import threading +import traceback +import urlparse +import uuid + +from .base import (CallbackHandler, + RefTestExecutor, + RefTestImplementation, + TestharnessExecutor, + extra_timeout, + strip_server) +from .protocol import (BaseProtocolPart, + TestharnessProtocolPart, + Protocol, + SelectorProtocolPart, + ClickProtocolPart, + SendKeysProtocolPart, + TestDriverProtocolPart) +from ..testrunner import Stop + +import webdriver as client + +here = os.path.join(os.path.split(__file__)[0]) + +class WebDriverBaseProtocolPart(BaseProtocolPart): + def setup(self): + self.webdriver = self.parent.webdriver + + def execute_script(self, script, async=False): + method = self.webdriver.execute_async_script if async else self.webdriver.execute_script + return method(script) + + def set_timeout(self, timeout): + try: + self.webdriver.timeouts.script = timeout + except client.WebDriverException: + # workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2057 + body = {"type": "script", "ms": timeout * 1000} + self.webdriver.send_session_command("POST", "timeouts", body) + + @property + def current_window(self): + return self.webdriver.window_handle + + def set_window(self, handle): + self.webdriver.window_handle = handle + + def wait(self): + while True: + try: + self.webdriver.execute_async_script("") + except client.TimeoutException: + pass + except (socket.timeout, client.NoSuchWindowException, + client.UnknownErrorException, IOError): + break + except Exception as e: + self.logger.error(traceback.format_exc(e)) + break + + +class WebDriverTestharnessProtocolPart(TestharnessProtocolPart): + def setup(self): + self.webdriver = self.parent.webdriver + + def load_runner(self, url_protocol): + url = urlparse.urljoin(self.parent.executor.server_url(url_protocol), + "/testharness_runner.html") + self.logger.debug("Loading %s" % url) + + self.webdriver.url = url + self.webdriver.execute_script("document.title = '%s'" % + threading.current_thread().name.replace("'", '"')) + + def close_old_windows(self): + exclude = self.webdriver.window_handle + handles = [item for item in self.webdriver.handles if item != exclude] + for handle in handles: + try: + self.webdriver.window_handle = handle + self.webdriver.close() + except client.NoSuchWindowException: + pass + self.webdriver.window_handle = exclude + return exclude + + def get_test_window(self, window_id, parent): + test_window = None + try: + # Try using the JSON serialization of the WindowProxy object, + # it's in Level 1 but nothing supports it yet + win_s = self.webdriver.execute_script("return window['%s'];" % window_id) + win_obj = json.loads(win_s) + test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"] + except Exception: + pass + + if test_window is None: + after = self.webdriver.handles + if len(after) == 2: + test_window = next(iter(set(after) - set([parent]))) + elif after[0] == parent and len(after) > 2: + # Hope the first one here is the test window + test_window = after[1] + else: + raise Exception("unable to find test window") + + assert test_window != parent + return test_window + + +class WebDriverSelectorProtocolPart(SelectorProtocolPart): + def setup(self): + self.webdriver = self.parent.webdriver + + def elements_by_selector(self, selector): + return self.webdriver.find.css(selector) + + +class WebDriverClickProtocolPart(ClickProtocolPart): + def setup(self): + self.webdriver = self.parent.webdriver + + def element(self, element): + return element.click() + + +class WebDriverSendKeysProtocolPart(SendKeysProtocolPart): + def setup(self): + self.webdriver = self.parent.webdriver + + def send_keys(self, element, keys): + try: + return element.send_keys(keys) + except client.UnknownErrorException as e: + # workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=1999 + if (e.http_status != 500 or + e.status_code != "unknown error"): + raise + return element.send_element_command("POST", "value", {"value": list(keys)}) + + +class WebDriverTestDriverProtocolPart(TestDriverProtocolPart): + def setup(self): + self.webdriver = self.parent.webdriver + + def send_message(self, message_type, status, message=None): + obj = { + "type": "testdriver-%s" % str(message_type), + "status": str(status) + } + if message: + obj["message"] = str(message) + self.webdriver.execute_script("window.postMessage(%s, '*')" % json.dumps(obj)) + + +class WebDriverProtocol(Protocol): + implements = [WebDriverBaseProtocolPart, + WebDriverTestharnessProtocolPart, + WebDriverSelectorProtocolPart, + WebDriverClickProtocolPart, + WebDriverSendKeysProtocolPart, + WebDriverTestDriverProtocolPart] + + def __init__(self, executor, browser, capabilities, **kwargs): + super(WebDriverProtocol, self).__init__(executor, browser) + self.capabilities = capabilities + self.url = browser.webdriver_url + self.webdriver = None + + def connect(self): + """Connect to browser via WebDriver.""" + self.logger.debug("Connecting to WebDriver on URL: %s" % self.url) + + host, port = self.url.split(":")[1].strip("/"), self.url.split(':')[-1].strip("/") + + capabilities = {"alwaysMatch": self.capabilities} + self.webdriver = client.Session(host, port, capabilities=capabilities) + self.webdriver.start() + + + def after_conect(self): + pass + + def teardown(self): + self.logger.debug("Hanging up on WebDriver session") + try: + self.webdriver.quit() + except Exception: + pass + del self.webdriver + + def is_alive(self): + try: + # Get a simple property over the connection + self.webdriver.window_handle + except (socket.timeout, client.UnknownErrorException): + return False + return True + + def after_connect(self): + self.testharness.load_runner(self.executor.last_environment["protocol"]) + + +class WebDriverRun(object): + def __init__(self, func, protocol, url, timeout): + self.func = func + self.result = None + self.protocol = protocol + self.url = url + self.timeout = timeout + self.result_flag = threading.Event() + + def run(self): + timeout = self.timeout + + try: + self.protocol.base.set_timeout((timeout + extra_timeout)) + except client.UnknownErrorException: + self.logger.error("Lost WebDriver connection") + return Stop + + executor = threading.Thread(target=self._run) + executor.start() + + flag = self.result_flag.wait(timeout + 2 * extra_timeout) + if self.result is None: + assert not flag + self.result = False, ("EXTERNAL-TIMEOUT", None) + + return self.result + + def _run(self): + try: + self.result = True, self.func(self.protocol, self.url, self.timeout) + except client.TimeoutException: + self.result = False, ("EXTERNAL-TIMEOUT", None) + except (socket.timeout, client.UnknownErrorException): + self.result = False, ("CRASH", None) + except Exception as e: + if (isinstance(e, client.WebDriverException) and + e.http_status == 408 and + e.status_code == "asynchronous script timeout"): + # workaround for https://bugs.chromium.org/p/chromedriver/issues/detail?id=2001 + self.result = False, ("EXTERNAL-TIMEOUT", None) + else: + message = getattr(e, "message", "") + if message: + message += "\n" + message += traceback.format_exc(e) + self.result = False, ("ERROR", message) + finally: + self.result_flag.set() + + +class WebDriverTestharnessExecutor(TestharnessExecutor): + supports_testdriver = True + + def __init__(self, browser, server_config, timeout_multiplier=1, + close_after_done=True, capabilities=None, debug_info=None, + **kwargs): + """WebDriver-based executor for testharness.js tests""" + TestharnessExecutor.__init__(self, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.protocol = WebDriverProtocol(self, browser, capabilities) + with open(os.path.join(here, "testharness_webdriver.js")) as f: + self.script = f.read() + with open(os.path.join(here, "testharness_webdriver_resume.js")) as f: + self.script_resume = f.read() + self.close_after_done = close_after_done + self.window_id = str(uuid.uuid4()) + + def is_alive(self): + return self.protocol.is_alive() + + def on_environment_change(self, new_environment): + if new_environment["protocol"] != self.last_environment["protocol"]: + self.protocol.testharness.load_runner(new_environment["protocol"]) + + def do_test(self, test): + url = self.test_url(test) + + success, data = WebDriverRun(self.do_testharness, + self.protocol, + url, + test.timeout * self.timeout_multiplier).run() + + if success: + return self.convert_result(test, data) + + return (test.result_cls(*data), []) + + def do_testharness(self, protocol, url, timeout): + format_map = {"abs_url": url, + "url": strip_server(url), + "window_id": self.window_id, + "timeout_multiplier": self.timeout_multiplier, + "timeout": timeout * 1000} + + parent_window = protocol.testharness.close_old_windows() + # Now start the test harness + protocol.base.execute_script(self.script % format_map) + test_window = protocol.testharness.get_test_window(self.window_id, parent_window) + + handler = CallbackHandler(self.logger, protocol, test_window) + while True: + result = protocol.base.execute_script( + self.script_resume % format_map, async=True) + done, rv = handler(result) + if done: + break + return rv + + +class WebDriverRefTestExecutor(RefTestExecutor): + def __init__(self, browser, server_config, timeout_multiplier=1, + screenshot_cache=None, close_after_done=True, + debug_info=None, capabilities=None, **kwargs): + """WebDriver-based executor for reftests""" + RefTestExecutor.__init__(self, + browser, + server_config, + screenshot_cache=screenshot_cache, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.protocol = WebDriverProtocol(self, browser, + capabilities=capabilities) + self.implementation = RefTestImplementation(self) + self.close_after_done = close_after_done + self.has_window = False + + with open(os.path.join(here, "reftest.js")) as f: + self.script = f.read() + with open(os.path.join(here, "reftest-wait_webdriver.js")) as f: + self.wait_script = f.read() + + def is_alive(self): + return self.protocol.is_alive() + + def do_test(self, test): + self.protocol.webdriver.window.size = (600, 600) + + result = self.implementation.run_test(test) + + return self.convert_result(test, result) + + def screenshot(self, test, viewport_size, dpi): + # https://github.com/w3c/wptrunner/issues/166 + assert viewport_size is None + assert dpi is None + + return WebDriverRun(self._screenshot, + self.protocol, + self.test_url(test), + test.timeout).run() + + def _screenshot(self, protocol, url, timeout): + webdriver = protocol.webdriver + webdriver.url = url + + webdriver.execute_async_script(self.wait_script) + + screenshot = webdriver.screenshot() + + # strip off the data:img/png, part of the url + if screenshot.startswith("data:image/png;base64,"): + screenshot = screenshot.split(",", 1)[1] + + return screenshot diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py index ed2a4ec39dd..e684bf68076 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py @@ -96,8 +96,12 @@ class LogHandler(reader.LogHandler): duration = data["time"] - test.pop("start_time") test["longest_duration"][data["status"]] = max( duration, test["longest_duration"][data["status"]]) - # test_timeout is in seconds; convert it to ms. - test["timeout"] = data["extra"]["test_timeout"] * 1000 + try: + # test_timeout is in seconds; convert it to ms. + test["timeout"] = data["extra"]["test_timeout"] * 1000 + except KeyError: + # If a test is skipped, it won't have extra info. + pass def is_inconsistent(results_dict, iterations): @@ -118,6 +122,8 @@ def find_slow_status(test): A result status produced by a run that almost times out; None, if no runs almost time out. """ + if "timeout" not in test: + return None threshold = test["timeout"] * FLAKY_THRESHOLD for status in ['PASS', 'FAIL', 'OK', 'ERROR']: if (status in test["longest_duration"] and diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/base.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/base.py index b5173f3b513..84dc4f2e7f8 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/base.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/base.py @@ -17,7 +17,9 @@ if "CURRENT_TOX_ENV" in os.environ: current_tox_env_split = os.environ["CURRENT_TOX_ENV"].split("-") tox_env_extra_browsers = { - "chrome": {"chrome_android"}, + "chrome": {"chrome_android", "chrome_webdriver"}, + "edge": {"edge_webdriver"}, + "safari": {"safari_webdriver"}, "servo": {"servodriver"}, } diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_stability.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_stability.py index 80c964455ed..5a051b6c899 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_stability.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_stability.py @@ -29,3 +29,5 @@ def test_find_slow_status(): assert stability.find_slow_status({ "longest_duration": {"TIMEOUT": 10, "FAIL": 81}, "timeout": 100}) == "FAIL" + assert stability.find_slow_status({ + "longest_duration": {"SKIP": 0}}) is None diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py index 5685f840670..e5678be4f54 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py @@ -96,11 +96,38 @@ class UpdateMetadata(Step): runner.run() +class RemoveObsolete(Step): + """Remove metadata files that don't corespond to an existing test file""" + + def create(self, state): + if not state.kwargs["remove_obsolete"]: + return + + paths = state.kwargs["test_paths"] + state.tests_path = state.paths["/"]["tests_path"] + state.metadata_path = state.paths["/"]["metadata_path"] + + for url_paths in paths.itervalues(): + tests_path = url_paths["tests_path"] + metadata_path = url_paths["metadata_path"] + for dirpath, dirnames, filenames in os.walk(metadata_path): + for filename in filenames: + if filename == "__dir__.ini": + continue + if filename.endswith(".ini"): + full_path = os.path.join(dirpath, filename) + rel_path = os.path.relpath(full_path, metadata_path) + test_path = os.path.join(tests_path, rel_path[:-4]) + if not os.path.exists(test_path): + os.unlink(full_path) + + class UpdateRunner(StepRunner): """Runner for doing an overall update.""" steps = [LoadConfig, LoadTrees, SyncFromUpstream, + RemoveObsolete, UpdateMetadata] diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py index e6c624994d9..0075ad90962 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py @@ -565,8 +565,14 @@ def create_parser_update(product_choices=None): parser.add_argument("--stability", nargs="?", action="store", const="unstable", default=None, help=("Reason for disabling tests. When updating test results, disable tests that have " "inconsistent results across many runs with the given reason.")) - parser.add_argument("--continue", action="store_true", help="Continue a previously started run of the update script") - parser.add_argument("--abort", action="store_true", help="Clear state from a previous incomplete run of the update script") + parser.add_argument("--no-remove-obsolete", action="store_false", dest="remove_obsolete", default=True, + help=("Don't remove metadata files that no longer correspond to a test file")) + parser.add_argument("--no-store-state", action="store_false", dest="store_state", + help="Store state so that steps can be resumed after failure") + parser.add_argument("--continue", action="store_true", + help="Continue a previously started run of the update script") + parser.add_argument("--abort", action="store_true", + help="Clear state from a previous incomplete run of the update script") parser.add_argument("--exclude", action="store", nargs="*", help="List of glob-style paths to exclude when syncing tests") parser.add_argument("--include", action="store", nargs="*", diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/assertions.js b/tests/wpt/web-platform-tests/wasm/jsapi/assertions.js index 151a406655c..bda3ae7bc3c 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/assertions.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/assertions.js @@ -15,3 +15,59 @@ function assert_function_length(fn, length, description) { assert_true(propdesc.configurable, "configurable", `${description} length should be configurable`); assert_equals(propdesc.value, length, `${description} length should be ${length}`); } + +function assert_exported_function(fn, { name, length }, description) { + assert_equals(Object.getPrototypeOf(fn), Function.prototype, + `${description}: prototype`); + + assert_function_name(fn, name, description); + assert_function_length(fn, length, description); +} + +function assert_Instance(instance, expected_exports) { + assert_equals(Object.getPrototypeOf(instance), WebAssembly.Instance.prototype, + "prototype"); + assert_true(Object.isExtensible(instance), "extensible"); + + assert_equals(instance.exports, instance.exports, "exports should be idempotent"); + const exports = instance.exports; + + assert_equals(Object.getPrototypeOf(exports), null, "exports prototype"); + assert_false(Object.isExtensible(exports), "extensible exports"); + for (const [key, expected] of Object.entries(expected_exports)) { + const property = Object.getOwnPropertyDescriptor(exports, key); + assert_equals(typeof property, "object", `${key} should be present`); + assert_false(property.writable, `${key}: writable`); + assert_true(property.enumerable, `${key}: enumerable`); + assert_false(property.configurable, `${key}: configurable`); + const actual = property.value; + assert_true(Object.isExtensible(actual), `${key}: extensible`); + + switch (expected.kind) { + case "function": + assert_exported_function(actual, expected, `value of ${key}`); + break; + case "global": + assert_equals(Object.getPrototypeOf(actual), WebAssembly.Global.prototype, + `value of ${key}: prototype`); + assert_equals(actual.value, expected.value, `value of ${key}: value`); + assert_equals(actual.valueOf(), expected.value, `value of ${key}: valueOf()`); + break; + case "memory": + assert_equals(Object.getPrototypeOf(actual), WebAssembly.Memory.prototype, + `value of ${key}: prototype`); + assert_equals(Object.getPrototypeOf(actual.buffer), ArrayBuffer.prototype, + `value of ${key}: prototype of buffer`); + assert_equals(actual.buffer.byteLength, 0x10000 * expected.size, `value of ${key}: size of buffer`); + const array = new Uint8Array(actual.buffer); + assert_equals(array[0], 0, `value of ${key}: first element of buffer`); + assert_equals(array[array.byteLength - 1], 0, `value of ${key}: last element of buffer`); + break; + case "table": + assert_equals(Object.getPrototypeOf(actual), WebAssembly.Table.prototype, + `value of ${key}: prototype`); + assert_equals(actual.length, expected.length, `value of ${key}: length of table`); + break; + } + } +} diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/constructor/compile.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/compile.any.js new file mode 100644 index 00000000000..0139a18fda3 --- /dev/null +++ b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/compile.any.js @@ -0,0 +1,77 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js + +function assert_Module(module) { + assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype, + "Prototype"); + assert_true(Object.isExtensible(module), "Extensibility"); +} + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +promise_test(t => { + return promise_rejects(t, new TypeError(), WebAssembly.compile()); +}, "Missing argument"); + +promise_test(t => { + const invalidArguments = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + ArrayBuffer, + ArrayBuffer.prototype, + Array.from(emptyModuleBinary), + ]; + return Promise.all(invalidArguments.map(argument => { + return promise_rejects(t, new TypeError(), WebAssembly.compile(argument), + `compile(${format_value(argument)})`); + })); +}, "Invalid arguments"); + +promise_test(() => { + const fn = WebAssembly.compile; + const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly, + ]; + return Promise.all(thisValues.map(thisValue => { + return fn.call(thisValue, emptyModuleBinary).then(assert_Module); + })); +}, "Branding"); + +test(() => { + const promise = WebAssembly.compile(emptyModuleBinary); + assert_equals(Object.getPrototypeOf(promise), Promise.prototype, "prototype"); + assert_true(Object.isExtensible(promise), "extensibility"); +}, "Promise type"); + +promise_test(t => { + const buffer = new Uint8Array(); + return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.compile(buffer)); +}, "Invalid code"); + +promise_test(() => { + return WebAssembly.compile(emptyModuleBinary).then(assert_Module); +}, "Result type"); + +promise_test(() => { + const buffer = new WasmModuleBuilder().toBuffer(); + assert_equals(buffer[0], 0); + const promise = WebAssembly.compile(buffer); + buffer[0] = 1; + return promise.then(assert_Module); +}, "Changing the buffer"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/constructor/instantiate.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/instantiate.any.js new file mode 100644 index 00000000000..e90f21e28eb --- /dev/null +++ b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/instantiate.any.js @@ -0,0 +1,196 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js +// META: script=/wasm/jsapi/assertions.js + +function assert_WebAssemblyInstantiatedSource(actual, expected_exports={}) { + assert_equals(Object.getPrototypeOf(actual), Object.prototype, + "Prototype"); + assert_true(Object.isExtensible(actual), "Extensibility"); + + const module = Object.getOwnPropertyDescriptor(actual, "module"); + assert_equals(typeof module, "object", "module: type of descriptor"); + assert_true(module.writable, "module: writable"); + assert_true(module.enumerable, "module: enumerable"); + assert_true(module.configurable, "module: configurable"); + assert_equals(Object.getPrototypeOf(module.value), WebAssembly.Module.prototype, + "module: prototype"); + + const instance = Object.getOwnPropertyDescriptor(actual, "instance"); + assert_equals(typeof instance, "object", "instance: type of descriptor"); + assert_true(instance.writable, "instance: writable"); + assert_true(instance.enumerable, "instance: enumerable"); + assert_true(instance.configurable, "instance: configurable"); + assert_Instance(instance.value, expected_exports); +} + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +promise_test(t => { + return promise_rejects(t, new TypeError(), WebAssembly.instantiate()); +}, "Missing arguments"); + +promise_test(() => { + const fn = WebAssembly.instantiate; + const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly, + ]; + return Promise.all(thisValues.map(thisValue => { + return fn.call(thisValue, emptyModuleBinary).then(assert_WebAssemblyInstantiatedSource); + })); +}, "Branding"); + +promise_test(t => { + const invalidArguments = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly.Module, + WebAssembly.Module.prototype, + ArrayBuffer, + ArrayBuffer.prototype, + Array.from(emptyModuleBinary), + ]; + return Promise.all(invalidArguments.map(argument => { + return promise_rejects(t, new TypeError(), WebAssembly.instantiate(argument), + `instantiate(${format_value(argument)})`); + })); +}, "Invalid arguments"); + +test(() => { + const promise = WebAssembly.instantiate(emptyModuleBinary); + assert_equals(Object.getPrototypeOf(promise), Promise.prototype, "prototype"); + assert_true(Object.isExtensible(promise), "extensibility"); +}, "Promise type"); + +const createModule = () => { + const builder = new WasmModuleBuilder(); + + builder + .addFunction("fn", kSig_v_d) + .addBody([ + kExprEnd + ]) + .exportFunc(); + builder + .addFunction("fn2", kSig_v_v) + .addBody([ + kExprEnd + ]) + .exportFunc(); + + builder.setFunctionTableLength(1); + builder.addExportOfKind("table", kExternalTable, 0); + + builder.addGlobal(kWasmI32, true) + .exportAs("global") + .init = 7; + builder.addGlobal(kWasmF64, true) + .exportAs("global2") + .init = 1.2; + + builder.addMemory(4, 8, true); + + const buffer = builder.toBuffer(); + + const exports = { + "fn": { "kind": "function", "name": "0", "length": 1 }, + "fn2": { "kind": "function", "name": "1", "length": 0 }, + "table": { "kind": "table", "length": 1 }, + "global": { "kind": "global", "value": 7 }, + "global2": { "kind": "global", "value": 1.2 }, + "memory": { "kind": "memory", "size": 4 }, + }; + + return [buffer, exports]; +} + +promise_test(() => { + const [buffer, expected] = createModule(); + return WebAssembly.instantiate(buffer).then(result => assert_WebAssemblyInstantiatedSource(result, expected)); +}, "BufferSource argument"); + +promise_test(() => { + const [buffer, expected] = createModule(); + const module = new WebAssembly.Module(buffer); + return WebAssembly.instantiate(module).then(instance => assert_Instance(instance, expected)); +}, "Module argument"); + +const createModuleWithImports = () => { + const builder = new WasmModuleBuilder(); + + const index = builder.addImportedGlobal("module", "global", kWasmI32); + builder + .addFunction("fn", kSig_i_v) + .addBody([ + kExprGetGlobal, + index, + kExprReturn, + kExprEnd, + ]) + .exportFunc(); + + const buffer = builder.toBuffer(); + + const expected = { + "fn": { "kind": "function", "name": "0", "length": 0 }, + }; + + return [buffer, expected]; +}; + +promise_test(() => { + const [buffer, expected] = createModuleWithImports(); + + const value = 102; + return WebAssembly.instantiate(buffer, { + "module": { + "global": value, + }, + }).then(result => { + assert_WebAssemblyInstantiatedSource(result, expected) + assert_equals(result.instance.exports.fn(), value); + }); +}, "exports and imports: buffer argument"); + +promise_test(() => { + const [buffer, expected] = createModuleWithImports(); + const module = new WebAssembly.Module(buffer); + + const value = 102; + return WebAssembly.instantiate(module, { + "module": { + "global": value, + }, + }).then(instance => { + assert_Instance(instance, expected) + assert_equals(instance.exports.fn(), value); + }); +}, "exports and imports: Module argument"); + +promise_test(t => { + const buffer = new Uint8Array(); + return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.instantiate(buffer)); +}, "Invalid code"); + +promise_test(() => { + const buffer = new WasmModuleBuilder().toBuffer(); + assert_equals(buffer[0], 0); + const promise = WebAssembly.instantiate(buffer); + buffer[0] = 1; + return promise.then(assert_WebAssemblyInstantiatedSource); +}, "Changing the buffer"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/constructor/validate.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/validate.any.js new file mode 100644 index 00000000000..70bd9f7022a --- /dev/null +++ b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/validate.any.js @@ -0,0 +1,96 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +test(() => { + assert_throws(new TypeError(), () => WebAssembly.validate()); +}, "Missing argument"); + +test(() => { + const invalidArguments = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + ArrayBuffer, + ArrayBuffer.prototype, + Array.from(emptyModuleBinary), + ]; + for (const argument of invalidArguments) { + assert_throws(new TypeError(), () => WebAssembly.validate(argument), + `validate(${format_value(argument)})`); + } +}, "Invalid arguments"); + +test(() => { + const fn = WebAssembly.validate; + const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly, + ]; + for (const thisValue of thisValues) { + assert_true(fn.call(thisValue, emptyModuleBinary), `this=${format_value(thisValue)}`); + } +}, "Branding"); + +const modules = [ + // Incomplete header. + [[], false], + [[0x00], false], + [[0x00, 0x61], false], + [[0x00, 0x61, 0x73], false], + [[0x00, 0x61, 0x73, 0x6d], false], + [[0x00, 0x61, 0x73, 0x6d, 0x01], false], + [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00], false], + [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00], false], + + // Complete header. + [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00], true], + + // Invalid version. + [[0x00, 0x61, 0x73, 0x6d, 0x00, 0x00, 0x00, 0x00], false], + [[0x00, 0x61, 0x73, 0x6d, 0x02, 0x00, 0x00, 0x00], false], + + // Nameless custom section. + [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], false], + + // Custom section with empty name. + [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00], true], + + // Custom section with name "a". + [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x61], true], +]; +const bufferTypes = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, +]; +for (const [module, expected] of modules) { + const name = module.map(n => n.toString(16)).join(" "); + for (const bufferType of bufferTypes) { + if (module.length % bufferType.BYTES_PER_ELEMENT === 0) { + test(() => { + const bytes = new Uint8Array(module); + const moduleBuffer = new bufferType(bytes.buffer); + assert_equals(WebAssembly.validate(moduleBuffer), expected); + }, `Validating module [${name}] in ${bufferType.name}`); + } + } +} diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/instance/constructor.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/instance/constructor.any.js index 61a8f53a014..f9bd06ac8e9 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/instance/constructor.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/instance/constructor.any.js @@ -3,62 +3,6 @@ // META: script=/wasm/jsapi/wasm-module-builder.js // META: script=/wasm/jsapi/assertions.js -function assert_exported_function(fn, { name, length }, description) { - assert_equals(Object.getPrototypeOf(fn), Function.prototype, - `${description}: prototype`); - - assert_function_name(fn, name, description); - assert_function_length(fn, length, description); -} - -function assert_Instance(instance, expected_exports) { - assert_equals(Object.getPrototypeOf(instance), WebAssembly.Instance.prototype, - "prototype"); - assert_true(Object.isExtensible(instance), "extensible"); - - assert_equals(instance.exports, instance.exports, "exports should be idempotent"); - const exports = instance.exports; - - assert_equals(Object.getPrototypeOf(exports), null, "exports prototype"); - assert_false(Object.isExtensible(exports), "extensible exports"); - for (const [key, expected] of Object.entries(expected_exports)) { - const property = Object.getOwnPropertyDescriptor(exports, key); - assert_equals(typeof property, "object", `${key} should be present`); - assert_false(property.writable, `${key}: writable`); - assert_true(property.enumerable, `${key}: enumerable`); - assert_false(property.configurable, `${key}: configurable`); - const actual = property.value; - assert_true(Object.isExtensible(actual), `${key}: extensible`); - - switch (expected.kind) { - case "function": - assert_exported_function(actual, expected, `value of ${key}`); - break; - case "global": - assert_equals(Object.getPrototypeOf(actual), WebAssembly.Global.prototype, - `value of ${key}: prototype`); - assert_equals(actual.value, expected.value, `value of ${key}: value`); - assert_equals(actual.valueOf(), expected.value, `value of ${key}: valueOf()`); - break; - case "memory": - assert_equals(Object.getPrototypeOf(actual), WebAssembly.Memory.prototype, - `value of ${key}: prototype`); - assert_equals(Object.getPrototypeOf(actual.buffer), ArrayBuffer.prototype, - `value of ${key}: prototype of buffer`); - assert_equals(actual.buffer.byteLength, 0x10000 * expected.size, `value of ${key}: size of buffer`); - const array = new Uint8Array(actual.buffer); - assert_equals(array[0], 0, `value of ${key}: first element of buffer`); - assert_equals(array[array.byteLength - 1], 0, `value of ${key}: last element of buffer`); - break; - case "table": - assert_equals(Object.getPrototypeOf(actual), WebAssembly.Table.prototype, - `value of ${key}: prototype`); - assert_equals(actual.length, expected.length, `value of ${key}: length of table`); - break; - } - } -} - let emptyModuleBinary; setup(() => { emptyModuleBinary = new WasmModuleBuilder().toBuffer(); @@ -130,6 +74,8 @@ test(() => { test(() => { const builder = new WasmModuleBuilder(); builder.addImportedGlobal("module", "global1", kWasmI32); + builder.addImportedGlobal("module2", "global3", kWasmI32); + builder.addImportedMemory("module", "memory", 0, 128); builder.addImportedGlobal("module", "global2", kWasmI32); const buffer = builder.toBuffer(); const module = new WebAssembly.Module(buffer); @@ -146,6 +92,19 @@ test(() => { order.push("global2 getter"); return 0; }, + get memory() { + order.push("memory getter"); + return new WebAssembly.Memory({ "initial": 64, maximum: 128 }); + }, + } + }, + get module2() { + order.push("module2 getter"); + return { + get global3() { + order.push("global3 getter"); + return 0; + }, } }, }; @@ -153,6 +112,10 @@ test(() => { const expected = [ "module getter", "global1 getter", + "module2 getter", + "global3 getter", + "module getter", + "memory getter", "module getter", "global2 getter", ]; @@ -225,3 +188,34 @@ test(() => { }; assert_Instance(instance, expected); }, "exports"); + +test(() => { + const value = 102; + + const builder = new WasmModuleBuilder(); + + builder.addImportedGlobal("module", "global", kWasmI32); + builder + .addFunction("fn", kSig_i_v) + .addBody([ + kExprGetGlobal, + 0, + kExprReturn, + kExprEnd, + ]) + .exportFunc(); + + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + const instance = new WebAssembly.Instance(module, { + "module": { + "global": value, + }, + }); + const expected = { + "fn": { "kind": "function", "name": "0", "length": 0 }, + }; + assert_Instance(instance, expected); + + assert_equals(instance.exports.fn(), value); +}, "exports and imports"); diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/buffer-resampling.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/buffer-resampling.html new file mode 100644 index 00000000000..c181ceb8e0f --- /dev/null +++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/buffer-resampling.html @@ -0,0 +1,101 @@ + + + + Test Extrapolation at end of AudibBuffer in an AudioBufferSourceNode + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/xhr/abort-after-stop.htm b/tests/wpt/web-platform-tests/xhr/abort-after-stop.htm index 7c5060fa4c6..d28d046fa98 100644 --- a/tests/wpt/web-platform-tests/xhr/abort-after-stop.htm +++ b/tests/wpt/web-platform-tests/xhr/abort-after-stop.htm @@ -13,7 +13,9 @@ window.onload = test.step_func(function() { var client = new XMLHttpRequest(); var abortFired = false; + var sync = true; client.onabort = test.step_func(function (e) { + assert_false(sync); assert_equals(e.type, 'abort'); abortFired = true; }); @@ -24,6 +26,7 @@ test.done(); }, 200); window.stop(); + sync = false; }); diff --git a/tests/wpt/web-platform-tests/xhr/open-after-abort.htm b/tests/wpt/web-platform-tests/xhr/open-after-abort.htm index c9c63044228..c9ef6e7ac94 100644 --- a/tests/wpt/web-platform-tests/xhr/open-after-abort.htm +++ b/tests/wpt/web-platform-tests/xhr/open-after-abort.htm @@ -9,27 +9,69 @@
diff --git a/tests/wpt/web-platform-tests/xhr/open-after-stop.window.js b/tests/wpt/web-platform-tests/xhr/open-after-stop.window.js new file mode 100644 index 00000000000..e836a523f86 --- /dev/null +++ b/tests/wpt/web-platform-tests/xhr/open-after-stop.window.js @@ -0,0 +1,43 @@ +// window.stop() below prevents the load event from firing, so wait until it is +// fired to start the test. +setup({explicit_done: true }); + +onload = () => { + async_test(function(t) { + const client = new XMLHttpRequest(); + + const result = []; + const expected = [ + 'readystatechange', 0, 1, // open() + ]; + + let state = 0; + + client.onreadystatechange = t.step_func(() => { + result.push('readystatechange', state, client.readyState); + }); + client.onabort = t.unreached_func("abort should not be fired after window.stop() and open()"); + client.onloadend = t.unreached_func("loadend should not be fired after window.stop() and open()"); + + client.open("GET", "resources/well-formed.xml"); + assert_equals(client.readyState, 1); + + state = 1; + client.send(null); + state = 2; + window.stop(); + // Unlike client.abort(), window.stop() does not change readyState + // immediately, rather through a task... + assert_equals(client.readyState, 1); + state = 3; + // ... which is then canceled when we open a new request anyway. + client.open("GET", "resources/well-formed.xml"); + assert_equals(client.readyState, 1); + assert_array_equals(result, expected); + + // Give the abort and loadend events a chance to fire (erroneously) before + // calling this a success. + t.step_timeout(t.step_func_done(), 1000); + }, "open() after window.stop()"); + done(); +};