diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index e6d7c8291ce5..b460cc44e7ae 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -19663,78 +19663,6 @@ {} ] ], - "web-nfc/NFCReader-manual.https.html": [ - [ - "web-nfc/NFCReader-manual.https.html", - {} - ] - ], - "web-nfc/NFCReader_options_mediaType-manual.https.html": [ - [ - "web-nfc/NFCReader_options_mediaType-manual.https.html", - {} - ] - ], - "web-nfc/NFCReader_options_recordType_empty-manual.https.html": [ - [ - "web-nfc/NFCReader_options_recordType_empty-manual.https.html", - {} - ] - ], - "web-nfc/NFCReader_options_recordType_json-manual.https.html": [ - [ - "web-nfc/NFCReader_options_recordType_json-manual.https.html", - {} - ] - ], - "web-nfc/NFCReader_options_recordType_opaque-manual.https.html": [ - [ - "web-nfc/NFCReader_options_recordType_opaque-manual.https.html", - {} - ] - ], - "web-nfc/NFCReader_options_recordType_text-manual.https.html": [ - [ - "web-nfc/NFCReader_options_recordType_text-manual.https.html", - {} - ] - ], - "web-nfc/NFCReader_options_recordType_url-manual.https.html": [ - [ - "web-nfc/NFCReader_options_recordType_url-manual.https.html", - {} - ] - ], - "web-nfc/NFCReader_options_url-manual.https.html": [ - [ - "web-nfc/NFCReader_options_url-manual.https.html", - {} - ] - ], - "web-nfc/NFCWriter_push_signal-manual.https.html": [ - [ - "web-nfc/NFCWriter_push_signal-manual.https.html", - {} - ] - ], - "web-nfc/nfc_hw_disabled-manual.https.html": [ - [ - "web-nfc/nfc_hw_disabled-manual.https.html", - {} - ] - ], - "web-nfc/nfc_push_ArrayBuffer-manual.https.html": [ - [ - "web-nfc/nfc_push_ArrayBuffer-manual.https.html", - {} - ] - ], - "web-nfc/nfc_push_DOMString-manual.https.html": [ - [ - "web-nfc/nfc_push_DOMString-manual.https.html", - {} - ] - ], "web-share/share-cancel-manual.html": [ [ "web-share/share-cancel-manual.html", @@ -121569,6 +121497,18 @@ {} ] ], + "css/css-flexbox/inline-flex-min-content-height.html": [ + [ + "css/css-flexbox/inline-flex-min-content-height.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], "css/css-flexbox/item-with-max-height-and-scrollbar.html": [ [ "css/css-flexbox/item-with-max-height-and-scrollbar.html", @@ -128719,6 +128659,66 @@ {} ] ], + "css/css-lists/inline-block-list-marker.html": [ + [ + "css/css-lists/inline-block-list-marker.html", + [ + [ + "/css/css-lists/inline-block-list-marker-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-lists/inline-block-list.html": [ + [ + "css/css-lists/inline-block-list.html", + [ + [ + "/css/css-lists/inline-block-list-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-lists/inline-list-marker.html": [ + [ + "css/css-lists/inline-list-marker.html", + [ + [ + "/css/css-lists/inline-list-marker-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-lists/inline-list-with-table-child.html": [ + [ + "css/css-lists/inline-list-with-table-child.html", + [ + [ + "/css/css-lists/inline-list-with-table-child-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-lists/inline-list.html": [ + [ + "css/css-lists/inline-list.html", + [ + [ + "/css/css-lists/inline-list-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-lists/li-insert-child.html": [ [ "css/css-lists/li-insert-child.html", @@ -128755,6 +128755,66 @@ {} ] ], + "css/css-lists/li-value-reversed-001.html": [ + [ + "css/css-lists/li-value-reversed-001.html", + [ + [ + "/css/css-lists/li-value-reversed-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-lists/li-value-reversed-002.html": [ + [ + "css/css-lists/li-value-reversed-002.html", + [ + [ + "/css/css-lists/li-value-reversed-002-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-lists/li-value-reversed-003.html": [ + [ + "css/css-lists/li-value-reversed-003.html", + [ + [ + "/css/css-lists/li-value-reversed-002-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-lists/li-value-reversed-004.html": [ + [ + "css/css-lists/li-value-reversed-004.html", + [ + [ + "/css/css-lists/li-value-reversed-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-lists/li-value-reversed-005.html": [ + [ + "css/css-lists/li-value-reversed-005.html", + [ + [ + "/css/css-lists/li-value-reversed-004-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-lists/li-with-height-001.html": [ [ "css/css-lists/li-with-height-001.html", @@ -131359,6 +131419,18 @@ {} ] ], + "css/css-multicol/multicol-breaking-nobackground-004.html": [ + [ + "css/css-multicol/multicol-breaking-nobackground-004.html", + [ + [ + "/css/css-multicol/multicol-breaking-nobackground-004-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-multicol/multicol-clip-001.xht": [ [ "css/css-multicol/multicol-clip-001.xht", @@ -132403,6 +132475,18 @@ {} ] ], + "css/css-multicol/multicol-rule-nested-balancing-003.html": [ + [ + "css/css-multicol/multicol-rule-nested-balancing-003.html", + [ + [ + "/css/css-multicol/multicol-rule-nested-balancing-003-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-multicol/multicol-rule-none-000.xht": [ [ "css/css-multicol/multicol-rule-none-000.xht", @@ -134299,6 +134383,18 @@ {} ] ], + "css/css-paint-api/custom-property-animation-on-main-thread.https.html": [ + [ + "css/css-paint-api/custom-property-animation-on-main-thread.https.html", + [ + [ + "/css/css-paint-api/one-custom-property-animation-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-paint-api/geometry-background-image-001.https.html": [ [ "css/css-paint-api/geometry-background-image-001.https.html", @@ -134479,6 +134575,18 @@ {} ] ], + "css/css-paint-api/one-custom-property-animation.https.html": [ + [ + "css/css-paint-api/one-custom-property-animation.https.html", + [ + [ + "/css/css-paint-api/one-custom-property-animation-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-paint-api/overdraw.https.html": [ [ "css/css-paint-api/overdraw.https.html", @@ -135283,6 +135391,18 @@ {} ] ], + "css/css-paint-api/two-custom-property-animation.https.html": [ + [ + "css/css-paint-api/two-custom-property-animation.https.html", + [ + [ + "/css/css-paint-api/two-custom-property-animation-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-paint-api/valid-image-after-load.https.html": [ [ "css/css-paint-api/valid-image-after-load.https.html", @@ -136447,6 +136567,18 @@ {} ] ], + "css/css-pseudo/first-letter-of-html-root-crash.html": [ + [ + "css/css-pseudo/first-letter-of-html-root-crash.html", + [ + [ + "/css/css-pseudo/first-letter-of-html-root-crash-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-pseudo/first-letter-opacity-float-001.html": [ [ "css/css-pseudo/first-letter-opacity-float-001.html", @@ -139199,6 +139331,90 @@ {} ] ], + "css/css-ruby/block-ruby-001.html": [ + [ + "css/css-ruby/block-ruby-001.html", + [ + [ + "/css/css-ruby/block-ruby-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-ruby/block-ruby-002.html": [ + [ + "css/css-ruby/block-ruby-002.html", + [ + [ + "/css/css-ruby/block-ruby-002-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-ruby/block-ruby-003.html": [ + [ + "css/css-ruby/block-ruby-003.html", + [ + [ + "/css/css-ruby/block-ruby-003-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-ruby/block-ruby-004.html": [ + [ + "css/css-ruby/block-ruby-004.html", + [ + [ + "/css/css-ruby/block-ruby-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-ruby/block-ruby-005.html": [ + [ + "css/css-ruby/block-ruby-005.html", + [ + [ + "/css/css-ruby/block-ruby-005-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-ruby/root-block-ruby.xhtml": [ + [ + "css/css-ruby/root-block-ruby.xhtml", + [ + [ + "/css/css-ruby/root-ruby-ref.xhtml", + "==" + ] + ], + {} + ] + ], + "css/css-ruby/root-ruby.xhtml": [ + [ + "css/css-ruby/root-ruby.xhtml", + [ + [ + "/css/css-ruby/root-ruby-ref.xhtml", + "==" + ] + ], + {} + ] + ], "css/css-ruby/ruby-layout-internal-boxes.html": [ [ "css/css-ruby/ruby-layout-internal-boxes.html", @@ -142451,6 +142667,18 @@ {} ] ], + "css/css-tables/table-cell-overflow-auto.html": [ + [ + "css/css-tables/table-cell-overflow-auto.html", + [ + [ + "/css/css-tables/table-cell-overflow-auto-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-tables/table-has-box-sizing-border-box-001.html": [ [ "css/css-tables/table-has-box-sizing-border-box-001.html", @@ -165099,6 +165327,30 @@ {} ] ], + "css/css-typed-om/width-by-max-px-em.html": [ + [ + "css/css-typed-om/width-by-max-px-em.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-typed-om/width-by-min-px-em.html": [ + [ + "css/css-typed-om/width-by-min-px-em.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], "css/css-ui/appearance-auto-001.html": [ [ "css/css-ui/appearance-auto-001.html", @@ -167139,6 +167391,30 @@ {} ] ], + "css/css-values/max-length-percent-001.html": [ + [ + "css/css-values/max-length-percent-001.html", + [ + [ + "/css/css-values/reference/200-200-green.html", + "==" + ] + ], + {} + ] + ], + "css/css-values/min-length-percent-001.html": [ + [ + "css/css-values/min-length-percent-001.html", + [ + [ + "/css/css-values/reference/200-200-green.html", + "==" + ] + ], + {} + ] + ], "css/css-values/q-unit-case-insensitivity-001.html": [ [ "css/css-values/q-unit-case-insensitivity-001.html", @@ -202321,6 +202597,30 @@ {} ] ], + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html": [ + [ + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html", + [ + [ + "/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html", + "==" + ] + ], + {} + ] + ], + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html": [ + [ + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html", + [ + [ + "/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html", + "==" + ] + ], + {} + ] + ], "html/rendering/replaced-elements/the-select-element/select-1-block-size.html": [ [ "html/rendering/replaced-elements/the-select-element/select-1-block-size.html", @@ -204077,6 +204377,66 @@ {} ] ], + "mathml/presentation-markup/direction/direction-006.html": [ + [ + "mathml/presentation-markup/direction/direction-006.html", + [ + [ + "/mathml/presentation-markup/direction/direction-006-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/presentation-markup/direction/direction-007.html": [ + [ + "mathml/presentation-markup/direction/direction-007.html", + [ + [ + "/mathml/presentation-markup/direction/direction-007-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/presentation-markup/direction/direction-008.html": [ + [ + "mathml/presentation-markup/direction/direction-008.html", + [ + [ + "/mathml/presentation-markup/direction/direction-008-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/presentation-markup/direction/direction-009.html": [ + [ + "mathml/presentation-markup/direction/direction-009.html", + [ + [ + "/mathml/presentation-markup/direction/direction-009-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/presentation-markup/direction/direction-010.html": [ + [ + "mathml/presentation-markup/direction/direction-010.html", + [ + [ + "/mathml/presentation-markup/direction/direction-010-ref.html", + "==" + ] + ], + {} + ] + ], "mathml/presentation-markup/direction/direction-overall.html": [ [ "mathml/presentation-markup/direction/direction-overall.html", @@ -204617,6 +204977,18 @@ {} ] ], + "mathml/relations/css-styling/mathvariant-case-sensitivity.html": [ + [ + "mathml/relations/css-styling/mathvariant-case-sensitivity.html", + [ + [ + "/mathml/relations/css-styling/mathvariant-case-sensitivity-ref.html", + "==" + ] + ], + {} + ] + ], "mathml/relations/css-styling/mathvariant-double-struck.html": [ [ "mathml/relations/css-styling/mathvariant-double-struck.html", @@ -205013,6 +205385,18 @@ {} ] ], + "quirks/dd-dl-firefox-001.html": [ + [ + "quirks/dd-dl-firefox-001.html", + [ + [ + "/quirks/dd-dl-firefox-001-ref.html", + "==" + ] + ], + {} + ] + ], "quirks/historical/list-item-bullet-size.html": [ [ "quirks/historical/list-item-bullet-size.html", @@ -251518,6 +251902,21 @@ "css/css-lists/counter-set-002-ref.html": [ [] ], + "css/css-lists/inline-block-list-marker-ref.html": [ + [] + ], + "css/css-lists/inline-block-list-ref.html": [ + [] + ], + "css/css-lists/inline-list-marker-ref.html": [ + [] + ], + "css/css-lists/inline-list-ref.html": [ + [] + ], + "css/css-lists/inline-list-with-table-child-ref.html": [ + [] + ], "css/css-lists/li-insert-child-ref.html": [ [] ], @@ -251527,6 +251926,15 @@ "css/css-lists/li-value-counter-reset-001-ref.html": [ [] ], + "css/css-lists/li-value-reversed-001-ref.html": [ + [] + ], + "css/css-lists/li-value-reversed-002-ref.html": [ + [] + ], + "css/css-lists/li-value-reversed-004-ref.html": [ + [] + ], "css/css-lists/li-with-height-001-ref.html": [ [] ], @@ -251824,6 +252232,9 @@ "css/css-multicol/multicol-breaking-nobackground-003-ref.html": [ [] ], + "css/css-multicol/multicol-breaking-nobackground-004-ref.html": [ + [] + ], "css/css-multicol/multicol-clip-001-ref.xht": [ [] ], @@ -252010,6 +252421,9 @@ "css/css-multicol/multicol-rule-nested-balancing-002-ref.html": [ [] ], + "css/css-multicol/multicol-rule-nested-balancing-003-ref.html": [ + [] + ], "css/css-multicol/multicol-rule-ref.xht": [ [] ], @@ -252664,6 +253078,9 @@ "css/css-paint-api/invalid-image-pending-script-ref.html": [ [] ], + "css/css-paint-api/one-custom-property-animation-ref.html": [ + [] + ], "css/css-paint-api/overdraw-ref.html": [ [] ], @@ -252718,6 +253135,9 @@ "css/css-paint-api/style-first-letter-pseudo-ref.html": [ [] ], + "css/css-paint-api/two-custom-property-animation-ref.html": [ + [] + ], "css/css-paint-api/valid-image-after-load-ref.html": [ [] ], @@ -252871,6 +253291,9 @@ "css/css-pseudo/first-letter-list-item-dynamic-001-ref.html": [ [] ], + "css/css-pseudo/first-letter-of-html-root-crash-ref.html": [ + [] + ], "css/css-pseudo/first-letter-opacity-float-001-ref.html": [ [] ], @@ -253624,6 +254047,24 @@ "css/css-ruby/META.yml": [ [] ], + "css/css-ruby/block-ruby-001-ref.html": [ + [] + ], + "css/css-ruby/block-ruby-002-ref.html": [ + [] + ], + "css/css-ruby/block-ruby-003-ref.html": [ + [] + ], + "css/css-ruby/block-ruby-004-ref.html": [ + [] + ], + "css/css-ruby/block-ruby-005-ref.html": [ + [] + ], + "css/css-ruby/root-ruby-ref.xhtml": [ + [] + ], "css/css-ruby/ruby-layout-internal-boxes-ref.html": [ [] ], @@ -254314,6 +254755,9 @@ "css/css-tables/support/base.css": [ [] ], + "css/css-tables/table-cell-overflow-auto-ref.html": [ + [] + ], "css/css-tables/toggle-row-display-property-001-ref.html": [ [] ], @@ -268042,67 +268486,106 @@ "html/browsers/windows/resources/window-opener.html": [ [] ], - "html/cross-origin-opener/common.sub.js": [ + "html/cross-origin-embedder-policy/README.md": [ + [] + ], + "html/cross-origin-embedder-policy/blob.https.html.headers": [ + [] + ], + "html/cross-origin-embedder-policy/data.https.html.headers": [ + [] + ], + "html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers": [ + [] + ], + "html/cross-origin-embedder-policy/none.https.html.headers": [ + [] + ], + "html/cross-origin-embedder-policy/require-corp.https.html.headers": [ + [] + ], + "html/cross-origin-embedder-policy/resources/blob-url-factory.html": [ + [] + ], + "html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers": [ + [] + ], + "html/cross-origin-embedder-policy/resources/navigate-none.sub.html": [ + [] + ], + "html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html": [ + [] + ], + "html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers": [ + [] + ], + "html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt": [ + [] + ], + "html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers": [ + [] + ], + "html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt": [ [] ], - "html/cross-origin-opener/new_window_same_origin.tentative.html.headers": [ + "html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers": [ [] ], - "html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html.headers": [ + "html/cross-origin-embedder-policy/resources/script-factory.js": [ [] ], - "html/cross-origin-opener/new_window_same_site.tentative.html.headers": [ + "html/cross-origin-embedder-policy/sandbox.https.html.headers": [ [] ], - "html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html.headers": [ + "html/cross-origin-embedder-policy/srcdoc.https.html.headers": [ [] ], - "html/cross-origin-opener/resources/coop_window.py": [ + "html/cross-origin-opener-policy/README.md": [ [] ], - "html/cross-origin-opener/resources/postback.sub.html": [ + "html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers": [ [] ], - "html/cross-origin-opener/resources/window.sub.html": [ + "html/cross-origin-opener-policy/coep-redirect.https.html.headers": [ [] ], - "html/cross-origin-opener/resources/window.sub.html.headers": [ + "html/cross-origin-opener-policy/coep.https.html.headers": [ [] ], - "html/cross-origin/anonymous.tentative.html.headers": [ + "html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers": [ [] ], - "html/cross-origin/null.tentative.html.headers": [ + "html/cross-origin-opener-policy/coop-sandbox.https.html.headers": [ [] ], - "html/cross-origin/resources/navigate_anonymous.sub.html": [ + "html/cross-origin-opener-policy/no-https.html.headers": [ [] ], - "html/cross-origin/resources/navigate_anonymous.sub.html.headers": [ + "html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers": [ [] ], - "html/cross-origin/resources/navigate_null.sub.html": [ + "html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.headers": [ [] ], - "html/cross-origin/resources/navigate_usecredentials.sub.html": [ + "html/cross-origin-opener-policy/popup-same-origin.https.html.headers": [ [] ], - "html/cross-origin/resources/navigate_usecredentials.sub.html.headers": [ + "html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.headers": [ [] ], - "html/cross-origin/resources/nothing.txt": [ + "html/cross-origin-opener-policy/popup-same-site.https.html.headers": [ [] ], - "html/cross-origin/resources/nothing.txt.headers": [ + "html/cross-origin-opener-policy/resources/common.js": [ [] ], - "html/cross-origin/resources/popup_and_close.sub.html": [ + "html/cross-origin-opener-policy/resources/coop-coep.py": [ [] ], - "html/cross-origin/resources/popup_and_close.sub.html.headers": [ + "html/cross-origin-opener-policy/resources/postback.html": [ [] ], - "html/cross-origin/usecredentials.tentative.html.headers": [ + "html/cross-origin-opener-policy/resources/postback.html.headers": [ [] ], "html/dom/documents/dom-tree-accessors/cross-domain.js": [ @@ -271456,6 +271939,12 @@ "html/rendering/replaced-elements/the-option-element/option-with-br-ref.html": [ [] ], + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html": [ + [] + ], + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html": [ + [] + ], "html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html": [ [] ], @@ -273790,16 +274279,43 @@ "import-maps/bare/to-data": [ [] ], + "import-maps/imported/resources/helpers/parsing.js": [ + [] + ], + "import-maps/imported/resources/parsing-addresses.js": [ + [] + ], + "import-maps/imported/resources/parsing-schema.js": [ + [] + ], + "import-maps/imported/resources/parsing-scope-keys.js": [ + [] + ], + "import-maps/imported/resources/parsing-specifier-keys.js": [ + [] + ], + "import-maps/imported/resources/resolving-builtins.js": [ + [] + ], + "import-maps/imported/resources/resolving-not-yet-implemented.js": [ + [] + ], + "import-maps/imported/resources/resolving-scopes.js": [ + [] + ], + "import-maps/imported/resources/resolving.js": [ + [] + ], "import-maps/resources/empty.js": [ [] ], - "import-maps/resources/log.js": [ + "import-maps/resources/jest-test-helper.js": [ [] ], - "import-maps/resources/log.js.headers": [ + "import-maps/resources/log.js": [ [] ], - "import-maps/resources/resolving.js": [ + "import-maps/resources/log.js.headers": [ [] ], "import-maps/resources/test-helper.js": [ @@ -274573,6 +275089,21 @@ "mathml/README.md": [ [] ], + "mathml/presentation-markup/direction/direction-006-ref.html": [ + [] + ], + "mathml/presentation-markup/direction/direction-007-ref.html": [ + [] + ], + "mathml/presentation-markup/direction/direction-008-ref.html": [ + [] + ], + "mathml/presentation-markup/direction/direction-009-ref.html": [ + [] + ], + "mathml/presentation-markup/direction/direction-010-ref.html": [ + [] + ], "mathml/presentation-markup/direction/direction-overall-ref.html": [ [] ], @@ -274708,6 +275239,9 @@ "mathml/relations/css-styling/mathvariant-bold-script-ref.html": [ [] ], + "mathml/relations/css-styling/mathvariant-case-sensitivity-ref.html": [ + [] + ], "mathml/relations/css-styling/mathvariant-double-struck-ref.html": [ [] ], @@ -276445,6 +276979,9 @@ "quirks/body-fills-html-quirk-ref.html": [ [] ], + "quirks/dd-dl-firefox-001-ref.html": [ + [] + ], "quirks/hashless-hex-color/support/common.js": [ [] ], @@ -278473,6 +279010,9 @@ "resources/chromium/mojo_web_test_helper_test.mojom.js.headers": [ [] ], + "resources/chromium/nfc-mock.js": [ + [] + ], "resources/chromium/sensor.mojom.js": [ [] ], @@ -280561,6 +281101,9 @@ "shadow-dom/directionality-001-ref.html": [ [] ], + "shadow-dom/focus/resources/shadow-utils.js": [ + [] + ], "shadow-dom/reference/empty.html": [ [] ], @@ -280819,6 +281362,9 @@ "signed-exchange/resources/sxg/sxg-variants-mismatch.sxg": [ [] ], + "sms/README.md": [ + [] + ], "sms/resources/iframe.html": [ [] ], @@ -286363,7 +286909,10 @@ "web-nfc/META.yml": [ [] ], - "web-nfc/resources/nfc_help.js": [ + "web-nfc/README.md": [ + [] + ], + "web-nfc/resources/nfc-helpers.js": [ [] ], "web-share/META.yml": [ @@ -311367,6 +311916,24 @@ {} ] ], + "css/css-align/parsing/gap-computed.html": [ + [ + "css/css-align/parsing/gap-computed.html", + {} + ] + ], + "css/css-align/parsing/gap-invalid.html": [ + [ + "css/css-align/parsing/gap-invalid.html", + {} + ] + ], + "css/css-align/parsing/gap-valid.html": [ + [ + "css/css-align/parsing/gap-valid.html", + {} + ] + ], "css/css-align/parsing/justify-content-computed.html": [ [ "css/css-align/parsing/justify-content-computed.html", @@ -311907,12 +312474,6 @@ {} ] ], - "css/css-animations/parsing/transition-timing-function-computed.html": [ - [ - "css/css-animations/parsing/transition-timing-function-computed.html", - {} - ] - ], "css/css-animations/pending-style-changes-001.html": [ [ "css/css-animations/pending-style-changes-001.html", @@ -318213,6 +318774,24 @@ {} ] ], + "css/css-rhythm/parsing/line-height-step-computed.html": [ + [ + "css/css-rhythm/parsing/line-height-step-computed.html", + {} + ] + ], + "css/css-rhythm/parsing/line-height-step-invalid.html": [ + [ + "css/css-rhythm/parsing/line-height-step-invalid.html", + {} + ] + ], + "css/css-rhythm/parsing/line-height-step-valid.html": [ + [ + "css/css-rhythm/parsing/line-height-step-valid.html", + {} + ] + ], "css/css-ruby/inheritance.html": [ [ "css/css-ruby/inheritance.html", @@ -320655,6 +321234,24 @@ {} ] ], + "css/css-text-decor/parsing/text-shadow-computed.html": [ + [ + "css/css-text-decor/parsing/text-shadow-computed.html", + {} + ] + ], + "css/css-text-decor/parsing/text-shadow-invalid.html": [ + [ + "css/css-text-decor/parsing/text-shadow-invalid.html", + {} + ] + ], + "css/css-text-decor/parsing/text-shadow-valid.html": [ + [ + "css/css-text-decor/parsing/text-shadow-valid.html", + {} + ] + ], "css/css-text-decor/parsing/text-underline-position-computed.html": [ [ "css/css-text-decor/parsing/text-underline-position-computed.html", @@ -322407,6 +323004,12 @@ {} ] ], + "css/css-transforms/animation/composited-transform.html": [ + [ + "css/css-transforms/animation/composited-transform.html", + {} + ] + ], "css/css-transforms/animation/list-interpolation.html": [ [ "css/css-transforms/animation/list-interpolation.html", @@ -322905,6 +323508,12 @@ {} ] ], + "css/css-transitions/parsing/transition-timing-function-computed.html": [ + [ + "css/css-transitions/parsing/transition-timing-function-computed.html", + {} + ] + ], "css/css-transitions/parsing/transition-timing-function-invalid.html": [ [ "css/css-transitions/parsing/transition-timing-function-invalid.html", @@ -332473,6 +333082,12 @@ {} ] ], + "element-timing/toJSON.html": [ + [ + "element-timing/toJSON.html", + {} + ] + ], "encoding/api-basics.any.js": [ [ "encoding/api-basics.any.html", @@ -342028,6 +342643,14 @@ } ] ], + "event-timing/toJSON.html": [ + [ + "event-timing/toJSON.html", + { + "testdriver": true + } + ] + ], "eventsource/dedicated-worker/eventsource-close.htm": [ [ "eventsource/dedicated-worker/eventsource-close.htm", @@ -348893,60 +349516,126 @@ {} ] ], - "html/cross-origin-opener/new_window_null.tentative.html": [ + "html/cross-origin-embedder-policy/blob.https.html": [ [ - "html/cross-origin-opener/new_window_null.tentative.html", + "html/cross-origin-embedder-policy/blob.https.html", {} ] ], - "html/cross-origin-opener/new_window_same_origin.tentative.html": [ + "html/cross-origin-embedder-policy/data.https.html": [ [ - "html/cross-origin-opener/new_window_same_origin.tentative.html", + "html/cross-origin-embedder-policy/data.https.html", {} ] ], - "html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html": [ + "html/cross-origin-embedder-policy/non-initial-about-blank.https.html": [ [ - "html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html", + "html/cross-origin-embedder-policy/non-initial-about-blank.https.html", {} ] ], - "html/cross-origin-opener/new_window_same_site.tentative.html": [ + "html/cross-origin-embedder-policy/none.https.html": [ + [ + "html/cross-origin-embedder-policy/none.https.html", + { + "timeout": "long" + } + ] + ], + "html/cross-origin-embedder-policy/require-corp.https.html": [ + [ + "html/cross-origin-embedder-policy/require-corp.https.html", + { + "timeout": "long" + } + ] + ], + "html/cross-origin-embedder-policy/sandbox.https.html": [ [ - "html/cross-origin-opener/new_window_same_site.tentative.html", + "html/cross-origin-embedder-policy/sandbox.https.html", {} ] ], - "html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html": [ + "html/cross-origin-embedder-policy/srcdoc.https.html": [ [ - "html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html", + "html/cross-origin-embedder-policy/srcdoc.https.html", {} ] ], - "html/cross-origin/anonymous.tentative.html": [ + "html/cross-origin-opener-policy/coep-navigate-popup.https.html": [ [ - "html/cross-origin/anonymous.tentative.html", - { - "timeout": "long" - } + "html/cross-origin-opener-policy/coep-navigate-popup.https.html", + {} ] ], - "html/cross-origin/null.tentative.html": [ + "html/cross-origin-opener-policy/coep-redirect.https.html": [ [ - "html/cross-origin/null.tentative.html", - { - "timeout": "long" - } + "html/cross-origin-opener-policy/coep-redirect.https.html", + {} + ] + ], + "html/cross-origin-opener-policy/coep.https.html": [ + [ + "html/cross-origin-opener-policy/coep.https.html", + {} + ] + ], + "html/cross-origin-opener-policy/coop-navigated-popup.https.html": [ + [ + "html/cross-origin-opener-policy/coop-navigated-popup.https.html", + {} + ] + ], + "html/cross-origin-opener-policy/coop-sandbox.https.html": [ + [ + "html/cross-origin-opener-policy/coop-sandbox.https.html", + {} ] ], - "html/cross-origin/usecredentials.tentative.html": [ + "html/cross-origin-opener-policy/no-https.html": [ [ - "html/cross-origin/usecredentials.tentative.html", + "html/cross-origin-opener-policy/no-https.html", { "timeout": "long" } ] ], + "html/cross-origin-opener-policy/popup-none.https.html": [ + [ + "html/cross-origin-opener-policy/popup-none.https.html", + {} + ] + ], + "html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html": [ + [ + "html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html", + {} + ] + ], + "html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html": [ + [ + "html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html", + {} + ] + ], + "html/cross-origin-opener-policy/popup-same-origin.https.html": [ + [ + "html/cross-origin-opener-policy/popup-same-origin.https.html", + {} + ] + ], + "html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html": [ + [ + "html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html", + {} + ] + ], + "html/cross-origin-opener-policy/popup-same-site.https.html": [ + [ + "html/cross-origin-opener-policy/popup-same-site.https.html", + {} + ] + ], "html/dom/documents/dom-tree-accessors/Document.body.html": [ [ "html/dom/documents/dom-tree-accessors/Document.body.html", @@ -349729,18 +350418,6 @@ {} ] ], - "html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.html": [ - [ - "html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.html", - {} - ] - ], - "html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.worker.js": [ - [ - "html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.worker.html", - {} - ] - ], "html/infrastructure/common-dom-interfaces/collections/domstringlist.html": [ [ "html/infrastructure/common-dom-interfaces/collections/domstringlist.html", @@ -350174,6 +350851,12 @@ } ] ], + "html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html": [ + [ + "html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html", + {} + ] + ], "html/interaction/focus/tabindex-focus-flag.html": [ [ "html/interaction/focus/tabindex-focus-flag.html", @@ -359610,12 +360293,6 @@ {} ] ], - "html/webappapis/animation-frames/idlharness.html": [ - [ - "html/webappapis/animation-frames/idlharness.html", - {} - ] - ], "html/webappapis/animation-frames/same-dispatch-time.html": [ [ "html/webappapis/animation-frames/same-dispatch-time.html", @@ -361461,15 +362138,57 @@ {} ] ], - "import-maps/module-map-key.tentative.html": [ + "import-maps/imported/parsing-addresses.tentative.html": [ [ - "import-maps/module-map-key.tentative.html", + "import-maps/imported/parsing-addresses.tentative.html", {} ] ], - "import-maps/resolving.tentative.html": [ + "import-maps/imported/parsing-schema.tentative.html": [ [ - "import-maps/resolving.tentative.html", + "import-maps/imported/parsing-schema.tentative.html", + {} + ] + ], + "import-maps/imported/parsing-scope-keys.tentative.html": [ + [ + "import-maps/imported/parsing-scope-keys.tentative.html", + {} + ] + ], + "import-maps/imported/parsing-specifier-keys.tentative.html": [ + [ + "import-maps/imported/parsing-specifier-keys.tentative.html", + {} + ] + ], + "import-maps/imported/resolving-builtins.tentative.html": [ + [ + "import-maps/imported/resolving-builtins.tentative.html", + {} + ] + ], + "import-maps/imported/resolving-not-yet-implemented.tentative.html": [ + [ + "import-maps/imported/resolving-not-yet-implemented.tentative.html", + {} + ] + ], + "import-maps/imported/resolving-scopes.tentative.html": [ + [ + "import-maps/imported/resolving-scopes.tentative.html", + {} + ] + ], + "import-maps/imported/resolving.tentative.html": [ + [ + "import-maps/imported/resolving.tentative.html", + {} + ] + ], + "import-maps/module-map-key.tentative.html": [ + [ + "import-maps/module-map-key.tentative.html", {} ] ], @@ -362615,6 +363334,12 @@ {} ] ], + "largest-contentful-paint/first-letter-background.html": [ + [ + "largest-contentful-paint/first-letter-background.html", + {} + ] + ], "largest-contentful-paint/idlharness.html": [ [ "largest-contentful-paint/idlharness.html", @@ -362669,6 +363394,12 @@ {} ] ], + "largest-contentful-paint/toJSON.html": [ + [ + "largest-contentful-paint/toJSON.html", + {} + ] + ], "layout-instability/buffer-layout-shift.html": [ [ "layout-instability/buffer-layout-shift.html", @@ -362712,6 +363443,12 @@ {} ] ], + "layout-instability/toJSON.html": [ + [ + "layout-instability/toJSON.html", + {} + ] + ], "lifecycle/child-display-none.tentative.html": [ [ "lifecycle/child-display-none.tentative.html", @@ -378757,6 +379494,30 @@ } ] ], + "pointerevents/inheritance.html": [ + [ + "pointerevents/inheritance.html", + {} + ] + ], + "pointerevents/parsing/touch-action-computed.html": [ + [ + "pointerevents/parsing/touch-action-computed.html", + {} + ] + ], + "pointerevents/parsing/touch-action-invalid.html": [ + [ + "pointerevents/parsing/touch-action-invalid.html", + {} + ] + ], + "pointerevents/parsing/touch-action-valid.html": [ + [ + "pointerevents/parsing/touch-action-valid.html", + {} + ] + ], "pointerevents/pointerevent_attributes_hoverable_pointers.html": [ [ "pointerevents/pointerevent_attributes_hoverable_pointers.html", @@ -392887,6 +393648,70 @@ {} ] ], + "shadow-dom/focus/DocumentOrShadowRoot-activeElement.html": [ + [ + "shadow-dom/focus/DocumentOrShadowRoot-activeElement.html", + { + "testdriver": true + } + ] + ], + "shadow-dom/focus/focus-tabindex-order-shadow-negative.html": [ + [ + "shadow-dom/focus/focus-tabindex-order-shadow-negative.html", + { + "testdriver": true + } + ] + ], + "shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html": [ + [ + "shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html", + { + "testdriver": true + } + ] + ], + "shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html": [ + [ + "shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html", + { + "testdriver": true + } + ] + ], + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html": [ + [ + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html", + { + "testdriver": true + } + ] + ], + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html": [ + [ + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html", + { + "testdriver": true + } + ] + ], + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html": [ + [ + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html", + { + "testdriver": true + } + ] + ], + "shadow-dom/focus/focus-tabindex-order-shadow-zero.html": [ + [ + "shadow-dom/focus/focus-tabindex-order-shadow-zero.html", + { + "testdriver": true + } + ] + ], "shadow-dom/form-control-form-attribute.html": [ [ "shadow-dom/form-control-form-attribute.html", @@ -399445,12 +400270,204 @@ {} ] ], + "svg/animations/accumulate-values-width-animation.html": [ + [ + "svg/animations/accumulate-values-width-animation.html", + {} + ] + ], + "svg/animations/additive-from-to-width-animation.html": [ + [ + "svg/animations/additive-from-to-width-animation.html", + {} + ] + ], + "svg/animations/additive-type-by-animation.html": [ + [ + "svg/animations/additive-type-by-animation.html", + {} + ] + ], + "svg/animations/additive-values-width-animation.html": [ + [ + "svg/animations/additive-values-width-animation.html", + {} + ] + ], "svg/animations/animVal-basics.html": [ [ "svg/animations/animVal-basics.html", {} ] ], + "svg/animations/animate-calcMode-spline-by.html": [ + [ + "svg/animations/animate-calcMode-spline-by.html", + {} + ] + ], + "svg/animations/animate-calcMode-spline-from-by.html": [ + [ + "svg/animations/animate-calcMode-spline-from-by.html", + {} + ] + ], + "svg/animations/animate-calcMode-spline-from-to.html": [ + [ + "svg/animations/animate-calcMode-spline-from-to.html", + {} + ] + ], + "svg/animations/animate-calcMode-spline-to.html": [ + [ + "svg/animations/animate-calcMode-spline-to.html", + {} + ] + ], + "svg/animations/animate-calcMode-spline-values.html": [ + [ + "svg/animations/animate-calcMode-spline-values.html", + {} + ] + ], + "svg/animations/animate-color-calcMode-discrete.html": [ + [ + "svg/animations/animate-color-calcMode-discrete.html", + {} + ] + ], + "svg/animations/animate-color-fill-currentColor.html": [ + [ + "svg/animations/animate-color-fill-currentColor.html", + {} + ] + ], + "svg/animations/animate-color-fill-from-by.html": [ + [ + "svg/animations/animate-color-fill-from-by.html", + {} + ] + ], + "svg/animations/animate-color-transparent.html": [ + [ + "svg/animations/animate-color-transparent.html", + {} + ] + ], + "svg/animations/animate-css-xml-attributeType.html": [ + [ + "svg/animations/animate-css-xml-attributeType.html", + {} + ] + ], + "svg/animations/animate-currentColor.html": [ + [ + "svg/animations/animate-currentColor.html", + {} + ] + ], + "svg/animations/animate-dynamic-update-attributeName.html": [ + [ + "svg/animations/animate-dynamic-update-attributeName.html", + {} + ] + ], + "svg/animations/animate-elem-02-t-drt.html": [ + [ + "svg/animations/animate-elem-02-t-drt.html", + {} + ] + ], + "svg/animations/animate-elem-14-t-drt.html": [ + [ + "svg/animations/animate-elem-14-t-drt.html", + {} + ] + ], + "svg/animations/animate-elem-15-t-drt.html": [ + [ + "svg/animations/animate-elem-15-t-drt.html", + {} + ] + ], + "svg/animations/animate-elem-16-t-drt.html": [ + [ + "svg/animations/animate-elem-16-t-drt.html", + {} + ] + ], + "svg/animations/animate-elem-17-t-drt.html": [ + [ + "svg/animations/animate-elem-17-t-drt.html", + {} + ] + ], + "svg/animations/animate-elem-18-t-drt.html": [ + [ + "svg/animations/animate-elem-18-t-drt.html", + {} + ] + ], + "svg/animations/animate-elem-19-t-drt.html": [ + [ + "svg/animations/animate-elem-19-t-drt.html", + {} + ] + ], + "svg/animations/animate-end-attribute-numeric-precision.html": [ + [ + "svg/animations/animate-end-attribute-numeric-precision.html", + {} + ] + ], + "svg/animations/animate-fill-freeze-with-repeatDur.html": [ + [ + "svg/animations/animate-fill-freeze-with-repeatDur.html", + {} + ] + ], + "svg/animations/animate-from-to-keyTimes.html": [ + [ + "svg/animations/animate-from-to-keyTimes.html", + {} + ] + ], + "svg/animations/animate-gradient-transform.html": [ + [ + "svg/animations/animate-gradient-transform.html", + {} + ] + ], + "svg/animations/animate-inherit-css-property.html": [ + [ + "svg/animations/animate-inherit-css-property.html", + {} + ] + ], + "svg/animations/animate-insert-begin.html": [ + [ + "svg/animations/animate-insert-begin.html", + {} + ] + ], + "svg/animations/animate-insert-no-begin.html": [ + [ + "svg/animations/animate-insert-no-begin.html", + {} + ] + ], + "svg/animations/animate-keySplines.html": [ + [ + "svg/animations/animate-keySplines.html", + {} + ] + ], + "svg/animations/animate-marker-orient-from-angle-to-angle.html": [ + [ + "svg/animations/animate-marker-orient-from-angle-to-angle.html", + {} + ] + ], "svg/animations/animate-marker-orient-from-angle-to-auto.html": [ [ "svg/animations/animate-marker-orient-from-angle-to-auto.html", @@ -400107,6 +401124,12 @@ {} ] ], + "svg/animations/syncbase-remove-add-while-running.html": [ + [ + "svg/animations/syncbase-remove-add-while-running.html", + {} + ] + ], "svg/coordinate-systems/outer-svg-intrinsic-size-001.html": [ [ "svg/coordinate-systems/outer-svg-intrinsic-size-001.html", @@ -406651,6 +407674,12 @@ {} ] ], + "web-nfc/NFCReader_options.https.html": [ + [ + "web-nfc/NFCReader_options.https.html", + {} + ] + ], "web-nfc/NFCReadingEvent_constructor.https.html": [ [ "web-nfc/NFCReadingEvent_constructor.https.html", @@ -440139,7 +441168,7 @@ }, "paths": { ".azure-pipelines.yml": [ - "3bd94f97b220da54e24d99e26c08144f34cc489f", + "4a4e9c7ff5ead2be22dda7ab7b50071bd70817e4", "support" ], ".codecov.yml": [ @@ -472731,19 +473760,19 @@ "testharness" ], "cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.js": [ - "31e644d50b2a922122cfaeaba4acf41db205ce07", + "258441921bf6bf7f72eeaf8602653c55ca991af0", "support" ], "cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.tentative.https.html": [ - "8f9255b46491c9e0aac1be7d460f83e99b57bbcc", + "ee9713e933b8432c73c7e2e9ad523a453ddb4c60", "testharness" ], "cookie-store/serviceworker_cookieStore_subscriptions_mismatch.js": [ - "3d07c86492e1a860e97568edcdc277d460de7f6c", + "bd37b9be1eec4aa4a1469502074463acd37f17fc", "support" ], "cookie-store/serviceworker_cookieStore_subscriptions_mismatch.tentative.https.html": [ - "ea70a1efcd05a4c2e891c79f38abbc81234cf2b0", + "b8ad46a57101386bd84b391953e76228249eff29", "testharness" ], "cookies/META.yml": [ @@ -526131,11 +527160,11 @@ "reftest" ], "css/CSS2/text/text-decoration-va-length-002-ref.xht": [ - "e872737b1ca26e147f01f689ac4ccd3f8668b323", + "6b44915705366ccf698fb854a4c700a3e732ddac", "support" ], "css/CSS2/text/text-decoration-va-length-002.xht": [ - "28b38f31e28672dee690b20451fc8306ccc1da6c", + "09b0b4ed5f89764f6aa060dabcc3530b194845c1", "reftest" ], "css/CSS2/text/text-decoration-va-sub-super-001.xht": [ @@ -535263,15 +536292,15 @@ "testharness" ], "css/css-align/gaps/gap-animation-001.html": [ - "881bb18446e842192e81b65402fac90bb9d9986d", + "7ce3b69f6b573c8b2b57d191dd2a4cfc60f42993", "testharness" ], "css/css-align/gaps/gap-animation-002.html": [ - "44d8c70b3a85831d23e36f263e9dd5e09a5820d4", + "6056aad6740db1c96ae47da2d15c386caf6f6249", "testharness" ], "css/css-align/gaps/gap-animation-003.html": [ - "c047946fb7f94b035876d2b32a3a2fd9e7ae9d39", + "2ec4551acb763ccb95c717df32aa53d4e6378e1d", "testharness" ], "css/css-align/gaps/gap-animation-004.html": [ @@ -535374,6 +536403,18 @@ "4be3b50989f56de6d1209c196e6cb28cb2c2d151", "testharness" ], + "css/css-align/parsing/gap-computed.html": [ + "b93b2378136a7aa52fefa9a4d83e003377e4d554", + "testharness" + ], + "css/css-align/parsing/gap-invalid.html": [ + "c2eae8f7aad23be0bda0dc423b62bd6cece1e1d0", + "testharness" + ], + "css/css-align/parsing/gap-valid.html": [ + "3104e3fbbdf31742bc7247180aef51f8e8b24c4c", + "testharness" + ], "css/css-align/parsing/justify-content-computed.html": [ "b04d2db1429c385d57b9d6b232282d7924d6589b", "testharness" @@ -536066,10 +537107,6 @@ "7ab823ea1da1535606ac4aad30fb21f423ba6703", "testharness" ], - "css/css-animations/parsing/transition-timing-function-computed.html": [ - "9834dfdbf0dde78d0d2c1b468c5badddc2460ac9", - "testharness" - ], "css/css-animations/pending-style-changes-001.html": [ "fb74d7fa7d062d60153d47913df9eb2b0c7267c8", "testharness" @@ -539867,11 +540904,11 @@ "testharness" ], "css/css-box/parsing/padding-invalid.html": [ - "e995ac616a1dca834cbe53c91e02052047e32f4a", + "3e3a560c2f71877494577f9dbc5c2eecfbab8a62", "testharness" ], "css/css-box/parsing/padding-valid.html": [ - "ba3c3a7fd4aabdf998fbc39bbd9aee429d9ac564", + "0d3d51e86bb015dd5720041cdae671a29a74c77b", "testharness" ], "css/css-box/parsing/visibility-computed.html": [ @@ -543547,11 +544584,11 @@ "testharness" ], "css/css-display/parsing/display-invalid.html": [ - "70516ad4901f684b9d0ecd49a82671172fbc8f14", + "7c4054747e28114abe322332160daed30c955385", "testharness" ], "css/css-display/parsing/display-valid.html": [ - "efa48350a62dd0210009069475ac9243bba51104", + "ecd57511422eeb4ea64f65bd832d41b6f1f3f6a7", "testharness" ], "css/css-display/run-in/after-content-display-004.xht": [ @@ -547266,6 +548303,10 @@ "aad25677739b7a101987edd9d1effc5c7d4a3098", "testharness" ], + "css/css-flexbox/inline-flex-min-content-height.html": [ + "b84b9afc0b67b83d3d3e2abb73c9b7e22aeb3cbe", + "reftest" + ], "css/css-flexbox/interactive/flexbox_interactive_break-after-column-item.html": [ "f015d29f7cdea9307cb49248e1e1ad7f441da8b7", "manual" @@ -559930,6 +560971,46 @@ "590319d63fd09466f4d5fffe6943b4ff0430fcee", "testharness" ], + "css/css-lists/inline-block-list-marker-ref.html": [ + "6a36181107e81a1651d7939ebc94a525bbcc262b", + "support" + ], + "css/css-lists/inline-block-list-marker.html": [ + "73a163fa9dbe472fb6223c42fd0075843faf4b51", + "reftest" + ], + "css/css-lists/inline-block-list-ref.html": [ + "41b8504e4df193a2e7da24de8836c7484ab697f5", + "support" + ], + "css/css-lists/inline-block-list.html": [ + "52220ae4241c2523ebe5fdf32c7ed2907268d296", + "reftest" + ], + "css/css-lists/inline-list-marker-ref.html": [ + "e5a3c2e490ab2ae93bd64fd0e98eff3cfee9c6ab", + "support" + ], + "css/css-lists/inline-list-marker.html": [ + "3535f22ce2b2fe47d21b2f72037fdf1d88324379", + "reftest" + ], + "css/css-lists/inline-list-ref.html": [ + "ae1570a9703e52bdfdeb4a09b3c954ab92e7a59b", + "support" + ], + "css/css-lists/inline-list-with-table-child-ref.html": [ + "c35f640b2267fa76e4ea04db013f2fb7aaebb6ad", + "support" + ], + "css/css-lists/inline-list-with-table-child.html": [ + "0b897ec1da1f9bf9e3826b33d04ed74b334e5ff5", + "reftest" + ], + "css/css-lists/inline-list.html": [ + "f4b48230e1a7b0a86eb6f249de868a773a2aa875", + "reftest" + ], "css/css-lists/li-counter-increment-computed-style.html": [ "0fae6e3f6036c46b8f658304787da5879913296f", "testharness" @@ -559958,6 +561039,38 @@ "0e91c3a03d618a9d17194c883f80fd90899d4459", "reftest" ], + "css/css-lists/li-value-reversed-001-ref.html": [ + "7b5c5d86087fa9ad09296b519e582e6d0f161b09", + "support" + ], + "css/css-lists/li-value-reversed-001.html": [ + "616d7ccc66bb7fbe543daf4a469344e568013f0d", + "reftest" + ], + "css/css-lists/li-value-reversed-002-ref.html": [ + "71c187d3069c3ca4e6961c4788365d05ee15bd4f", + "support" + ], + "css/css-lists/li-value-reversed-002.html": [ + "0c89ad21222aad4a4773833f3600dd48b22e0e81", + "reftest" + ], + "css/css-lists/li-value-reversed-003.html": [ + "6e4d3d5f1ced2349355eae1fc097ae68daa0d591", + "reftest" + ], + "css/css-lists/li-value-reversed-004-ref.html": [ + "da95a042cfdc4a701d2293f3834c3598d95f5648", + "support" + ], + "css/css-lists/li-value-reversed-004.html": [ + "48ac24a6a2f6e5b81c380cdfc71350099a8eb93a", + "reftest" + ], + "css/css-lists/li-value-reversed-005.html": [ + "84f017b4992f0f268537dcd9706bef2c454d17b8", + "reftest" + ], "css/css-lists/li-with-height-001-ref.html": [ "486009d5604ab7a2cb66df735efff3c11c00b685", "support" @@ -561702,6 +562815,14 @@ "edf18f98981753750ec6588e5fd0ff97c1475005", "reftest" ], + "css/css-multicol/multicol-breaking-nobackground-004-ref.html": [ + "2245fae043e11c8c0b00113186b497abca3faa70", + "support" + ], + "css/css-multicol/multicol-breaking-nobackground-004.html": [ + "7b810423c91d862b80891902c4ba405975c0a493", + "reftest" + ], "css/css-multicol/multicol-clip-001-ref.xht": [ "d742ea716d38b186ce5598b4e7db28e6ae74985b", "support" @@ -562322,6 +563443,14 @@ "b38f90947a917fba51d6b7192e567ec7816de1c8", "reftest" ], + "css/css-multicol/multicol-rule-nested-balancing-003-ref.html": [ + "573afe683fe963ef980cb232ceeb50f420ae72bd", + "support" + ], + "css/css-multicol/multicol-rule-nested-balancing-003.html": [ + "3dea42550e5e50846de681efc95e0221036511bb", + "reftest" + ], "css/css-multicol/multicol-rule-none-000.xht": [ "32ca043957782f09c69bd77bd4933345228b81d7", "reftest" @@ -564070,6 +565199,10 @@ "2eccfd2a7d0b6e894a66f1afedc6969090f8ad9c", "reftest" ], + "css/css-paint-api/custom-property-animation-on-main-thread.https.html": [ + "13ccf3fc27372d9494e09a36095140e4dbef236b", + "reftest" + ], "css/css-paint-api/geometry-background-image-001-ref.html": [ "83edae100ee4ecd02315147ddf96ef61f34e875d", "support" @@ -564194,6 +565327,14 @@ "20a61eff41b68e8f756de2f3fe81bd20e736c92c", "reftest" ], + "css/css-paint-api/one-custom-property-animation-ref.html": [ + "c221aa0e89d30c68781be2c2c512e81b4403f921", + "support" + ], + "css/css-paint-api/one-custom-property-animation.https.html": [ + "1675bba1696e9ce8d442af5e6e8c25c61c2d07db", + "reftest" + ], "css/css-paint-api/overdraw-ref.html": [ "b6a6dec6c6087633b6e3efd8e7e9dcf49a3fea8b", "support" @@ -564534,6 +565675,14 @@ "d3c31a0508dc86aa0da95815ff2448bc2e074caf", "reftest" ], + "css/css-paint-api/two-custom-property-animation-ref.html": [ + "1acef69f9413c154b2f527d3792f24bbbdb38643", + "support" + ], + "css/css-paint-api/two-custom-property-animation.https.html": [ + "392b5291f92e4c1330b5843beb40b92f25abc45e", + "reftest" + ], "css/css-paint-api/valid-image-after-load-ref.html": [ "b6a6dec6c6087633b6e3efd8e7e9dcf49a3fea8b", "support" @@ -565490,6 +566639,14 @@ "f990cd2bb716aafff143f99889d2be61c72b6171", "reftest" ], + "css/css-pseudo/first-letter-of-html-root-crash-ref.html": [ + "f63dd580aa8414c945a8fd2c99ccc6dca0e7a24d", + "support" + ], + "css/css-pseudo/first-letter-of-html-root-crash.html": [ + "4233dd1dc351b14e5f514599107cc7b478b9d634", + "reftest" + ], "css/css-pseudo/first-letter-opacity-float-001-ref.html": [ "38c230045bd0cbec0d94da16b27fd56aa58456a1", "support" @@ -567782,6 +568939,18 @@ "44123ac65d884c5dd69271c22e69bb4b694586ce", "reftest" ], + "css/css-rhythm/parsing/line-height-step-computed.html": [ + "4153645dddf9c07bde36490c82537b01f62874fa", + "testharness" + ], + "css/css-rhythm/parsing/line-height-step-invalid.html": [ + "e2049057f1e6da2910c789fcd325fb1bbe19282e", + "testharness" + ], + "css/css-rhythm/parsing/line-height-step-valid.html": [ + "ea47a63678620ffa7f7f376f9652d62803290577", + "testharness" + ], "css/css-rhythm/reference/line-height-step-basic-001.html": [ "343026e07b817cc0f7d225b461d98ccceb310df0", "support" @@ -567890,6 +569059,46 @@ "b0098caea13c61def740fa706be68efb74b3bd9b", "support" ], + "css/css-ruby/block-ruby-001-ref.html": [ + "b8d851fb532107b8d3e7fd792438295577b6ac23", + "support" + ], + "css/css-ruby/block-ruby-001.html": [ + "f6a058807c48dc5c0cfe056a95355f3d234ac0ad", + "reftest" + ], + "css/css-ruby/block-ruby-002-ref.html": [ + "a4d26153da64266a1cd4366eb05e18291e0b3d07", + "support" + ], + "css/css-ruby/block-ruby-002.html": [ + "73fbc3015bfdb7b9835525a6d6d8362b31231545", + "reftest" + ], + "css/css-ruby/block-ruby-003-ref.html": [ + "b89f33cfdaef9b2038bb65234500b53fcdb6abd0", + "support" + ], + "css/css-ruby/block-ruby-003.html": [ + "861ba8352ca5fb002935a24896a130c0d320eb9e", + "reftest" + ], + "css/css-ruby/block-ruby-004-ref.html": [ + "879609f4daf8654ae0f7821d48308dbb035b3dbe", + "support" + ], + "css/css-ruby/block-ruby-004.html": [ + "fcddc1dbda215eda2c3251174ecf439c92c02efa", + "reftest" + ], + "css/css-ruby/block-ruby-005-ref.html": [ + "a7f9353b590eb090abb442702b70b77825a2f67a", + "support" + ], + "css/css-ruby/block-ruby-005.html": [ + "8750b63d9956e9e807c087d35f7f1478f77809b4", + "reftest" + ], "css/css-ruby/inheritance.html": [ "9f546c23bb864fc83588d326b7314141401e50dd", "testharness" @@ -567914,6 +569123,18 @@ "2a21748613787f59ce725cec1e47bf9e0115ada0", "testharness" ], + "css/css-ruby/root-block-ruby.xhtml": [ + "51ac507c3bec74bff8650965b327089e4d9853ce", + "reftest" + ], + "css/css-ruby/root-ruby-ref.xhtml": [ + "9edd7e3601d3c90f8af670ad81a9dcc2e1ebe5b1", + "support" + ], + "css/css-ruby/root-ruby.xhtml": [ + "4b78690dd4ba72c495429e5decb111a47fcf1825", + "reftest" + ], "css/css-ruby/ruby-001.xht": [ "80f49f0dbcf3e3a76ba6f740243e19a5f627bfd2", "visual" @@ -571326,6 +572547,14 @@ "52be1bb4e52e5705319ebf5525f6d89839356d65", "support" ], + "css/css-tables/table-cell-overflow-auto-ref.html": [ + "18163de30320bd1f0f1a7248cd4c2f2d2897d0c5", + "support" + ], + "css/css-tables/table-cell-overflow-auto.html": [ + "6b688561b91321990f18680f88aa4873dd35916a", + "reftest" + ], "css/css-tables/table-has-box-sizing-border-box-001.html": [ "e3cddd12a6686bec09e5b0d0f47e62e6517c69ae", "reftest" @@ -571555,7 +572784,7 @@ "support" ], "css/css-text-decor/inheritance.html": [ - "b106343742e03aa305a3017610272c8692b2a428", + "9ee65b4e5926f043b4841bc1f5a7cf84e214ce49", "testharness" ], "css/css-text-decor/line-through-vertical.html": [ @@ -571579,7 +572808,7 @@ "testharness" ], "css/css-text-decor/parsing/text-decoration-invalid.html": [ - "90095c0114f08dfab0ec184ca1b256066583071f", + "9cba2423206f03a632cd2ce40b59d93741e2da88", "testharness" ], "css/css-text-decor/parsing/text-decoration-line-computed.html": [ @@ -571619,7 +572848,19 @@ "testharness" ], "css/css-text-decor/parsing/text-decoration-valid.html": [ - "1c1aef3ff00a9f0d3867be9d395485d5b93bbede", + "fd12ab4dc31d5de8e1212f26fa18adb0d0e7166c", + "testharness" + ], + "css/css-text-decor/parsing/text-shadow-computed.html": [ + "a90738d825f2132bd6236f550f7525157b18e102", + "testharness" + ], + "css/css-text-decor/parsing/text-shadow-invalid.html": [ + "dfaa4a5b48b9e6b6c668bc1833083b1b2f453ced", + "testharness" + ], + "css/css-text-decor/parsing/text-shadow-valid.html": [ + "cbf9df547906aaa5095359ad3847123d3756205e", "testharness" ], "css/css-text-decor/parsing/text-underline-position-computed.html": [ @@ -575803,7 +577044,7 @@ "support" ], "css/css-text/shaping/reference/shaping-014-ref.html": [ - "f32ae1c23ecaefcdd660446d037cf0386ed6904e", + "6555baf1c74b3094b90821adb9154bd0131f247e", "reftest_node" ], "css/css-text/shaping/reference/shaping-014-sanity-ref.html": [ @@ -575939,7 +577180,7 @@ "reftest" ], "css/css-text/shaping/shaping-014.html": [ - "01e80c35f2febb0b72b588c4e36977c613da51a3", + "b817f2c094761ea2a7595f4f74e37ffb7ca17e73", "reftest" ], "css/css-text/shaping/shaping-016.html": [ @@ -579138,6 +580379,10 @@ "b948e3a31ed377091417bbf32d02791965b15a92", "support" ], + "css/css-transforms/animation/composited-transform.html": [ + "182321b9d30807a3231ce894a58d41bcea2dc04e", + "testharness" + ], "css/css-transforms/animation/list-interpolation.html": [ "4755279d73cc32b6396d332bdbbfdcbcc3624f52", "testharness" @@ -584687,7 +585932,7 @@ "testharness" ], "css/css-transitions/CSSTransition-effect.tentative.html": [ - "a6153b33171daee1dc0e9cb5b98c2ff89059fbae", + "41bd23eb53122ed228eb18c3c3e73148b7e2e20e", "testharness" ], "css/css-transitions/CSSTransition-finished.tentative.html": [ @@ -584854,6 +586099,10 @@ "4e3894f5aa94e00aa59406ee1aab92b9226483af", "testharness" ], + "css/css-transitions/parsing/transition-timing-function-computed.html": [ + "9834dfdbf0dde78d0d2c1b468c5badddc2460ac9", + "testharness" + ], "css/css-transitions/parsing/transition-timing-function-invalid.html": [ "00bd2131e0927ba38e633ad7be404b8ec26e51a9", "testharness" @@ -585675,7 +586924,7 @@ "testharness" ], "css/css-typed-om/stylevalue-subclasses/numeric-objects/parse.tentative.html": [ - "80e4f44b3a01be23e6459e7e9e1d7dd44318e809", + "98384b6fcc5efd446833e7d8a9f4d8a7ff61167c", "testharness" ], "css/css-typed-om/stylevalue-subclasses/numeric-objects/resources/testhelper.js": [ @@ -586770,6 +588019,14 @@ "53773fb96fc1b6112ad5b297480dac56360de343", "testharness" ], + "css/css-typed-om/width-by-max-px-em.html": [ + "2aac59b70744e24fccd91bfc92d1177d6bb5c3a6", + "reftest" + ], + "css/css-typed-om/width-by-min-px-em.html": [ + "615cb15708c35caf3e3c8af49f349a93df9429ff", + "reftest" + ], "css/css-ui/META.yml": [ "7ce4b54a22c78576dc2318ebd651dfd1cce374ad", "support" @@ -589826,6 +591083,14 @@ "295b418f304a76cde4dba21a1d24022557882b18", "testharness" ], + "css/css-values/max-length-percent-001.html": [ + "ffb6c27db278bc030923745d0e06c47d2af897c3", + "reftest" + ], + "css/css-values/min-length-percent-001.html": [ + "73069ecfe1e6d5b198f6e01df48facbe117d6828", + "reftest" + ], "css/css-values/q-unit-case-insensitivity-001.html": [ "b4a08aa117952c6f92e2aec6f57843b46a460104", "reftest" @@ -615366,6 +616631,10 @@ "15733d46f95c9079acfec06cdd25f70ca0e056a6", "testharness" ], + "element-timing/toJSON.html": [ + "d988934708116f29f9289511559079544aba1ba6", + "testharness" + ], "encoding/META.yml": [ "a219a492f0b963f19c50c094e9f00cf3cb69d467", "support" @@ -617570,6 +618839,10 @@ "1fcda21a197028ee3b6812f63aef41503d2a7b9b", "testharness" ], + "event-timing/toJSON.html": [ + "05a7ba76319b0947c6c3057ae35e97b7c9d4d3c1", + "testharness" + ], "eventsource/META.yml": [ "92f1036338515da7807fdbde7ab0a26f509cc986", "support" @@ -621907,7 +623180,7 @@ "testharness" ], "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html": [ - "7d9a31d0d40e16aabe8b921cbba09690e09d9f41", + "4b81c7c44f94c42680a812e9bf5b8eddbe7055a7", "testharness" ], "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html": [ @@ -624426,120 +625699,216 @@ "7407248ffe9fe3da977275c2192e31e3db9fc8a9", "testharness" ], - "html/cross-origin-opener/common.sub.js": [ - "a73a95aba8625230b84e917eba6b469be5459cc8", + "html/cross-origin-embedder-policy/README.md": [ + "16179eb0133a9e14667e127da05f3dc796975875", "support" ], - "html/cross-origin-opener/new_window_null.tentative.html": [ - "35a42fd2f0963f886324ac7ca01d5b45cdc1588e", + "html/cross-origin-embedder-policy/blob.https.html": [ + "aa4cf969d9e0fe369ce812896e6eb8d13cb02377", "testharness" ], - "html/cross-origin-opener/new_window_same_origin.tentative.html": [ - "6bbb37cafca07cec641e925b9d06d803b3cf2ae8", + "html/cross-origin-embedder-policy/blob.https.html.headers": [ + "6604450991a122e3e241e40b1b9e0516c525389d", + "support" + ], + "html/cross-origin-embedder-policy/data.https.html": [ + "c34f1336c8bd22aadd0e867b8fcced598a1c4786", "testharness" ], - "html/cross-origin-opener/new_window_same_origin.tentative.html.headers": [ - "46ad58d83bf6e98913ca4c564b7acb8f19fa0093", + "html/cross-origin-embedder-policy/data.https.html.headers": [ + "6604450991a122e3e241e40b1b9e0516c525389d", "support" ], - "html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html": [ - "bbd55130d7a903bf24fb8d2e3660131009d4b42d", + "html/cross-origin-embedder-policy/non-initial-about-blank.https.html": [ + "7fed1fe58194a2b15b1af4804e2215bcd8353fde", "testharness" ], - "html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html.headers": [ - "a19f4400cea33a60c99807330704a23ee363b146", + "html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers": [ + "6604450991a122e3e241e40b1b9e0516c525389d", "support" ], - "html/cross-origin-opener/new_window_same_site.tentative.html": [ - "e1efac12d02e26ca4db9f43f660155e9d916b531", + "html/cross-origin-embedder-policy/none.https.html": [ + "b1bb6fefc6cfa45a217cc3b04534df8065fa1579", "testharness" ], - "html/cross-origin-opener/new_window_same_site.tentative.html.headers": [ - "34bd099a302f893f92586241ea38aac812bf28d0", + "html/cross-origin-embedder-policy/none.https.html.headers": [ + "43c44cffd64e01f12a8d0dc22bbddfdd05a79a90", "support" ], - "html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html": [ - "d81506f434b70d9b66d0f8aa41d845c1541ae8a8", + "html/cross-origin-embedder-policy/require-corp.https.html": [ + "0bd6aab729533ba90ffaefccd4ea06e192b1e6b7", "testharness" ], - "html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html.headers": [ - "ab7b28948150ff64101ef080b0d9c7cc9a6a34d2", + "html/cross-origin-embedder-policy/require-corp.https.html.headers": [ + "6604450991a122e3e241e40b1b9e0516c525389d", "support" ], - "html/cross-origin-opener/resources/coop_window.py": [ - "b24d6d55a9a368057376436c0e2692a9ed27a1da", + "html/cross-origin-embedder-policy/resources/blob-url-factory.html": [ + "7d90aacd8bbf207b25405bea8f2e9f0263570392", "support" ], - "html/cross-origin-opener/resources/postback.sub.html": [ - "ee08bab4d55ed45523ae862f65a41b29046fba69", + "html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers": [ + "4e798cd9f5d3f756df077a43ce9a1a6f9b41fd28", "support" ], - "html/cross-origin-opener/resources/window.sub.html": [ - "524efe2588d08e77419cda38319f4b1fbcfdea3c", + "html/cross-origin-embedder-policy/resources/navigate-none.sub.html": [ + "1008f70ff123ae5e507a95ac4f16d32bbb74c983", "support" ], - "html/cross-origin-opener/resources/window.sub.html.headers": [ - "34bd099a302f893f92586241ea38aac812bf28d0", + "html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html": [ + "d4b38bc1a10003f8adc0e62224c5d3378638fb4f", + "support" + ], + "html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers": [ + "6604450991a122e3e241e40b1b9e0516c525389d", + "support" + ], + "html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt": [ + "e61d8ee36c9af68287e4f7538d3f1420521df598", "support" ], - "html/cross-origin/anonymous.tentative.html": [ - "ef9b9bb7b878a738c8f7e377d4cfe62b41dfea7f", + "html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers": [ + "1b88136c01cbca187f68799b0a54169b34978ac7", + "support" + ], + "html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt": [ + "b9ba801f78e5f35e7eb0225572e6b2b50b5e71c5", + "support" + ], + "html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers": [ + "30ddeac2e7a3596de3910def1a7066e817873cbe", + "support" + ], + "html/cross-origin-embedder-policy/resources/script-factory.js": [ + "9db755226020479fd87e87f42ea622c999b38f7d", + "support" + ], + "html/cross-origin-embedder-policy/sandbox.https.html": [ + "1e3f80a9186107350c307a3ff16fd5ad84e11ead", "testharness" ], - "html/cross-origin/anonymous.tentative.html.headers": [ - "a76b601291ec4323da4469a0e09d62c84f81efc3", + "html/cross-origin-embedder-policy/sandbox.https.html.headers": [ + "6604450991a122e3e241e40b1b9e0516c525389d", "support" ], - "html/cross-origin/null.tentative.html": [ - "ae871c4a273533eaae2e4dbfb2f0dd71f4ea34d0", + "html/cross-origin-embedder-policy/srcdoc.https.html": [ + "3fbba961b2736ed8c9fb973d61dfac5e54267c40", "testharness" ], - "html/cross-origin/null.tentative.html.headers": [ - "fd34f127d558b1288829b8e15f35bcc01c54749e", + "html/cross-origin-embedder-policy/srcdoc.https.html.headers": [ + "6604450991a122e3e241e40b1b9e0516c525389d", "support" ], - "html/cross-origin/resources/navigate_anonymous.sub.html": [ - "d4b38bc1a10003f8adc0e62224c5d3378638fb4f", + "html/cross-origin-opener-policy/README.md": [ + "3f080c82d25de71d899d3b3011afcc3c553fb2a2", "support" ], - "html/cross-origin/resources/navigate_anonymous.sub.html.headers": [ - "a76b601291ec4323da4469a0e09d62c84f81efc3", + "html/cross-origin-opener-policy/coep-navigate-popup.https.html": [ + "717122b4b2f2e766a8fe172a8751f5e6c63d0e8a", + "testharness" + ], + "html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers": [ + "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8", "support" ], - "html/cross-origin/resources/navigate_null.sub.html": [ - "1008f70ff123ae5e507a95ac4f16d32bbb74c983", + "html/cross-origin-opener-policy/coep-redirect.https.html": [ + "73f07ddef88877aacf36ea43d47cc7aee85e5508", + "testharness" + ], + "html/cross-origin-opener-policy/coep-redirect.https.html.headers": [ + "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8", "support" ], - "html/cross-origin/resources/navigate_usecredentials.sub.html": [ - "1008f70ff123ae5e507a95ac4f16d32bbb74c983", + "html/cross-origin-opener-policy/coep.https.html": [ + "1c04ed30dd7b3e7cdf7df43e29eca3b433000703", + "testharness" + ], + "html/cross-origin-opener-policy/coep.https.html.headers": [ + "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8", + "support" + ], + "html/cross-origin-opener-policy/coop-navigated-popup.https.html": [ + "0b51512c221d9035bac5a99b83b661af2fc65d5a", + "testharness" + ], + "html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers": [ + "a19f4400cea33a60c99807330704a23ee363b146", "support" ], - "html/cross-origin/resources/navigate_usecredentials.sub.html.headers": [ - "a84d3782037e7a0573f3b621941e293560792628", + "html/cross-origin-opener-policy/coop-sandbox.https.html": [ + "e471b1eda2ef28a1022e86a9d254608d02578e55", + "testharness" + ], + "html/cross-origin-opener-policy/coop-sandbox.https.html.headers": [ + "46ad58d83bf6e98913ca4c564b7acb8f19fa0093", "support" ], - "html/cross-origin/resources/nothing.txt": [ - "9dafe9be2099a3b02b618c673bcf865a1ffb4f9d", + "html/cross-origin-opener-policy/no-https.html": [ + "da9efdce777c43e5b3f37bda628884c1a3579fde", + "testharness" + ], + "html/cross-origin-opener-policy/no-https.html.headers": [ + "46ad58d83bf6e98913ca4c564b7acb8f19fa0093", "support" ], - "html/cross-origin/resources/nothing.txt.headers": [ - "cb762eff806849df46dc758ef7b98b63f27f54c9", + "html/cross-origin-opener-policy/popup-none.https.html": [ + "62633457d3f57135658fb4bdf959fce278dc9851", + "testharness" + ], + "html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html": [ + "65ec3b26aa0c6e7e5df857bde88f67d394af2e9e", + "testharness" + ], + "html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers": [ + "46ad58d83bf6e98913ca4c564b7acb8f19fa0093", "support" ], - "html/cross-origin/resources/popup_and_close.sub.html": [ - "2489fa8d2470df6930601c79fc1a9c1575733524", + "html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html": [ + "2f8ebc3be3fcc7e23e64c95d5ceaaf83dfa1f67f", + "testharness" + ], + "html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.headers": [ + "a19f4400cea33a60c99807330704a23ee363b146", + "support" + ], + "html/cross-origin-opener-policy/popup-same-origin.https.html": [ + "964011ff7621155446925010c143b025954a5a61", + "testharness" + ], + "html/cross-origin-opener-policy/popup-same-origin.https.html.headers": [ + "46ad58d83bf6e98913ca4c564b7acb8f19fa0093", "support" ], - "html/cross-origin/resources/popup_and_close.sub.html.headers": [ - "a76b601291ec4323da4469a0e09d62c84f81efc3", + "html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html": [ + "18ee909d1865567706674b75b40a6615ef75908c", + "testharness" + ], + "html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.headers": [ + "ab7b28948150ff64101ef080b0d9c7cc9a6a34d2", "support" ], - "html/cross-origin/usecredentials.tentative.html": [ - "55c0f2235db27ad119d652782141de68f5de62a6", + "html/cross-origin-opener-policy/popup-same-site.https.html": [ + "9a0db2765daeb445a892a8ece7347c6b97f24917", "testharness" ], - "html/cross-origin/usecredentials.tentative.html.headers": [ - "a84d3782037e7a0573f3b621941e293560792628", + "html/cross-origin-opener-policy/popup-same-site.https.html.headers": [ + "34bd099a302f893f92586241ea38aac812bf28d0", + "support" + ], + "html/cross-origin-opener-policy/resources/common.js": [ + "b60093f1c62c5d77b213ed95e25ee468b2c2200c", + "support" + ], + "html/cross-origin-opener-policy/resources/coop-coep.py": [ + "8b12341be7356c58c41308e073131ad6c8c3fc35", + "support" + ], + "html/cross-origin-opener-policy/resources/postback.html": [ + "cf3c93bbe1d3589e9a649db34995e02e2ac9c1e4", + "support" + ], + "html/cross-origin-opener-policy/resources/postback.html.headers": [ + "6604450991a122e3e241e40b1b9e0516c525389d", "support" ], "html/dom/documents/dom-tree-accessors/Document.body.html": [ @@ -625591,7 +626960,7 @@ "testharness" ], "html/dom/interfaces.https.html": [ - "7745e4c68e25f3291e91a5f8b701ed6985923b84", + "0d3f1160d2819601afb2168bc15bfeeaddfed6f1", "testharness" ], "html/dom/interfaces.worker.js": [ @@ -629662,14 +631031,6 @@ "9db9bc7bf50d3c7139e2ab921d3adb662e1bf959", "support" ], - "html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.html": [ - "e991e19f059ea73321b8df94c95f841ec8277ed8", - "testharness" - ], - "html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.worker.js": [ - "e957b9e9b500e5d1f7237f3bca62a6a1523c82ed", - "testharness" - ], "html/infrastructure/common-dom-interfaces/collections/domstringlist.html": [ "ab5a5c025a35d8e706f3ea7cfb553c72cd1a0206", "testharness" @@ -630154,6 +631515,10 @@ "bda7c846878833fd50daf1a877ba068a18bc7833", "testharness" ], + "html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html": [ + "773739804b3aeaea268080317cd0cb79fba486d7", + "testharness" + ], "html/interaction/focus/tabindex-focus-flag.html": [ "e40bc077594351019591de8cbfae8fb0d6af13fe", "testharness" @@ -631258,6 +632623,22 @@ "3b8d992cc2a07dfd902dbb1011e2c348e862baaa", "reftest" ], + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html": [ + "5f03a761dc8729632ef74dcf189b7945ae3cee8d", + "reftest" + ], + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html": [ + "385c2a75d427dde8ef0ba71cc777f298027423b9", + "support" + ], + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html": [ + "ad504846dfa29297927a369149d427499f0657b5", + "support" + ], + "html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html": [ + "5dc0fc15dc52c8f3af4595a7901fd89b1827f2a2", + "reftest" + ], "html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html": [ "3e437494c0ad8dadd4d58b630194678753516fde", "support" @@ -639914,10 +641295,6 @@ "9c9aff511d03106c72ea379ff594dd063b8935ea", "testharness" ], - "html/webappapis/animation-frames/idlharness.html": [ - "3a9d1d9b583aa075a0b2bf8ba2a1b8f7c64e57b7", - "testharness" - ], "html/webappapis/animation-frames/same-dispatch-time.html": [ "28e94f1e338914287f9e7d991e61bc1b26818138", "testharness" @@ -641622,18 +642999,86 @@ "bd24f3535507334a69bb98b711106466c8a340a3", "testharness" ], - "import-maps/module-map-key.tentative.html": [ - "13bd122c673144f001048eacbaf4fc7bb78c9b58", + "import-maps/imported/parsing-addresses.tentative.html": [ + "ddb3b724bb64e2edd60a620dc6ae1cc98f32a92a", + "testharness" + ], + "import-maps/imported/parsing-schema.tentative.html": [ + "6b7c0e5b0eb40eee9c8a415af5b1af87a4af3492", + "testharness" + ], + "import-maps/imported/parsing-scope-keys.tentative.html": [ + "601ac37720d700d3f68e3b2f6aeae3b06c112132", + "testharness" + ], + "import-maps/imported/parsing-specifier-keys.tentative.html": [ + "dd547f01d1dfb2379f6afa893385fadc8f1217d1", + "testharness" + ], + "import-maps/imported/resolving-builtins.tentative.html": [ + "c1395c175c77455361e5ea51819ece56dd24737a", + "testharness" + ], + "import-maps/imported/resolving-not-yet-implemented.tentative.html": [ + "7db5f29f892976720a145499d6e40ccb8959b006", + "testharness" + ], + "import-maps/imported/resolving-scopes.tentative.html": [ + "4985249f4e2951965ad78321208ee08eca8617fa", "testharness" ], - "import-maps/resolving.tentative.html": [ - "f2b09a7ae02422c8f6fd3f8dad1f9b8d52a43831", + "import-maps/imported/resolving.tentative.html": [ + "339026259b0f0b8286bc68ddf6976dac0009418b", + "testharness" + ], + "import-maps/imported/resources/helpers/parsing.js": [ + "5c22f6de710ea32753707273be5d63a285633860", + "support" + ], + "import-maps/imported/resources/parsing-addresses.js": [ + "0f5fc73506b1222dd7b3ac422d8c6232ac202bd7", + "support" + ], + "import-maps/imported/resources/parsing-schema.js": [ + "695034533c7faa248a29436cfbe805f86506dc48", + "support" + ], + "import-maps/imported/resources/parsing-scope-keys.js": [ + "cd1d9b34890971dbb21f7bde5d34ed9f2cc91f20", + "support" + ], + "import-maps/imported/resources/parsing-specifier-keys.js": [ + "9eb423a19eb1fb417526946c1701c7c9dde27c9c", + "support" + ], + "import-maps/imported/resources/resolving-builtins.js": [ + "a9383df843d44794351d5c6ffa5580d4d1254b9c", + "support" + ], + "import-maps/imported/resources/resolving-not-yet-implemented.js": [ + "93d782fdad83d58160061a4caa40659292a50866", + "support" + ], + "import-maps/imported/resources/resolving-scopes.js": [ + "ca19a66840601efe66fa2db24cffdcc0727681c5", + "support" + ], + "import-maps/imported/resources/resolving.js": [ + "29ee31ccbc936787894a43de1f6625608d14a192", + "support" + ], + "import-maps/module-map-key.tentative.html": [ + "13bd122c673144f001048eacbaf4fc7bb78c9b58", "testharness" ], "import-maps/resources/empty.js": [ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "support" ], + "import-maps/resources/jest-test-helper.js": [ + "86556ed3dd9585c95d258cbfabc8bb81ed5bc90d", + "support" + ], "import-maps/resources/log.js": [ "a024a29bf2482c78cf7eb96544d38217f1d81f81", "support" @@ -641642,10 +643087,6 @@ "cb762eff806849df46dc758ef7b98b63f27f54c9", "support" ], - "import-maps/resources/resolving.js": [ - "0409962e4d7904bd9ddbe8601b7328d8d0ad6d11", - "support" - ], "import-maps/resources/test-helper.js": [ "2447bfb94353e1ec193857cbcda79f46556216a1", "support" @@ -642359,7 +643800,7 @@ "support" ], "interfaces/element-timing.idl": [ - "dc3b886cfe5b6da608cc71fbc13c97e3d7695b76", + "cf56426fb6ea9ed133c76d1b36327ca95fe348b9", "support" ], "interfaces/encoding.idl": [ @@ -642375,7 +643816,7 @@ "support" ], "interfaces/event-timing.idl": [ - "c6790e16e3dbb736e2db8aad5f5405376f807d72", + "e8475d31922f03d34dd70f1fbee094c7977f6676", "support" ], "interfaces/feature-policy.idl": [ @@ -642455,11 +643896,11 @@ "support" ], "interfaces/largest-contentful-paint.idl": [ - "f16a7ff812c96ab28f7d3b8d0f1b92d141e552a0", + "d2c69c4757553fd4b6d7133067859fa39fe013b5", "support" ], "interfaces/layout-instability.idl": [ - "1bacea77bcef8913b1df220a29cf35448074707c", + "c46151a923dd32f1eb186b18e6d6d26bfb800451", "support" ], "interfaces/longtasks.idl": [ @@ -642731,7 +644172,7 @@ "support" ], "interfaces/webrtc-stats.idl": [ - "48ebc187bc4814156eeb61810dbc01355e13de90", + "e92533a226e97da4bac61fd8b2ce192568976791", "support" ], "interfaces/webrtc.idl": [ @@ -643250,6 +644691,10 @@ "9f64189eda60bc74b41d2526e577dcd0e0cf88d2", "testharness" ], + "largest-contentful-paint/first-letter-background.html": [ + "19544c8edeedb163dc20fa9b2ef654255d050ddf", + "testharness" + ], "largest-contentful-paint/idlharness.html": [ "273fef80ce2d855075781512a9a8ab0a736af420", "testharness" @@ -643267,7 +644712,7 @@ "testharness" ], "largest-contentful-paint/observe-after-untrusted-scroll.html": [ - "abe753fc14a33f88a398900632146ae3b8e8ee13", + "b551e7632b5ce20e2bbc40758f623fac972b3b73", "testharness" ], "largest-contentful-paint/observe-image.html": [ @@ -643290,6 +644735,10 @@ "25d4eaa0367f45440d286c6c1c14de4458465d7b", "testharness" ], + "largest-contentful-paint/toJSON.html": [ + "7defcce1b6f9f2b681405988f74d3977fa3f29e8", + "testharness" + ], "layout-instability/buffer-layout-shift.html": [ "0cfce2f7124226cf4256284c1238ba1ef024c42b", "testharness" @@ -643314,6 +644763,10 @@ "8679a2de7388c5e43a8d784cb3a986d4e23ca568", "testharness" ], + "layout-instability/toJSON.html": [ + "3d39d623e13314b183463fa1c365df3a7b725243", + "testharness" + ], "lifecycle/META.yml": [ "c1fcbca4c1f8366da1dd9eb91bc9427edeef1153", "support" @@ -643367,7 +644820,7 @@ "testharness" ], "lint.whitelist": [ - "c344c3a834444db4be24db1d0132c85a4b14395c", + "669038166ab38e540f817a760d8346088f2219b9", "support" ], "loading/lazyload/common.js": [ @@ -643586,6 +645039,46 @@ "9524d275e479ba2db2aaaab9fdbc1203c79009cb", "support" ], + "mathml/presentation-markup/direction/direction-006-ref.html": [ + "39e6dabdfb19ac8ccd43605a01633b2730f6f95c", + "support" + ], + "mathml/presentation-markup/direction/direction-006.html": [ + "904e7d3fed8c7ae6d1a19d522fe08a1e282a59c6", + "reftest" + ], + "mathml/presentation-markup/direction/direction-007-ref.html": [ + "5c77395f2008ba5e6f1068b345e8ff1c58f93ee4", + "support" + ], + "mathml/presentation-markup/direction/direction-007.html": [ + "7137e2640fa4ee76135f1d77f10ab329119c5332", + "reftest" + ], + "mathml/presentation-markup/direction/direction-008-ref.html": [ + "492fa9539ae83285940b44f9463e1439c54705cf", + "support" + ], + "mathml/presentation-markup/direction/direction-008.html": [ + "5c98b07410079806fc0163e1f9c4a98bcfe4cc3d", + "reftest" + ], + "mathml/presentation-markup/direction/direction-009-ref.html": [ + "7ed4796814a7c0561b3ecaeeedf2eac7a5533e60", + "support" + ], + "mathml/presentation-markup/direction/direction-009.html": [ + "bf8caf16aed28f2b55f5bdd96009f0cd9bfc1785", + "reftest" + ], + "mathml/presentation-markup/direction/direction-010-ref.html": [ + "4f595ed49f698a7a70392edb5e72dd1df8471368", + "support" + ], + "mathml/presentation-markup/direction/direction-010.html": [ + "6dc095ac1fd490ca3bcb869014c6e32428110f9e", + "reftest" + ], "mathml/presentation-markup/direction/direction-overall-ref.html": [ "5ce6c5c42bb8068b895cdbe111644c339c4b9676", "support" @@ -644082,6 +645575,14 @@ "a14fadfdf7e408e204472aee047a08e86efaf03e", "reftest" ], + "mathml/relations/css-styling/mathvariant-case-sensitivity-ref.html": [ + "28d9acc1f4c2466c0d13c6bacc4e454b3bf365f3", + "support" + ], + "mathml/relations/css-styling/mathvariant-case-sensitivity.html": [ + "0d3e706d961e2294d59cc4d737fc07f586c30bf5", + "reftest" + ], "mathml/relations/css-styling/mathvariant-double-struck-ref.html": [ "686aa492e0f08ef340ae3de7c1856170743cfe72", "support" @@ -656214,6 +657715,22 @@ "89a994af3048cc0b9fc3212fd6f1497bc717208a", "testharness" ], + "pointerevents/inheritance.html": [ + "0bf39bcb4ddc5badaad5c7a3f940c4deb4fa5861", + "testharness" + ], + "pointerevents/parsing/touch-action-computed.html": [ + "59255bec4550b7997d7b3dc8b1737fab5b1b812a", + "testharness" + ], + "pointerevents/parsing/touch-action-invalid.html": [ + "979dc252d3fea4f4c39c0120fbdcf27026d41d54", + "testharness" + ], + "pointerevents/parsing/touch-action-valid.html": [ + "9bb5d023edcfad425fcaa23d20abf0c4bf479034", + "testharness" + ], "pointerevents/pointerevent_attributes_hoverable_pointers.html": [ "97e0db158ed0b2f5ccba6ea30a31c531fc9f23ef", "testharness" @@ -657390,6 +658907,14 @@ "0fcad36776d5a7fe160244dc342f227b76083798", "testharness" ], + "quirks/dd-dl-firefox-001-ref.html": [ + "46a4d7d156f6e99040cd500e241b56440e695796", + "support" + ], + "quirks/dd-dl-firefox-001.html": [ + "96fc76f08f45b800f5e210aee135bf880f8f2d32", + "reftest" + ], "quirks/hashless-hex-color/limited-quirks.html": [ "f7dd7ed4bd4634667f8f139b6d196824f8948c12", "testharness" @@ -657675,7 +659200,7 @@ "support" ], "referrer-policy/generic/referrer-policy-test-case.sub.js": [ - "0c0f38195309e45de66e106f574a18cdde0e7cdf", + "d1cb469b3dfba788b0042e41427d637dfb14fad4", "support" ], "referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html": [ @@ -667090,6 +668615,10 @@ "6805c323df5a975231648b830e33ce183c3cbbd3", "support" ], + "resources/chromium/nfc-mock.js": [ + "83bd6b8a0dea2d2434728b9ed52027e6b79b798a", + "support" + ], "resources/chromium/sensor.mojom.js": [ "7578dd6d64f0e91d94c9dcc32432fd2ceadd38b6", "support" @@ -667527,11 +669056,11 @@ "support" ], "resources/webidl2/lib/README.md": [ - "3f9d75f57ba8506537f75ae2958df6a74abcba3d", + "1bd583269d2929a16b1c7ad0c58fab6e99b72a10", "support" ], "resources/webidl2/lib/webidl2.js": [ - "9cb975a8bb30075e7ab377bc95b69ecc4f7e77f6", + "900694b095df7f6a4b791ea41e096744d06a6089", "support" ], "resources/webidl2/lib/webidl2.js.headers": [ @@ -670867,7 +672396,7 @@ "support" ], "service-workers/service-worker/resources/update-during-installation-worker.js": [ - "3f89881c04384590b8b132c392977256bfb847ed", + "f1997bd824e8e165cc119a52082d742bd63f4e4d", "support" ], "service-workers/service-worker/resources/update-during-installation-worker.py": [ @@ -671498,6 +673027,42 @@ "77da4476025fb6160f34efb1df9cfd87226cda02", "testharness" ], + "shadow-dom/focus/DocumentOrShadowRoot-activeElement.html": [ + "20456b057e1e724cdac9bc656f3b3d6c7ac2f658", + "testharness" + ], + "shadow-dom/focus/focus-tabindex-order-shadow-negative.html": [ + "ab25ea829bd10952ad6e96898fc95a1a1ae25d8f", + "testharness" + ], + "shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html": [ + "3c9e70867c5883e96f6288b85a9bac60b9526f4e", + "testharness" + ], + "shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html": [ + "875e5b6814a95754f5c01d18c125c39c363ad3c6", + "testharness" + ], + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html": [ + "b491c7d237c20604039f2b6482d484635c9f50da", + "testharness" + ], + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html": [ + "f257261477186b94320a48ba1650348991dc2a26", + "testharness" + ], + "shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html": [ + "1aa5292997a3e28750e1437939e3c24448245c8c", + "testharness" + ], + "shadow-dom/focus/focus-tabindex-order-shadow-zero.html": [ + "d8b12ed8ac6e24553f0cccced7f1616bb588413e", + "testharness" + ], + "shadow-dom/focus/resources/shadow-utils.js": [ + "6ea372afdf180a95d9fda632ebccd00a13df85bf", + "support" + ], "shadow-dom/form-control-form-attribute.html": [ "2e782b2587d8dc6b71deee7d229ed4e8a996703c", "testharness" @@ -672454,6 +674019,10 @@ "43b340dbb79f2585ef4acc4361ee94c6f22003f0", "testharness" ], + "sms/README.md": [ + "7cd98964c24979d427b51c095e178b0622efa971", + "support" + ], "sms/idlharness.https.any.js": [ "0c31744937c6dbc9b292586ab8ce5f10b268f3ed", "testharness" @@ -672819,7 +674388,7 @@ "testharness" ], "streams/readable-streams/patched-global.any.js": [ - "500979f5b37ad1af106fcbb76ca531d4dc539129", + "813dd42e68aa9f2c2bbb5e7bd6d8d4a78ef43db5", "testharness" ], "streams/readable-streams/reentrant-strategies.any.js": [ @@ -673150,10 +674719,138 @@ "ee86b537ae987483687cc8ba6181db82f99ab162", "support" ], + "svg/animations/accumulate-values-width-animation.html": [ + "7813494a6a2cb9ad33a16d65a6b6869f9c639ce9", + "testharness" + ], + "svg/animations/additive-from-to-width-animation.html": [ + "0899f5e0b53120cb116b781f6f0dbdfaa7ee26f9", + "testharness" + ], + "svg/animations/additive-type-by-animation.html": [ + "2dc7732dd6effc05e5eac59305de8ed4e22ab9d0", + "testharness" + ], + "svg/animations/additive-values-width-animation.html": [ + "5b874f5a4f838cd9b3d3c9e9d3e2917862d79ee5", + "testharness" + ], "svg/animations/animVal-basics.html": [ "7eb968af01e0b23fa270a71f8788415ea3eed049", "testharness" ], + "svg/animations/animate-calcMode-spline-by.html": [ + "5ce9bcc763e50e34afefb67b0fddd20b8a5ad247", + "testharness" + ], + "svg/animations/animate-calcMode-spline-from-by.html": [ + "1f15760c7d845a42e89b7ae9d15e602658a795a8", + "testharness" + ], + "svg/animations/animate-calcMode-spline-from-to.html": [ + "4d6080083148b6567d66bc92834e36bbd226b310", + "testharness" + ], + "svg/animations/animate-calcMode-spline-to.html": [ + "4a26cd716ed5c74c96a43108686d97b854f853d4", + "testharness" + ], + "svg/animations/animate-calcMode-spline-values.html": [ + "46952aa45db5d5ca05f085f25e9ebd0339085dfb", + "testharness" + ], + "svg/animations/animate-color-calcMode-discrete.html": [ + "980f39282e33f3cb89f91c8652071a9a8d6a83b7", + "testharness" + ], + "svg/animations/animate-color-fill-currentColor.html": [ + "2780ce2ac9a8e69ae10c1ffda3b56e741127e241", + "testharness" + ], + "svg/animations/animate-color-fill-from-by.html": [ + "410b27b75a732f2e846d9d17bac421a6fdbda8cb", + "testharness" + ], + "svg/animations/animate-color-transparent.html": [ + "e2a946cfb0b14337c82bd3920e5d958dfc5e8ee5", + "testharness" + ], + "svg/animations/animate-css-xml-attributeType.html": [ + "4494eb773693d2c65620030f975d13db21c60077", + "testharness" + ], + "svg/animations/animate-currentColor.html": [ + "a8b3c1f16f25823f674c69f0c2bd472b8b044c4a", + "testharness" + ], + "svg/animations/animate-dynamic-update-attributeName.html": [ + "47ca52526ae127ba16d009dad63772e4cd343de2", + "testharness" + ], + "svg/animations/animate-elem-02-t-drt.html": [ + "31f34ce56f8beddc12d5097d28c29d76bb0d6760", + "testharness" + ], + "svg/animations/animate-elem-14-t-drt.html": [ + "64fc35f596fd7768ce41dedc6b46136868f89ff8", + "testharness" + ], + "svg/animations/animate-elem-15-t-drt.html": [ + "9d5cb1b437bc7d7fe40dc5a26f20e450f733c4f5", + "testharness" + ], + "svg/animations/animate-elem-16-t-drt.html": [ + "0ac98e2fc80f1549bb07abf858b7e9665a289f96", + "testharness" + ], + "svg/animations/animate-elem-17-t-drt.html": [ + "1b101491953b95fcaffad8e1e8ae1e13edfff1b8", + "testharness" + ], + "svg/animations/animate-elem-18-t-drt.html": [ + "4f9dbb7765812acc3d338ac7966a5a5b8ebcd6dd", + "testharness" + ], + "svg/animations/animate-elem-19-t-drt.html": [ + "9b9d61c90bddf6862fabe222b3f4488e546e124f", + "testharness" + ], + "svg/animations/animate-end-attribute-numeric-precision.html": [ + "d0515ac850e86cd99091bfe78f1ef07bc2de9980", + "testharness" + ], + "svg/animations/animate-fill-freeze-with-repeatDur.html": [ + "aab9eacff26bbf684cb15c33203ebf3da263f502", + "testharness" + ], + "svg/animations/animate-from-to-keyTimes.html": [ + "7295bcdb630f4423bd2a2280d2f082a87a92d63d", + "testharness" + ], + "svg/animations/animate-gradient-transform.html": [ + "ddb9946fda6b45c35c02a154b6047058c1a1470c", + "testharness" + ], + "svg/animations/animate-inherit-css-property.html": [ + "a8b56bab2bfa6a8b61f14fbf31d9760fc537ccc7", + "testharness" + ], + "svg/animations/animate-insert-begin.html": [ + "5155391a9123e995ba52a7ebaa76d863eaa0ead8", + "testharness" + ], + "svg/animations/animate-insert-no-begin.html": [ + "3db406ecd4823c39bbae6204797ca70451f5d049", + "testharness" + ], + "svg/animations/animate-keySplines.html": [ + "0b02f71d3fa4cecc07e455f2d7000922db46bcc9", + "testharness" + ], + "svg/animations/animate-marker-orient-from-angle-to-angle.html": [ + "a9c16740e63292022682a24f801a4dd88eb46c79", + "testharness" + ], "svg/animations/animate-marker-orient-from-angle-to-auto.html": [ "40fc57b4f3c9bdc2c9a68e59c1d15495cc445124", "testharness" @@ -673590,6 +675287,10 @@ "17b78a2787d0becf64b90136fcf0f6f966404baa", "testharness" ], + "svg/animations/syncbase-remove-add-while-running.html": [ + "bebd537250151a254b2b672bc11ba28f80595790", + "testharness" + ], "svg/coordinate-systems/abspos.html": [ "fb37bbe7f3ae4a61d1c216970c8a263673aed0dc", "reftest" @@ -677791,7 +679492,7 @@ "support" ], "tools/ci/manifest_build.py": [ - "98e7ce75e512c1568f3d7fa6ca94fa58e0c10835", + "de17089214ed041ed98a07583ea8c4628b147e5a", "support" ], "tools/ci/run_tc.py": [ @@ -677815,15 +679516,15 @@ "support" ], "tools/ci/tests/test_update_pr_preview.py": [ - "08e46b9a63ee77f6635d27b482e1c727774fe606", + "3202a1a2df6ac1d6c1485b1e6b72b3b425b351e6", "support" ], "tools/ci/update_pr_preview.py": [ - "9b104c66bb6a8089e81f633ad5e64cb33ea4f7c1", + "eca4a30678cf82aede0d90db9b63ee94b6393f78", "support" ], "tools/ci/website_build.sh": [ - "aadfcbd6a212574fa5462447072b996ae214de6b", + "e99fcb0cc9fb8b7451301a1e2d318daa631baf62", "support" ], "tools/conftest.py": [ @@ -684547,7 +686248,7 @@ "testharness" ], "user-timing/mark-measure-return-objects.any.js": [ - "fa45388d7b118ac17fd5e0a85990352070877e35", + "bb15c5839818babf731bfec600395e13e5b794aa", "testharness" ], "user-timing/mark.any.js": [ @@ -684571,7 +686272,7 @@ "testharness" ], "user-timing/measure-with-dict.any.js": [ - "99a2fe4d79841e5bd7fab3c0db50acb9434ef29b", + "95160fea8941d55a04381f46b730afc5a0956901", "testharness" ], "user-timing/measure.html": [ @@ -684583,7 +686284,7 @@ "testharness" ], "user-timing/measure_exception.html": [ - "8783ff7e22671309eda54962903a1610c352285d", + "df674d931f48f15e5164ff8b34d060c1966240d9", "testharness" ], "user-timing/measure_exceptions_navigation_timing.html": [ @@ -684619,7 +686320,7 @@ "support" ], "user-timing/structured-serialize-detail.any.js": [ - "55cbd9246f9cef890c4f9dc79c47a1b3e4611375", + "0c4be9a3bcb0acbdeed2a2c4dae22ab2a1a3d587", "testharness" ], "user-timing/supported-usertiming-types.any.js": [ @@ -686203,7 +687904,7 @@ "testharness" ], "web-animations/animation-model/animation-types/property-list.js": [ - "7b14797d962d5a52e641a1823e2b88927eabba90", + "3c1750f1f266985a449ab19e212a1166369f230d", "support" ], "web-animations/animation-model/animation-types/property-types.js": [ @@ -686659,87 +688360,47 @@ "support" ], "web-nfc/NDEFMessage_constructor.https.html": [ - "73bbb4f8ab5182995fd66459148e3399be1361a4", + "5be4571493ad9b6ac9f677d66e81806b4590034e", "testharness" ], "web-nfc/NDEFRecord_constructor.https.html": [ - "81148856473c4823422f59511a5e9de8bbfc4771", + "e2e2c45507225ab17c72849928142e7f24a57813", "testharness" ], "web-nfc/NFCErrorEvent_constructor.https.html": [ "1cc9ce160be46955a9b15485ee4c040605722961", "testharness" ], - "web-nfc/NFCReader-manual.https.html": [ - "a3171c3544e4640ca35d2a6de451d05cf8aa008c", - "manual" - ], "web-nfc/NFCReader.https.html": [ - "3032b652edfb7ad36d531a9b27b95c865877814a", + "4488097d6ebee463545666b123ed4893b72080c6", "testharness" ], - "web-nfc/NFCReader_options_mediaType-manual.https.html": [ - "faaf8f39a77ff81bcc037eb8902355b847cd05ba", - "manual" - ], - "web-nfc/NFCReader_options_recordType_empty-manual.https.html": [ - "995072b260d8759e618f5606bed2231c67c6bc80", - "manual" - ], - "web-nfc/NFCReader_options_recordType_json-manual.https.html": [ - "4120bc72f308b4711455844340647822738a5f13", - "manual" - ], - "web-nfc/NFCReader_options_recordType_opaque-manual.https.html": [ - "94ded3e8a0fcba2f0fef86cc6a878f8c5091ac76", - "manual" - ], - "web-nfc/NFCReader_options_recordType_text-manual.https.html": [ - "72ca3e70d430d1d141a520af0d6b34240ebca9f9", - "manual" - ], - "web-nfc/NFCReader_options_recordType_url-manual.https.html": [ - "af57610c285a36e68cf4eadfed3293bbcb0ee245", - "manual" - ], - "web-nfc/NFCReader_options_url-manual.https.html": [ - "aa0e72b089a1b1c445eb8b7ba8c478158d47173f", - "manual" + "web-nfc/NFCReader_options.https.html": [ + "ebda3859834c5bd146fba5d5b8a2982d5c6722df", + "testharness" ], "web-nfc/NFCReadingEvent_constructor.https.html": [ - "172b0a619c2b27b9c8d0f04101094f7969aa11e9", + "c2f9cef6e505637684281a799d44107c1557b00a", "testharness" ], "web-nfc/NFCWriter_push.https.html": [ - "0b804615930b12d1ac4d7bfc1b395e715de03778", + "33471a18d8e1f960bbf6ad06b412515f5a0ba87e", "testharness" ], - "web-nfc/NFCWriter_push_signal-manual.https.html": [ - "f45d0bbbd49821d0de8953884f5dbb908e904f83", - "manual" + "web-nfc/README.md": [ + "8ae597e36fd10ee0af2e86059688cb001e326b4b", + "support" ], "web-nfc/idlharness.https.window.js": [ "c19458aed83f505472e35c8f3affa3247a814989", "testharness" ], - "web-nfc/nfc_hw_disabled-manual.https.html": [ - "bb2cd42f1e65cca49b03385e9e553cc8077aa08d", - "manual" - ], "web-nfc/nfc_insecure_context.html": [ - "0e5764e6ebca0cc5b2c16cfe34c1379a3601aa80", + "f883f0473b7c7a7b9b622cad5214ca529885b34e", "testharness" ], - "web-nfc/nfc_push_ArrayBuffer-manual.https.html": [ - "90a356f9b26409e233cb7d4cdb858daab2515125", - "manual" - ], - "web-nfc/nfc_push_DOMString-manual.https.html": [ - "15e1da50fb3acd9f23f22b6876e2bd5867225fee", - "manual" - ], - "web-nfc/resources/nfc_help.js": [ - "67fd5af381c9fa96c921b9fd6a2d6559562f4066", + "web-nfc/resources/nfc-helpers.js": [ + "fc72fa2de89f8d634ff142a0cba58ac866172d60", "support" ], "web-share/META.yml": [ diff --git a/tests/wpt/metadata/css/css-align/parsing/gap-computed.html.ini b/tests/wpt/metadata/css/css-align/parsing/gap-computed.html.ini new file mode 100644 index 000000000000..77d70251f90f --- /dev/null +++ b/tests/wpt/metadata/css/css-align/parsing/gap-computed.html.ini @@ -0,0 +1,34 @@ +[gap-computed.html] + [Property gap value '10px 20%' computes to '10px 20%'] + expected: FAIL + + [Property gap value '10px' computes to '10px'] + expected: FAIL + + [Property gap value 'normal 10px' computes to 'normal 10px'] + expected: FAIL + + [Property gap value '20% calc(20% + 10px)' computes to '20% calc(20% + 10px)'] + expected: FAIL + + [Property gap value 'calc(20% + 10px) normal' computes to 'calc(20% + 10px) normal'] + expected: FAIL + + [Property gap value 'calc(20% + 10px)' computes to 'calc(20% + 10px)'] + expected: FAIL + + [Property gap value 'calc(-0.5em + 10px) calc(0.5em + 10px)' computes to '0px 30px'] + expected: FAIL + + [Property gap value 'calc(0.5em + 10px)' computes to '30px'] + expected: FAIL + + [Property gap value 'normal' computes to 'normal'] + expected: FAIL + + [Property gap value '20%' computes to '20%'] + expected: FAIL + + [Property gap value 'calc(-0.5em + 10px)' computes to '0px'] + expected: FAIL + diff --git a/tests/wpt/metadata/css/css-align/parsing/gap-valid.html.ini b/tests/wpt/metadata/css/css-align/parsing/gap-valid.html.ini new file mode 100644 index 000000000000..61c7e78a8189 --- /dev/null +++ b/tests/wpt/metadata/css/css-align/parsing/gap-valid.html.ini @@ -0,0 +1,28 @@ +[gap-valid.html] + [e.style['gap'\] = "20% calc(20% + 10px)" should set the property value] + expected: FAIL + + [e.style['gap'\] = "20% 20%" should set the property value] + expected: FAIL + + [e.style['gap'\] = "10px 20%" should set the property value] + expected: FAIL + + [e.style['gap'\] = "0px normal" should set the property value] + expected: FAIL + + [e.style['gap'\] = "calc(20% + 10px) 0px" should set the property value] + expected: FAIL + + [e.style['gap'\] = "10px 10px" should set the property value] + expected: FAIL + + [e.style['gap'\] = "normal normal" should set the property value] + expected: FAIL + + [e.style['gap'\] = "normal 10px" should set the property value] + expected: FAIL + + [e.style['gap'\] = "calc(20% + 10px) calc(20% + 10px)" should set the property value] + expected: FAIL + diff --git a/tests/wpt/metadata/css/css-paint-api/custom-property-animation-on-main-thread.https.html.ini b/tests/wpt/metadata/css/css-paint-api/custom-property-animation-on-main-thread.https.html.ini new file mode 100644 index 000000000000..2460e466ee2e --- /dev/null +++ b/tests/wpt/metadata/css/css-paint-api/custom-property-animation-on-main-thread.https.html.ini @@ -0,0 +1,2 @@ +[custom-property-animation-on-main-thread.https.html] + expected: FAIL diff --git a/tests/wpt/metadata/css/css-paint-api/one-custom-property-animation.https.html.ini b/tests/wpt/metadata/css/css-paint-api/one-custom-property-animation.https.html.ini new file mode 100644 index 000000000000..46b6997ba486 --- /dev/null +++ b/tests/wpt/metadata/css/css-paint-api/one-custom-property-animation.https.html.ini @@ -0,0 +1,2 @@ +[one-custom-property-animation.https.html] + expected: FAIL diff --git a/tests/wpt/metadata/css/css-paint-api/two-custom-property-animation.https.html.ini b/tests/wpt/metadata/css/css-paint-api/two-custom-property-animation.https.html.ini new file mode 100644 index 000000000000..2c201848a381 --- /dev/null +++ b/tests/wpt/metadata/css/css-paint-api/two-custom-property-animation.https.html.ini @@ -0,0 +1,2 @@ +[two-custom-property-animation.https.html] + expected: FAIL diff --git a/tests/wpt/metadata/css/css-text-decor/parsing/text-decoration-valid.html.ini b/tests/wpt/metadata/css/css-text-decor/parsing/text-decoration-valid.html.ini index b153c32c44ef..6a2d6c0ede6b 100644 --- a/tests/wpt/metadata/css/css-text-decor/parsing/text-decoration-valid.html.ini +++ b/tests/wpt/metadata/css/css-text-decor/parsing/text-decoration-valid.html.ini @@ -17,3 +17,24 @@ [e.style['text-decoration'\] = "double overline underline" should set the property value] expected: FAIL + [e.style['text-decoration'\] = "underline auto" should set the property value] + expected: FAIL + + [e.style['text-decoration'\] = "auto" should set the property value] + expected: FAIL + + [e.style['text-decoration'\] = "10px" should set the property value] + expected: FAIL + + [e.style['text-decoration'\] = "line-through 20px" should set the property value] + expected: FAIL + + [e.style['text-decoration'\] = "overline 3em" should set the property value] + expected: FAIL + + [e.style['text-decoration'\] = "from-font" should set the property value] + expected: FAIL + + [e.style['text-decoration'\] = "overline green from-font" should set the property value] + expected: FAIL + diff --git a/tests/wpt/metadata/css/css-transforms/animation/composited-transform.html.ini b/tests/wpt/metadata/css/css-transforms/animation/composited-transform.html.ini new file mode 100644 index 000000000000..a8bac605c988 --- /dev/null +++ b/tests/wpt/metadata/css/css-transforms/animation/composited-transform.html.ini @@ -0,0 +1,4 @@ +[composited-transform.html] + [An additive transform animation on-top of a replace transform animation should composite correctly] + expected: FAIL + diff --git a/tests/wpt/metadata/css/css-transitions/CSSTransition-effect.tentative.html.ini b/tests/wpt/metadata/css/css-transitions/CSSTransition-effect.tentative.html.ini index 09cab11e134f..37478df22046 100644 --- a/tests/wpt/metadata/css/css-transitions/CSSTransition-effect.tentative.html.ini +++ b/tests/wpt/metadata/css/css-transitions/CSSTransition-effect.tentative.html.ini @@ -20,3 +20,6 @@ [After setting a transition's effect to null, a new transition can be started] expected: FAIL + [After setting a transition's effect to null, it should be possible to interrupt that transition] + expected: FAIL + diff --git a/tests/wpt/metadata/css/css-transitions/parsing/transition-timing-function-computed.html.ini b/tests/wpt/metadata/css/css-transitions/parsing/transition-timing-function-computed.html.ini new file mode 100644 index 000000000000..5a41ca5ad572 --- /dev/null +++ b/tests/wpt/metadata/css/css-transitions/parsing/transition-timing-function-computed.html.ini @@ -0,0 +1,13 @@ +[transition-timing-function-computed.html] + [Property transition-timing-function value 'steps(2, jump-none)' computes to 'steps(2, jump-none)'] + expected: FAIL + + [Property transition-timing-function value 'steps(2, jump-start)' computes to 'steps(2, jump-start)'] + expected: FAIL + + [Property transition-timing-function value 'steps(2, jump-end)' computes to 'steps(2)'] + expected: FAIL + + [Property transition-timing-function value 'steps(2, jump-both)' computes to 'steps(2, jump-both)'] + expected: FAIL + diff --git a/tests/wpt/metadata/css/css-values/max-length-percent-001.html.ini b/tests/wpt/metadata/css/css-values/max-length-percent-001.html.ini new file mode 100644 index 000000000000..d9ddfa2bf689 --- /dev/null +++ b/tests/wpt/metadata/css/css-values/max-length-percent-001.html.ini @@ -0,0 +1,2 @@ +[max-length-percent-001.html] + expected: FAIL diff --git a/tests/wpt/metadata/css/css-values/min-length-percent-001.html.ini b/tests/wpt/metadata/css/css-values/min-length-percent-001.html.ini new file mode 100644 index 000000000000..e70af2a782ff --- /dev/null +++ b/tests/wpt/metadata/css/css-values/min-length-percent-001.html.ini @@ -0,0 +1,2 @@ +[min-length-percent-001.html] + expected: FAIL diff --git a/tests/wpt/metadata/css/cssom-view/matchMedia-display-none-iframe.html.ini b/tests/wpt/metadata/css/cssom-view/matchMedia-display-none-iframe.html.ini deleted file mode 100644 index e6e1f29e2743..000000000000 --- a/tests/wpt/metadata/css/cssom-view/matchMedia-display-none-iframe.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[matchMedia-display-none-iframe.html] - expected: ERROR diff --git a/tests/wpt/metadata/fetch/content-type/response.window.js.ini b/tests/wpt/metadata/fetch/content-type/response.window.js.ini index 032451b7dfa7..a70942e359e4 100644 --- a/tests/wpt/metadata/fetch/content-type/response.window.js.ini +++ b/tests/wpt/metadata/fetch/content-type/response.window.js.ini @@ -312,21 +312,9 @@ [ + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/README.md b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/README.md new file mode 100644 index 000000000000..16179eb0133a --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/README.md @@ -0,0 +1 @@ +See `../cross-origin-opener-policy/README.md`. diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html new file mode 100644 index 000000000000..aa4cf969d9e0 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html @@ -0,0 +1,44 @@ + + + + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html.headers new file mode 100644 index 000000000000..6604450991a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html new file mode 100644 index 000000000000..c34f1336c8bd --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html @@ -0,0 +1,20 @@ + + + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html.headers new file mode 100644 index 000000000000..6604450991a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html new file mode 100644 index 000000000000..7fed1fe58194 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html @@ -0,0 +1,21 @@ + + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers new file mode 100644 index 000000000000..6604450991a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html new file mode 100644 index 000000000000..b1bb6fefc6cf --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html @@ -0,0 +1,79 @@ + + +Cross-Origin-Embedder-Policy header and nested navigable resource without such header + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html.headers new file mode 100644 index 000000000000..43c44cffd64e --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: unknown-should-be-parsed-as-null diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html new file mode 100644 index 000000000000..0bd6aab72953 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html @@ -0,0 +1,138 @@ + + +Cross-Origin-Embedder-Policy header and nested navigable resource without such header + + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html.headers new file mode 100644 index 000000000000..6604450991a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html new file mode 100644 index 000000000000..7d90aacd8bbf --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html @@ -0,0 +1,17 @@ + + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers new file mode 100644 index 000000000000..4e798cd9f5d3 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Resource-Policy: cross-origin diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_null.sub.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-none.sub.html similarity index 100% rename from tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_null.sub.html rename to tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-none.sub.html diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_anonymous.sub.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html similarity index 100% rename from tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_anonymous.sub.html rename to tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers new file mode 100644 index 000000000000..6604450991a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt new file mode 100644 index 000000000000..e61d8ee36c9a --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt @@ -0,0 +1 @@ +nothing with cross-origin CORP diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers new file mode 100644 index 000000000000..1b88136c01cb --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers @@ -0,0 +1 @@ +Cross-Origin-Resource-Policy: cross-origin diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt new file mode 100644 index 000000000000..b9ba801f78e5 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt @@ -0,0 +1 @@ +nothing with same-origin CORP diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers new file mode 100644 index 000000000000..30ddeac2e7a3 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers @@ -0,0 +1 @@ +Cross-Origin-Resource-Policy: same-origin diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/script-factory.js b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/script-factory.js new file mode 100644 index 000000000000..9db755226020 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/script-factory.js @@ -0,0 +1,23 @@ +// This creates a serialized + + +
+ diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/sandbox.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/sandbox.https.html.headers new file mode 100644 index 000000000000..6604450991a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/sandbox.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html new file mode 100644 index 000000000000..3fbba961b273 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html @@ -0,0 +1,21 @@ + + + + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html.headers new file mode 100644 index 000000000000..6604450991a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/README.md b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/README.md new file mode 100644 index 000000000000..3f080c82d25d --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/README.md @@ -0,0 +1,11 @@ +This directory as well as `../cross-origin-embedder-policy/` contains tests for `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy`. Some light background reading: + +* [COOP and COEP explained](https://docs.google.com/document/d/1zDlfvfTJ_9e8Jdc8ehuV4zMEu9ySMCiTGMS9y0GU92k/edit) +* [COOP processing model](https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e) (also defines interaction with COEP) +* [COEP processing model](https://mikewest.github.io/corpp/) +* [Open COOP issues](https://github.com/whatwg/html/labels/topic%3A%20cross-origin-opener-policy) +* [Open COEP issues](https://github.com/whatwg/html/labels/topic%3A%20cross-origin-embedder-policy) + +Notes: + +* Top-level navigation to a `data:` URL does not work in Chrome and Firefox and is therefore not tested. (This should probably be standardized.) diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html new file mode 100644 index 000000000000..717122b4b2f2 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html @@ -0,0 +1,62 @@ + +Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: a navigating popup + + + + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers new file mode 100644 index 000000000000..63b60e490f47 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html new file mode 100644 index 000000000000..73f07ddef888 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html @@ -0,0 +1,67 @@ + +Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: redirects + + + + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html.headers new file mode 100644 index 000000000000..63b60e490f47 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html new file mode 100644 index 000000000000..1c04ed30dd7b --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html @@ -0,0 +1,43 @@ + +Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy + + + + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html.headers new file mode 100644 index 000000000000..63b60e490f47 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html new file mode 100644 index 000000000000..0b51512c221d --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html @@ -0,0 +1,29 @@ + +Cross-Origin-Opener-Policy: a navigated popup + + + + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers similarity index 100% rename from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html.headers rename to tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https.html new file mode 100644 index 000000000000..e471b1eda2ef --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https.html @@ -0,0 +1,22 @@ + +Sandboxed Cross-Origin-Opener-Policy popup should result in a network error + + + +
+ diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin.tentative.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https.html.headers similarity index 100% rename from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin.tentative.html.headers rename to tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https.html.headers diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html new file mode 100644 index 000000000000..da9efdce777c --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html @@ -0,0 +1,18 @@ + + +Cross-Origin-Opener-Policy requires secure contexts + + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html.headers new file mode 100644 index 000000000000..46ad58d83bf6 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_null.tentative.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-none.https.html similarity index 93% rename from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_null.tentative.html rename to tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-none.https.html index 35a42fd2f096..62633457d3f5 100644 --- a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_null.tentative.html +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-none.https.html @@ -3,8 +3,7 @@ - - +
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html new file mode 100644 index 000000000000..65ec3b26aa0c --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html @@ -0,0 +1,15 @@ + +Cross-Origin-Opener-Policy: about:blank + + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers new file mode 100644 index 000000000000..46ad58d83bf6 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html similarity index 96% rename from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html rename to tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html index bbd55130d7a9..2f8ebc3be3fc 100644 --- a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html @@ -3,8 +3,7 @@ - - +
- - +
- - +
- - +
+ + +""" diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html new file mode 100644 index 000000000000..cf3c93bbe1d3 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html @@ -0,0 +1,10 @@ + + + diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html.headers new file mode 100644 index 000000000000..6604450991a1 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html.headers @@ -0,0 +1 @@ +Cross-Origin-Embedder-Policy: require-corp diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/common.sub.js b/tests/wpt/web-platform-tests/html/cross-origin-opener/common.sub.js deleted file mode 100644 index a73a95aba862..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin-opener/common.sub.js +++ /dev/null @@ -1,28 +0,0 @@ -const SAME_ORIGIN = {origin: get_host_info().HTTP_ORIGIN, name: "SAME_ORIGIN"}; -const SAME_SITE = {origin: get_host_info().HTTP_REMOTE_ORIGIN, name: "SAME_SITE"}; -const CROSS_ORIGIN = {origin: get_host_info().HTTP_NOTSAMESITE_ORIGIN, name: "CROSS_ORIGIN"} - -function coop_test(t, host, coop, channelName, hasOpener) { - let bc = new BroadcastChannel(channelName); - bc.onmessage = t.step_func_done((event) => { - let payload = event.data; - assert_equals(payload.name, hasOpener ? channelName : ""); - assert_equals(payload.opener, hasOpener); - }); - - let w = window.open(`${host.origin}/html/cross-origin-opener/resources/coop_window.py?path=window.sub.html&coop=${escape(coop)}&channel=${channelName}`, channelName); - - // w will be closed by its postback iframe. When out of process, - // window.close() does not work. - t.add_cleanup(() => w.close()); -} - -function run_coop_tests(mainTest, testArray) { - for (let test of tests) { - async_test(t => { - coop_test(t, test[0], test[1], - `${mainTest}_to_${test[0].name}_${test[1].replace(/ /g,"-")}`, - test[2]); - }, `${mainTest} document opening popup to ${test[0].origin} with COOP: "${test[1]}"`); - } -} diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/coop_window.py b/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/coop_window.py deleted file mode 100644 index b24d6d55a9a3..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/coop_window.py +++ /dev/null @@ -1,10 +0,0 @@ -import urllib -import os.path - -def main(request, response): - coop = request.GET.first('coop') - if coop: - response.headers.set('Cross-Origin-Opener-Policy', urllib.unquote(coop)) - - path = os.path.join(os.path.dirname(__file__), request.GET.first('path')) - response.content = open(path, mode='rb').read() diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/postback.sub.html b/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/postback.sub.html deleted file mode 100644 index ee08bab4d55e..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/postback.sub.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html b/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html deleted file mode 100644 index 524efe2588d0..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html.headers deleted file mode 100644 index 34bd099a302f..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html.headers +++ /dev/null @@ -1 +0,0 @@ -Cross-Origin-Opener-Policy: same-site diff --git a/tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html b/tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html deleted file mode 100644 index ef9b9bb7b878..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html +++ /dev/null @@ -1,219 +0,0 @@ - - -Cross-Origin header and nested navigable resource without such header - - - -
- diff --git a/tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html.headers b/tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html.headers deleted file mode 100644 index a76b601291ec..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html.headers +++ /dev/null @@ -1 +0,0 @@ -Cross-Origin: anonymous diff --git a/tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html b/tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html deleted file mode 100644 index ae871c4a2735..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html +++ /dev/null @@ -1,103 +0,0 @@ - - -Cross-Origin header and nested navigable resource without such header - - - -
- diff --git a/tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html.headers b/tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html.headers deleted file mode 100644 index fd34f127d558..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html.headers +++ /dev/null @@ -1 +0,0 @@ -Cross-Origin: unknown-should-be-parsed-as-null diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_anonymous.sub.html.headers b/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_anonymous.sub.html.headers deleted file mode 100644 index a76b601291ec..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_anonymous.sub.html.headers +++ /dev/null @@ -1 +0,0 @@ -Cross-Origin: anonymous diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html b/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html deleted file mode 100644 index 1008f70ff123..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html +++ /dev/null @@ -1,18 +0,0 @@ - - diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html.headers b/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html.headers deleted file mode 100644 index a84d3782037e..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html.headers +++ /dev/null @@ -1 +0,0 @@ -Cross-Origin: use-credentials diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/nothing.txt b/tests/wpt/web-platform-tests/html/cross-origin/resources/nothing.txt deleted file mode 100644 index 9dafe9be2099..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/resources/nothing.txt +++ /dev/null @@ -1 +0,0 @@ -nothing diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/nothing.txt.headers b/tests/wpt/web-platform-tests/html/cross-origin/resources/nothing.txt.headers deleted file mode 100644 index cb762eff8068..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/resources/nothing.txt.headers +++ /dev/null @@ -1 +0,0 @@ -Access-Control-Allow-Origin: * diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html b/tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html deleted file mode 100644 index 2489fa8d2470..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html +++ /dev/null @@ -1,18 +0,0 @@ - - diff --git a/tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html.headers b/tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html.headers deleted file mode 100644 index a76b601291ec..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html.headers +++ /dev/null @@ -1 +0,0 @@ -Cross-Origin: anonymous diff --git a/tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html b/tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html deleted file mode 100644 index 55c0f2235db2..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html +++ /dev/null @@ -1,54 +0,0 @@ - - -Cross-Origin header and nested navigable resource without such header - - -
- diff --git a/tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html.headers b/tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html.headers deleted file mode 100644 index a84d3782037e..000000000000 --- a/tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html.headers +++ /dev/null @@ -1 +0,0 @@ -Cross-Origin: use-credentials diff --git a/tests/wpt/web-platform-tests/html/dom/interfaces.https.html b/tests/wpt/web-platform-tests/html/dom/interfaces.https.html index 7745e4c68e25..0d3f1160d281 100644 --- a/tests/wpt/web-platform-tests/html/dom/interfaces.https.html +++ b/tests/wpt/web-platform-tests/html/dom/interfaces.https.html @@ -223,6 +223,7 @@

HTML IDL tests

HTMLFrameElement: ['document.createElement("frame")'], HTMLDirectoryElement: ['document.createElement("dir")'], HTMLFontElement: ['document.createElement("font")'], + DOMStringList: ['location.ancestorOrigins'], }); idlArray.prevent_multiple_testing('HTMLElement'); await waitForLoad; diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.html b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.html deleted file mode 100644 index e991e19f059e..000000000000 --- a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.html +++ /dev/null @@ -1,32 +0,0 @@ - - -DOMStringList IDL tests - - - - - -

DOMStringList IDL tests

-
- - diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.worker.js b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.worker.js deleted file mode 100644 index e957b9e9b500..000000000000 --- a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.worker.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -importScripts("/resources/testharness.js"); -importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js"); - -async_test(function(t) { - var request = new XMLHttpRequest(); - request.open("GET", "/interfaces/html.idl"); - request.send(); - request.onload = t.step_func(function() { - var idlArray = new IdlArray(); - var idls = request.responseText; - - idlArray.add_idls(idls, { only: ["DOMStringList"] }); - - idlArray.add_objects({ - DOMStringList: [], - }); - idlArray.test(); - t.done(); - }); -}); - -done(); diff --git a/tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html b/tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html new file mode 100644 index 000000000000..773739804b3a --- /dev/null +++ b/tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html @@ -0,0 +1,74 @@ + + +HTML Test: tabIndex getter return value + + + + + + + + + +a +a +svg a +svg a + + + + + + + + +
+
summarysecond summarydetails
+
+
+ + + diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html new file mode 100644 index 000000000000..5f03a761dc87 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html @@ -0,0 +1,29 @@ + +Select block size when line-height is specified + + + + + + + + diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html new file mode 100644 index 000000000000..385c2a75d427 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html @@ -0,0 +1,24 @@ + +CSS Test Reference + + + + +
A
+
A
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html new file mode 100644 index 000000000000..ad504846dfa2 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html @@ -0,0 +1,23 @@ + +CSS Test Reference + + + + + + diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html new file mode 100644 index 000000000000..5dc0fc15dc52 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html @@ -0,0 +1,24 @@ + +Select block size when line-height is specified + + + + + + + diff --git a/tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html b/tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html deleted file mode 100644 index 3a9d1d9b583a..000000000000 --- a/tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - -idlharness test - - - - - - - - -

idlharness test

-

This test validates the WebIDL included in the Timing control for script-based animations specification.

- - - -
-partial interface Window {
-  long requestAnimationFrame(FrameRequestCallback callback);
-  void cancelAnimationFrame(long handle);
-};
-
-callback FrameRequestCallback = void (DOMHighResTimeStamp time);
-
- - - -
- - - diff --git a/tests/wpt/web-platform-tests/import-maps/imported/parsing-addresses.tentative.html b/tests/wpt/web-platform-tests/import-maps/imported/parsing-addresses.tentative.html new file mode 100644 index 000000000000..ddb3b724bb64 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/parsing-addresses.tentative.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/import-maps/imported/parsing-schema.tentative.html b/tests/wpt/web-platform-tests/import-maps/imported/parsing-schema.tentative.html new file mode 100644 index 000000000000..6b7c0e5b0eb4 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/parsing-schema.tentative.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/import-maps/imported/parsing-scope-keys.tentative.html b/tests/wpt/web-platform-tests/import-maps/imported/parsing-scope-keys.tentative.html new file mode 100644 index 000000000000..601ac37720d7 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/parsing-scope-keys.tentative.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/import-maps/imported/parsing-specifier-keys.tentative.html b/tests/wpt/web-platform-tests/import-maps/imported/parsing-specifier-keys.tentative.html new file mode 100644 index 000000000000..dd547f01d1df --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/parsing-specifier-keys.tentative.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resolving-builtins.tentative.html b/tests/wpt/web-platform-tests/import-maps/imported/resolving-builtins.tentative.html new file mode 100644 index 000000000000..c1395c175c77 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resolving-builtins.tentative.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resolving-not-yet-implemented.tentative.html b/tests/wpt/web-platform-tests/import-maps/imported/resolving-not-yet-implemented.tentative.html new file mode 100644 index 000000000000..7db5f29f8929 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resolving-not-yet-implemented.tentative.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resolving-scopes.tentative.html b/tests/wpt/web-platform-tests/import-maps/imported/resolving-scopes.tentative.html new file mode 100644 index 000000000000..4985249f4e29 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resolving-scopes.tentative.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resolving.tentative.html b/tests/wpt/web-platform-tests/import-maps/imported/resolving.tentative.html new file mode 100644 index 000000000000..339026259b0f --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resolving.tentative.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resources/helpers/parsing.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/helpers/parsing.js new file mode 100644 index 000000000000..5c22f6de710e --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/helpers/parsing.js @@ -0,0 +1,50 @@ +'use strict'; +const { parseFromString } = require('../../lib/parser.js'); + +// Local modifications from upstream: +// Currently warnings and scopes are not checked in expectSpecifierMap(). +exports.expectSpecifierMap = (input, baseURL, output, warnings = []) => { + expect(parseFromString(`{ "imports": ${input} }`, baseURL)) + .toEqual({ imports: output, scopes: {} }); +}; + +exports.expectScopes = (inputArray, baseURL, outputArray, warnings = []) => { + const checkWarnings = testWarningHandler(warnings); + + const inputScopesAsStrings = inputArray.map(scopePrefix => `${JSON.stringify(scopePrefix)}: {}`); + const inputString = `{ "scopes": { ${inputScopesAsStrings.join(', ')} } }`; + + const outputScopesObject = {}; + for (const outputScopePrefix of outputArray) { + outputScopesObject[outputScopePrefix] = {}; + } + + expect(parseFromString(inputString, baseURL)).toEqual({ imports: {}, scopes: outputScopesObject }); + + checkWarnings(); +}; + +exports.expectBad = (input, baseURL, warnings = []) => { + const checkWarnings = testWarningHandler(warnings); + expect(() => parseFromString(input, baseURL)).toThrow(TypeError); + checkWarnings(); +}; + +exports.expectWarnings = (input, baseURL, output, warnings = []) => { + const checkWarnings = testWarningHandler(warnings); + expect(parseFromString(input, baseURL)).toEqual(output); + + checkWarnings(); +}; + +function testWarningHandler(expectedWarnings) { + const warnings = []; + const { warn } = console; + console.warn = warning => { + warnings.push(warning); + }; + return () => { + console.warn = warn; + expect(warnings).toEqual(expectedWarnings); + }; +} diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-addresses.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-addresses.js new file mode 100644 index 000000000000..0f5fc73506b1 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-addresses.js @@ -0,0 +1,351 @@ +'use strict'; +const { expectSpecifierMap } = require('./helpers/parsing.js'); +const { BUILT_IN_MODULE_SCHEME } = require('../lib/utils.js'); + +describe('Relative URL-like addresses', () => { + it('should accept strings prefixed with ./, ../, or /', () => { + expectSpecifierMap( + `{ + "dotSlash": "./foo", + "dotDotSlash": "../foo", + "slash": "/foo" + }`, + 'https://base.example/path1/path2/path3', + { + dotSlash: [expect.toMatchURL('https://base.example/path1/path2/foo')], + dotDotSlash: [expect.toMatchURL('https://base.example/path1/foo')], + slash: [expect.toMatchURL('https://base.example/foo')] + } + ); + }); + + it('should not accept strings prefixed with ./, ../, or / for data: base URLs', () => { + expectSpecifierMap( + `{ + "dotSlash": "./foo", + "dotDotSlash": "../foo", + "slash": "/foo" + }`, + 'data:text/html,test', + { + dotSlash: [], + dotDotSlash: [], + slash: [] + }, + [ + `Invalid address "./foo" for the specifier key "dotSlash".`, + `Invalid address "../foo" for the specifier key "dotDotSlash".`, + `Invalid address "/foo" for the specifier key "slash".` + ] + ); + }); + + it('should accept the literal strings ./, ../, or / with no suffix', () => { + expectSpecifierMap( + `{ + "dotSlash": "./", + "dotDotSlash": "../", + "slash": "/" + }`, + 'https://base.example/path1/path2/path3', + { + dotSlash: [expect.toMatchURL('https://base.example/path1/path2/')], + dotDotSlash: [expect.toMatchURL('https://base.example/path1/')], + slash: [expect.toMatchURL('https://base.example/')] + } + ); + }); + + it('should ignore percent-encoded variants of ./, ../, or /', () => { + expectSpecifierMap( + `{ + "dotSlash1": "%2E/", + "dotDotSlash1": "%2E%2E/", + "dotSlash2": ".%2F", + "dotDotSlash2": "..%2F", + "slash2": "%2F", + "dotSlash3": "%2E%2F", + "dotDotSlash3": "%2E%2E%2F" + }`, + 'https://base.example/path1/path2/path3', + { + dotSlash1: [], + dotDotSlash1: [], + dotSlash2: [], + dotDotSlash2: [], + slash2: [], + dotSlash3: [], + dotDotSlash3: [] + }, + [ + `Invalid address "%2E/" for the specifier key "dotSlash1".`, + `Invalid address "%2E%2E/" for the specifier key "dotDotSlash1".`, + `Invalid address ".%2F" for the specifier key "dotSlash2".`, + `Invalid address "..%2F" for the specifier key "dotDotSlash2".`, + `Invalid address "%2F" for the specifier key "slash2".`, + `Invalid address "%2E%2F" for the specifier key "dotSlash3".`, + `Invalid address "%2E%2E%2F" for the specifier key "dotDotSlash3".` + ] + ); + }); +}); + +describe('Built-in module addresses', () => { + it('should accept URLs using the built-in module scheme', () => { + expectSpecifierMap( + `{ + "foo": "${BUILT_IN_MODULE_SCHEME}:foo" + }`, + 'https://base.example/path1/path2/path3', + { + foo: [expect.toMatchURL(`${BUILT_IN_MODULE_SCHEME}:foo`)] + } + ); + }); + + it('should ignore percent-encoded variants of the built-in module scheme', () => { + expectSpecifierMap( + `{ + "foo": "${encodeURIComponent(BUILT_IN_MODULE_SCHEME + ':')}foo" + }`, + 'https://base.example/path1/path2/path3', + { + foo: [] + }, + [`Invalid address "${encodeURIComponent(BUILT_IN_MODULE_SCHEME + ':')}foo" for the specifier key "foo".`] + ); + }); + + it('should allow built-in module URLs that contain "/" or "\\"', () => { + expectSpecifierMap( + `{ + "slashEnd": "${BUILT_IN_MODULE_SCHEME}:foo/", + "slashMiddle": "${BUILT_IN_MODULE_SCHEME}:foo/bar", + "backslash": "${BUILT_IN_MODULE_SCHEME}:foo\\\\baz" + }`, + 'https://base.example/path1/path2/path3', + { + slashEnd: [expect.toMatchURL(`${BUILT_IN_MODULE_SCHEME}:foo/`)], + slashMiddle: [expect.toMatchURL(`${BUILT_IN_MODULE_SCHEME}:foo/bar`)], + backslash: [expect.toMatchURL(`${BUILT_IN_MODULE_SCHEME}:foo\\baz`)] + } + ); + }); +}); + +describe('Absolute URL addresses', () => { + it('should only accept absolute URL addresses with fetch schemes', () => { + expectSpecifierMap( + `{ + "about": "about:good", + "blob": "blob:good", + "data": "data:good", + "file": "file:///good", + "filesystem": "filesystem:good", + "http": "http://good/", + "https": "https://good/", + "ftp": "ftp://good/", + "import": "import:bad", + "mailto": "mailto:bad", + "javascript": "javascript:bad", + "wss": "wss:bad" + }`, + 'https://base.example/path1/path2/path3', + { + about: [expect.toMatchURL('about:good')], + blob: [expect.toMatchURL('blob:good')], + data: [expect.toMatchURL('data:good')], + file: [expect.toMatchURL('file:///good')], + filesystem: [expect.toMatchURL('filesystem:good')], + http: [expect.toMatchURL('http://good/')], + https: [expect.toMatchURL('https://good/')], + ftp: [expect.toMatchURL('ftp://good/')], + import: [], + mailto: [], + javascript: [], + wss: [] + }, + [ + `Invalid address "import:bad" for the specifier key "import".`, + `Invalid address "mailto:bad" for the specifier key "mailto".`, + `Invalid address "javascript:bad" for the specifier key "javascript".`, + `Invalid address "wss:bad" for the specifier key "wss".` + ] + ); + }); + + it('should only accept absolute URL addresses with fetch schemes inside arrays', () => { + expectSpecifierMap( + `{ + "about": ["about:good"], + "blob": ["blob:good"], + "data": ["data:good"], + "file": ["file:///good"], + "filesystem": ["filesystem:good"], + "http": ["http://good/"], + "https": ["https://good/"], + "ftp": ["ftp://good/"], + "import": ["import:bad"], + "mailto": ["mailto:bad"], + "javascript": ["javascript:bad"], + "wss": ["wss:bad"] + }`, + 'https://base.example/path1/path2/path3', + { + about: [expect.toMatchURL('about:good')], + blob: [expect.toMatchURL('blob:good')], + data: [expect.toMatchURL('data:good')], + file: [expect.toMatchURL('file:///good')], + filesystem: [expect.toMatchURL('filesystem:good')], + http: [expect.toMatchURL('http://good/')], + https: [expect.toMatchURL('https://good/')], + ftp: [expect.toMatchURL('ftp://good/')], + import: [], + mailto: [], + javascript: [], + wss: [] + }, + [ + `Invalid address "import:bad" for the specifier key "import".`, + `Invalid address "mailto:bad" for the specifier key "mailto".`, + `Invalid address "javascript:bad" for the specifier key "javascript".`, + `Invalid address "wss:bad" for the specifier key "wss".` + ] + ); + }); + + it('should parse absolute URLs, ignoring unparseable ones', () => { + expectSpecifierMap( + `{ + "unparseable1": "https://ex ample.org/", + "unparseable2": "https://example.com:demo", + "unparseable3": "http://[www.example.com]/", + "invalidButParseable1": "https:example.org", + "invalidButParseable2": "https://///example.com///", + "prettyNormal": "https://example.net", + "percentDecoding": "https://ex%41mple.com/", + "noPercentDecoding": "https://example.com/%41" + }`, + 'https://base.example/path1/path2/path3', + { + unparseable1: [], + unparseable2: [], + unparseable3: [], + invalidButParseable1: [expect.toMatchURL('https://example.org/')], + invalidButParseable2: [expect.toMatchURL('https://example.com///')], + prettyNormal: [expect.toMatchURL('https://example.net/')], + percentDecoding: [expect.toMatchURL('https://example.com/')], + noPercentDecoding: [expect.toMatchURL('https://example.com/%41')] + }, + [ + `Invalid address "https://ex ample.org/" for the specifier key "unparseable1".`, + `Invalid address "https://example.com:demo" for the specifier key "unparseable2".`, + `Invalid address "http://[www.example.com]/" for the specifier key "unparseable3".` + ] + ); + }); + + it('should parse absolute URLs, ignoring unparseable ones inside arrays', () => { + expectSpecifierMap( + `{ + "unparseable1": ["https://ex ample.org/"], + "unparseable2": ["https://example.com:demo"], + "unparseable3": ["http://[www.example.com]/"], + "invalidButParseable1": ["https:example.org"], + "invalidButParseable2": ["https://///example.com///"], + "prettyNormal": ["https://example.net"], + "percentDecoding": ["https://ex%41mple.com/"], + "noPercentDecoding": ["https://example.com/%41"] + }`, + 'https://base.example/path1/path2/path3', + { + unparseable1: [], + unparseable2: [], + unparseable3: [], + invalidButParseable1: [expect.toMatchURL('https://example.org/')], + invalidButParseable2: [expect.toMatchURL('https://example.com///')], + prettyNormal: [expect.toMatchURL('https://example.net/')], + percentDecoding: [expect.toMatchURL('https://example.com/')], + noPercentDecoding: [expect.toMatchURL('https://example.com/%41')] + }, + [ + `Invalid address "https://ex ample.org/" for the specifier key "unparseable1".`, + `Invalid address "https://example.com:demo" for the specifier key "unparseable2".`, + `Invalid address "http://[www.example.com]/" for the specifier key "unparseable3".` + ] + ); + }); +}); + +describe('Failing addresses: mismatched trailing slashes', () => { + it('should warn for the simple case', () => { + expectSpecifierMap( + `{ + "trailer/": "/notrailer", + "${BUILT_IN_MODULE_SCHEME}:trailer/": "/bim-notrailer" + }`, + 'https://base.example/path1/path2/path3', + { + 'trailer/': [], + [`${BUILT_IN_MODULE_SCHEME}:trailer/`]: [] + }, + [ + `Invalid address "https://base.example/notrailer" for package specifier key "trailer/". Package addresses must end with "/".`, + `Invalid address "https://base.example/bim-notrailer" for package specifier key "${BUILT_IN_MODULE_SCHEME}:trailer/". Package addresses must end with "/".` + ] + ); + }); + + it('should warn for a mismatch alone in an array', () => { + expectSpecifierMap( + `{ + "trailer/": ["/notrailer"], + "${BUILT_IN_MODULE_SCHEME}:trailer/": ["/bim-notrailer"] + }`, + 'https://base.example/path1/path2/path3', + { + 'trailer/': [], + [`${BUILT_IN_MODULE_SCHEME}:trailer/`]: [] + }, + [ + `Invalid address "https://base.example/notrailer" for package specifier key "trailer/". Package addresses must end with "/".`, + `Invalid address "https://base.example/bim-notrailer" for package specifier key "${BUILT_IN_MODULE_SCHEME}:trailer/". Package addresses must end with "/".` + ] + ); + }); + + it('should warn for a mismatch alongside non-mismatches in an array', () => { + expectSpecifierMap( + `{ + "trailer/": ["/atrailer/", "/notrailer"], + "${BUILT_IN_MODULE_SCHEME}:trailer/": ["/bim-atrailer/", "/bim-notrailer"] + }`, + 'https://base.example/path1/path2/path3', + { + 'trailer/': [expect.toMatchURL('https://base.example/atrailer/')], + [`${BUILT_IN_MODULE_SCHEME}:trailer/`]: [expect.toMatchURL('https://base.example/bim-atrailer/')] + }, + [ + `Invalid address "https://base.example/notrailer" for package specifier key "trailer/". Package addresses must end with "/".`, + `Invalid address "https://base.example/bim-notrailer" for package specifier key "${BUILT_IN_MODULE_SCHEME}:trailer/". Package addresses must end with "/".` + ] + ); + }); +}); + +describe('Other invalid addresses', () => { + it('should ignore unprefixed strings that are not absolute URLs', () => { + for (const bad of ['bar', '\\bar', '~bar', '#bar', '?bar']) { + expectSpecifierMap( + `{ + "foo": ${JSON.stringify(bad)} + }`, + 'https://base.example/path1/path2/path3', + { + foo: [] + }, + [`Invalid address "${bad}" for the specifier key "foo".`] + ); + } + }); +}); diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-schema.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-schema.js new file mode 100644 index 000000000000..695034533c7f --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-schema.js @@ -0,0 +1,139 @@ +'use strict'; +const { parseFromString } = require('../lib/parser.js'); +const { expectBad, expectWarnings, expectSpecifierMap } = require('./helpers/parsing.js'); + +const nonObjectStrings = ['null', 'true', '1', '"foo"', '[]']; + +test('Invalid JSON', () => { + expect(() => parseFromString('{ imports: {} }', 'https://base.example/')).toThrow(SyntaxError); +}); + +describe('Mismatching the top-level schema', () => { + it('should throw for top-level non-objects', () => { + for (const nonObject of nonObjectStrings) { + expectBad(nonObject, 'https://base.example/'); + } + }); + + it('should throw if imports is a non-object', () => { + for (const nonObject of nonObjectStrings) { + expectBad(`{ "imports": ${nonObject} }`, 'https://base.example/'); + } + }); + + it('should throw if scopes is a non-object', () => { + for (const nonObject of nonObjectStrings) { + expectBad(`{ "scopes": ${nonObject} }`, 'https://base.example/'); + } + }); + + it('should ignore unspecified top-level entries', () => { + expectWarnings( + `{ + "imports": {}, + "new-feature": {}, + "scops": {} + }`, + 'https://base.example/', + { imports: {}, scopes: {} }, + [ + `Invalid top-level key "new-feature". Only "imports" and "scopes" can be present.`, + `Invalid top-level key "scops". Only "imports" and "scopes" can be present.` + ] + ); + }); +}); + +describe('Mismatching the specifier map schema', () => { + const invalidAddressStrings = ['true', '1', '{}']; + const invalidInsideArrayStrings = ['null', 'true', '1', '{}', '[]']; + + it('should ignore entries where the address is not a string, array, or null', () => { + for (const invalid of invalidAddressStrings) { + expectSpecifierMap( + `{ + "foo": ${invalid}, + "bar": ["https://example.com/"] + }`, + 'https://base.example/', + { + bar: [expect.toMatchURL('https://example.com/')] + }, + [ + `Invalid address ${invalid} for the specifier key "foo". ` + + `Addresses must be strings, arrays, or null.` + ] + ); + } + }); + + it('should ignore entries where the specifier key is an empty string', () => { + expectSpecifierMap( + `{ + "": ["https://example.com/"] + }`, + 'https://base.example/', + {}, + [`Invalid empty string specifier key.`] + ); + }); + + it('should ignore members of an address array that are not strings', () => { + for (const invalid of invalidInsideArrayStrings) { + expectSpecifierMap( + `{ + "foo": ["https://example.com/", ${invalid}], + "bar": ["https://example.com/"] + }`, + 'https://base.example/', + { + foo: [expect.toMatchURL('https://example.com/')], + bar: [expect.toMatchURL('https://example.com/')] + }, + [ + `Invalid address ${invalid} inside the address array for the specifier key "foo". ` + + `Address arrays must only contain strings.` + ] + ); + } + }); + + it('should throw if a scope\'s value is not an object', () => { + for (const invalid of nonObjectStrings) { + expectBad(`{ "scopes": { "https://scope.example/": ${invalid} } }`, 'https://base.example/'); + } + }); +}); + +describe('Normalization', () => { + it('should normalize empty import maps to have imports and scopes keys', () => { + expect(parseFromString(`{}`, 'https://base.example/')) + .toEqual({ imports: {}, scopes: {} }); + }); + + it('should normalize an import map without imports to have imports', () => { + expect(parseFromString(`{ "scopes": {} }`, 'https://base.example/')) + .toEqual({ imports: {}, scopes: {} }); + }); + + it('should normalize an import map without scopes to have scopes', () => { + expect(parseFromString(`{ "imports": {} }`, 'https://base.example/')) + .toEqual({ imports: {}, scopes: {} }); + }); + + it('should normalize addresses to arrays', () => { + expectSpecifierMap( + `{ + "foo": "https://example.com/1", + "bar": ["https://example.com/2"], + "baz": null + }`, + 'https://base.example/', + { + foo: [expect.toMatchURL('https://example.com/1')], + bar: [expect.toMatchURL('https://example.com/2')], + baz: [] + } + ); + }); +}); diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-scope-keys.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-scope-keys.js new file mode 100644 index 000000000000..cd1d9b348909 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-scope-keys.js @@ -0,0 +1,145 @@ +'use strict'; +const { expectScopes } = require('./helpers/parsing.js'); + +describe('Relative URL scope keys', () => { + it('should work with no prefix', () => { + expectScopes( + ['foo'], + 'https://base.example/path1/path2/path3', + ['https://base.example/path1/path2/foo'] + ); + }); + + it('should work with ./, ../, and / prefixes', () => { + expectScopes( + ['./foo', '../foo', '/foo'], + 'https://base.example/path1/path2/path3', + [ + 'https://base.example/path1/path2/foo', + 'https://base.example/path1/foo', + 'https://base.example/foo' + ] + ); + }); + + it('should work with /s, ?s, and #s', () => { + expectScopes( + ['foo/bar?baz#qux'], + 'https://base.example/path1/path2/path3', + ['https://base.example/path1/path2/foo/bar?baz#qux'] + ); + }); + + it('should work with an empty string scope key', () => { + expectScopes( + [''], + 'https://base.example/path1/path2/path3', + ['https://base.example/path1/path2/path3'] + ); + }); + + it('should work with / suffixes', () => { + expectScopes( + ['foo/', './foo/', '../foo/', '/foo/', '/foo//'], + 'https://base.example/path1/path2/path3', + [ + 'https://base.example/path1/path2/foo/', + 'https://base.example/path1/path2/foo/', + 'https://base.example/path1/foo/', + 'https://base.example/foo/', + 'https://base.example/foo//' + ] + ); + }); + + it('should deduplicate based on URL parsing rules', () => { + expectScopes( + ['foo/\\', 'foo//', 'foo\\\\'], + 'https://base.example/path1/path2/path3', + ['https://base.example/path1/path2/foo//'] + ); + }); +}); + +describe('Absolute URL scope keys', () => { + it('should only accept absolute URL scope keys with fetch schemes', () => { + expectScopes( + [ + 'about:good', + 'blob:good', + 'data:good', + 'file:///good', + 'filesystem:good', + 'http://good/', + 'https://good/', + 'ftp://good/', + 'import:bad', + 'mailto:bad', + 'javascript:bad', + 'wss:ba' + ], + 'https://base.example/path1/path2/path3', + [ + 'about:good', + 'blob:good', + 'data:good', + 'file:///good', + 'filesystem:good', + 'http://good/', + 'https://good/', + 'ftp://good/' + ], + [ + 'Invalid scope "import:bad". Scope URLs must have a fetch scheme.', + 'Invalid scope "mailto:bad". Scope URLs must have a fetch scheme.', + 'Invalid scope "javascript:bad". Scope URLs must have a fetch scheme.', + 'Invalid scope "wss://ba/". Scope URLs must have a fetch scheme.' + ] + ); + }); + + it('should parse absolute URL scope keys, ignoring unparseable ones', () => { + expectScopes( + [ + 'https://ex ample.org/', + 'https://example.com:demo', + 'http://[www.example.com]/', + 'https:example.org', + 'https://///example.com///', + 'https://example.net', + 'https://ex%41mple.com/foo/', + 'https://example.com/%41' + ], + 'https://base.example/path1/path2/path3', + [ + 'https://base.example/path1/path2/example.org', // tricky case! remember we have a base URL + 'https://example.com///', + 'https://example.net/', + 'https://example.com/foo/', + 'https://example.com/%41' + ], + [ + 'Invalid scope "https://ex ample.org/" (parsed against base URL "https://base.example/path1/path2/path3").', + 'Invalid scope "https://example.com:demo" (parsed against base URL "https://base.example/path1/path2/path3").', + 'Invalid scope "http://[www.example.com]/" (parsed against base URL "https://base.example/path1/path2/path3").' + ] + ); + }); + + it('should ignore relative URL scope keys when the base URL is a data: URL', () => { + expectScopes( + [ + './foo', + '../foo', + '/foo' + ], + 'data:text/html,test', + [], + [ + 'Invalid scope "./foo" (parsed against base URL "data:text/html,test").', + 'Invalid scope "../foo" (parsed against base URL "data:text/html,test").', + 'Invalid scope "/foo" (parsed against base URL "data:text/html,test").' + ] + ); + }); +}); diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-specifier-keys.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-specifier-keys.js new file mode 100644 index 000000000000..9eb423a19eb1 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-specifier-keys.js @@ -0,0 +1,159 @@ +'use strict'; +const { expectSpecifierMap } = require('./helpers/parsing.js'); +const { BUILT_IN_MODULE_SCHEME } = require('../lib/utils.js'); + +const BLANK = `${BUILT_IN_MODULE_SCHEME}:blank`; + +describe('Relative URL-like specifier keys', () => { + it('should absolutize strings prefixed with ./, ../, or / into the corresponding URLs', () => { + expectSpecifierMap( + `{ + "./foo": "/dotslash", + "../foo": "/dotdotslash", + "/foo": "/slash" + }`, + 'https://base.example/path1/path2/path3', + { + 'https://base.example/path1/path2/foo': [expect.toMatchURL('https://base.example/dotslash')], + 'https://base.example/path1/foo': [expect.toMatchURL('https://base.example/dotdotslash')], + 'https://base.example/foo': [expect.toMatchURL('https://base.example/slash')] + } + ); + }); + + it('should not absolutize strings prefixed with ./, ../, or / with a data: URL base', () => { + expectSpecifierMap( + `{ + "./foo": "https://example.com/dotslash", + "../foo": "https://example.com/dotdotslash", + "/foo": "https://example.com/slash" + }`, + 'data:text/html,test', + { + './foo': [expect.toMatchURL('https://example.com/dotslash')], + '../foo': [expect.toMatchURL('https://example.com/dotdotslash')], + '/foo': [expect.toMatchURL('https://example.com/slash')] + } + ); + }); + + it('should absolutize the literal strings ./, ../, or / with no suffix', () => { + expectSpecifierMap( + `{ + "./": "/dotslash/", + "../": "/dotdotslash/", + "/": "/slash/" + }`, + 'https://base.example/path1/path2/path3', + { + 'https://base.example/path1/path2/': [expect.toMatchURL('https://base.example/dotslash/')], + 'https://base.example/path1/': [expect.toMatchURL('https://base.example/dotdotslash/')], + 'https://base.example/': [expect.toMatchURL('https://base.example/slash/')] + } + ); + }); + + it('should treat percent-encoded variants of ./, ../, or / as bare specifiers', () => { + expectSpecifierMap( + `{ + "%2E/": "/dotSlash1/", + "%2E%2E/": "/dotDotSlash1/", + ".%2F": "/dotSlash2", + "..%2F": "/dotDotSlash2", + "%2F": "/slash2", + "%2E%2F": "/dotSlash3", + "%2E%2E%2F": "/dotDotSlash3" + }`, + 'https://base.example/path1/path2/path3', + { + '%2E/': [expect.toMatchURL('https://base.example/dotSlash1/')], + '%2E%2E/': [expect.toMatchURL('https://base.example/dotDotSlash1/')], + '.%2F': [expect.toMatchURL('https://base.example/dotSlash2')], + '..%2F': [expect.toMatchURL('https://base.example/dotDotSlash2')], + '%2F': [expect.toMatchURL('https://base.example/slash2')], + '%2E%2F': [expect.toMatchURL('https://base.example/dotSlash3')], + '%2E%2E%2F': [expect.toMatchURL('https://base.example/dotDotSlash3')] + } + ); + }); +}); + +describe('Absolute URL specifier keys', () => { + it('should only accept absolute URL specifier keys with fetch schemes, treating others as bare specifiers', () => { + expectSpecifierMap( + `{ + "about:good": "/about", + "blob:good": "/blob", + "data:good": "/data", + "file:///good": "/file", + "filesystem:good": "/filesystem", + "http://good/": "/http/", + "https://good/": "/https/", + "ftp://good/": "/ftp/", + "import:bad": "/import", + "mailto:bad": "/mailto", + "javascript:bad": "/javascript", + "wss:bad": "/wss" + }`, + 'https://base.example/path1/path2/path3', + { + 'about:good': [expect.toMatchURL('https://base.example/about')], + 'blob:good': [expect.toMatchURL('https://base.example/blob')], + 'data:good': [expect.toMatchURL('https://base.example/data')], + 'file:///good': [expect.toMatchURL('https://base.example/file')], + 'filesystem:good': [expect.toMatchURL('https://base.example/filesystem')], + 'http://good/': [expect.toMatchURL('https://base.example/http/')], + 'https://good/': [expect.toMatchURL('https://base.example/https/')], + 'ftp://good/': [expect.toMatchURL('https://base.example/ftp/')], + 'import:bad': [expect.toMatchURL('https://base.example/import')], + 'mailto:bad': [expect.toMatchURL('https://base.example/mailto')], + 'javascript:bad': [expect.toMatchURL('https://base.example/javascript')], + 'wss:bad': [expect.toMatchURL('https://base.example/wss')] + } + ); + }); + + it('should parse absolute URLs, treating unparseable ones as bare specifiers', () => { + expectSpecifierMap( + `{ + "https://ex ample.org/": "/unparseable1/", + "https://example.com:demo": "/unparseable2", + "http://[www.example.com]/": "/unparseable3/", + "https:example.org": "/invalidButParseable1/", + "https://///example.com///": "/invalidButParseable2/", + "https://example.net": "/prettyNormal/", + "https://ex%41mple.com/": "/percentDecoding/", + "https://example.com/%41": "/noPercentDecoding" + }`, + 'https://base.example/path1/path2/path3', + { + 'https://ex ample.org/': [expect.toMatchURL('https://base.example/unparseable1/')], + 'https://example.com:demo': [expect.toMatchURL('https://base.example/unparseable2')], + 'http://[www.example.com]/': [expect.toMatchURL('https://base.example/unparseable3/')], + 'https://example.org/': [expect.toMatchURL('https://base.example/invalidButParseable1/')], + 'https://example.com///': [expect.toMatchURL('https://base.example/invalidButParseable2/')], + 'https://example.net/': [expect.toMatchURL('https://base.example/prettyNormal/')], + 'https://example.com/': [expect.toMatchURL('https://base.example/percentDecoding/')], + 'https://example.com/%41': [expect.toMatchURL('https://base.example/noPercentDecoding')] + } + ); + }); + + it('should parse built-in module specifier keys, including with a "/"', () => { + expectSpecifierMap( + `{ + "${BLANK}": "/blank", + "${BLANK}/": "/blank/", + "${BLANK}/foo": "/blank/foo", + "${BLANK}\\\\foo": "/blank/backslashfoo" + }`, + 'https://base.example/path1/path2/path3', + { + [BLANK]: [expect.toMatchURL('https://base.example/blank')], + [`${BLANK}/`]: [expect.toMatchURL('https://base.example/blank/')], + [`${BLANK}/foo`]: [expect.toMatchURL('https://base.example/blank/foo')], + [`${BLANK}\\foo`]: [expect.toMatchURL('https://base.example/blank/backslashfoo')] + } + ); + }); +}); diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-builtins.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-builtins.js new file mode 100644 index 000000000000..a9383df843d4 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-builtins.js @@ -0,0 +1,158 @@ +'use strict'; +const { URL } = require('url'); +const { parseFromString } = require('../lib/parser.js'); +const { resolve } = require('../lib/resolver.js'); +const { BUILT_IN_MODULE_SCHEME } = require('../lib/utils.js'); + +const mapBaseURL = new URL('https://example.com/app/index.html'); +const scriptURL = new URL('https://example.com/js/app.mjs'); + +const BLANK = `${BUILT_IN_MODULE_SCHEME}:blank`; +const NONE = `${BUILT_IN_MODULE_SCHEME}:none`; + +function makeResolveUnderTest(mapString) { + const map = parseFromString(mapString, mapBaseURL); + return specifier => resolve(specifier, map, scriptURL); +} + +describe('Unmapped built-in module specifiers', () => { + const resolveUnderTest = makeResolveUnderTest(`{}`); + + it(`should resolve "${BLANK}" to "${BLANK}"`, () => { + expect(resolveUnderTest(BLANK)).toMatchURL(BLANK); + }); + + it(`should error resolving "${NONE}"`, () => { + expect(() => resolveUnderTest(NONE)).toThrow(TypeError); + }); +}); + +describe('Remapping built-in module specifiers', () => { + it('should remap built-in modules', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "${BLANK}": "./blank.mjs", + "${NONE}": "./none.mjs" + } + }`); + + expect(resolveUnderTest(BLANK)).toMatchURL('https://example.com/app/blank.mjs'); + expect(resolveUnderTest(NONE)).toMatchURL('https://example.com/app/none.mjs'); + }); + + it('should remap built-in modules with slashes', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "${BLANK}/": "./blank-slash/", + "${BLANK}/foo": "./blank-foo.mjs", + "${NONE}/": "./none-slash/", + "${NONE}/foo": "./none-foo.mjs" + } + }`); + + expect(resolveUnderTest(`${BLANK}/`)).toMatchURL('https://example.com/app/blank-slash/'); + expect(resolveUnderTest(`${BLANK}/foo`)).toMatchURL('https://example.com/app/blank-foo.mjs'); + expect(resolveUnderTest(`${BLANK}/bar`)).toMatchURL('https://example.com/app/blank-slash/bar'); + expect(resolveUnderTest(`${NONE}/`)).toMatchURL('https://example.com/app/none-slash/'); + expect(resolveUnderTest(`${NONE}/foo`)).toMatchURL('https://example.com/app/none-foo.mjs'); + expect(resolveUnderTest(`${NONE}/bar`)).toMatchURL('https://example.com/app/none-slash/bar'); + }); + + it('should remap built-in modules with fallbacks', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "${BLANK}": ["${BLANK}", "./blank.mjs"], + "${NONE}": ["${NONE}", "./none.mjs"] + } + }`); + + expect(resolveUnderTest(BLANK)).toMatchURL(BLANK); + expect(resolveUnderTest(NONE)).toMatchURL('https://example.com/app/none.mjs'); + }); + + it('should remap built-in modules with slashes and fallbacks', () => { + // NOTE: `${BLANK}/for-testing` is not per spec, just for these tests. + // See resolver.js. + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "${BLANK}/": ["${BLANK}/", "./blank/"], + "${BLANK}/for-testing": ["${BLANK}/for-testing", "./blank-for-testing-special"], + "${NONE}/": ["${NONE}/", "./none/"], + "${NONE}/foo": ["${NONE}/foo", "./none-foo-special"] + } + }`); + + // Built-in modules only resolve for exact matches, so this will trigger the fallback. + expect(resolveUnderTest(`${BLANK}/`)).toMatchURL('https://example.com/app/blank/'); + expect(resolveUnderTest(`${BLANK}/foo`)).toMatchURL('https://example.com/app/blank/foo'); + + // This would fall back in a real implementation; it's only because we've gone against + // spec in the reference implementation (to make this testable) that this maps. + expect(resolveUnderTest(`${BLANK}/for-testing`)).toMatchURL(`${BLANK}/for-testing`); + + expect(resolveUnderTest(`${NONE}/`)).toMatchURL('https://example.com/app/none/'); + expect(resolveUnderTest(`${NONE}/bar`)).toMatchURL('https://example.com/app/none/bar'); + expect(resolveUnderTest(`${NONE}/foo`)).toMatchURL('https://example.com/app/none-foo-special'); + }); +}); + +describe('Remapping to built-in modules', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "blank": "${BLANK}", + "/blank": "${BLANK}", + "/blank/": "${BLANK}/", + "/blank-for-testing": "${BLANK}/for-testing", + "none": "${NONE}", + "/none": "${NONE}" + } + }`); + + it(`should remap to "${BLANK}"`, () => { + expect(resolveUnderTest('blank')).toMatchURL(BLANK); + expect(resolveUnderTest('/blank')).toMatchURL(BLANK); + }); + + it(`should fail when remapping to "${BLANK}/"`, () => { + expect(() => resolveUnderTest('/blank/')).toThrow(TypeError); + }); + + it(`should remap to "${BLANK}/for-testing"`, () => { + expect(resolveUnderTest('/blank/for-testing')).toMatchURL(`${BLANK}/for-testing`); + expect(resolveUnderTest('/blank-for-testing')).toMatchURL(`${BLANK}/for-testing`); + }); + + it(`should remap to "${BLANK}" for URL-like specifiers`, () => { + expect(resolveUnderTest('/blank')).toMatchURL(BLANK); + expect(resolveUnderTest('https://example.com/blank')).toMatchURL(BLANK); + expect(resolveUnderTest('https://///example.com/blank')).toMatchURL(BLANK); + }); + + it(`should fail when remapping to "${NONE}"`, () => { + expect(() => resolveUnderTest('none')).toThrow(TypeError); + expect(() => resolveUnderTest('/none')).toThrow(TypeError); + }); +}); + +describe('Fallbacks with built-in module addresses', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "blank": [ + "${BLANK}", + "./blank-fallback.mjs" + ], + "none": [ + "${NONE}", + "./none-fallback.mjs" + ] + } + }`); + + it(`should resolve to "${BLANK}"`, () => { + expect(resolveUnderTest('blank')).toMatchURL(BLANK); + }); + + it(`should fall back past "${NONE}"`, () => { + expect(resolveUnderTest('none')).toMatchURL('https://example.com/app/none-fallback.mjs'); + }); +}); diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-not-yet-implemented.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-not-yet-implemented.js new file mode 100644 index 000000000000..93d782fdad83 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-not-yet-implemented.js @@ -0,0 +1,47 @@ +'use strict'; +const { URL } = require('url'); +const { parseFromString } = require('../lib/parser.js'); +const { resolve } = require('../lib/resolver.js'); +const { BUILT_IN_MODULE_SCHEME } = require('../lib/utils.js'); + +const mapBaseURL = new URL('https://example.com/app/index.html'); +const scriptURL = new URL('https://example.com/js/app.mjs'); + +const BLANK = `${BUILT_IN_MODULE_SCHEME}:blank`; + +function makeResolveUnderTest(mapString) { + const map = parseFromString(mapString, mapBaseURL); + return specifier => resolve(specifier, map, scriptURL); +} + +describe('Fallbacks that are not [built-in, fetch scheme]', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "bad1": [ + "${BLANK}", + "${BLANK}" + ], + "bad2": [ + "${BLANK}", + "/bad2-1.mjs", + "/bad2-2.mjs" + ], + "bad3": [ + "/bad3-1.mjs", + "/bad3-2.mjs" + ] + } + }`); + + it('should fail for [built-in, built-in]', () => { + expect(() => resolveUnderTest('bad1')).toThrow(/not yet implemented/); + }); + + it('should fail for [built-in, fetch scheme, fetch scheme]', () => { + expect(() => resolveUnderTest('bad2')).toThrow(/not yet implemented/); + }); + + it('should fail for [fetch scheme, fetch scheme]', () => { + expect(() => resolveUnderTest('bad3')).toThrow(/not yet implemented/); + }); +}); diff --git a/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-scopes.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-scopes.js new file mode 100644 index 000000000000..ca19a6684060 --- /dev/null +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-scopes.js @@ -0,0 +1,230 @@ +'use strict'; +const { URL } = require('url'); +const { parseFromString } = require('../lib/parser.js'); +const { resolve } = require('../lib/resolver.js'); + +const mapBaseURL = new URL('https://example.com/app/index.html'); + +function makeResolveUnderTest(mapString) { + const map = parseFromString(mapString, mapBaseURL); + return (specifier, baseURL) => resolve(specifier, map, baseURL); +} + +describe('Mapped using scope instead of "imports"', () => { + const jsNonDirURL = new URL('https://example.com/js'); + const jsPrefixedURL = new URL('https://example.com/jsiscool'); + const inJSDirURL = new URL('https://example.com/js/app.mjs'); + const topLevelURL = new URL('https://example.com/app.mjs'); + + it('should fail when the mapping is to an empty array', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "scopes": { + "/js/": { + "moment": null, + "lodash": [] + } + } + }`); + + expect(() => resolveUnderTest('moment', inJSDirURL)).toThrow(TypeError); + expect(() => resolveUnderTest('lodash', inJSDirURL)).toThrow(TypeError); + }); + + describe('Exact vs. prefix based matching', () => { + it('should match correctly when both are in the map', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "scopes": { + "/js": { + "moment": "/only-triggered-by-exact/moment", + "moment/": "/only-triggered-by-exact/moment/" + }, + "/js/": { + "moment": "/triggered-by-any-subpath/moment", + "moment/": "/triggered-by-any-subpath/moment/" + } + } + }`); + + expect(resolveUnderTest('moment', jsNonDirURL)).toMatchURL('https://example.com/only-triggered-by-exact/moment'); + expect(resolveUnderTest('moment/foo', jsNonDirURL)).toMatchURL('https://example.com/only-triggered-by-exact/moment/foo'); + + expect(resolveUnderTest('moment', inJSDirURL)).toMatchURL('https://example.com/triggered-by-any-subpath/moment'); + expect(resolveUnderTest('moment/foo', inJSDirURL)).toMatchURL('https://example.com/triggered-by-any-subpath/moment/foo'); + + expect(() => resolveUnderTest('moment', jsPrefixedURL)).toThrow(TypeError); + expect(() => resolveUnderTest('moment/foo', jsPrefixedURL)).toThrow(TypeError); + }); + + it('should match correctly when only an exact match is in the map', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "scopes": { + "/js": { + "moment": "/only-triggered-by-exact/moment", + "moment/": "/only-triggered-by-exact/moment/" + } + } + }`); + + expect(resolveUnderTest('moment', jsNonDirURL)).toMatchURL('https://example.com/only-triggered-by-exact/moment'); + expect(resolveUnderTest('moment/foo', jsNonDirURL)).toMatchURL('https://example.com/only-triggered-by-exact/moment/foo'); + + expect(() => resolveUnderTest('moment', inJSDirURL)).toThrow(TypeError); + expect(() => resolveUnderTest('moment/foo', inJSDirURL)).toThrow(TypeError); + + expect(() => resolveUnderTest('moment', jsPrefixedURL)).toThrow(TypeError); + expect(() => resolveUnderTest('moment/foo', jsPrefixedURL)).toThrow(TypeError); + }); + + it('should match correctly when only a prefix match is in the map', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "scopes": { + "/js/": { + "moment": "/triggered-by-any-subpath/moment", + "moment/": "/triggered-by-any-subpath/moment/" + } + } + }`); + + expect(() => resolveUnderTest('moment', jsNonDirURL)).toThrow(TypeError); + expect(() => resolveUnderTest('moment/foo', jsNonDirURL)).toThrow(TypeError); + + expect(resolveUnderTest('moment', inJSDirURL)).toMatchURL('https://example.com/triggered-by-any-subpath/moment'); + expect(resolveUnderTest('moment/foo', inJSDirURL)).toMatchURL('https://example.com/triggered-by-any-subpath/moment/foo'); + + expect(() => resolveUnderTest('moment', jsPrefixedURL)).toThrow(TypeError); + expect(() => resolveUnderTest('moment/foo', jsPrefixedURL)).toThrow(TypeError); + }); + }); + + describe('Package-like scenarios', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "moment": "/node_modules/moment/src/moment.js", + "moment/": "/node_modules/moment/src/", + "lodash-dot": "./node_modules/lodash-es/lodash.js", + "lodash-dot/": "./node_modules/lodash-es/", + "lodash-dotdot": "../node_modules/lodash-es/lodash.js", + "lodash-dotdot/": "../node_modules/lodash-es/" + }, + "scopes": { + "/": { + "moment": "/node_modules_3/moment/src/moment.js", + "vue": "/node_modules_3/vue/dist/vue.runtime.esm.js" + }, + "/js/": { + "lodash-dot": "./node_modules_2/lodash-es/lodash.js", + "lodash-dot/": "./node_modules_2/lodash-es/", + "lodash-dotdot": "../node_modules_2/lodash-es/lodash.js", + "lodash-dotdot/": "../node_modules_2/lodash-es/" + } + } + }`); + + it('should resolve scoped', () => { + expect(resolveUnderTest('lodash-dot', inJSDirURL)).toMatchURL('https://example.com/app/node_modules_2/lodash-es/lodash.js'); + expect(resolveUnderTest('lodash-dotdot', inJSDirURL)).toMatchURL('https://example.com/node_modules_2/lodash-es/lodash.js'); + expect(resolveUnderTest('lodash-dot/foo', inJSDirURL)).toMatchURL('https://example.com/app/node_modules_2/lodash-es/foo'); + expect(resolveUnderTest('lodash-dotdot/foo', inJSDirURL)).toMatchURL('https://example.com/node_modules_2/lodash-es/foo'); + }); + + it('should apply best scope match', () => { + expect(resolveUnderTest('moment', topLevelURL)).toMatchURL('https://example.com/node_modules_3/moment/src/moment.js'); + expect(resolveUnderTest('moment', inJSDirURL)).toMatchURL('https://example.com/node_modules_3/moment/src/moment.js'); + expect(resolveUnderTest('vue', inJSDirURL)).toMatchURL('https://example.com/node_modules_3/vue/dist/vue.runtime.esm.js'); + }); + + it('should fallback to "imports"', () => { + expect(resolveUnderTest('moment/foo', topLevelURL)).toMatchURL('https://example.com/node_modules/moment/src/foo'); + expect(resolveUnderTest('moment/foo', inJSDirURL)).toMatchURL('https://example.com/node_modules/moment/src/foo'); + expect(resolveUnderTest('lodash-dot', topLevelURL)).toMatchURL('https://example.com/app/node_modules/lodash-es/lodash.js'); + expect(resolveUnderTest('lodash-dotdot', topLevelURL)).toMatchURL('https://example.com/node_modules/lodash-es/lodash.js'); + expect(resolveUnderTest('lodash-dot/foo', topLevelURL)).toMatchURL('https://example.com/app/node_modules/lodash-es/foo'); + expect(resolveUnderTest('lodash-dotdot/foo', topLevelURL)).toMatchURL('https://example.com/node_modules/lodash-es/foo'); + }); + + it('should still fail for package-like specifiers that are not declared', () => { + expect(() => resolveUnderTest('underscore/', inJSDirURL)).toThrow(TypeError); + expect(() => resolveUnderTest('underscore/foo', inJSDirURL)).toThrow(TypeError); + }); + }); + + describe('The scope inheritance example from the README', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "a": "/a-1.mjs", + "b": "/b-1.mjs", + "c": "/c-1.mjs" + }, + "scopes": { + "/scope2/": { + "a": "/a-2.mjs" + }, + "/scope2/scope3/": { + "b": "/b-3.mjs" + } + } + }`); + + const scope1URL = new URL('https://example.com/scope1/foo.mjs'); + const scope2URL = new URL('https://example.com/scope2/foo.mjs'); + const scope3URL = new URL('https://example.com/scope2/scope3/foo.mjs'); + + it('should fall back to "imports" when none match', () => { + expect(resolveUnderTest('a', scope1URL)).toMatchURL('https://example.com/a-1.mjs'); + expect(resolveUnderTest('b', scope1URL)).toMatchURL('https://example.com/b-1.mjs'); + expect(resolveUnderTest('c', scope1URL)).toMatchURL('https://example.com/c-1.mjs'); + }); + + it('should use a direct scope override', () => { + expect(resolveUnderTest('a', scope2URL)).toMatchURL('https://example.com/a-2.mjs'); + expect(resolveUnderTest('b', scope2URL)).toMatchURL('https://example.com/b-1.mjs'); + expect(resolveUnderTest('c', scope2URL)).toMatchURL('https://example.com/c-1.mjs'); + }); + + it('should use an indirect scope override', () => { + expect(resolveUnderTest('a', scope3URL)).toMatchURL('https://example.com/a-2.mjs'); + expect(resolveUnderTest('b', scope3URL)).toMatchURL('https://example.com/b-3.mjs'); + expect(resolveUnderTest('c', scope3URL)).toMatchURL('https://example.com/c-1.mjs'); + }); + }); + + describe('Relative URL scope keys', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "a": "/a-1.mjs", + "b": "/b-1.mjs", + "c": "/c-1.mjs" + }, + "scopes": { + "": { + "a": "/a-empty-string.mjs" + }, + "./": { + "b": "/b-dot-slash.mjs" + }, + "../": { + "c": "/c-dot-dot-slash.mjs" + } + } + }`); + const inSameDirAsMap = new URL('./foo.mjs', mapBaseURL); + const inDirAboveMap = new URL('../foo.mjs', mapBaseURL); + + it('should resolve an empty string scope using the import map URL', () => { + expect(resolveUnderTest('a', mapBaseURL)).toMatchURL('https://example.com/a-empty-string.mjs'); + expect(resolveUnderTest('a', inSameDirAsMap)).toMatchURL('https://example.com/a-1.mjs'); + }); + + it('should resolve a ./ scope using the import map URL\'s directory', () => { + expect(resolveUnderTest('b', mapBaseURL)).toMatchURL('https://example.com/b-dot-slash.mjs'); + expect(resolveUnderTest('b', inSameDirAsMap)).toMatchURL('https://example.com/b-dot-slash.mjs'); + }); + + it('should resolve a ../ scope using the import map URL\'s directory', () => { + expect(resolveUnderTest('c', mapBaseURL)).toMatchURL('https://example.com/c-dot-dot-slash.mjs'); + expect(resolveUnderTest('c', inSameDirAsMap)).toMatchURL('https://example.com/c-dot-dot-slash.mjs'); + expect(resolveUnderTest('c', inDirAboveMap)).toMatchURL('https://example.com/c-dot-dot-slash.mjs'); + }); + }); +}); + diff --git a/tests/wpt/web-platform-tests/import-maps/resources/resolving.js b/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving.js similarity index 77% rename from tests/wpt/web-platform-tests/import-maps/resources/resolving.js rename to tests/wpt/web-platform-tests/import-maps/imported/resources/resolving.js index 0409962e4d79..29ee31ccbc93 100644 --- a/tests/wpt/web-platform-tests/import-maps/resources/resolving.js +++ b/tests/wpt/web-platform-tests/import-maps/imported/resources/resolving.js @@ -1,9 +1,4 @@ 'use strict'; - -// Imported from: -// https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving.js -// TODO: Upstream local changes. - const { URL } = require('url'); const { parseFromString } = require('../lib/parser.js'); const { resolve } = require('../lib/resolver.js'); @@ -89,7 +84,8 @@ describe('Mapped using the "imports" key only (no scopes)', () => { "lodash-dot": "./node_modules/lodash-es/lodash.js", "lodash-dot/": "./node_modules/lodash-es/", "lodash-dotdot": "../node_modules/lodash-es/lodash.js", - "lodash-dotdot/": "../node_modules/lodash-es/" + "lodash-dotdot/": "../node_modules/lodash-es/", + "nowhere/": [] } }`); @@ -114,6 +110,10 @@ describe('Mapped using the "imports" key only (no scopes)', () => { expect(() => resolveUnderTest('underscore/')).toThrow(TypeError); expect(() => resolveUnderTest('underscore/foo')).toThrow(TypeError); }); + + it('should fail for package submodules that map to nowhere', () => { + expect(() => resolveUnderTest('nowhere/foo')).toThrow(TypeError); + }); }); describe('Tricky specifiers', () => { @@ -149,7 +149,7 @@ describe('Mapped using the "imports" key only (no scopes)', () => { describe('URL-like specifiers', () => { const resolveUnderTest = makeResolveUnderTest(`{ "imports": { - "/node_modules/als-polyfill/index.mjs": "@std/kv-storage", + "/node_modules/als-polyfill/index.mjs": "std:kv-storage", "/lib/foo.mjs": "./more/bar.mjs", "./dotrelative/foo.mjs": "/lib/dot.mjs", @@ -158,20 +158,17 @@ describe('Mapped using the "imports" key only (no scopes)', () => { "/lib/no.mjs": null, "./dotrelative/no.mjs": [], - "/": "/lib/slash-only.mjs", - "./": "/lib/dotslash-only.mjs", + "/": "/lib/slash-only/", + "./": "/lib/dotslash-only/", + + "/test/": "/lib/url-trailing-slash/", + "./test/": "/lib/url-trailing-slash-dot/", "/test": "/lib/test1.mjs", "../test": "/lib/test2.mjs" } }`); - it('should remap to built-in modules', () => { - expect(resolveUnderTest('/node_modules/als-polyfill/index.mjs')).toMatchURL('import:@std/kv-storage'); - expect(resolveUnderTest('https://example.com/node_modules/als-polyfill/index.mjs')).toMatchURL('import:@std/kv-storage'); - expect(resolveUnderTest('https://///example.com/node_modules/als-polyfill/index.mjs')).toMatchURL('import:@std/kv-storage'); - }); - it('should remap to other URLs', () => { expect(resolveUnderTest('https://example.com/lib/foo.mjs')).toMatchURL('https://example.com/app/more/bar.mjs'); expect(resolveUnderTest('https://///example.com/lib/foo.mjs')).toMatchURL('https://example.com/app/more/bar.mjs'); @@ -195,13 +192,18 @@ describe('Mapped using the "imports" key only (no scopes)', () => { }); it('should remap URLs that are just composed from / and .', () => { - expect(resolveUnderTest('https://example.com/')).toMatchURL('https://example.com/lib/slash-only.mjs'); - expect(resolveUnderTest('/')).toMatchURL('https://example.com/lib/slash-only.mjs'); - expect(resolveUnderTest('../')).toMatchURL('https://example.com/lib/slash-only.mjs'); + expect(resolveUnderTest('https://example.com/')).toMatchURL('https://example.com/lib/slash-only/'); + expect(resolveUnderTest('/')).toMatchURL('https://example.com/lib/slash-only/'); + expect(resolveUnderTest('../')).toMatchURL('https://example.com/lib/slash-only/'); + + expect(resolveUnderTest('https://example.com/app/')).toMatchURL('https://example.com/lib/dotslash-only/'); + expect(resolveUnderTest('/app/')).toMatchURL('https://example.com/lib/dotslash-only/'); + expect(resolveUnderTest('../app/')).toMatchURL('https://example.com/lib/dotslash-only/'); + }); - expect(resolveUnderTest('https://example.com/app/')).toMatchURL('https://example.com/lib/dotslash-only.mjs'); - expect(resolveUnderTest('/app/')).toMatchURL('https://example.com/lib/dotslash-only.mjs'); - expect(resolveUnderTest('../app/')).toMatchURL('https://example.com/lib/dotslash-only.mjs'); + it('should remap URLs that are prefix-matched by keys with trailing slashes', () => { + expect(resolveUnderTest('/test/foo.mjs')).toMatchURL('https://example.com/lib/url-trailing-slash/foo.mjs'); + expect(resolveUnderTest('https://example.com/app/test/foo.mjs')).toMatchURL('https://example.com/lib/url-trailing-slash-dot/foo.mjs'); }); it('should use the last entry\'s address when URL-like specifiers parse to the same absolute URL', () => { @@ -209,22 +211,60 @@ describe('Mapped using the "imports" key only (no scopes)', () => { }); }); - describe('overlapping entries with trailing slashes', () => { - const resolveUnderTest = makeResolveUnderTest(`{ - "imports": { - "a": "/1", - "a/": "/2/", - "a/b": "/3", - "a/b/": "/4/" - } - }`); + describe('Overlapping entries with trailing slashes', () => { + it('should favor the most-specific key (no empty arrays)', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "a": "/1", + "a/": "/2/", + "a/b": "/3", + "a/b/": "/4/" + } + }`); - it('most-specific wins', () => { expect(resolveUnderTest('a')).toMatchURL('https://example.com/1'); expect(resolveUnderTest('a/')).toMatchURL('https://example.com/2/'); expect(resolveUnderTest('a/b')).toMatchURL('https://example.com/3'); expect(resolveUnderTest('a/b/')).toMatchURL('https://example.com/4/'); expect(resolveUnderTest('a/b/c')).toMatchURL('https://example.com/4/c'); }); + + it('should favor the most-specific key when empty arrays are involved for less-specific keys', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "a": [], + "a/": [], + "a/b": "/3", + "a/b/": "/4/" + } + }`); + + expect(() => resolveUnderTest('a')).toThrow(TypeError); + expect(() => resolveUnderTest('a/')).toThrow(TypeError); + expect(() => resolveUnderTest('a/x')).toThrow(TypeError); + expect(resolveUnderTest('a/b')).toMatchURL('https://example.com/3'); + expect(resolveUnderTest('a/b/')).toMatchURL('https://example.com/4/'); + expect(resolveUnderTest('a/b/c')).toMatchURL('https://example.com/4/c'); + expect(() => resolveUnderTest('a/x/c')).toThrow(TypeError); + }); + + it('should favor the most-specific key when empty arrays are involved for more-specific keys', () => { + const resolveUnderTest = makeResolveUnderTest(`{ + "imports": { + "a": "/1", + "a/": "/2/", + "a/b": [], + "a/b/": [] + } + }`); + + expect(resolveUnderTest('a')).toMatchURL('https://example.com/1'); + expect(resolveUnderTest('a/')).toMatchURL('https://example.com/2/'); + expect(resolveUnderTest('a/x')).toMatchURL('https://example.com/2/x'); + expect(() => resolveUnderTest('a/b')).toThrow(TypeError); + expect(() => resolveUnderTest('a/b/')).toThrow(TypeError); + expect(() => resolveUnderTest('a/b/c')).toThrow(TypeError); + expect(resolveUnderTest('a/x/c')).toMatchURL('https://example.com/2/x/c'); + }); }); }); diff --git a/tests/wpt/web-platform-tests/import-maps/resolving.tentative.html b/tests/wpt/web-platform-tests/import-maps/resources/jest-test-helper.js similarity index 56% rename from tests/wpt/web-platform-tests/import-maps/resolving.tentative.html rename to tests/wpt/web-platform-tests/import-maps/resources/jest-test-helper.js index f2b09a7ae024..86556ed3dd95 100644 --- a/tests/wpt/web-platform-tests/import-maps/resolving.tentative.html +++ b/tests/wpt/web-platform-tests/import-maps/resources/jest-test-helper.js @@ -1,27 +1,56 @@ - - - - - - - - diff --git a/tests/wpt/web-platform-tests/interfaces/element-timing.idl b/tests/wpt/web-platform-tests/interfaces/element-timing.idl index dc3b886cfe5b..cf56426fb6ea 100644 --- a/tests/wpt/web-platform-tests/interfaces/element-timing.idl +++ b/tests/wpt/web-platform-tests/interfaces/element-timing.idl @@ -13,6 +13,7 @@ interface PerformanceElementTiming : PerformanceEntry { readonly attribute DOMString id; readonly attribute Element? element; readonly attribute DOMString url; + [Default] object toJSON(); }; partial interface Element { diff --git a/tests/wpt/web-platform-tests/interfaces/event-timing.idl b/tests/wpt/web-platform-tests/interfaces/event-timing.idl index c6790e16e3db..e8475d31922f 100644 --- a/tests/wpt/web-platform-tests/interfaces/event-timing.idl +++ b/tests/wpt/web-platform-tests/interfaces/event-timing.idl @@ -8,6 +8,7 @@ interface PerformanceEventTiming : PerformanceEntry { readonly attribute DOMHighResTimeStamp processingStart; readonly attribute DOMHighResTimeStamp processingEnd; readonly attribute boolean cancelable; + [Default] object toJSON(); }; [Exposed=Window] diff --git a/tests/wpt/web-platform-tests/interfaces/largest-contentful-paint.idl b/tests/wpt/web-platform-tests/interfaces/largest-contentful-paint.idl index f16a7ff812c9..d2c69c475755 100644 --- a/tests/wpt/web-platform-tests/interfaces/largest-contentful-paint.idl +++ b/tests/wpt/web-platform-tests/interfaces/largest-contentful-paint.idl @@ -10,4 +10,5 @@ interface LargestContentfulPaint : PerformanceEntry { readonly attribute DOMString id; readonly attribute DOMString url; readonly attribute Element? element; + [Default] object toJSON(); }; diff --git a/tests/wpt/web-platform-tests/interfaces/layout-instability.idl b/tests/wpt/web-platform-tests/interfaces/layout-instability.idl index 1bacea77bcef..c46151a923dd 100644 --- a/tests/wpt/web-platform-tests/interfaces/layout-instability.idl +++ b/tests/wpt/web-platform-tests/interfaces/layout-instability.idl @@ -7,4 +7,5 @@ interface LayoutShift : PerformanceEntry { readonly attribute long value; readonly attribute boolean hadRecentInput; readonly attribute DOMHighResTimeStamp lastInputTime; + [Default] object toJSON(); }; diff --git a/tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl b/tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl index 48ebc187bc48..e92533a226e9 100644 --- a/tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl +++ b/tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl @@ -70,8 +70,12 @@ dictionary RTCInboundRtpStreamStats : RTCReceivedRtpStreamStats { DOMString remoteId; unsigned long framesDecoded; unsigned long keyFramesDecoded; + unsigned long frameWidth; + unsigned long frameHeight; + double framesPerSecond; unsigned long long qpSum; double totalDecodeTime; + boolean voiceActivityFlag; DOMHighResTimeStamp lastPacketReceivedTimestamp; double averageRtcpInterval; unsigned long fecPacketsReceived; @@ -84,6 +88,22 @@ dictionary RTCInboundRtpStreamStats : RTCReceivedRtpStreamStats { unsigned long firCount; unsigned long pliCount; unsigned long sliCount; + DOMHighResTimeStamp estimatedPlayoutTimestamp; + double jitterBufferDelay; + unsigned long long jitterBufferEmittedCount; + unsigned long long totalSamplesReceived; + unsigned long long concealedSamples; + unsigned long long silentConcealedSamples; + unsigned long long concealmentEvents; + unsigned long long insertedSamplesForDeceleration; + unsigned long long removedSamplesForAcceleration; + double audioLevel; + double totalAudioEnergy; + double totalSamplesDuration; + unsigned long framesReceived; + unsigned long framesDropped; + unsigned long partialFramesLost; + unsigned long fullFramesLost; }; dictionary RTCRemoteInboundRtpStreamStats : RTCReceivedRtpStreamStats { @@ -110,9 +130,16 @@ dictionary RTCOutboundRtpStreamStats : RTCSentRtpStreamStats { unsigned long long retransmittedBytesSent; double targetBitrate; unsigned long long totalEncodedBytesTarget; + unsigned long frameWidth; + unsigned long frameHeight; + double framesPerSecond; + unsigned long framesSent; + unsigned long hugeFramesSent; unsigned long framesEncoded; unsigned long keyFramesEncoded; unsigned long long qpSum; + unsigned long long totalSamplesSent; + boolean voiceActivityFlag; double totalEncodeTime; double totalPacketSendDelay; double averageRtcpInterval; @@ -146,6 +173,8 @@ dictionary RTCAudioSourceStats : RTCMediaSourceStats { double audioLevel; double totalAudioEnergy; double totalSamplesDuration; + double echoReturnLoss; + double echoReturnLossEnhancement; }; dictionary RTCVideoSourceStats : RTCMediaSourceStats { @@ -183,59 +212,29 @@ dictionary RTCMediaHandlerStats : RTCStats { }; dictionary RTCVideoHandlerStats : RTCMediaHandlerStats { - unsigned long frameWidth; - unsigned long frameHeight; - double framesPerSecond; }; dictionary RTCVideoSenderStats : RTCVideoHandlerStats { DOMString mediaSourceId; - unsigned long framesCaptured; - unsigned long framesSent; - unsigned long hugeFramesSent; }; dictionary RTCSenderVideoTrackAttachmentStats : RTCVideoSenderStats { }; dictionary RTCVideoReceiverStats : RTCVideoHandlerStats { - DOMHighResTimeStamp estimatedPlayoutTimestamp; - double jitterBufferDelay; - unsigned long long jitterBufferEmittedCount; - unsigned long framesReceived; - unsigned long framesDecoded; - unsigned long framesDropped; - unsigned long partialFramesLost; - unsigned long fullFramesLost; }; dictionary RTCAudioHandlerStats : RTCMediaHandlerStats { - boolean voiceActivityFlag; }; dictionary RTCAudioSenderStats : RTCAudioHandlerStats { DOMString mediaSourceId; - double echoReturnLoss; - double echoReturnLossEnhancement; - unsigned long long totalSamplesSent; }; dictionary RTCSenderAudioTrackAttachmentStats : RTCAudioSenderStats { }; dictionary RTCAudioReceiverStats : RTCAudioHandlerStats { - DOMHighResTimeStamp estimatedPlayoutTimestamp; - double jitterBufferDelay; - unsigned long long jitterBufferEmittedCount; - unsigned long long totalSamplesReceived; - unsigned long long concealedSamples; - unsigned long long silentConcealedSamples; - unsigned long long concealmentEvents; - unsigned long long insertedSamplesForDeceleration; - unsigned long long removedSamplesForAcceleration; - double audioLevel; - double totalAudioEnergy; - double totalSamplesDuration; }; dictionary RTCDataChannelStats : RTCStats { @@ -367,12 +366,51 @@ partial dictionary RTCAudioHandlerStats { double audioLevel; double totalAudioEnergy; double totalSamplesDuration; + boolean voiceActivityFlag; +}; + +partial dictionary RTCAudioSenderStats { + unsigned long long totalSamplesSent; + double echoReturnLoss; + double echoReturnLossEnhancement; +}; + +partial dictionary RTCAudioReceiverStats { + DOMHighResTimeStamp estimatedPlayoutTimestamp; + double jitterBufferDelay; + unsigned long long jitterBufferEmittedCount; + unsigned long long totalSamplesReceived; + unsigned long long concealedSamples; + unsigned long long silentConcealedSamples; + unsigned long long concealmentEvents; + unsigned long long insertedSamplesForDeceleration; + unsigned long long removedSamplesForAcceleration; + double audioLevel; + double totalAudioEnergy; + double totalSamplesDuration; +}; + +partial dictionary RTCVideoHandlerStats { + unsigned long frameWidth; + unsigned long frameHeight; + double framesPerSecond; }; partial dictionary RTCVideoSenderStats { unsigned long keyFramesSent; + unsigned long framesCaptured; + unsigned long framesSent; + unsigned long hugeFramesSent; }; partial dictionary RTCVideoReceiverStats { unsigned long keyFramesReceived; + DOMHighResTimeStamp estimatedPlayoutTimestamp; + double jitterBufferDelay; + unsigned long long jitterBufferEmittedCount; + unsigned long framesReceived; + unsigned long framesDecoded; + unsigned long framesDropped; + unsigned long partialFramesLost; + unsigned long fullFramesLost; }; diff --git a/tests/wpt/web-platform-tests/largest-contentful-paint/first-letter-background.html b/tests/wpt/web-platform-tests/largest-contentful-paint/first-letter-background.html new file mode 100644 index 000000000000..19544c8edeed --- /dev/null +++ b/tests/wpt/web-platform-tests/largest-contentful-paint/first-letter-background.html @@ -0,0 +1,48 @@ + + +Largest Contentful Paint: observe element with background image in its first letter + + + + + + +
A
+ diff --git a/tests/wpt/web-platform-tests/largest-contentful-paint/observe-after-untrusted-scroll.html b/tests/wpt/web-platform-tests/largest-contentful-paint/observe-after-untrusted-scroll.html index abe753fc14a3..b551e7632b5c 100644 --- a/tests/wpt/web-platform-tests/largest-contentful-paint/observe-after-untrusted-scroll.html +++ b/tests/wpt/web-platform-tests/largest-contentful-paint/observe-after-untrusted-scroll.html @@ -19,7 +19,7 @@ 'The rendering timestamp should occur after script starts running.'); assert_greater_than_equal(performance.now(), entry.renderTime, 'The rendering timestamp should occur before the entry is dispatched to the observer.'); - assert_equals(entry.startTime, 0); + assert_equals(entry.startTime, entry.renderTime, 'startTime should equal renderTime'); assert_equals(entry.duration, 0); // blue.png is 133 x 106. assert_equals(entry.size, 14098); diff --git a/tests/wpt/web-platform-tests/largest-contentful-paint/toJSON.html b/tests/wpt/web-platform-tests/largest-contentful-paint/toJSON.html new file mode 100644 index 000000000000..7defcce1b6f9 --- /dev/null +++ b/tests/wpt/web-platform-tests/largest-contentful-paint/toJSON.html @@ -0,0 +1,42 @@ + + +Largest Contentful Paint: toJSON + + + +

Text!

+ + diff --git a/tests/wpt/web-platform-tests/layout-instability/toJSON.html b/tests/wpt/web-platform-tests/layout-instability/toJSON.html new file mode 100644 index 000000000000..3d39d623e133 --- /dev/null +++ b/tests/wpt/web-platform-tests/layout-instability/toJSON.html @@ -0,0 +1,42 @@ + + +Layout Instability: toJSON + + +
+ + + + diff --git a/tests/wpt/web-platform-tests/lint.whitelist b/tests/wpt/web-platform-tests/lint.whitelist index c344c3a83444..669038166ab3 100644 --- a/tests/wpt/web-platform-tests/lint.whitelist +++ b/tests/wpt/web-platform-tests/lint.whitelist @@ -309,6 +309,8 @@ SET TIMEOUT: css/css-fonts/font-display/font-display-feature-policy-01.tentative SET TIMEOUT: css/css-fonts/font-display/font-display-feature-policy-02.tentative.html SET TIMEOUT: css/css-fonts/font-display/font-display-preload.html SET TIMEOUT: html/browsers/windows/auxiliary-browsing-contexts/resources/close-opener.html +SET TIMEOUT: html/cross-origin-embedder-policy/resources/navigate-none.sub.html +SET TIMEOUT: html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html SET TIMEOUT: html/dom/documents/dom-tree-accessors/Document.currentScript.html SET TIMEOUT: html/webappapis/timers/* SET TIMEOUT: resources/chromium/* @@ -808,7 +810,7 @@ MISSING-LINK: css/filter-effects/*.any.js # Tests that use WebKit/Blink testing APIs LAYOUTTESTS APIS: css/css-regions/interactivity/* -LAYOUTTESTS APIS: import-maps/resolving.tentative.html +LAYOUTTESTS APIS: import-maps/resources/jest-test-helper.js LAYOUTTESTS APIS: permissions/test-background-fetch-permission.html LAYOUTTESTS APIS: resources/chromium/generic_sensor_mocks.js LAYOUTTESTS APIS: resources/chromium/webxr-test.js diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006-ref.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006-ref.html new file mode 100644 index 000000000000..39e6dabdfb19 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006-ref.html @@ -0,0 +1,74 @@ + + + + + RTL mtable and mtable with frame + + + + + +

+ + + + + É + + + p + + + X + + + + + + + + + + + Xp + + + + +

+ +

+ + + + + É + + + p + + + X + + + + + + + + + + + Xp + + + + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006.html new file mode 100644 index 000000000000..904e7d3fed8c --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006.html @@ -0,0 +1,79 @@ + + + + + RTL mtable and mtable with frame + + + + + + + + + + +

+ + + + + X + + + p + + + É + + + + + Xp + + + + + + + + + + +

+ +

+ + + + + X + + + p + + + É + + + + + Xp + + + + + + + + + + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007-ref.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007-ref.html new file mode 100644 index 000000000000..5c77395f2008 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007-ref.html @@ -0,0 +1,42 @@ + + + + + mo and embellished mrow/munderover (lspace=1em rspace=2em) + + + + + +

+ + pXp + +

+ +

+ + p + X + p + +

+ +

+ + p + + X + É + É + + p + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007.html new file mode 100644 index 000000000000..7137e2640fa4 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007.html @@ -0,0 +1,50 @@ + + + + + mo and embellished mrow/munderover (lspace=1em rspace=2em) + + + + + + + + + + + + + +

+ + pXp + +

+ +

+ + p + X + p + +

+ +

+ + p + + X + É + É + + p + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008-ref.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008-ref.html new file mode 100644 index 000000000000..492fa9539ae8 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008-ref.html @@ -0,0 +1,27 @@ + + + + + embellished mfrac (lspace=1em rspace=2em) + + + + + +

+ + p + + X + É + + p + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008.html new file mode 100644 index 000000000000..5c98b0741007 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008.html @@ -0,0 +1,33 @@ + + + + + embellished mfrac (lspace=1em rspace=2em) + + + + + + + + + + + +

+ + p + + X + É + + p + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009-ref.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009-ref.html new file mode 100644 index 000000000000..7ed4796814a7 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009-ref.html @@ -0,0 +1,21 @@ + + + + + RTL ms lquote="X" rquote="p" + + + + +

+ + É + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009.html new file mode 100644 index 000000000000..bf8caf16aed2 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009.html @@ -0,0 +1,27 @@ + + + + + RTL ms lquote="X" rquote="p" + + + + + + + + + + +

+ + É + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010-ref.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010-ref.html new file mode 100644 index 000000000000..4f595ed49f69 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010-ref.html @@ -0,0 +1,44 @@ + + + + + dir="rtl" VS direction: rtl on math/mrow/mstyle + + + + + +

+ + X + p + É + +

+ +

+ + + X + p + É + + +

+ +

+ + + X + p + É + + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010.html new file mode 100644 index 000000000000..6dc095ac1fd4 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010.html @@ -0,0 +1,51 @@ + + + + + dir="rtl" VS direction: rtl on math/mrow/mstyle + + + + + + + + + + + + +

+ + X + p + É + +

+ +

+ + + X + p + É + + +

+ +

+ + + X + p + É + + +

+ + + diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity-ref.html new file mode 100644 index 000000000000..28d9acc1f4c2 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity-ref.html @@ -0,0 +1,163 @@ + + + + +mathvariant case sensitivity + + +

+ + 𝕬 + +

+

+ + 𝐀 + +

+

+ + 𝑨 + +

+

+ + 𝗔 + +

+

+ + 𝓐 + +

+

+ + 𝔸 + +

+

+ + 𝔄 + +

+

+ + 𞸰 + +

+

+ + 𝐴 + +

+

+ + 𞺐 + +

+

+ + 𝙰 + +

+

+ + 𝘼 + +

+

+ + 𝖠 + +

+

+ + 𝘈 + +

+

+ + 𝒜 + +

+

+ + 𞹰 + +

+

+ + 𞹒 + +

+ + diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity.html new file mode 100644 index 000000000000..0d3e706d961e --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity.html @@ -0,0 +1,168 @@ + + + + +mathvariant case sensitivity + + + + + + + +

+ + A + +

+

+ + A + +

+

+ + A + +

+

+ + A + +

+

+ + A + +

+

+ + A + +

+

+ + A + +

+

+ + ف + +

+

+ + A + +

+

+ + ف + +

+

+ + A + +

+

+ + A + +

+

+ + A + +

+

+ + A + +

+

+ + A + +

+

+ + ف + +

+

+ + ق + +

+ + diff --git a/tests/wpt/web-platform-tests/pointerevents/inheritance.html b/tests/wpt/web-platform-tests/pointerevents/inheritance.html new file mode 100644 index 000000000000..0bf39bcb4ddc --- /dev/null +++ b/tests/wpt/web-platform-tests/pointerevents/inheritance.html @@ -0,0 +1,21 @@ + + + + +Inheritance of touch-action + + + + + + + + +
+
+
+ + + diff --git a/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-computed.html b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-computed.html new file mode 100644 index 000000000000..59255bec4550 --- /dev/null +++ b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-computed.html @@ -0,0 +1,24 @@ + + + + +Pointer Events: getComputedStyle().touchAction + + + + + + + +
+ + + diff --git a/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-invalid.html b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-invalid.html new file mode 100644 index 000000000000..979dc252d3fe --- /dev/null +++ b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-invalid.html @@ -0,0 +1,18 @@ + + + +Pointer Events: parsing touch-action with invalid values + + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-valid.html b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-valid.html new file mode 100644 index 000000000000..9bb5d023edcf --- /dev/null +++ b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-valid.html @@ -0,0 +1,23 @@ + + + +Pointer Events: parsing touch-action with valid values + + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001-ref.html b/tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001-ref.html new file mode 100644 index 000000000000..46a4d7d156f6 --- /dev/null +++ b/tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001-ref.html @@ -0,0 +1,8 @@ + +CSS Test Reference +
Prevent quirky dl margin from messing up with us
+
+
One
+
Two
+
+
Three
Four
diff --git a/tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001.html b/tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001.html new file mode 100644 index 000000000000..96fc76f08f45 --- /dev/null +++ b/tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001.html @@ -0,0 +1,18 @@ + +dd and dl don't have weird text-indent quirks + + + + + +
Prevent quirky dl margin from messing up with us
+
+
One
+
Two
+
+
Three
Four
diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/referrer-policy-test-case.sub.js b/tests/wpt/web-platform-tests/referrer-policy/generic/referrer-policy-test-case.sub.js index 0c0f38195309..d1cb469b3dfb 100644 --- a/tests/wpt/web-platform-tests/referrer-policy/generic/referrer-policy-test-case.sub.js +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/referrer-policy-test-case.sub.js @@ -129,6 +129,12 @@ function ReferrerPolicyTestCase(scenario, testDescription, sanityChecker) { const expectedReferrer = referrerUrlResolver[scenario.referrer_url](currentURL); + function asyncResolve(result) { + return new Promise((resolve, reject) => { + step_timeout(() => resolve(result), 0); + }); + } + // Request in the top-level document. promise_test(_ => { return invokeRequest(subresource, []) @@ -146,7 +152,8 @@ function ReferrerPolicyTestCase(scenario, testDescription, sanityChecker) { subresource.url += "&-1"; return invokeRequest(subresource, []) .then(result => checkResult(location.href, result)) - .finally(_ => history.back()); + .then(_ => history.back()) + .then(asyncResolve); }, "`Referer` header with length < 4k is not stripped to an origin."); promise_test(_ => { @@ -157,7 +164,8 @@ function ReferrerPolicyTestCase(scenario, testDescription, sanityChecker) { subresource.url += "&0"; return invokeRequest(subresource, []) .then(result => checkResult(expectedReferrer, result)) - .finally(_ => history.back()); + .then(_ => history.back()) + .then(asyncResolve); }, "`Referer` header with length == 4k is not stripped to an origin."); promise_test(_ => { @@ -168,7 +176,8 @@ function ReferrerPolicyTestCase(scenario, testDescription, sanityChecker) { subresource.url += "&+1"; return invokeRequest(subresource, []) .then(result => checkResult(originString, result)) - .finally(_ => history.back()); + .then(_ => history.back()) + .then(asyncResolve); }, "`Referer` header with length > 4k is stripped to an origin."); } diff --git a/tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js b/tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js new file mode 100644 index 000000000000..83bd6b8a0dea --- /dev/null +++ b/tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js @@ -0,0 +1,415 @@ +'use strict'; + +function toMojoNDEFRecordType(type) { + switch (type) { + case 'text': + return device.mojom.NDEFRecordType.TEXT; + case 'url': + return device.mojom.NDEFRecordType.URL; + case 'json': + return device.mojom.NDEFRecordType.JSON; + case 'opaque': + return device.mojom.NDEFRecordType.OPAQUE_RECORD; + } + + return device.mojom.NDEFRecordType.EMPTY; +} + +function toMojoNFCPushTarget(target) { + switch (target) { + case 'peer': + return device.mojom.NFCPushTarget.PEER; + case 'tag': + return device.mojom.NFCPushTarget.TAG; + } + + return device.mojom.NFCPushTarget.ANY; +} + +function toMojoNDEFCompatibility(compatibility) { + if (compatibility === 'nfc-forum') + return device.mojom.NDEFCompatibility.NFC_FORUM; + if (compatibility === 'vendor') + return device.mojom.NDEFCompatibility.VENDOR; + return device.mojom.NDEFCompatibility.ANY; +} + +// Converts between NDEFMessageInit https://w3c.github.io/web-nfc/#dom-ndefmessage +// and mojom.NDEFMessage structure, so that watch function can be tested. +function toMojoNDEFMessage(message) { + let ndefMessage = new device.mojom.NDEFMessage(); + ndefMessage.url = message.url; + ndefMessage.data = []; + for (let record of message.records) { + ndefMessage.data.push(toMojoNDEFRecord(record)); + } + return ndefMessage; +} + +function toMojoNDEFRecord(record) { + let nfcRecord = new device.mojom.NDEFRecord(); + nfcRecord.recordType = toMojoNDEFRecordType(record.recordType); + nfcRecord.mediaType = record.mediaType; + nfcRecord.data = toByteArray(record.data); + return nfcRecord; +} + +function toByteArray(data) { + // Convert JS objects to byte array + let byteArray = new Uint8Array(0); + let tmpData = data; + + if (tmpData instanceof ArrayBuffer) + byteArray = new Uint8Array(tmpData); + else if (typeof tmpData === 'object' || typeof tmpData === 'number') + tmpData = JSON.stringify(tmpData); + + if (typeof tmpData === 'string') + byteArray = new TextEncoder('utf-8').encode(tmpData); + + return byteArray; +} + +// Compares NDEFRecords that were provided / received by the mock service. +// TODO: Use different getters to get received record data, +// see spec changes at https://github.com/w3c/web-nfc/pull/243 +function compareNDEFRecords(providedRecord, receivedRecord) { + assert_equals(toMojoNDEFRecordType(providedRecord.recordType), + receivedRecord.recordType); + + // Compare media types without charset. + // Charset should be compared when watch method is implemented, in order + // to check that written and read strings are equal. + assert_equals(providedRecord.mediaType, + receivedRecord.mediaType.substring(0, providedRecord.mediaType.length)); + + assert_false(toMojoNDEFRecordType(providedRecord.recordType) == + device.mojom.NDEFRecordType.EMPTY); + + assert_array_equals(toByteArray(providedRecord.data), + new Uint8Array(receivedRecord.data)); +} + +// Compares NFCPushOptions structures that were provided to API and +// received by the mock mojo service. +function assertNFCPushOptionsEqual(provided, received) { + if (provided.ignoreRead !== undefined) + assert_equals(provided.ignoreRead, !!received.ignoreRead); + else + assert_equals(!!received.ignore_read, true); + + if (provided.timeout !== undefined) + assert_equals(provided.timeout, received.timeout); + else + assert_equals(received.timeout, Infinity); + + if (provided.target !== undefined) + assert_equals(toMojoNFCPushTarget(provided.target), received.target); + else + assert_equals(received.target, device.mojom.NFCPushTarget.ANY); + + if (provided.compatibility !== undefined) { + assert_equals(toMojoNDEFCompatibility(provided.compatibility), + received.compatibility); + } else { + assert_equals(received.compatibility, + device.mojom.NDEFCompatibility.NFC_FORUM); + } +} + +// Compares NFCReaderOptions structures that were provided to API and +// received by the mock mojo service. +function assertNFCReaderOptionsEqual(provided, received) { + if (provided.url !== undefined) + assert_equals(provided.url, received.url); + else + assert_equals(received.url, ''); + + if (provided.mediaType !== undefined) + assert_equals(provided.mediaType, received.mediaType); + else + assert_equals(received.mediaType, ''); + + if (provided.compatibility !== undefined) { + assert_equals(toMojoNDEFCompatibility(provided.compatibility), + received.compatibility); + } else { + assert_equals(received.compatibility, + device.mojom.NDEFCompatibility.NFC_FORUM); + } + + if (provided.recordType !== undefined) { + assert_equals(!+received.record_filter, true); + assert_equals(toMojoNDEFRecordType(provided.recordType), + received.recordFilter.recordType); + } +} + +// Checks whether NFCReaderOptions are matched with given message +// and mock nfc's compatibility +function matchesWatchOptions(message, compatibility, options) { + // Filter by NDEFCompatibility + if (options.compatibility !== toMojoNDEFCompatibility("any") + && options.compatibility !== compatibility) { + return false; + } + + // Filter by Web NFC id + if (!matchesWebNfcId(message.url, options.url)) return false; + + // Matches any record / media type. + if ((options.mediaType == null || options.mediaType === "") + && options.recordFilter == null) { + return true; + } + + // Filter by mediaType and recordType + for (let record of message.records) { + if (options.mediaType != null && options.mediaType !== "" + && options.mediaType !== record.mediaType) { + return false; + } + if (options.recordFilter != null + && options.recordFilter.recordType + !== toMojoNDEFRecordType(record.recordType)) { + return false; + } + } + + return true; +} + +// Web NFC id match algorithm. +// https://w3c.github.io/web-nfc/#url-pattern-match-algorithm +function matchesWebNfcId(id, pattern) { + if (id != null && id !== "" && pattern != null && pattern !== "") { + const id_url = new URL(id); + const pattern_url = new URL(pattern); + + if (id_url.protocol !== pattern_url.protocol) return false; + if (!id_url.host.endsWith("." + pattern_url.host) + && id_url.host !== pattern_url.host) { + return false; + } + if (pattern_url.pathname === "/*") return true; + if (id_url.pathname.startsWith(pattern_url.pathname)) return true; + + return false; + } + + return true; +} + +function createNFCError(type) { + return { error: type ? + new device.mojom.NFCError({ errorType: type }) : null }; +} + +var WebNFCTest = (() => { + class MockNFC { + constructor() { + this.bindingSet_ = new mojo.BindingSet(device.mojom.NFC); + + this.interceptor_ = new MojoInterfaceInterceptor( + device.mojom.NFC.name); + this.interceptor_.oninterfacerequest = + e => this.bindingSet_.addBinding(this, e.handle); + this.interceptor_.start(); + + this.hw_status_ = NFCHWStatus.ENABLED; + this.pushed_message_ = null; + this.push_options_ = null; + this.pending_promise_func_ = null; + this.push_completed_ = true; + this.push_should_timeout_ = false; + this.client_ = null; + this.watchers_ = []; + this.reading_messages_ = []; + } + + // NFC delegate functions + async push(message, options) { + let error = this.getHWError(); + if (error) + return error; + + this.pushed_message_ = message; + this.push_options_ = options; + + return new Promise(resolve => { + this.pending_promise_func_ = resolve; + if (options.timeout && options.timeout !== Infinity && + !this.push_completed_) { + // Resolve with TimeoutError, else pending push operation. + if (this.push_should_timeout_) { + resolve( + createNFCError(device.mojom.NFCErrorType.TIMER_EXPIRED)); + } + } else { + resolve(createNFCError(null)); + } + }); + } + + async cancelPush(target) { + if (this.push_options_ && ((target === device.mojom.NFCPushTarget.ANY) || + (this.push_options_.target === target))) { + this.cancelPendingPushOperation(); + } + + return createNFCError(null); + } + + setClient(client) { + this.client_ = client; + } + + async watch(options, id) { + assert_true(id > 0); + let error = this.getHWError(); + if (error) { + return error; + } + + this.watchers_.push({id: id, options: options}); + // Triggers onWatch if the new watcher matches existing messages + if (this.reading_messages_.length !== 0) { + for(let message of this.reading_messages_) { + if (matchesWatchOptions(message.message, + message.compatibility, options)) { + this.client_.onWatch([id], fake_tag_serial_number, + toMojoNDEFMessage(message.message)); + } + } + } + + return createNFCError(null); + } + + async cancelWatch(id) { + let index = this.watchers_.findIndex(value => value.id === id); + if (index === -1) { + return createNFCError(device.mojom.NFCErrorType.NOT_FOUND); + } + + this.watchers_.splice(index, 1); + return createNFCError(null); + } + + async cancelAllWatches() { + if (this.watchers_.length === 0) { + return createNFCError(device.mojom.NFCErrorType.NOT_FOUND); + } + + this.watchers_.splice(0, this.watchers_.length); + return createNFCError(null); + } + + getHWError() { + if (this.hw_status_ === NFCHWStatus.DISABLED) + return createNFCError(device.mojom.NFCErrorType.NOT_READABLE); + if (this.hw_status_ === NFCHWStatus.NOT_SUPPORTED) + return createNFCError(device.mojom.NFCErrorType.NOT_SUPPORTED); + return null; + } + + setHWStatus(status) { + this.hw_status_ = status; + } + + pushedMessage() { + return this.pushed_message_; + } + + pushOptions() { + return this.push_options_; + } + + watchOptions() { + assert_not_equals(this.watchers_.length, 0); + return this.watchers_[this.watchers_.length - 1].options; + } + + setPendingPushCompleted(result) { + this.push_completed_ = result; + } + + reset() { + this.hw_status_ = NFCHWStatus.ENABLED; + this.push_completed_ = true; + this.watchers_ = []; + this.reading_messages_ = []; + this.cancelPendingPushOperation(); + this.bindingSet_.closeAllBindings(); + this.interceptor_.stop(); + } + + cancelPendingPushOperation() { + if (this.pending_promise_func_) { + this.pending_promise_func_( + createNFCError(device.mojom.NFCErrorType.OPERATION_CANCELLED)); + } + + this.pushed_message_ = null; + this.push_options_ = null; + this.pending_promise_func_ = null; + this.push_should_timeout_ = false; + } + + // Sets message that is used to deliver NFC reading updates + // with a specific NDEFCompatibility. + setReadingMessage(message, compatibility = 'nfc-forum') { + this.reading_messages_.push({message: message, + compatibility: toMojoNDEFCompatibility(compatibility)}); + // Triggers onWatch if the new message matches existing watchers + if (this.watchers_.length !== 0) { + for (let watcher of this.watchers_) { + if (matchesWatchOptions(message, + message.compatibility, watcher.options)) { + this.client_.onWatch([watcher.id], fake_tag_serial_number, + toMojoNDEFMessage(message.message)); + } + } + } + } + + setPushShouldTimeout(result) { + this.push_should_timeout_ = result; + } + } + + let testInternal = { + initialized: false, + mockNFC: null + } + + class NFCTestChromium { + constructor() { + Object.freeze(this); // Make it immutable. + } + + initialize() { + if (testInternal.initialized) + throw new Error('Call reset() before initialize().'); + + testInternal.mockNFC = new MockNFC; + testInternal.initialized = true; + } + // Resets state of nfc mocks between test runs. + async reset() { + if (!testInternal.initialized) + throw new Error('Call initialize() before reset().'); + testInternal.mockNFC.reset(); + testInternal.mockNFC = null; + testInternal.initialized = false; + + await new Promise(resolve => setTimeout(resolve, 0)); + } + + getMockNFC() { + return testInternal.mockNFC; + } + } + + return NFCTestChromium; +})(); diff --git a/tests/wpt/web-platform-tests/resources/webidl2/lib/README.md b/tests/wpt/web-platform-tests/resources/webidl2/lib/README.md index 3f9d75f57ba8..1bd583269d29 100644 --- a/tests/wpt/web-platform-tests/resources/webidl2/lib/README.md +++ b/tests/wpt/web-platform-tests/resources/webidl2/lib/README.md @@ -1,4 +1,4 @@ This directory contains a built version of the [webidl2.js library](https://github.com/w3c/webidl2.js). -It is built by running `npx webpack --mode none` at the root of that repository. +It is built by running `npm run build-debug` at the root of that repository. The `webidl2.js.headers` file is a local addition to ensure the script is interpreted as UTF-8. diff --git a/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js b/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js index 9cb975a8bb30..900694b095df 100644 --- a/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js +++ b/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js @@ -103,10 +103,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _lib_webidl2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return _lib_webidl2_js__WEBPACK_IMPORTED_MODULE_0__["parse"]; }); -/* harmony import */ var _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(29); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "write", function() { return _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__["write"]; }); -/* harmony import */ var _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(15); +/* harmony import */ var _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(30); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "validate", function() { return _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__["validate"]; }); @@ -121,14 +121,20 @@ __webpack_require__.r(__webpack_exports__); "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return parse; }); -/* harmony import */ var _productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); -/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* harmony import */ var _productions_base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); -/* harmony import */ var _productions_default_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8); -/* harmony import */ var _productions_enum_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(12); -/* harmony import */ var _productions_includes_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(13); -/* harmony import */ var _productions_type_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3); -/* harmony import */ var _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(9); +/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var _productions_enum_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); +/* harmony import */ var _productions_includes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); +/* harmony import */ var _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); +/* harmony import */ var _productions_typedef_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); +/* harmony import */ var _productions_callback_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(18); +/* harmony import */ var _productions_interface_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19); +/* harmony import */ var _productions_mixin_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(24); +/* harmony import */ var _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(25); +/* harmony import */ var _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(27); +/* harmony import */ var _productions_callback_interface_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(28); + + + @@ -148,469 +154,57 @@ __webpack_require__.r(__webpack_exports__); function parseByTokens(tokeniser, options) { const source = tokeniser.source; - const ID = "identifier"; - function error(str) { tokeniser.error(str); } - function probe(type) { - return tokeniser.probe(type); - } - function consume(...candidates) { return tokeniser.consume(...candidates); } - function unconsume(position) { - return tokeniser.unconsume(position); - } - - class Constant extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { - static parse() { - const tokens = {}; - tokens.base = consume("const"); - if (!tokens.base) { - return; - } - let idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["primitive_type"])(tokeniser); - if (!idlType) { - const base = consume(ID) || error("No type for const"); - idlType = new _productions_type_js__WEBPACK_IMPORTED_MODULE_6__["Type"]({ source, tokens: { base } }); - } - if (probe("?")) { - error("Unexpected nullable constant type"); - } - idlType.type = "const-type"; - tokens.name = consume(ID) || error("No name for const"); - tokens.assign = consume("=") || error("No value assignment for const"); - tokens.value = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["const_value"])(tokeniser) || error("No value for const"); - tokens.termination = consume(";") || error("Unterminated const"); - const ret = new Constant({ source, tokens }); - ret.idlType = idlType; - return ret; - } - - get type() { - return "const"; - } - get name() { - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); - } - get value() { - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["const_data"])(this.tokens.value); - } - } - - class CallbackFunction extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { - static parse(base) { - const tokens = { base }; - const ret = new CallbackFunction({ source, tokens }); - tokens.name = consume(ID) || error("No name for callback"); - tokeniser.current = ret; - tokens.assign = consume("=") || error("No assignment in callback"); - ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["return_type"])(tokeniser) || error("Missing return type"); - tokens.open = consume("(") || error("No arguments in callback"); - ret.arguments = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["argument_list"])(tokeniser); - tokens.close = consume(")") || error("Unterminated callback"); - tokens.termination = consume(";") || error("Unterminated callback"); - return ret; - } - - get type() { - return "callback"; - } - get name() { - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); - } - } - function callback() { const callback = consume("callback"); if (!callback) return; - const tok = consume("interface"); - if (tok) { - return Interface.parse(tok, { callback }); - } - return CallbackFunction.parse(callback); - } - - class Attribute extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { - static parse({ special, noInherit = false, readonly = false } = {}) { - const start_position = tokeniser.position; - const tokens = { special }; - const ret = new Attribute({ source, tokens }); - if (!special && !noInherit) { - tokens.special = consume("inherit"); - } - if (ret.special === "inherit" && probe("readonly")) { - error("Inherited attributes cannot be read-only"); - } - tokens.readonly = consume("readonly"); - if (readonly && !tokens.readonly && probe("attribute")) { - error("Attributes must be readonly in this context"); - } - tokens.base = consume("attribute"); - if (!tokens.base) { - unconsume(start_position); - return; - } - ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser, "attribute-type") || error("No type in attribute"); - switch (ret.idlType.generic) { - case "sequence": - case "record": error(`Attributes cannot accept ${ret.idlType.generic} types`); - } - tokens.name = consume(ID, "required") || error("No name in attribute"); - tokens.termination = consume(";") || error("Unterminated attribute"); - return ret; - } - - get type() { - return "attribute"; - } - get special() { - if (!this.tokens.special) { - return ""; - } - return this.tokens.special.value; - } - get readonly() { - return !!this.tokens.readonly; - } - get name() { - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); - } - } - - class Operation extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { - static parse({ special, regular } = {}) { - const tokens = { special }; - const ret = new Operation({ source, tokens }); - if (special && special.value === "stringifier") { - tokens.termination = consume(";"); - if (tokens.termination) { - ret.arguments = []; - return ret; - } - } - if (!special && !regular) { - tokens.special = consume("getter", "setter", "deleter"); - } - ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["return_type"])(tokeniser) || error("Missing return type"); - tokens.name = consume(ID); - tokens.open = consume("(") || error("Invalid operation"); - ret.arguments = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["argument_list"])(tokeniser); - tokens.close = consume(")") || error("Unterminated operation"); - tokens.termination = consume(";") || error("Unterminated attribute"); - return ret; - } - - get type() { - return "operation"; - } - get name() { - const { name } = this.tokens; - if (!name) { - return ""; - } - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(name.value); - } - get special() { - if (!this.tokens.special) { - return ""; - } - return this.tokens.special.value; - } - } - - function static_member() { - const special = consume("static"); - if (!special) return; - const member = Attribute.parse({ special }) || - Operation.parse({ special }) || - error("No body in static member"); - return member; - } - - function stringifier() { - const special = consume("stringifier"); - if (!special) return; - const member = Attribute.parse({ special }) || - Operation.parse({ special }) || - error("Unterminated stringifier"); - return member; - } - - class IterableLike extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { - static parse() { - const start_position = tokeniser.position; - const tokens = {}; - const ret = new IterableLike({ source, tokens }); - tokens.readonly = consume("readonly"); - tokens.base = tokens.readonly ? - consume("maplike", "setlike") : - consume("iterable", "maplike", "setlike"); - if (!tokens.base) { - unconsume(start_position); - return; - } - - const { type } = ret; - const secondTypeRequired = type === "maplike"; - const secondTypeAllowed = secondTypeRequired || type === "iterable"; - - tokens.open = consume("<") || error(`Error parsing ${type} declaration`); - const first = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser) || error(`Error parsing ${type} declaration`); - ret.idlType = [first]; - if (secondTypeAllowed) { - first.tokens.separator = consume(","); - if (first.tokens.separator) { - ret.idlType.push(Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser)); - } - else if (secondTypeRequired) - error(`Missing second type argument in ${type} declaration`); - } - tokens.close = consume(">") || error(`Unterminated ${type} declaration`); - tokens.termination = consume(";") || error(`Missing semicolon after ${type} declaration`); - - return ret; - } - - get type() { - return this.tokens.base.value; - } - get readonly() { - return !!this.tokens.readonly; - } - } - - function inheritance() { - const colon = consume(":"); - if (!colon) { - return {}; - } - const inheritance = consume(ID) || error("No type in inheritance"); - return { colon, inheritance }; - } - - class Container extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { - static parse(instance, { type, inheritable, allowedMembers }) { - const { tokens } = instance; - tokens.name = consume(ID) || error("No name for interface"); - tokeniser.current = instance; - if (inheritable) { - Object.assign(tokens, inheritance()); - } - tokens.open = consume("{") || error(`Bodyless ${type}`); - instance.members = []; - while (true) { - tokens.close = consume("}"); - if (tokens.close) { - tokens.termination = consume(";") || error(`Missing semicolon after ${type}`); - return instance; - } - const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__["ExtendedAttributes"].parse(tokeniser); - let mem; - for (const [parser, ...args] of allowedMembers) { - mem = parser(...args); - if (mem) { - break; - } - } - if (!mem) { - error("Unknown member"); - } - mem.extAttrs = ea; - instance.members.push(mem); - } - } - - get partial() { - return !!this.tokens.partial; - } - get name() { - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); - } - get inheritance() { - if (!this.tokens.inheritance) { - return null; - } - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.inheritance.value); - } - } - - class Interface extends Container { - static parse(base, { callback = null, partial = null } = {}) { - const tokens = { callback, partial, base }; - return Container.parse(new Interface({ source, tokens }), { - type: "interface", - inheritable: !partial, - allowedMembers: [ - [Constant.parse], - [static_member], - [stringifier], - [IterableLike.parse], - [Attribute.parse], - [Operation.parse] - ] - }); - } - - get type() { - if (this.tokens.callback) { - return "callback interface"; - } - return "interface"; - } - } - - class Mixin extends Container { - static parse(base, { partial } = {}) { - const tokens = { partial, base }; - tokens.mixin = consume("mixin"); - if (!tokens.mixin) { - return; - } - return Container.parse(new Mixin({ source, tokens }), { - type: "interface mixin", - allowedMembers: [ - [Constant.parse], - [stringifier], - [Attribute.parse, { noInherit: true }], - [Operation.parse, { regular: true }] - ] - }); - } - - get type() { - return "interface mixin"; + if (tokeniser.probe("interface")) { + return _productions_callback_interface_js__WEBPACK_IMPORTED_MODULE_10__["CallbackInterface"].parse(tokeniser, callback); } + return _productions_callback_js__WEBPACK_IMPORTED_MODULE_5__["CallbackFunction"].parse(tokeniser, callback); } function interface_(opts) { const base = consume("interface"); if (!base) return; - const ret = Mixin.parse(base, opts) || - Interface.parse(base, opts) || + const ret = _productions_mixin_js__WEBPACK_IMPORTED_MODULE_7__["Mixin"].parse(tokeniser, base, opts) || + _productions_interface_js__WEBPACK_IMPORTED_MODULE_6__["Interface"].parse(tokeniser, base, opts) || error("Interface has no proper body"); return ret; } - class Namespace extends Container { - static parse({ partial } = {}) { - const tokens = { partial }; - tokens.base = consume("namespace"); - if (!tokens.base) { - return; - } - return Container.parse(new Namespace({ source, tokens }), { - type: "namespace", - allowedMembers: [ - [Attribute.parse, { noInherit: true, readonly: true }], - [Operation.parse, { regular: true }] - ] - }); - } - - get type() { - return "namespace"; - } - } - function partial() { const partial = consume("partial"); if (!partial) return; - return Dictionary.parse({ partial }) || + return _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__["Dictionary"].parse(tokeniser, { partial }) || interface_({ partial }) || - Namespace.parse({ partial }) || + _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__["Namespace"].parse(tokeniser, { partial }) || error("Partial doesn't apply to anything"); } - class Dictionary extends Container { - static parse({ partial } = {}) { - const tokens = { partial }; - tokens.base = consume("dictionary"); - if (!tokens.base) { - return; - } - return Container.parse(new Dictionary({ source, tokens }), { - type: "dictionary", - inheritable: !partial, - allowedMembers: [ - [Field.parse], - ] - }); - } - - get type() { - return "dictionary"; - } - } - - class Field extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { - static parse() { - const tokens = {}; - const ret = new Field({ source, tokens }); - ret.extAttrs = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__["ExtendedAttributes"].parse(tokeniser); - tokens.required = consume("required"); - ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser, "dictionary-type") || error("No type for dictionary member"); - tokens.name = consume(ID) || error("No name for dictionary member"); - ret.default = _productions_default_js__WEBPACK_IMPORTED_MODULE_3__["Default"].parse(tokeniser); - if (tokens.required && ret.default) error("Required member must not have a default"); - tokens.termination = consume(";") || error("Unterminated dictionary member"); - return ret; - } - - get type() { - return "field"; - } - get name() { - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); - } - get required() { - return !!this.tokens.required; - } - } - - class Typedef extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { - static parse() { - const tokens = {}; - const ret = new Typedef({ source, tokens }); - tokens.base = consume("typedef"); - if (!tokens.base) { - return; - } - ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser, "typedef-type") || error("No type in typedef"); - tokens.name = consume(ID) || error("No name in typedef"); - tokeniser.current = ret; - tokens.termination = consume(";") || error("Unterminated typedef"); - return ret; - } - - get type() { - return "typedef"; - } - get name() { - return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); - } - } - function definition() { return callback() || interface_() || partial() || - Dictionary.parse() || - _productions_enum_js__WEBPACK_IMPORTED_MODULE_4__["Enum"].parse(tokeniser) || - Typedef.parse() || - _productions_includes_js__WEBPACK_IMPORTED_MODULE_5__["Includes"].parse(tokeniser) || - Namespace.parse(); + _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__["Dictionary"].parse(tokeniser) || + _productions_enum_js__WEBPACK_IMPORTED_MODULE_1__["Enum"].parse(tokeniser) || + _productions_typedef_js__WEBPACK_IMPORTED_MODULE_4__["Typedef"].parse(tokeniser) || + _productions_includes_js__WEBPACK_IMPORTED_MODULE_2__["Includes"].parse(tokeniser) || + _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__["Namespace"].parse(tokeniser); } function definitions() { if (!source.length) return []; const defs = []; while (true) { - const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__["ExtendedAttributes"].parse(tokeniser); + const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__["ExtendedAttributes"].parse(tokeniser); const def = definition(); if (!def) { if (ea.length) error("Stray extended attributes"); @@ -631,7 +225,10 @@ function parseByTokens(tokeniser, options) { } function parse(str, options = {}) { - const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_1__["Tokeniser"](str); + const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_0__["Tokeniser"](str); + if (typeof options.sourceName !== "undefined") { + tokeniser.source.name = options.sourceName; + } return parseByTokens(tokeniser, options); } @@ -642,170 +239,245 @@ function parse(str, options = {}) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unescape", function() { return unescape; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "list", function() { return list; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "const_value", function() { return const_value; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "const_data", function() { return const_data; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "primitive_type", function() { return primitive_type; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "identifiers", function() { return identifiers; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argument_list", function() { return argument_list; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "type_with_extended_attributes", function() { return type_with_extended_attributes; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "return_type", function() { return return_type; }); -/* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); -/* harmony import */ var _argument_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7); -/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11); -/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringTypes", function() { return stringTypes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argumentNameKeywords", function() { return argumentNameKeywords; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Tokeniser", function() { return Tokeniser; }); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); +// These regular expressions use the sticky flag so they will only match at +// the current location (ie. the offset of lastIndex). +const tokenRe = { + // This expression uses a lookahead assertion to catch false matches + // against integers early. + "decimal": /-?(?=[0-9]*\.|[0-9]+[eE])(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/y, + "integer": /-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/y, + "identifier": /[_-]?[A-Za-z][0-9A-Z_a-z-]*/y, + "string": /"[^"]*"/y, + "whitespace": /[\t\n\r ]+/y, + "comment": /((\/(\/.*|\*([^*]|\*[^/])*\*\/)[\t\n\r ]*)+)/y, + "other": /[^\t\n\r 0-9A-Za-z]/y +}; + +const stringTypes = [ + "ByteString", + "DOMString", + "USVString" +]; +const argumentNameKeywords = [ + "async", + "attribute", + "callback", + "const", + "deleter", + "dictionary", + "enum", + "getter", + "includes", + "inherit", + "interface", + "iterable", + "maplike", + "namespace", + "partial", + "required", + "setlike", + "setter", + "static", + "stringifier", + "typedef", + "unrestricted" +]; +const nonRegexTerminals = [ + "-Infinity", + "FrozenArray", + "Infinity", + "NaN", + "Promise", + "async", + "boolean", + "byte", + "double", + "false", + "float", + "long", + "mixin", + "null", + "octet", + "optional", + "or", + "readonly", + "record", + "sequence", + "short", + "true", + "unsigned", + "void" +].concat(argumentNameKeywords, stringTypes); -/** - * @param {string} identifier - */ -function unescape(identifier) { - return identifier.startsWith('_') ? identifier.slice(1) : identifier; -} +const punctuations = [ + "(", + ")", + ",", + "...", + ":", + ";", + "<", + "=", + ">", + "?", + "[", + "]", + "{", + "}" +]; /** - * Parses comma-separated list - * @param {import("../tokeniser").Tokeniser} tokeniser - * @param {object} args - * @param {Function} args.parser parser function for each item - * @param {boolean} [args.allowDangler] whether to allow dangling comma - * @param {string} [args.listName] the name to be shown on error messages + * @param {string} str */ -function list(tokeniser, { parser, allowDangler, listName = "list" }) { - const first = parser(tokeniser); - if (!first) { - return []; - } - first.tokens.separator = tokeniser.consume(","); - const items = [first]; - while (first.tokens.separator) { - const item = parser(tokeniser); - if (!item) { - if (!allowDangler) { - tokeniser.error(`Trailing comma in ${listName}`); +function tokenise(str) { + const tokens = []; + let lastCharIndex = 0; + let trivia = ""; + let line = 1; + let index = 0; + while (lastCharIndex < str.length) { + const nextChar = str.charAt(lastCharIndex); + let result = -1; + + if (/[\t\n\r ]/.test(nextChar)) { + result = attemptTokenMatch("whitespace", { noFlushTrivia: true }); + } else if (nextChar === '/') { + result = attemptTokenMatch("comment", { noFlushTrivia: true }); + } + + if (result !== -1) { + const currentTrivia = tokens.pop().value; + line += (currentTrivia.match(/\n/g) || []).length; + trivia += currentTrivia; + index -= 1; + } else if (/[-0-9.A-Z_a-z]/.test(nextChar)) { + result = attemptTokenMatch("decimal"); + if (result === -1) { + result = attemptTokenMatch("integer"); } - break; + if (result === -1) { + result = attemptTokenMatch("identifier"); + const token = tokens[tokens.length - 1]; + if (result !== -1 && nonRegexTerminals.includes(token.value)) { + token.type = token.value; + } + } + } else if (nextChar === '"') { + result = attemptTokenMatch("string"); } - item.tokens.separator = tokeniser.consume(","); - items.push(item); - if (!item.tokens.separator) break; + + for (const punctuation of punctuations) { + if (str.startsWith(punctuation, lastCharIndex)) { + tokens.push({ type: punctuation, value: punctuation, trivia, line, index }); + trivia = ""; + lastCharIndex += punctuation.length; + result = lastCharIndex; + break; + } + } + + // other as the last try + if (result === -1) { + result = attemptTokenMatch("other"); + } + if (result === -1) { + throw new Error("Token stream not progressing"); + } + lastCharIndex = result; + index += 1; } - return items; -} -/** - * @param {import("../tokeniser").Tokeniser} tokeniser - */ -function const_value(tokeniser) { - return tokeniser.consume("true", "false", "Infinity", "-Infinity", "NaN", "decimal", "integer"); -} + // remaining trivia as eof + tokens.push({ + type: "eof", + value: "", + trivia + }); -/** - * @param {object} token - * @param {string} token.type - * @param {string} token.value - */ -function const_data({ type, value }) { - switch (type) { - case "true": - case "false": - return { type: "boolean", value: type === "true" }; - case "Infinity": - case "-Infinity": - return { type: "Infinity", negative: type.startsWith("-") }; - case "[": - return { type: "sequence", value: [] }; - case "{": - return { type: "dictionary" }; - case "decimal": - case "integer": - return { type: "number", value }; - case "string": - return { type: "string", value: value.slice(1, -1) }; - default: - return { type }; + return tokens; + + /** + * @param {keyof tokenRe} type + * @param {object} [options] + * @param {boolean} [options.noFlushTrivia] + */ + function attemptTokenMatch(type, { noFlushTrivia } = {}) { + const re = tokenRe[type]; + re.lastIndex = lastCharIndex; + const result = re.exec(str); + if (result) { + tokens.push({ type, value: result[0], trivia, line, index }); + if (!noFlushTrivia) { + trivia = ""; + } + return re.lastIndex; + } + return -1; } } -/** - * @param {import("../tokeniser").Tokeniser} tokeniser - */ -function primitive_type(tokeniser) { - function integer_type() { - const prefix = tokeniser.consume("unsigned"); - const base = tokeniser.consume("short", "long"); - if (base) { - const postfix = tokeniser.consume("long"); - return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { prefix, base, postfix } }); - } - if (prefix) tokeniser.error("Failed to parse integer type"); +class Tokeniser { + /** + * @param {string} idl + */ + constructor(idl) { + this.source = tokenise(idl); + this.position = 0; } - function decimal_type() { - const prefix = tokeniser.consume("unrestricted"); - const base = tokeniser.consume("float", "double"); - if (base) { - return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { prefix, base } }); - } - if (prefix) tokeniser.error("Failed to parse float type"); + /** + * @param {string} message + */ + error(message) { + throw new WebIDLParseError(Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["syntaxError"])(this.source, this.position, this.current, message)); } - const { source } = tokeniser; - const num_type = integer_type(tokeniser) || decimal_type(tokeniser); - if (num_type) return num_type; - const base = tokeniser.consume("boolean", "byte", "octet"); - if (base) { - return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { base } }); + /** + * @param {string} type + */ + probe(type) { + return this.source.length > this.position && this.source[this.position].type === type; } -} -/** - * @param {import("../tokeniser").Tokeniser} tokeniser - */ -function identifiers(tokeniser) { - const ids = list(tokeniser, { parser: _token_js__WEBPACK_IMPORTED_MODULE_2__["Token"].parser(tokeniser, "identifier"), listName: "identifier list" }); - if (!ids.length) { - tokeniser.error("Expected identifiers but none found"); + /** + * @param {...string} candidates + */ + consume(...candidates) { + for (const type of candidates) { + if (!this.probe(type)) continue; + const token = this.source[this.position]; + this.position++; + return token; + } } - return ids; -} -/** - * @param {import("../tokeniser").Tokeniser} tokeniser - */ -function argument_list(tokeniser) { - return list(tokeniser, { parser: _argument_js__WEBPACK_IMPORTED_MODULE_1__["Argument"].parse, listName: "arguments list" }); + /** + * @param {number} position + */ + unconsume(position) { + this.position = position; + } } -/** - * @param {import("../tokeniser").Tokeniser} tokeniser - * @param {string} typeName - */ -function type_with_extended_attributes(tokeniser, typeName) { - const extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__["ExtendedAttributes"].parse(tokeniser); - const ret = _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"].parse(tokeniser, typeName); - if (ret) ret.extAttrs = extAttrs; - return ret; -} +class WebIDLParseError extends Error { + constructor({ message, bareMessage, context, line, sourceName, input, tokens }) { + super(message); -/** - * @param {import("../tokeniser").Tokeniser} tokeniser - * @param {string} typeName - */ -function return_type(tokeniser, typeName) { - const typ = _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"].parse(tokeniser, typeName || "return-type"); - if (typ) { - return typ; - } - const voidToken = tokeniser.consume("void"); - if (voidToken) { - const ret = new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source: tokeniser.source, tokens: { base: voidToken } }); - ret.type = "return-type"; - return ret; + this.name = "WebIDLParseError"; // not to be mangled + this.bareMessage = bareMessage; + this.context = context; + this.line = line; + this.sourceName = sourceName; + this.input = input; + this.tokens = tokens; } } @@ -816,903 +488,1774 @@ function return_type(tokeniser, typeName) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Type", function() { return Type; }); -/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); -/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); -/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5); - - - +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "syntaxError", function() { return syntaxError; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validationError", function() { return validationError; }); +/** + * @param {string} text + */ +function lastLine(text) { + const splitted = text.split("\n"); + return splitted[splitted.length - 1]; +} /** - * @param {import("../tokeniser").Tokeniser} tokeniser - * @param {string} typeName + * @typedef {object} WebIDL2ErrorOptions + * @property {"error" | "warning"} level + * + * @param {string} message error message + * @param {"Syntax" | "Validation"} kind error type + * @param {WebIDL2ErrorOptions} [options] */ -function generic_type(tokeniser, typeName) { - const base = tokeniser.consume("FrozenArray", "Promise", "sequence", "record"); - if (!base) { - return; +function error(source, position, current, message, kind, { level = "error" } = {}) { + /** + * @param {number} count + */ + function sliceTokens(count) { + return count > 0 ? + source.slice(position, position + count) : + source.slice(Math.max(position + count, 0), position); } - const ret = new Type({ source: tokeniser.source, tokens: { base } }); - ret.tokens.open = tokeniser.consume("<") || tokeniser.error(`No opening bracket after ${base.type}`); - switch (base.type) { - case "Promise": { - if (tokeniser.probe("[")) tokeniser.error("Promise type cannot have extended attribute"); - const subtype = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser, typeName) || tokeniser.error("Missing Promise subtype"); - ret.subtype.push(subtype); - break; - } - case "sequence": - case "FrozenArray": { - const subtype = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, typeName) || tokeniser.error(`Missing ${base.type} subtype`); - ret.subtype.push(subtype); - break; + + function tokensToText(inputs, { precedes } = {}) { + const text = inputs.map(t => t.trivia + t.value).join(""); + const nextToken = source[position]; + if (nextToken.type === "eof") { + return text; } - case "record": { - if (tokeniser.probe("[")) tokeniser.error("Record key cannot have extended attribute"); - const keyType = tokeniser.consume(..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"]) || tokeniser.error(`Record key must be one of: ${_tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"].join(", ")}`); - const keyIdlType = new Type({ source: tokeniser.source, tokens: { base: keyType }}); - keyIdlType.tokens.separator = tokeniser.consume(",") || tokeniser.error("Missing comma after record key type"); - keyIdlType.type = typeName; - const valueType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, typeName) || tokeniser.error("Error parsing generic type record"); - ret.subtype.push(keyIdlType, valueType); - break; + if (precedes) { + return text + nextToken.trivia; } + return text.slice(nextToken.trivia.length); } - if (!ret.idlType) tokeniser.error(`Error parsing generic type ${base.type}`); - ret.tokens.close = tokeniser.consume(">") || tokeniser.error(`Missing closing bracket after ${base.type}`); - return ret; -} -/** - * @param {import("../tokeniser").Tokeniser} tokeniser - */ -function type_suffix(tokeniser, obj) { - const nullable = tokeniser.consume("?"); - if (nullable) { - obj.tokens.nullable = nullable; - } - if (tokeniser.probe("?")) tokeniser.error("Can't nullable more than once"); + const maxTokens = 5; // arbitrary but works well enough + const line = + source[position].type !== "eof" ? source[position].line : + source.length > 1 ? source[position - 1].line : + 1; + + const precedingLastLine = lastLine( + tokensToText(sliceTokens(-maxTokens), { precedes: true }) + ); + + const subsequentTokens = sliceTokens(maxTokens); + const subsequentText = tokensToText(subsequentTokens); + const subsequentFirstLine = subsequentText.split("\n")[0]; + + const spaced = " ".repeat(precedingLastLine.length) + "^"; + const sourceContext = precedingLastLine + subsequentFirstLine + "\n" + spaced; + + const contextType = kind === "Syntax" ? "since" : "inside"; + const inSourceName = source.name ? ` in ${source.name}` : ""; + const grammaticalContext = (current && current.name) ? `, ${contextType} \`${current.partial ? "partial " : ""}${current.type} ${current.name}\`` : ""; + const context = `${kind} error at line ${line}${inSourceName}${grammaticalContext}:\n${sourceContext}`; + return { + message: `${context} ${message}`, + bareMessage: message, + context, + line, + sourceName: source.name, + level, + input: subsequentText, + tokens: subsequentTokens + }; } /** - * @param {import("../tokeniser").Tokeniser} tokeniser - * @param {string} typeName + * @param {string} message error message */ -function single_type(tokeniser, typeName) { - let ret = generic_type(tokeniser, typeName) || Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["primitive_type"])(tokeniser); - if (!ret) { - const base = tokeniser.consume("identifier", ..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"]); - if (!base) { - return; - } - ret = new Type({ source: tokeniser.source, tokens: { base } }); - if (tokeniser.probe("<")) tokeniser.error(`Unsupported generic type ${base.value}`); - } - if (ret.generic === "Promise" && tokeniser.probe("?")) { - tokeniser.error("Promise type cannot be nullable"); - } - ret.type = typeName || null; - type_suffix(tokeniser, ret); - if (ret.nullable && ret.idlType === "any") tokeniser.error("Type `any` cannot be made nullable"); - return ret; +function syntaxError(source, position, current, message) { + return error(source, position, current, message, "Syntax"); } /** - * @param {import("../tokeniser").Tokeniser} tokeniser - * @param {string} type + * @param {string} message error message + * @param {WebIDL2ErrorOptions} [options] */ -function union_type(tokeniser, type) { - const tokens = {}; - tokens.open = tokeniser.consume("("); - if (!tokens.open) return; - const ret = new Type({ source: tokeniser.source, tokens }); - ret.type = type || null; - while (true) { - const typ = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser) || tokeniser.error("No type after open parenthesis or 'or' in union type"); - if (typ.idlType === "any") tokeniser.error("Type `any` cannot be included in a union type"); - ret.subtype.push(typ); - const or = tokeniser.consume("or"); - if (or) { - typ.tokens.separator = or; - } - else break; - } - if (ret.idlType.length < 2) { - tokeniser.error("At least two types are expected in a union type but found less"); - } - tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated union type"); - type_suffix(tokeniser, ret); - return ret; +function validationError(source, token, current, message, options) { + return error(source, token.index, current, message, "Validation", options); } -class Type extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + +/***/ }), +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Enum", function() { return Enum; }); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5); +/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7); + + + + +class EnumValue extends _token_js__WEBPACK_IMPORTED_MODULE_1__["Token"] { /** * @param {import("../tokeniser").Tokeniser} tokeniser - * @param {string} typeName */ - static parse(tokeniser, typeName) { - return single_type(tokeniser, typeName) || union_type(tokeniser, typeName); + static parse(tokeniser) { + const value = tokeniser.consume("string"); + if (value) { + return new EnumValue({ source: tokeniser.source, tokens: { value } }); + } } - constructor({ source, tokens }) { - super({ source, tokens }); - Object.defineProperty(this, "subtype", { value: [] }); - this.extAttrs = []; + get type() { + return "enum-value"; + } + get value() { + return super.value.slice(1, -1); } +} - get generic() { - if (this.subtype.length && this.tokens.base) { - return this.tokens.base.value; +class Enum extends _base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = {}; + tokens.base = tokeniser.consume("enum"); + if (!tokens.base) { + return; } - return ""; - } - get nullable() { - return Boolean(this.tokens.nullable); + tokens.name = tokeniser.consume("identifier") || tokeniser.error("No name for enum"); + const ret = tokeniser.current = new Enum({ source: tokeniser.source, tokens }); + tokens.open = tokeniser.consume("{") || tokeniser.error("Bodyless enum"); + ret.values = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["list"])(tokeniser, { + parser: EnumValue.parse, + allowDangler: true, + listName: "enumeration" + }); + if (tokeniser.probe("string")) { + tokeniser.error("No comma between enum values"); + } + tokens.close = tokeniser.consume("}") || tokeniser.error("Unexpected value in enum"); + if (!ret.values.length) { + tokeniser.error("No value in enum"); + } + tokens.termination = tokeniser.consume(";") || tokeniser.error("No semicolon after enum"); + return ret; } - get union() { - return Boolean(this.subtype.length) && !this.tokens.base; + + get type() { + return "enum"; } - get idlType() { - if (this.subtype.length) { - return this.subtype; - } - // Adding prefixes/postfixes for "unrestricted float", etc. - const name = [ - this.tokens.prefix, - this.tokens.base, - this.tokens.postfix - ].filter(t => t).map(t => t.value).join(" "); - return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(name); + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); } } /***/ }), -/* 4 */ +/* 5 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Base", function() { return Base; }); -class Base { - constructor({ source, tokens }) { - Object.defineProperties(this, { - source: { value: source }, - tokens: { value: tokens } - }); - } +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unescape", function() { return unescape; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "list", function() { return list; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "const_value", function() { return const_value; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "const_data", function() { return const_data; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "primitive_type", function() { return primitive_type; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "identifiers", function() { return identifiers; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argument_list", function() { return argument_list; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "type_with_extended_attributes", function() { return type_with_extended_attributes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "return_type", function() { return return_type; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringifier", function() { return stringifier; }); +/* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _argument_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9); +/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13); +/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(14); +/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(15); - toJSON() { - const json = { type: undefined, name: undefined, inheritance: undefined }; - let proto = this; - while (proto !== Object.prototype) { - const descMap = Object.getOwnPropertyDescriptors(proto); - for (const [key, value] of Object.entries(descMap)) { - if (value.enumerable || value.get) { - json[key] = this[key]; - } - } - proto = Object.getPrototypeOf(proto); - } - return json; - } -} -/***/ }), -/* 5 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringTypes", function() { return stringTypes; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argumentNameKeywords", function() { return argumentNameKeywords; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Tokeniser", function() { return Tokeniser; }); -/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); -// These regular expressions use the sticky flag so they will only match at -// the current location (ie. the offset of lastIndex). -const tokenRe = { - // This expression uses a lookahead assertion to catch false matches - // against integers early. - "decimal": /-?(?=[0-9]*\.|[0-9]+[eE])(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/y, - "integer": /-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/y, - "identifier": /[_-]?[A-Za-z][0-9A-Z_a-z-]*/y, - "string": /"[^"]*"/y, - "whitespace": /[\t\n\r ]+/y, - "comment": /((\/(\/.*|\*([^*]|\*[^/])*\*\/)[\t\n\r ]*)+)/y, - "other": /[^\t\n\r 0-9A-Za-z]/y -}; -const stringTypes = [ - "ByteString", - "DOMString", - "USVString" -]; +/** + * @param {string} identifier + */ +function unescape(identifier) { + return identifier.startsWith('_') ? identifier.slice(1) : identifier; +} -const argumentNameKeywords = [ - "attribute", - "callback", - "const", - "deleter", - "dictionary", - "enum", - "getter", - "includes", - "inherit", - "interface", - "iterable", - "maplike", - "namespace", - "partial", - "required", - "setlike", - "setter", - "static", - "stringifier", - "typedef", - "unrestricted" -]; +/** + * Parses comma-separated list + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {object} args + * @param {Function} args.parser parser function for each item + * @param {boolean} [args.allowDangler] whether to allow dangling comma + * @param {string} [args.listName] the name to be shown on error messages + */ +function list(tokeniser, { parser, allowDangler, listName = "list" }) { + const first = parser(tokeniser); + if (!first) { + return []; + } + first.tokens.separator = tokeniser.consume(","); + const items = [first]; + while (first.tokens.separator) { + const item = parser(tokeniser); + if (!item) { + if (!allowDangler) { + tokeniser.error(`Trailing comma in ${listName}`); + } + break; + } + item.tokens.separator = tokeniser.consume(","); + items.push(item); + if (!item.tokens.separator) break; + } + return items; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function const_value(tokeniser) { + return tokeniser.consume("true", "false", "Infinity", "-Infinity", "NaN", "decimal", "integer"); +} + +/** + * @param {object} token + * @param {string} token.type + * @param {string} token.value + */ +function const_data({ type, value }) { + switch (type) { + case "true": + case "false": + return { type: "boolean", value: type === "true" }; + case "Infinity": + case "-Infinity": + return { type: "Infinity", negative: type.startsWith("-") }; + case "[": + return { type: "sequence", value: [] }; + case "{": + return { type: "dictionary" }; + case "decimal": + case "integer": + return { type: "number", value }; + case "string": + return { type: "string", value: value.slice(1, -1) }; + default: + return { type }; + } +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function primitive_type(tokeniser) { + function integer_type() { + const prefix = tokeniser.consume("unsigned"); + const base = tokeniser.consume("short", "long"); + if (base) { + const postfix = tokeniser.consume("long"); + return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { prefix, base, postfix } }); + } + if (prefix) tokeniser.error("Failed to parse integer type"); + } + + function decimal_type() { + const prefix = tokeniser.consume("unrestricted"); + const base = tokeniser.consume("float", "double"); + if (base) { + return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { prefix, base } }); + } + if (prefix) tokeniser.error("Failed to parse float type"); + } + + const { source } = tokeniser; + const num_type = integer_type(tokeniser) || decimal_type(tokeniser); + if (num_type) return num_type; + const base = tokeniser.consume("boolean", "byte", "octet"); + if (base) { + return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { base } }); + } +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function identifiers(tokeniser) { + const ids = list(tokeniser, { parser: _token_js__WEBPACK_IMPORTED_MODULE_2__["Token"].parser(tokeniser, "identifier"), listName: "identifier list" }); + if (!ids.length) { + tokeniser.error("Expected identifiers but none found"); + } + return ids; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function argument_list(tokeniser) { + return list(tokeniser, { parser: _argument_js__WEBPACK_IMPORTED_MODULE_1__["Argument"].parse, listName: "arguments list" }); +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ +function type_with_extended_attributes(tokeniser, typeName) { + const extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__["ExtendedAttributes"].parse(tokeniser); + const ret = _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"].parse(tokeniser, typeName); + if (ret) ret.extAttrs = extAttrs; + return ret; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ +function return_type(tokeniser, typeName) { + const typ = _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"].parse(tokeniser, typeName || "return-type"); + if (typ) { + return typ; + } + const voidToken = tokeniser.consume("void"); + if (voidToken) { + const ret = new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source: tokeniser.source, tokens: { base: voidToken } }); + ret.type = "return-type"; + return ret; + } +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function stringifier(tokeniser) { + const special = tokeniser.consume("stringifier"); + if (!special) return; + const member = _attribute_js__WEBPACK_IMPORTED_MODULE_5__["Attribute"].parse(tokeniser, { special }) || + _operation_js__WEBPACK_IMPORTED_MODULE_4__["Operation"].parse(tokeniser, { special }) || + tokeniser.error("Unterminated stringifier"); + return member; +} + + +/***/ }), +/* 6 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Type", function() { return Type; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); +/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3); +/* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8); + + + + + + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ +function generic_type(tokeniser, typeName) { + const base = tokeniser.consume("FrozenArray", "Promise", "sequence", "record"); + if (!base) { + return; + } + const ret = new Type({ source: tokeniser.source, tokens: { base } }); + ret.tokens.open = tokeniser.consume("<") || tokeniser.error(`No opening bracket after ${base.type}`); + switch (base.type) { + case "Promise": { + if (tokeniser.probe("[")) tokeniser.error("Promise type cannot have extended attribute"); + const subtype = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser, typeName) || tokeniser.error("Missing Promise subtype"); + ret.subtype.push(subtype); + break; + } + case "sequence": + case "FrozenArray": { + const subtype = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, typeName) || tokeniser.error(`Missing ${base.type} subtype`); + ret.subtype.push(subtype); + break; + } + case "record": { + if (tokeniser.probe("[")) tokeniser.error("Record key cannot have extended attribute"); + const keyType = tokeniser.consume(..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"]) || tokeniser.error(`Record key must be one of: ${_tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"].join(", ")}`); + const keyIdlType = new Type({ source: tokeniser.source, tokens: { base: keyType }}); + keyIdlType.tokens.separator = tokeniser.consume(",") || tokeniser.error("Missing comma after record key type"); + keyIdlType.type = typeName; + const valueType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, typeName) || tokeniser.error("Error parsing generic type record"); + ret.subtype.push(keyIdlType, valueType); + break; + } + } + if (!ret.idlType) tokeniser.error(`Error parsing generic type ${base.type}`); + ret.tokens.close = tokeniser.consume(">") || tokeniser.error(`Missing closing bracket after ${base.type}`); + return ret; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function type_suffix(tokeniser, obj) { + const nullable = tokeniser.consume("?"); + if (nullable) { + obj.tokens.nullable = nullable; + } + if (tokeniser.probe("?")) tokeniser.error("Can't nullable more than once"); +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ +function single_type(tokeniser, typeName) { + let ret = generic_type(tokeniser, typeName) || Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["primitive_type"])(tokeniser); + if (!ret) { + const base = tokeniser.consume("identifier", ..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"]); + if (!base) { + return; + } + ret = new Type({ source: tokeniser.source, tokens: { base } }); + if (tokeniser.probe("<")) tokeniser.error(`Unsupported generic type ${base.value}`); + } + if (ret.generic === "Promise" && tokeniser.probe("?")) { + tokeniser.error("Promise type cannot be nullable"); + } + ret.type = typeName || null; + type_suffix(tokeniser, ret); + if (ret.nullable && ret.idlType === "any") tokeniser.error("Type `any` cannot be made nullable"); + return ret; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} type + */ +function union_type(tokeniser, type) { + const tokens = {}; + tokens.open = tokeniser.consume("("); + if (!tokens.open) return; + const ret = new Type({ source: tokeniser.source, tokens }); + ret.type = type || null; + while (true) { + const typ = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser) || tokeniser.error("No type after open parenthesis or 'or' in union type"); + if (typ.idlType === "any") tokeniser.error("Type `any` cannot be included in a union type"); + ret.subtype.push(typ); + const or = tokeniser.consume("or"); + if (or) { + typ.tokens.separator = or; + } + else break; + } + if (ret.idlType.length < 2) { + tokeniser.error("At least two types are expected in a union type but found less"); + } + tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated union type"); + type_suffix(tokeniser, ret); + return ret; +} + +class Type extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ + static parse(tokeniser, typeName) { + return single_type(tokeniser, typeName) || union_type(tokeniser, typeName); + } + + constructor({ source, tokens }) { + super({ source, tokens }); + Object.defineProperty(this, "subtype", { value: [] }); + this.extAttrs = []; + } + + get generic() { + if (this.subtype.length && this.tokens.base) { + return this.tokens.base.value; + } + return ""; + } + get nullable() { + return Boolean(this.tokens.nullable); + } + get union() { + return Boolean(this.subtype.length) && !this.tokens.base; + } + get idlType() { + if (this.subtype.length) { + return this.subtype; + } + // Adding prefixes/postfixes for "unrestricted float", etc. + const name = [ + this.tokens.prefix, + this.tokens.base, + this.tokens.postfix + ].filter(t => t).map(t => t.value).join(" "); + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(name); + } + + *validate(defs) { + /* + * If a union is nullable, its subunions cannot include a dictionary + * If not, subunions may include dictionaries if each union is not nullable + */ + const typedef = !this.union && defs.unique.get(this.idlType); + const target = + this.union ? this : + (typedef && typedef.type === "typedef") ? typedef.idlType : + undefined; + if (target && this.nullable) { + // do not allow any dictionary + const reference = Object(_validators_helpers_js__WEBPACK_IMPORTED_MODULE_4__["idlTypeIncludesDictionary"])(target, defs); + if (reference) { + const targetToken = (this.union ? reference : this).tokens.base; + const message = `Nullable union cannot include a dictionary type`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(this.source, targetToken, this, message); + } + } else { + // allow some dictionary + for (const subtype of this.subtype) { + yield* subtype.validate(defs); + } + } + } +} + + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Base", function() { return Base; }); +class Base { + constructor({ source, tokens }) { + Object.defineProperties(this, { + source: { value: source }, + tokens: { value: tokens } + }); + } + + toJSON() { + const json = { type: undefined, name: undefined, inheritance: undefined }; + let proto = this; + while (proto !== Object.prototype) { + const descMap = Object.getOwnPropertyDescriptors(proto); + for (const [key, value] of Object.entries(descMap)) { + if (value.enumerable || value.get) { + json[key] = this[key]; + } + } + proto = Object.getPrototypeOf(proto); + } + return json; + } +} -const nonRegexTerminals = [ - "-Infinity", - "FrozenArray", - "Infinity", - "NaN", - "Promise", - "boolean", - "byte", - "double", - "false", - "float", - "implements", - "legacyiterable", - "long", - "mixin", - "null", - "octet", - "optional", - "or", - "readonly", - "record", - "sequence", - "short", - "true", - "unsigned", - "void" -].concat(argumentNameKeywords, stringTypes); -const punctuations = [ - "(", - ")", - ",", - "...", - ":", - ";", - "<", - "=", - ">", - "?", - "[", - "]", - "{", - "}" -]; +/***/ }), +/* 8 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dictionaryWithinUnion", function() { return dictionaryWithinUnion; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "idlTypeIncludesDictionary", function() { return idlTypeIncludesDictionary; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "referencesTypedef", function() { return referencesTypedef; }); +/** + * Yields direct references to dictionary within union. + */ +function* dictionaryWithinUnion(subtypes, defs) { + for (const subtype of subtypes) { + const def = defs.unique.get(subtype.idlType); + if (def && def.type === "dictionary") { + yield subtype; + } + } +} + +/** + * @return the type reference that ultimately includes dictionary. + */ +function idlTypeIncludesDictionary(idlType, defs) { + if (!idlType.union) { + const def = defs.unique.get(idlType.idlType); + if (!def) { + return; + } + if (def.type === "typedef") { + const { typedefIncludesDictionary} = defs.cache; + if (typedefIncludesDictionary.has(def)) { + // Note that this also halts when it met indeterminate state + // to prevent infinite recursion + return typedefIncludesDictionary.get(def); + } + defs.cache.typedefIncludesDictionary.set(def, undefined); // indeterminate state + const result = idlTypeIncludesDictionary(def.idlType, defs); + defs.cache.typedefIncludesDictionary.set(def, result); + if (result) { + return idlType; + } + } + if (def.type === "dictionary") { + return idlType; + } + } + for (const subtype of idlType.subtype) { + const result = idlTypeIncludesDictionary(subtype, defs); + if (result) { + if (subtype.union) { + return result; + } + return subtype; + } + } +} + +/** + * @return true if the idlType directly references a typedef. + */ +function referencesTypedef(idlType, defs) { + const result = defs.unique.get(idlType.idlType); + return result && result.type === "typedef"; +} + + +/***/ }), +/* 9 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Argument", function() { return Argument; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10); +/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); +/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3); +/* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(8); + + + + + + + + +class Argument extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const start_position = tokeniser.position; + const tokens = {}; + const ret = new Argument({ source: tokeniser.source, tokens }); + ret.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__["ExtendedAttributes"].parse(tokeniser); + tokens.optional = tokeniser.consume("optional"); + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_3__["type_with_extended_attributes"])(tokeniser, "argument-type"); + if (!ret.idlType) { + return tokeniser.unconsume(start_position); + } + if (!tokens.optional) { + tokens.variadic = tokeniser.consume("..."); + } + tokens.name = tokeniser.consume("identifier", ..._tokeniser_js__WEBPACK_IMPORTED_MODULE_4__["argumentNameKeywords"]); + if (!tokens.name) { + return tokeniser.unconsume(start_position); + } + ret.default = tokens.optional ? _default_js__WEBPACK_IMPORTED_MODULE_1__["Default"].parse(tokeniser) : null; + return ret; + } + + get type() { + return "argument"; + } + get optional() { + return !!this.tokens.optional; + } + get variadic() { + return !!this.tokens.variadic; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_3__["unescape"])(this.tokens.name.value); + } + + *validate(defs) { + yield* this.idlType.validate(defs); + if (Object(_validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__["idlTypeIncludesDictionary"])(this.idlType, defs)) { + if (this.optional && !this.default) { + const message = `Optional dictionary arguments must have a default value of \`{}\`.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_5__["validationError"])(this.source, this.tokens.name, this, message); + } + if (this.idlType.nullable) { + const message = `Dictionary arguments cannot be nullable.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_5__["validationError"])(this.source, this.tokens.name, this, message); + } + } + } +} + + +/***/ }), +/* 10 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Default", function() { return Default; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); + + + +class Default extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const assign = tokeniser.consume("="); + if (!assign) { + return null; + } + const def = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_value"])(tokeniser) || tokeniser.consume("string", "null", "[", "{") || tokeniser.error("No value for default"); + const expression = [def]; + if (def.type === "[") { + const close = tokeniser.consume("]") || tokeniser.error("Default sequence value must be empty"); + expression.push(close); + } else if (def.type === "{") { + const close = tokeniser.consume("}") || tokeniser.error("Default dictionary value must be empty"); + expression.push(close); + } + return new Default({ source: tokeniser.source, tokens: { assign }, expression }); + } + + constructor({ source, tokens, expression }) { + super({ source, tokens }); + Object.defineProperty(this, "expression", { value: expression }); + } + + get type() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).type; + } + get value() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).value; + } + get negative() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).negative; + } +} + + +/***/ }), +/* 11 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExtendedAttributes", function() { return ExtendedAttributes; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _array_base_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3); + + + + + +class ExtendedAttributeParameters extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = { assign: tokeniser.consume("=") }; + const ret = new ExtendedAttributeParameters({ source: tokeniser.source, tokens }); + if (tokens.assign) { + tokens.secondaryName = tokeniser.consume("identifier", "decimal", "integer", "string"); + } + tokens.open = tokeniser.consume("("); + if (tokens.open) { + ret.list = ret.rhsType === "identifier-list" ? + // [Exposed=(Window,Worker)] + Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["identifiers"])(tokeniser) : + // [NamedConstructor=Audio(DOMString src)] or [Constructor(DOMString str)] + Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["argument_list"])(tokeniser); + tokens.close = tokeniser.consume(")") || tokeniser.error("Unexpected token in extended attribute argument list"); + } else if (ret.hasRhs && !tokens.secondaryName) { + tokeniser.error("No right hand side to extended attribute assignment"); + } + return ret; + } + + get rhsType() { + return !this.tokens.assign ? null : + !this.tokens.secondaryName ? "identifier-list" : + this.tokens.secondaryName.type; + } +} + +class SimpleExtendedAttribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const name = tokeniser.consume("identifier"); + if (name) { + return new SimpleExtendedAttribute({ + source: tokeniser.source, + tokens: { name }, + params: ExtendedAttributeParameters.parse(tokeniser) + }); + } + } + + constructor({ source, tokens, params }) { + super({ source, tokens }); + Object.defineProperty(this, "params", { value: params }); + } + + get type() { + return "extended-attribute"; + } + get name() { + return this.tokens.name.value; + } + get rhs() { + const { rhsType: type, tokens, list } = this.params; + if (!type) { + return null; + } + const value = type === "identifier-list" ? list : tokens.secondaryName.value; + return { type, value }; + } + get arguments() { + const { rhsType, list } = this.params; + if (!list || rhsType === "identifier-list") { + return []; + } + return list; + } + + *validate(defs) { + if (this.name === "NoInterfaceObject") { + const message = `\`[NoInterfaceObject]\` extended attribute is an \ +undesirable feature that may be removed from Web IDL in the future. Refer to the \ +[relevant upstream PR](https://github.com/heycam/webidl/pull/609) for more \ +information.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(this.source, this.tokens.name, this, message, { level: "warning" }); + } + for (const arg of this.arguments) { + yield* arg.validate(defs); + } + } +} -/** - * @param {string} str - */ -function tokenise(str) { - const tokens = []; - let lastCharIndex = 0; - let trivia = ""; - let line = 1; - let index = 0; - while (lastCharIndex < str.length) { - const nextChar = str.charAt(lastCharIndex); - let result = -1; +// Note: we parse something simpler than the official syntax. It's all that ever +// seems to be used +class ExtendedAttributes extends _array_base_js__WEBPACK_IMPORTED_MODULE_1__["ArrayBase"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = {}; + tokens.open = tokeniser.consume("["); + if (!tokens.open) return new ExtendedAttributes({}); + const ret = new ExtendedAttributes({ source: tokeniser.source, tokens }); + ret.push(...Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["list"])(tokeniser, { + parser: SimpleExtendedAttribute.parse, + listName: "extended attribute" + })); + tokens.close = tokeniser.consume("]") || tokeniser.error("Unexpected closing token of extended attribute"); + if (!ret.length) { + tokeniser.error("Found an empty extended attribute"); + } + if (tokeniser.probe("[")) { + tokeniser.error("Illegal double extended attribute lists, consider merging them"); + } + return ret; + } - if (/[\t\n\r ]/.test(nextChar)) { - result = attemptTokenMatch("whitespace", { noFlushTrivia: true }); - } else if (nextChar === '/') { - result = attemptTokenMatch("comment", { noFlushTrivia: true }); + *validate(defs) { + for (const extAttr of this) { + yield* extAttr.validate(defs); } + } +} - if (result !== -1) { - const currentTrivia = tokens.pop().value; - line += (currentTrivia.match(/\n/g) || []).length; - trivia += currentTrivia; - index -= 1; - } else if (/[-0-9.A-Z_a-z]/.test(nextChar)) { - result = attemptTokenMatch("decimal"); - if (result === -1) { - result = attemptTokenMatch("integer"); + +/***/ }), +/* 12 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArrayBase", function() { return ArrayBase; }); +class ArrayBase extends Array { + constructor({ source, tokens }) { + super(); + Object.defineProperties(this, { + source: { value: source }, + tokens: { value: tokens } + }); + } +} + + +/***/ }), +/* 13 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Token", function() { return Token; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); + + +class Token extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} type + */ + static parser(tokeniser, type) { + return () => { + const value = tokeniser.consume(type); + if (value) { + return new Token({ source: tokeniser.source, tokens: { value } }); } - if (result === -1) { - result = attemptTokenMatch("identifier"); - const token = tokens[tokens.length - 1]; - if (result !== -1 && nonRegexTerminals.includes(token.value)) { - token.type = token.value; - } + }; + } + + get value() { + return this.tokens.value.value; + } +} + + +/***/ }), +/* 14 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Operation", function() { return Operation; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); + + + +class Operation extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + */ + static parse(tokeniser, { special, regular } = {}) { + const tokens = { special }; + const ret = new Operation({ source: tokeniser.source, tokens }); + if (special && special.value === "stringifier") { + tokens.termination = tokeniser.consume(";"); + if (tokens.termination) { + ret.arguments = []; + return ret; } - } else if (nextChar === '"') { - result = attemptTokenMatch("string"); } + if (!special && !regular) { + tokens.special = tokeniser.consume("getter", "setter", "deleter"); + } + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser) || tokeniser.error("Missing return type"); + tokens.name = tokeniser.consume("identifier", "includes"); + tokens.open = tokeniser.consume("(") || tokeniser.error("Invalid operation"); + ret.arguments = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["argument_list"])(tokeniser); + tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated operation"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated operation, expected `;`"); + return ret; + } - for (const punctuation of punctuations) { - if (str.startsWith(punctuation, lastCharIndex)) { - tokens.push({ type: punctuation, value: punctuation, trivia, line, index }); - trivia = ""; - lastCharIndex += punctuation.length; - result = lastCharIndex; - break; - } + get type() { + return "operation"; + } + get name() { + const { name } = this.tokens; + if (!name) { + return ""; + } + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(name.value); + } + get special() { + if (!this.tokens.special) { + return ""; } + return this.tokens.special.value; + } - // other as the last try - if (result === -1) { - result = attemptTokenMatch("other"); + *validate(defs) { + if (this.idlType) { + yield* this.idlType.validate(defs); } - if (result === -1) { - throw new Error("Token stream not progressing"); + for (const argument of this.arguments) { + yield* argument.validate(defs); } - lastCharIndex = result; - index += 1; } +} - // remaining trivia as eof - tokens.push({ - type: "eof", - value: "", - trivia - }); - return tokens; +/***/ }), +/* 15 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Attribute", function() { return Attribute; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); + + +class Attribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { /** - * @param {keyof tokenRe} type - * @param {object} [options] - * @param {boolean} [options.noFlushTrivia] + * @param {import("../tokeniser.js").Tokeniser} tokeniser */ - function attemptTokenMatch(type, { noFlushTrivia } = {}) { - const re = tokenRe[type]; - re.lastIndex = lastCharIndex; - const result = re.exec(str); - if (result) { - tokens.push({ type, value: result[0], trivia, line, index }); - if (!noFlushTrivia) { - trivia = ""; - } - return re.lastIndex; + static parse(tokeniser, { special, noInherit = false, readonly = false } = {}) { + const start_position = tokeniser.position; + const tokens = { special }; + const ret = new Attribute({ source: tokeniser.source, tokens }); + if (!special && !noInherit) { + tokens.special = tokeniser.consume("inherit"); } - return -1; + if (ret.special === "inherit" && tokeniser.probe("readonly")) { + tokeniser.error("Inherited attributes cannot be read-only"); + } + tokens.readonly = tokeniser.consume("readonly"); + if (readonly && !tokens.readonly && tokeniser.probe("attribute")) { + tokeniser.error("Attributes must be readonly in this context"); + } + tokens.base = tokeniser.consume("attribute"); + if (!tokens.base) { + tokeniser.unconsume(start_position); + return; + } + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "attribute-type") || tokeniser.error("Attribute lacks a type"); + switch (ret.idlType.generic) { + case "sequence": + case "record": tokeniser.error(`Attributes cannot accept ${ret.idlType.generic} types`); + } + tokens.name = tokeniser.consume("identifier", "async", "required") || tokeniser.error("Attribute lacks a name"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated attribute, expected `;`"); + return ret; + } + + get type() { + return "attribute"; + } + get special() { + if (!this.tokens.special) { + return ""; + } + return this.tokens.special.value; + } + get readonly() { + return !!this.tokens.readonly; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value); + } + + *validate(defs) { + yield* this.idlType.validate(defs); } } -class Tokeniser { + +/***/ }), +/* 16 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Includes", function() { return Includes; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); + + + +class Includes extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { /** - * @param {string} idl + * @param {import("../tokeniser").Tokeniser} tokeniser */ - constructor(idl) { - this.source = tokenise(idl); - this.position = 0; + static parse(tokeniser) { + const target = tokeniser.consume("identifier"); + if (!target) { + return; + } + const tokens = { target }; + tokens.includes = tokeniser.consume("includes"); + if (!tokens.includes) { + tokeniser.unconsume(target.index); + return; + } + tokens.mixin = tokeniser.consume("identifier") || tokeniser.error("Incomplete includes statement"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("No terminating ; for includes statement"); + return new Includes({ source: tokeniser.source, tokens }); + } + + get type() { + return "includes"; + } + get target() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.target.value); + } + get includes() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.mixin.value); } +} + + +/***/ }), +/* 17 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Typedef", function() { return Typedef; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); - /** - * @param {string} message - */ - error(message) { - throw new WebIDLParseError(Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["syntaxError"])(this.source, this.position, this.current, message)); - } - /** - * @param {string} type - */ - probe(type) { - return this.source.length > this.position && this.source[this.position].type === type; - } +class Typedef extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { /** - * @param {...string} candidates + * @param {import("../tokeniser").Tokeniser} tokeniser */ - consume(...candidates) { - for (const type of candidates) { - if (!this.probe(type)) continue; - const token = this.source[this.position]; - this.position++; - return token; + static parse(tokeniser) { + const tokens = {}; + const ret = new Typedef({ source: tokeniser.source, tokens }); + tokens.base = tokeniser.consume("typedef"); + if (!tokens.base) { + return; } + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "typedef-type") || tokeniser.error("Typedef lacks a type"); + tokens.name = tokeniser.consume("identifier") || tokeniser.error("Typedef lacks a name"); + tokeniser.current = ret; + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated typedef, expected `;`"); + return ret; } - /** - * @param {number} position - */ - unconsume(position) { - this.position = position; + get type() { + return "typedef"; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value); } -} -class WebIDLParseError extends Error { - constructor({ message, line, input, tokens }) { - super(message); - this.name = "WebIDLParseError"; // not to be mangled - this.line = line; - this.input = input; - this.tokens = tokens; + *validate(defs) { + yield* this.idlType.validate(defs); } } /***/ }), -/* 6 */ +/* 18 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "syntaxError", function() { return syntaxError; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validationError", function() { return validationError; }); -/** - * @param {string} text - */ -function lastLine(text) { - const splitted = text.split("\n"); - return splitted[splitted.length - 1]; -} +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CallbackFunction", function() { return CallbackFunction; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/** - * @param {string} message error message - * @param {"Syntax" | "Validation"} type error type - */ -function error(source, position, current, message, type) { + + +class CallbackFunction extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { /** - * @param {number} count + * @param {import("../tokeniser.js").Tokeniser} tokeniser */ - function sliceTokens(count) { - return count > 0 ? - source.slice(position, position + count) : - source.slice(Math.max(position + count, 0), position); + static parse(tokeniser, base) { + const tokens = { base }; + const ret = new CallbackFunction({ source: tokeniser.source, tokens }); + tokens.name = tokeniser.consume("identifier") || tokeniser.error("Callback lacks a name"); + tokeniser.current = ret; + tokens.assign = tokeniser.consume("=") || tokeniser.error("Callback lacks an assignment"); + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser) || tokeniser.error("Callback lacks a return type"); + tokens.open = tokeniser.consume("(") || tokeniser.error("Callback lacks parentheses for arguments"); + ret.arguments = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["argument_list"])(tokeniser); + tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated callback"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated callback, expected `;`"); + return ret; } - function tokensToText(inputs, { precedes } = {}) { - const text = inputs.map(t => t.trivia + t.value).join(""); - const nextToken = source[position]; - if (nextToken.type === "eof") { - return text; - } - if (precedes) { - return text + nextToken.trivia; - } - return text.slice(nextToken.trivia.length); + get type() { + return "callback"; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value); } - const maxTokens = 5; // arbitrary but works well enough - const line = - source[position].type !== "eof" ? source[position].line : - source.length > 1 ? source[position - 1].line : - 1; - - const precedingLine = lastLine( - tokensToText(sliceTokens(-maxTokens), { precedes: true }) - ); - - const subsequentTokens = sliceTokens(maxTokens); - const subsequentText = tokensToText(subsequentTokens); - const sobsequentLine = subsequentText.split("\n")[0]; - - const spaced = " ".repeat(precedingLine.length) + "^ " + message; - const contextualMessage = precedingLine + sobsequentLine + "\n" + spaced; - - const contextType = type === "Syntax" ? "since" : "inside"; - const grammaticalContext = current ? `, ${contextType} \`${current.partial ? "partial " : ""}${current.type} ${current.name}\`` : ""; - return { - message: `${type} error at line ${line}${grammaticalContext}:\n${contextualMessage}`, - line, - input: subsequentText, - tokens: subsequentTokens - }; -} - -/** - * @param {string} message error message - */ -function syntaxError(source, position, current, message) { - return error(source, position, current, message, "Syntax"); -} - -/** - * @param {string} message error message - */ -function validationError(source, token, current, message) { - return error(source, token.index, current, message, "Validation").message; + *validate(defs) { + yield* this.idlType.validate(defs); + } } /***/ }), -/* 7 */ +/* 19 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Argument", function() { return Argument; }); -/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); -/* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8); -/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9); -/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2); -/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Interface", function() { return Interface; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(15); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); +/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(21); +/* harmony import */ var _iterable_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(22); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3); +/* harmony import */ var _validators_interface_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(23); -class Argument extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + + + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function static_member(tokeniser) { + const special = tokeniser.consume("static"); + if (!special) return; + const member = _attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse(tokeniser, { special }) || + _operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse(tokeniser, { special }) || + tokeniser.error("No body in static member"); + return member; +} + +class Interface extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { /** * @param {import("../tokeniser").Tokeniser} tokeniser */ - static parse(tokeniser) { - const start_position = tokeniser.position; - const tokens = {}; - const ret = new Argument({ source: tokeniser.source, tokens }); - ret.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__["ExtendedAttributes"].parse(tokeniser); - tokens.optional = tokeniser.consume("optional"); - ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_3__["type_with_extended_attributes"])(tokeniser, "argument-type"); - if (!ret.idlType) { - return tokeniser.unconsume(start_position); - } - if (!tokens.optional) { - tokens.variadic = tokeniser.consume("..."); - } - tokens.name = tokeniser.consume("identifier", ..._tokeniser_js__WEBPACK_IMPORTED_MODULE_4__["argumentNameKeywords"]); - if (!tokens.name) { - return tokeniser.unconsume(start_position); - } - ret.default = tokens.optional ? _default_js__WEBPACK_IMPORTED_MODULE_1__["Default"].parse(tokeniser) : null; - return ret; + static parse(tokeniser, base, { partial = null } = {}) { + const tokens = { partial, base }; + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Interface({ source: tokeniser.source, tokens }), { + type: "interface", + inheritable: !partial, + allowedMembers: [ + [_constant_js__WEBPACK_IMPORTED_MODULE_3__["Constant"].parse], + [static_member], + [_helpers_js__WEBPACK_IMPORTED_MODULE_5__["stringifier"]], + [_iterable_js__WEBPACK_IMPORTED_MODULE_4__["IterableLike"].parse], + [_attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse], + [_operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse] + ] + }); } - get optional() { - return !!this.tokens.optional; - } - get variadic() { - return !!this.tokens.variadic; + get type() { + return "interface"; } - get name() { - return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_3__["unescape"])(this.tokens.name.value); + + *validate(defs) { + yield* this.extAttrs.validate(defs); + if ( + !this.partial && + this.extAttrs.every(extAttr => extAttr.name !== "Exposed") && + this.extAttrs.every(extAttr => extAttr.name !== "NoInterfaceObject") + ) { + const message = `Interfaces must have \`[Exposed]\` extended attribute. \ +To fix, add, for example, \`[Exposed=Window]\`. Please also consider carefully \ +if your interface should also be exposed in a Worker scope. Refer to the \ +[WebIDL spec section on Exposed](https://heycam.github.io/webidl/#Exposed) \ +for more information.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_6__["validationError"])(this.source, this.tokens.name, this, message); + } + + yield* super.validate(defs); + if (!this.partial) { + yield* Object(_validators_interface_js__WEBPACK_IMPORTED_MODULE_7__["checkInterfaceMemberDuplication"])(defs, this); + } } } /***/ }), -/* 8 */ +/* 20 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Default", function() { return Default; }); -/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); -/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container", function() { return Container; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5); -class Default extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { - /** - * @param {import("../tokeniser").Tokeniser} tokeniser - */ - static parse(tokeniser) { - const assign = tokeniser.consume("="); - if (!assign) { - return null; - } - const def = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_value"])(tokeniser) || tokeniser.consume("string", "null", "[", "{") || tokeniser.error("No value for default"); - const expression = [def]; - if (def.type === "[") { - const close = tokeniser.consume("]") || tokeniser.error("Default sequence value must be empty"); - expression.push(close); - } else if (def.type === "{") { - const close = tokeniser.consume("}") || tokeniser.error("Default dictionary value must be empty"); - expression.push(close); - } - return new Default({ source: tokeniser.source, tokens: { assign }, expression }); - } - constructor({ source, tokens, expression }) { - super({ source, tokens }); - Object.defineProperty(this, "expression", { value: expression }); +/** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + */ +function inheritance(tokeniser) { + const colon = tokeniser.consume(":"); + if (!colon) { + return {}; } + const inheritance = tokeniser.consume("identifier") || tokeniser.error("Inheritance lacks a type"); + return { colon, inheritance }; +} - get type() { - return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).type; - } - get value() { - return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).value; - } - get negative() { - return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).negative; +class Container extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + * @param {*} instance + * @param {*} args + */ + static parse(tokeniser, instance, { type, inheritable, allowedMembers }) { + const { tokens } = instance; + tokens.name = tokeniser.consume("identifier") || tokeniser.error(`Missing name in ${instance.type}`); + tokeniser.current = instance; + if (inheritable) { + Object.assign(tokens, inheritance(tokeniser)); + } + tokens.open = tokeniser.consume("{") || tokeniser.error(`Bodyless ${type}`); + instance.members = []; + while (true) { + tokens.close = tokeniser.consume("}"); + if (tokens.close) { + tokens.termination = tokeniser.consume(";") || tokeniser.error(`Missing semicolon after ${type}`); + return instance; + } + const ea = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_1__["ExtendedAttributes"].parse(tokeniser); + let mem; + for (const [parser, ...args] of allowedMembers) { + mem = parser(tokeniser, ...args); + if (mem) { + break; + } + } + if (!mem) { + tokeniser.error("Unknown member"); + } + mem.extAttrs = ea; + instance.members.push(mem); + } + } + + get partial() { + return !!this.tokens.partial; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["unescape"])(this.tokens.name.value); + } + get inheritance() { + if (!this.tokens.inheritance) { + return null; + } + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["unescape"])(this.tokens.inheritance.value); + } + + *validate(defs) { + for (const member of this.members) { + if (member.validate) { + yield* member.validate(defs); + } + } + } } -} /***/ }), -/* 9 */ +/* 21 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExtendedAttributes", function() { return ExtendedAttributes; }); -/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); -/* harmony import */ var _array_base_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10); -/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Constant", function() { return Constant; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5); -class ExtendedAttributeParameters extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { +class Constant extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { /** - * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {import("../tokeniser.js").Tokeniser} tokeniser */ static parse(tokeniser) { - const tokens = { assign: tokeniser.consume("=") }; - const ret = new ExtendedAttributeParameters({ source: tokeniser.source, tokens }); - if (tokens.assign) { - tokens.secondaryName = tokeniser.consume("identifier", "decimal", "integer", "string"); - } - tokens.open = tokeniser.consume("("); - if (tokens.open) { - ret.list = ret.rhsType === "identifier-list" ? - // [Exposed=(Window,Worker)] - Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["identifiers"])(tokeniser) : - // [NamedConstructor=Audio(DOMString src)] or [Constructor(DOMString str)] - Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["argument_list"])(tokeniser); - tokens.close = tokeniser.consume(")") || tokeniser.error("Unexpected token in extended attribute argument list"); - } else if (ret.hasRhs && !tokens.secondaryName) { - tokeniser.error("No right hand side to extended attribute assignment"); + const tokens = {}; + tokens.base = tokeniser.consume("const"); + if (!tokens.base) { + return; } + let idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["primitive_type"])(tokeniser); + if (!idlType) { + const base = tokeniser.consume("identifier") || tokeniser.error("Const lacks a type"); + idlType = new _type_js__WEBPACK_IMPORTED_MODULE_1__["Type"]({ source: tokeniser.source, tokens: { base } }); + } + if (tokeniser.probe("?")) { + tokeniser.error("Unexpected nullable constant type"); + } + idlType.type = "const-type"; + tokens.name = tokeniser.consume("identifier") || tokeniser.error("Const lacks a name"); + tokens.assign = tokeniser.consume("=") || tokeniser.error("Const lacks value assignment"); + tokens.value = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["const_value"])(tokeniser) || tokeniser.error("Const lacks a value"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated const, expected `;`"); + const ret = new Constant({ source: tokeniser.source, tokens }); + ret.idlType = idlType; return ret; } - get rhsType() { - return !this.tokens.assign ? null : - !this.tokens.secondaryName ? "identifier-list" : - this.tokens.secondaryName.type; + get type() { + return "const"; + } + get name() { + return unescape(this.tokens.name.value); + } + get value() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["const_data"])(this.tokens.value); } } -class SimpleExtendedAttribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + +/***/ }), +/* 22 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "IterableLike", function() { return IterableLike; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); + + + +class IterableLike extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { /** - * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {import("../tokeniser.js").Tokeniser} tokeniser */ static parse(tokeniser) { - const name = tokeniser.consume("identifier"); - if (name) { - return new SimpleExtendedAttribute({ - tokens: { name }, - params: ExtendedAttributeParameters.parse(tokeniser) - }); + const start_position = tokeniser.position; + const tokens = {}; + const ret = new IterableLike({ source: tokeniser.source, tokens }); + tokens.readonly = tokeniser.consume("readonly"); + if (!tokens.readonly) { + tokens.async = tokeniser.consume("async"); + } + tokens.base = + tokens.readonly ? tokeniser.consume("maplike", "setlike") : + tokens.async ? tokeniser.consume("iterable") : + tokeniser.consume("iterable", "maplike", "setlike"); + if (!tokens.base) { + tokeniser.unconsume(start_position); + return; } - } - constructor({ source, tokens, params }) { - super({ source, tokens }); - Object.defineProperty(this, "params", { value: params }); + const { type } = ret; + const secondTypeRequired = type === "maplike" || ret.async; + const secondTypeAllowed = secondTypeRequired || type === "iterable"; + + tokens.open = tokeniser.consume("<") || tokeniser.error(`Missing less-than sign \`<\` in ${type} declaration`); + const first = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser) || tokeniser.error(`Missing a type argument in ${type} declaration`); + ret.idlType = [first]; + if (secondTypeAllowed) { + first.tokens.separator = tokeniser.consume(","); + if (first.tokens.separator) { + ret.idlType.push(Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser)); + } + else if (secondTypeRequired) { + tokeniser.error(`Missing second type argument in ${type} declaration`); + } + } + tokens.close = tokeniser.consume(">") || tokeniser.error(`Missing greater-than sign \`>\` in ${type} declaration`); + tokens.termination = tokeniser.consume(";") || tokeniser.error(`Missing semicolon after ${type} declaration`); + + return ret; } get type() { - return "extended-attribute"; + return this.tokens.base.value; } - get name() { - return this.tokens.name.value; - } - get rhs() { - const { rhsType: type, tokens, list } = this.params; - if (!type) { - return null; - } - const value = type === "identifier-list" ? list : tokens.secondaryName.value; - return { type, value }; + get readonly() { + return !!this.tokens.readonly; } - get arguments() { - const { rhsType, list } = this.params; - if (!list || rhsType === "identifier-list") { - return []; - } - return list; + get async() { + return !!this.tokens.async; } } -// Note: we parse something simpler than the official syntax. It's all that ever -// seems to be used -class ExtendedAttributes extends _array_base_js__WEBPACK_IMPORTED_MODULE_1__["ArrayBase"] { - /** - * @param {import("../tokeniser").Tokeniser} tokeniser - */ - static parse(tokeniser) { - const tokens = {}; - tokens.open = tokeniser.consume("["); - if (!tokens.open) return []; - const ret = new ExtendedAttributes({ source: tokeniser.source, tokens }); - ret.push(...Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["list"])(tokeniser, { - parser: SimpleExtendedAttribute.parse, - listName: "extended attribute" - })); - tokens.close = tokeniser.consume("]") || tokeniser.error("Unexpected closing token of extended attribute"); - if (!ret.length) { - tokeniser.error("Found an empty extended attribute"); + +/***/ }), +/* 23 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "checkInterfaceMemberDuplication", function() { return checkInterfaceMemberDuplication; }); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); + + +function* checkInterfaceMemberDuplication(defs, i) { + const opNames = new Set(getOperations(i).map(op => op.name)); + const partials = defs.partials.get(i.name) || []; + const mixins = defs.mixinMap.get(i.name) || []; + for (const ext of [...partials, ...mixins]) { + const additions = getOperations(ext); + yield* forEachExtension(additions, opNames, ext, i); + for (const addition of additions) { + opNames.add(addition.name); } - if (tokeniser.probe("[")) { - tokeniser.error("Illegal double extended attribute lists, consider merging them"); + } + + function* forEachExtension(additions, existings, ext, base) { + for (const addition of additions) { + const { name } = addition; + if (name && existings.has(name)) { + const message = `The operation "${name}" has already been defined for the base interface "${base.name}" either in itself or in a mixin`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["validationError"])(ext.source, addition.tokens.name, ext, message); + } } - return ret; + } + + function getOperations(i) { + return i.members + .filter(({type}) => type === "operation"); } } /***/ }), -/* 10 */ +/* 24 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArrayBase", function() { return ArrayBase; }); -class ArrayBase extends Array { - constructor({ source, tokens }) { - super(); - Object.defineProperties(this, { - source: { value: source }, - tokens: { value: tokens } +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Mixin", function() { return Mixin; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21); +/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(15); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(14); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5); + + + + + + +class Mixin extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser, base, { partial } = {}) { + const tokens = { partial, base }; + tokens.mixin = tokeniser.consume("mixin"); + if (!tokens.mixin) { + return; + } + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Mixin({ source: tokeniser.source, tokens }), { + type: "interface mixin", + allowedMembers: [ + [_constant_js__WEBPACK_IMPORTED_MODULE_1__["Constant"].parse], + [_helpers_js__WEBPACK_IMPORTED_MODULE_4__["stringifier"]], + [_attribute_js__WEBPACK_IMPORTED_MODULE_2__["Attribute"].parse, { noInherit: true }], + [_operation_js__WEBPACK_IMPORTED_MODULE_3__["Operation"].parse, { regular: true }] + ] }); } + + get type() { + return "interface mixin"; + } } /***/ }), -/* 11 */ +/* 25 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Token", function() { return Token; }); -/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Dictionary", function() { return Dictionary; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _field_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(26); -class Token extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + +class Dictionary extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { /** * @param {import("../tokeniser").Tokeniser} tokeniser - * @param {string} type */ - static parser(tokeniser, type) { - return () => { - const value = tokeniser.consume(type); - if (value) { - return new Token({ source: tokeniser.source, tokens: { value } }); - } - }; + static parse(tokeniser, { partial } = {}) { + const tokens = { partial }; + tokens.base = tokeniser.consume("dictionary"); + if (!tokens.base) { + return; + } + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Dictionary({ source: tokeniser.source, tokens }), { + type: "dictionary", + inheritable: !partial, + allowedMembers: [ + [_field_js__WEBPACK_IMPORTED_MODULE_1__["Field"].parse], + ] + }); } - get value() { - return this.tokens.value.value; + get type() { + return "dictionary"; } } /***/ }), -/* 12 */ +/* 26 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Enum", function() { return Enum; }); -/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); -/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); -/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Field", function() { return Field; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); +/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11); +/* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10); -class EnumValue extends _token_js__WEBPACK_IMPORTED_MODULE_1__["Token"] { + +class Field extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { /** * @param {import("../tokeniser").Tokeniser} tokeniser */ static parse(tokeniser) { - const value = tokeniser.consume("string"); - if (value) { - return new EnumValue({ source: tokeniser.source, tokens: { value } }); - } + const tokens = {}; + const ret = new Field({ source: tokeniser.source, tokens }); + ret.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__["ExtendedAttributes"].parse(tokeniser); + tokens.required = tokeniser.consume("required"); + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "dictionary-type") || tokeniser.error("Dictionary member lacks a type"); + tokens.name = tokeniser.consume("identifier") || tokeniser.error("Dictionary member lacks a name"); + ret.default = _default_js__WEBPACK_IMPORTED_MODULE_3__["Default"].parse(tokeniser); + if (tokens.required && ret.default) tokeniser.error("Required member must not have a default"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated dictionary member, expected `;`"); + return ret; } get type() { - return "enum-value"; + return "field"; } - get value() { - return super.value.slice(1, -1); + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value); + } + get required() { + return !!this.tokens.required; + } + + *validate(defs) { + yield* this.idlType.validate(defs); } } -class Enum extends _base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { + +/***/ }), +/* 27 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Namespace", function() { return Namespace; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(15); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3); + + + + + +class Namespace extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { /** * @param {import("../tokeniser").Tokeniser} tokeniser */ - static parse(tokeniser) { - const tokens = {}; - tokens.base = tokeniser.consume("enum"); + static parse(tokeniser, { partial } = {}) { + const tokens = { partial }; + tokens.base = tokeniser.consume("namespace"); if (!tokens.base) { return; } - tokens.name = tokeniser.consume("identifier") || tokeniser.error("No name for enum"); - const ret = tokeniser.current = new Enum({ source: tokeniser.source, tokens }); - tokens.open = tokeniser.consume("{") || tokeniser.error("Bodyless enum"); - ret.values = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["list"])(tokeniser, { - parser: EnumValue.parse, - allowDangler: true, - listName: "enumeration" + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Namespace({ source: tokeniser.source, tokens }), { + type: "namespace", + allowedMembers: [ + [_attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse, { noInherit: true, readonly: true }], + [_operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse, { regular: true }] + ] }); - if (tokeniser.probe("string")) { - tokeniser.error("No comma between enum values"); - } - tokens.close = tokeniser.consume("}") || tokeniser.error("Unexpected value in enum"); - if (!ret.values.length) { - tokeniser.error("No value in enum"); - } - tokens.termination = tokeniser.consume(";") || tokeniser.error("No semicolon after enum"); - return ret; } get type() { - return "enum"; + return "namespace"; } - get name() { - return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); + + *validate(defs) { + if (!this.partial && this.extAttrs.every(extAttr => extAttr.name !== "Exposed")) { + const message = `Namespaces must have [Exposed] extended attribute. \ +To fix, add, for example, [Exposed=Window]. Please also consider carefully \ +if your namespace should also be exposed in a Worker scope. Refer to the \ +[WebIDL spec section on Exposed](https://heycam.github.io/webidl/#Exposed) \ +for more information.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(this.source, this.tokens.name, this, message); + } + yield* super.validate(defs); } } /***/ }), -/* 13 */ +/* 28 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Includes", function() { return Includes; }); -/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); -/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CallbackInterface", function() { return CallbackInterface; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21); -class Includes extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + + +class CallbackInterface extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { /** * @param {import("../tokeniser").Tokeniser} tokeniser */ - static parse(tokeniser) { - const target = tokeniser.consume("identifier"); - if (!target) { - return; - } - const tokens = { target }; - tokens.includes = tokeniser.consume("includes"); - if (!tokens.includes) { - tokeniser.unconsume(target.index); + static parse(tokeniser, callback, { partial = null } = {}) { + const tokens = { callback }; + tokens.base = tokeniser.consume("interface"); + if (!tokens.base) { return; } - tokens.mixin = tokeniser.consume("identifier") || tokeniser.error("Incomplete includes statement"); - tokens.termination = tokeniser.consume(";") || tokeniser.error("No terminating ; for includes statement"); - return new Includes({ source: tokeniser.source, tokens }); + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new CallbackInterface({ source: tokeniser.source, tokens }), { + type: "callback interface", + inheritable: !partial, + allowedMembers: [ + [_constant_js__WEBPACK_IMPORTED_MODULE_2__["Constant"].parse], + [_operation_js__WEBPACK_IMPORTED_MODULE_1__["Operation"].parse, { regular: true }] + ] + }); } get type() { - return "includes"; - } - get target() { - return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.target.value); - } - get includes() { - return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.mixin.value); + return "callback interface"; } } /***/ }), -/* 14 */ +/* 29 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1977,6 +2520,7 @@ function write(ast, { templates: ts = templates } = {}) { return ts.definition(ts.wrap([ extended_attributes(it.extAttrs), token(it.tokens.readonly), + token(it.tokens.async), token(it.tokens.base, ts.generic), token(it.tokens.open), ts.wrap(it.idlType.map(type)), @@ -2026,17 +2570,35 @@ function write(ast, { templates: ts = templates } = {}) { /***/ }), -/* 15 */ +/* 30 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validate", function() { return validate; }); -/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); +function getMixinMap(all, unique) { + const map = new Map(); + const includes = all.filter(def => def.type === "includes"); + for (const include of includes) { + const mixin = unique.get(include.includes); + if (!mixin) { + continue; + } + const array = map.get(include.target); + if (array) { + array.push(mixin); + } else { + map.set(include.target, [mixin]); + } + } + return map; +} + function groupDefinitions(all) { const unique = new Map(); const duplicates = new Set(); @@ -2060,7 +2622,16 @@ function groupDefinitions(all) { duplicates.add(def); } } - return { all, unique, partials, duplicates }; + return { + all, + unique, + partials, + duplicates, + mixinMap: getMixinMap(all, unique), + cache: { + typedefIncludesDictionary: new WeakMap() + }, + }; } function* checkDuplicatedNames({ unique, duplicates }) { @@ -2071,67 +2642,29 @@ function* checkDuplicatedNames({ unique, duplicates }) { } } -function* checkInterfaceMemberDuplication(defs) { - const interfaces = [...defs.unique.values()].filter(def => def.type === "interface"); - const includesMap = getIncludesMap(); - - for (const i of interfaces) { - yield* forEachInterface(i); - } - - function* forEachInterface(i) { - const opNames = new Set(getOperations(i).map(op => op.name)); - const partials = defs.partials.get(i.name) || []; - const mixins = includesMap.get(i.name) || []; - for (const ext of [...partials, ...mixins]) { - const additions = getOperations(ext); - yield* forEachExtension(additions, opNames, ext, i); - for (const addition of additions) { - opNames.add(addition.name); - } - } - } - - function* forEachExtension(additions, existings, ext, base) { - for (const addition of additions) { - const { name } = addition; - if (name && existings.has(name)) { - const message = `The operation "${name}" has already been defined for the base interface "${base.name}" either in itself or in a mixin`; - yield Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["validationError"])(ext.source, addition.tokens.name, ext, message); - } +function* validateIterable(ast) { + const defs = groupDefinitions(ast); + for (const def of defs.all) { + if (def.validate) { + yield* def.validate(defs); } } + yield* checkDuplicatedNames(defs); +} - function getOperations(i) { - return i.members - .filter(({type}) => type === "operation"); - } - - function getIncludesMap() { - const map = new Map(); - const includes = defs.all.filter(def => def.type === "includes"); - for (const include of includes) { - const array = map.get(include.target); - const mixin = defs.unique.get(include.includes); - if (!mixin) { - continue; - } - if (array) { - array.push(mixin); - } else { - map.set(include.target, [mixin]); - } - } - return map; +// Remove this once all of our support targets expose `.flat()` by default +function flatten(array) { + if (array.flat) { + return array.flat(); } + return [].concat(...array); } +/** + * @param {*} ast AST or array of ASTs + */ function validate(ast) { - const defs = groupDefinitions(ast); - return [ - ...checkDuplicatedNames(defs), - ...checkInterfaceMemberDuplication(defs) - ]; + return [...validateIterable(flatten(ast))]; } diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.js index 3f89881c0438..f1997bd824e8 100644 --- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.js +++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.js @@ -14,6 +14,9 @@ addEventListener('install', event => { }); addEventListener('message', event => { + let resolveWaitUntil; + event.waitUntil(new Promise(resolve => { resolveWaitUntil = resolve; })); + // Use a dedicated MessageChannel for every request so senders can wait for // individual requests to finish, and concurrent requests (to different // workers) don't cause race conditions. @@ -23,13 +26,13 @@ addEventListener('message', event => { case 'awaitInstallEvent': installEventFired.then(() => { port.postMessage('installEventFired'); - }); + }).finally(resolveWaitUntil); break; case 'finishInstall': installFinished.then(() => { port.postMessage('installFinished'); - }); + }).finally(resolveWaitUntil); finishInstall(); break; @@ -44,13 +47,14 @@ addEventListener('message', event => { success: false, exception: exception.name, }); - }); + }).finally(resolveWaitUntil); port.postMessage(channel.port1, [channel.port1]); break; } default: port.postMessage('Unexpected command ' + event.data); + resolveWaitUntil(); break; } }; diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/DocumentOrShadowRoot-activeElement.html b/tests/wpt/web-platform-tests/shadow-dom/focus/DocumentOrShadowRoot-activeElement.html new file mode 100644 index 000000000000..20456b057e1e --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/DocumentOrShadowRoot-activeElement.html @@ -0,0 +1,92 @@ + + +HTML Test: DocumentOrShadowRoot.activeElement + + + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-negative.html b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-negative.html new file mode 100644 index 000000000000..ab25ea829bd1 --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-negative.html @@ -0,0 +1,34 @@ + + +HTML Test: focus - the sequential focus navigation order with shadow dom and negative tabindex in shadow scope + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html new file mode 100644 index 000000000000..3c9e70867c58 --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html @@ -0,0 +1,37 @@ + + +HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0 except for one of the slot + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html new file mode 100644 index 000000000000..875e5b6814a9 --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html @@ -0,0 +1,36 @@ + + +HTML Test: focus - the sequential focus navigation order with shadow dom with varying tabindex values + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html new file mode 100644 index 000000000000..b491c7d237c2 --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html @@ -0,0 +1,35 @@ + + +HTML Test: focus - the sequential focus navigation order with shadow dom and negative host tabindex + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html new file mode 100644 index 000000000000..f25726147718 --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html @@ -0,0 +1,37 @@ + + +HTML Test: focus - the sequential focus navigation order with shadow dom and non-focusable host + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html new file mode 100644 index 000000000000..1aa5292997a3 --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html @@ -0,0 +1,37 @@ + + +HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0 except host (tabindex=1) + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero.html b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero.html new file mode 100644 index 000000000000..d8b12ed8ac6e --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero.html @@ -0,0 +1,35 @@ + + +HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0 + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/shadow-dom/focus/resources/shadow-utils.js b/tests/wpt/web-platform-tests/shadow-dom/focus/resources/shadow-utils.js new file mode 100644 index 000000000000..6ea372afdf18 --- /dev/null +++ b/tests/wpt/web-platform-tests/shadow-dom/focus/resources/shadow-utils.js @@ -0,0 +1,79 @@ +// Structure: +//
+//
+// #shadowRoot +//
+// +// (slotted)
+// +// (slotted)
+//
+//
+function prepareDOM(container, delegatesFocus) { + + const aboveHost = document.createElement("div"); + aboveHost.innerText = "aboveHost"; + const host = document.createElement("div"); + host.id = "host"; + const slottedBelow = document.createElement("div"); + slottedBelow.innerText = "slotted below"; + slottedBelow.slot = "below"; + const slottedAbove = document.createElement("div"); + slottedAbove.innerText = "slotted above"; + slottedAbove.slot = "above"; + + const belowHost = document.createElement("div"); + belowHost.innerText = "belowHost"; + container.appendChild(aboveHost); + container.appendChild(host); + container.appendChild(belowHost); + host.appendChild(slottedBelow); + host.appendChild(slottedAbove); + const shadowRoot = host.attachShadow({ mode: "open", delegatesFocus: delegatesFocus}); + const aboveSlot = document.createElement("div"); + aboveSlot.innerText = "aboveSlot"; + + const slotAbove = document.createElement("slot"); + slotAbove.name = "above"; + const slotBelow = document.createElement("slot"); + slotBelow.name = "below"; + + const belowSlot = document.createElement("div"); + belowSlot.innerText = "belowSlot"; + shadowRoot.appendChild(aboveSlot); + shadowRoot.appendChild(slotAbove); + shadowRoot.appendChild(slotBelow); + shadowRoot.appendChild(belowSlot); + + return [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost]; +} + +function setTabIndex(elements, value) { + for (const el of elements) { + el.tabIndex = value; + } +} + +function removeTabIndex(elements) { + for (const el of elements) { + el.removeAttribute("tabindex"); + } +} + +function resetFocus() { + document.body.focus(); +} + +function navigateFocusForward() { + // TAB = '\ue004' + return test_driver.send_keys(document.body, "\ue004"); +} + +async function assertFocusOrder(expectedOrder) { + const shadowRoot = document.getElementById("host").shadowRoot; + for (const el of expectedOrder) { + await navigateFocusForward(); + const focused = shadowRoot.activeElement ? shadowRoot.activeElement : document.activeElement; + assert_equals(focused, el); + } +} diff --git a/tests/wpt/web-platform-tests/sms/README.md b/tests/wpt/web-platform-tests/sms/README.md new file mode 100644 index 000000000000..7cd98964c249 --- /dev/null +++ b/tests/wpt/web-platform-tests/sms/README.md @@ -0,0 +1,3 @@ +# SMS Receiver API + +This directory contains Web platform tests of the SMS Receiver API. For more details, refer to [this README file](https://cs.chromium.org/chromium/src/content/browser/sms/README.md). diff --git a/tests/wpt/web-platform-tests/streams/readable-streams/patched-global.any.js b/tests/wpt/web-platform-tests/streams/readable-streams/patched-global.any.js index 500979f5b37a..813dd42e68aa 100644 --- a/tests/wpt/web-platform-tests/streams/readable-streams/patched-global.any.js +++ b/tests/wpt/web-platform-tests/streams/readable-streams/patched-global.any.js @@ -107,3 +107,35 @@ promise_test(async t => { // stream should be cancelled await reader.closed; }, 'ReadableStream getIterator() should use the original values of getReader() and ReadableStreamDefaultReader methods'); + +test(t => { + const oldPromiseThen = Promise.prototype.then; + Promise.prototype.then = () => { + throw new Error('patched then() called'); + }; + t.add_cleanup(() => { + Promise.prototype.then = oldPromiseThen; + }); + const [branch1, branch2] = new ReadableStream().tee(); + assert_true(isReadableStream(branch1), 'branch1 should be a ReadableStream'); + assert_true(isReadableStream(branch2), 'branch2 should be a ReadableStream'); +}, 'tee() should not call Promise.prototype.then()'); + +test(t => { + const oldPromiseThen = Promise.prototype.then; + Promise.prototype.then = () => { + throw new Error('patched then() called'); + }; + t.add_cleanup(() => { + Promise.prototype.then = oldPromiseThen; + }); + let readableController; + const rs = new ReadableStream({ + start(c) { + readableController = c; + } + }); + const ws = new WritableStream(); + rs.pipeTo(ws); + readableController.close(); +}, 'pipeTo() should not call Promise.prototype.then()'); diff --git a/tests/wpt/web-platform-tests/svg/animations/accumulate-values-width-animation.html b/tests/wpt/web-platform-tests/svg/animations/accumulate-values-width-animation.html new file mode 100644 index 000000000000..7813494a6a2c --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/accumulate-values-width-animation.html @@ -0,0 +1,110 @@ + + + +This tests values animation and accumulate='sum' + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/additive-from-to-width-animation.html b/tests/wpt/web-platform-tests/svg/animations/additive-from-to-width-animation.html new file mode 100644 index 000000000000..0899f5e0b531 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/additive-from-to-width-animation.html @@ -0,0 +1,61 @@ + + + +This tests multiple additive='sum' animations running at the same time + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/additive-type-by-animation.html b/tests/wpt/web-platform-tests/svg/animations/additive-type-by-animation.html new file mode 100644 index 000000000000..2dc7732dd6ef --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/additive-type-by-animation.html @@ -0,0 +1,275 @@ + + + +This by animation for all XML property types + + + + + + + + + + + + + + + + + + + + + + + +ABCD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/additive-values-width-animation.html b/tests/wpt/web-platform-tests/svg/animations/additive-values-width-animation.html new file mode 100644 index 000000000000..5b874f5a4f83 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/additive-values-width-animation.html @@ -0,0 +1,83 @@ + + + +This tests values animation and additive='sum' + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-by.html b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-by.html new file mode 100644 index 000000000000..5ce9bcc763e5 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-by.html @@ -0,0 +1,70 @@ + + + +Test calcMode spline with by animation. You should see a green 100x100 rect and only PASS messages + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-by.html b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-by.html new file mode 100644 index 000000000000..1f15760c7d84 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-by.html @@ -0,0 +1,71 @@ + + + +Test calcMode spline with from-by animation. You should see a green 100x100 rect and only PASS messages + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-to.html b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-to.html new file mode 100644 index 000000000000..4d6080083148 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-to.html @@ -0,0 +1,71 @@ + + + +Test calcMode spline with from-to animation. You should see a green 100x100 rect and only PASS messages + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-to.html b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-to.html new file mode 100644 index 000000000000..4a26cd716ed5 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-to.html @@ -0,0 +1,70 @@ + + + +Test calcMode spline with to animation. You should see a green 100x100 rect and only PASS messages + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-values.html b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-values.html new file mode 100644 index 000000000000..46952aa45db5 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-values.html @@ -0,0 +1,70 @@ + + + +Test calcMode spline with values animation. You should see a green 100x100 rect and only PASS messages + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-color-calcMode-discrete.html b/tests/wpt/web-platform-tests/svg/animations/animate-color-calcMode-discrete.html new file mode 100644 index 000000000000..980f39282e33 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-color-calcMode-discrete.html @@ -0,0 +1,63 @@ + + + +Test calcMode discrete with from-to animation on colors. You should see a green 100x100 rect and only PASS messages + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-color-fill-currentColor.html b/tests/wpt/web-platform-tests/svg/animations/animate-color-fill-currentColor.html new file mode 100644 index 000000000000..2780ce2ac9a8 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-color-fill-currentColor.html @@ -0,0 +1,63 @@ + + + +Tests animation on 'currentColor'. + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-color-fill-from-by.html b/tests/wpt/web-platform-tests/svg/animations/animate-color-fill-from-by.html new file mode 100644 index 000000000000..410b27b75a73 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-color-fill-from-by.html @@ -0,0 +1,63 @@ + + + +Tests animation on 'currentColor'. + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-color-transparent.html b/tests/wpt/web-platform-tests/svg/animations/animate-color-transparent.html new file mode 100644 index 000000000000..e2a946cfb0b1 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-color-transparent.html @@ -0,0 +1,53 @@ + + + +Tests that 'transparent' is treated as a valid color. + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-css-xml-attributeType.html b/tests/wpt/web-platform-tests/svg/animations/animate-css-xml-attributeType.html new file mode 100644 index 000000000000..4494eb773693 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-css-xml-attributeType.html @@ -0,0 +1,88 @@ + + + +Tests that XML and CSS attributeTypes can be switched between. + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-currentColor.html b/tests/wpt/web-platform-tests/svg/animations/animate-currentColor.html new file mode 100644 index 000000000000..a8b3c1f16f25 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-currentColor.html @@ -0,0 +1,63 @@ + + + +Tests animation on 'currentColor'. + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-dynamic-update-attributeName.html b/tests/wpt/web-platform-tests/svg/animations/animate-dynamic-update-attributeName.html new file mode 100644 index 000000000000..47ca52526ae1 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-dynamic-update-attributeName.html @@ -0,0 +1,71 @@ + + + +Test behavior on dynamic-update of attributeName + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-elem-02-t-drt.html b/tests/wpt/web-platform-tests/svg/animations/animate-elem-02-t-drt.html new file mode 100644 index 000000000000..31f34ce56f8b --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-02-t-drt.html @@ -0,0 +1,183 @@ + + + +A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test 'additive' and 'accumulate' attributes. + + + The four pictures show the effect with the four possible combinations of + 'additive' (either 'replace' or 'sum') and 'accumulate' (either 'none' or 'sum'). + Because two animations are animating the height, the effects of 'additive' and + 'accumulate' are sometimes different than when there is only a single animation. + + + + animate-elem-02-t + Test 'additive' and 'accumulate' attributes. + + + + + + + + + + + + + anim.5 + + + + + + + + + anim.6 + + + + + + + + + anim.7 + + + + + + + + + anim.8 + + $Revision: 1.8 $ + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-elem-14-t-drt.html b/tests/wpt/web-platform-tests/svg/animations/animate-elem-14-t-drt.html new file mode 100644 index 000000000000..64fc35f596fd --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-14-t-drt.html @@ -0,0 +1,140 @@ + + + +A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test 'calcMode'=discrete + + + One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided + to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The + black text and ruler lines help show the size and movement of the rectangle over time. + + + This test shows an animation with calcMode="discrete" (i.e., a jumping animation). + + + + animate-elem-14-t + Test possible values for 'keyTimes' + + + + + calcMode="discrete" + keyTimes="0;.2;.4;.6" + + + Time (s): + 0 + + 2 + + 4 + + 6 + + + + + + + + + + $Revision: 1.6 $ + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-elem-15-t-drt.html b/tests/wpt/web-platform-tests/svg/animations/animate-elem-15-t-drt.html new file mode 100644 index 000000000000..9d5cb1b437bc --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-15-t-drt.html @@ -0,0 +1,136 @@ + + + +A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test 'calcMode'=paced + + + One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided + to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The + black text and ruler lines help show the size and movement of the rectangle over time. + + + This test shows calcMode="paced" for an animation that has constant velocity, thus showing how 'values' + and 'keyTimes' are ignored. + + + + animate-elem-15-t + Test possible values for 'keyTimes' + + + + + calcMode="paced" + keyTimes="0;.25;.5;1" + + + Time (s): + 0 + + 1.5 + + 4 + + 9 + + + + + + + + + + $Revision: 1.5 $ + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-elem-16-t-drt.html b/tests/wpt/web-platform-tests/svg/animations/animate-elem-16-t-drt.html new file mode 100644 index 000000000000..0ac98e2fc80f --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-16-t-drt.html @@ -0,0 +1,136 @@ + + + +A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test 'calcMode'=linear + + + One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided + to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The + black text and ruler lines help show the size and movement of the rectangle over time. + + + This test shows an animation with calcMode="linear". + + + + animate-elem-16-t + Test possible values for 'keyTimes' + + + + + calcMode="linear" + keyTimes="0;.25;.5;1" + + + Time (s): + 0 + + 2 + + 4 + + 8 + + + + + + + + + + + $Revision: 1.1 $ + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-elem-17-t-drt.html b/tests/wpt/web-platform-tests/svg/animations/animate-elem-17-t-drt.html new file mode 100644 index 000000000000..1b101491953b --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-17-t-drt.html @@ -0,0 +1,136 @@ + + + +A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test 'calcMode'=spline + + + One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided + to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The + black text and ruler lines help show the size and movement of the rectangle over time. + + + This animation shows calcMode="spline". Between time 4 seconds and 8 seconds, the animation displays an ease-in/ease-out approach + instead of a constant linear approach which would have been the case if calcMode had been linear instead. + + + + animate-elem-17-t + Test possible values for 'keyTimes' + + + + + calcMode="spline" + keyTimes="0;.25;.5;1" + + + Time (s): + 0 + + 2 + + 4 + + 8 + + + + + + + + + + $Revision: 1.6 $ + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-elem-18-t-drt.html b/tests/wpt/web-platform-tests/svg/animations/animate-elem-18-t-drt.html new file mode 100644 index 000000000000..4f9dbb776581 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-18-t-drt.html @@ -0,0 +1,137 @@ + + + +A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test 'calcMode'=discrete + + + One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided + to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The + black text and ruler lines help show the size and movement of the rectangle over time. + + + This test shows an animation with calcMode="discrete" (i.e., a jumping animation). + + + + animate-elem-18-t + Test possible values for 'keyTimes' + + + + + calcMode="discrete" + keyTimes="0;.2;.6;.8" + + + Time (s): + 0 + + 2 + + 6 + + 8 + + + + + + + + + + $Revision: 1.1 $ + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-elem-19-t-drt.html b/tests/wpt/web-platform-tests/svg/animations/animate-elem-19-t-drt.html new file mode 100644 index 000000000000..9b9d61c90bdd --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-19-t-drt.html @@ -0,0 +1,136 @@ + + + +A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test 'calcMode'=linear + + + One animation has been defined to animate the width of a rectangle. Ruler lines and text are provided + to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The + black text and ruler lines help show the size and movement of the rectangle over time. + + + This test shows an animation with calcMode="linear". + + + + animate-elem-19-t + Test possible values for 'keyTimes' + + + + + calcMode="linear" + keyTimes="0;.5;.75;1" + + + Time (s): + 0 + + 4 + + 6 + + 8 + + + + + + + + + + + $Revision: 1.6 $ + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-end-attribute-numeric-precision.html b/tests/wpt/web-platform-tests/svg/animations/animate-end-attribute-numeric-precision.html new file mode 100644 index 000000000000..d0515ac850e8 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-end-attribute-numeric-precision.html @@ -0,0 +1,57 @@ + + + +Tests end conditions are respected properly near the limits of float numeric precision + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-fill-freeze-with-repeatDur.html b/tests/wpt/web-platform-tests/svg/animations/animate-fill-freeze-with-repeatDur.html new file mode 100644 index 000000000000..aab9eacff26b --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-fill-freeze-with-repeatDur.html @@ -0,0 +1,47 @@ + + + +Test for animation freeze when repeatDur is not a multiple of dur + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-from-to-keyTimes.html b/tests/wpt/web-platform-tests/svg/animations/animate-from-to-keyTimes.html new file mode 100644 index 000000000000..7295bcdb630f --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-from-to-keyTimes.html @@ -0,0 +1,60 @@ + + + +Tests discrete from-to-keyTimes animations + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-gradient-transform.html b/tests/wpt/web-platform-tests/svg/animations/animate-gradient-transform.html new file mode 100644 index 000000000000..ddb9946fda6b --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-gradient-transform.html @@ -0,0 +1,103 @@ + + + +Tests if gradientTransform of a gradient is animateable. + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-inherit-css-property.html b/tests/wpt/web-platform-tests/svg/animations/animate-inherit-css-property.html new file mode 100644 index 000000000000..a8b56bab2bfa --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-inherit-css-property.html @@ -0,0 +1,69 @@ + + + +Tests animation with 'inherit'. + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-insert-begin.html b/tests/wpt/web-platform-tests/svg/animations/animate-insert-begin.html new file mode 100644 index 000000000000..5155391a9123 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-insert-begin.html @@ -0,0 +1,59 @@ + + + +Test behavior of dynamically inserting animate with begin attribute + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-insert-no-begin.html b/tests/wpt/web-platform-tests/svg/animations/animate-insert-no-begin.html new file mode 100644 index 000000000000..3db406ecd482 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-insert-no-begin.html @@ -0,0 +1,58 @@ + + + +Test behavior of dynamically inserting animate without begin attribute + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-keySplines.html b/tests/wpt/web-platform-tests/svg/animations/animate-keySplines.html new file mode 100644 index 000000000000..0b02f71d3fa4 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-keySplines.html @@ -0,0 +1,75 @@ + + + +Testing correct parsing of keySplines. + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/animate-marker-orient-from-angle-to-angle.html b/tests/wpt/web-platform-tests/svg/animations/animate-marker-orient-from-angle-to-angle.html new file mode 100644 index 000000000000..a9c16740e632 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/animate-marker-orient-from-angle-to-angle.html @@ -0,0 +1,104 @@ + + + +Animate SVGMarkerElement orientAttr from an angle to an angle + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/animations/syncbase-remove-add-while-running.html b/tests/wpt/web-platform-tests/svg/animations/syncbase-remove-add-while-running.html new file mode 100644 index 000000000000..bebd53725015 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/animations/syncbase-remove-add-while-running.html @@ -0,0 +1,44 @@ + + + +Remove/Add syncbase while animation is running + + + + + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/tools/ci/manifest_build.py b/tests/wpt/web-platform-tests/tools/ci/manifest_build.py index 98e7ce75e512..de17089214ed 100644 --- a/tests/wpt/web-platform-tests/tools/ci/manifest_build.py +++ b/tests/wpt/web-platform-tests/tools/ci/manifest_build.py @@ -21,7 +21,7 @@ class Status(object): SUCCESS = 0 FAIL = 1 - NEUTRAL = 78 + NEUTRAL = 0 def run(cmd, return_stdout=False, **kwargs): diff --git a/tests/wpt/web-platform-tests/tools/ci/tests/test_update_pr_preview.py b/tests/wpt/web-platform-tests/tools/ci/tests/test_update_pr_preview.py index 08e46b9a63ee..3202a1a2df6a 100644 --- a/tests/wpt/web-platform-tests/tools/ci/tests/test_update_pr_preview.py +++ b/tests/wpt/web-platform-tests/tools/ci/tests/test_update_pr_preview.py @@ -66,7 +66,7 @@ def assert_success(returncode): def assert_neutral(returncode): - assert returncode == 78 + assert returncode == 0 def assert_fail(returncode): diff --git a/tests/wpt/web-platform-tests/tools/ci/update_pr_preview.py b/tests/wpt/web-platform-tests/tools/ci/update_pr_preview.py index 9b104c66bb6a..eca4a30678cf 100644 --- a/tests/wpt/web-platform-tests/tools/ci/update_pr_preview.py +++ b/tests/wpt/web-platform-tests/tools/ci/update_pr_preview.py @@ -41,7 +41,7 @@ class Status(object): SUCCESS = 0 FAIL = 1 - NEUTRAL = 78 + NEUTRAL = 0 def request(url, method_name, data=None, json_data=None, ignore_body=False): diff --git a/tests/wpt/web-platform-tests/tools/ci/website_build.sh b/tests/wpt/web-platform-tests/tools/ci/website_build.sh index aadfcbd6a212..e99fcb0cc9fb 100755 --- a/tests/wpt/web-platform-tests/tools/ci/website_build.sh +++ b/tests/wpt/web-platform-tests/tools/ci/website_build.sh @@ -2,7 +2,7 @@ set -ex -neutral_status=78 +neutral_status=0 source_revision=$(git rev-parse HEAD) # The token available in the `GITHUB_TOKEN` variable may be used to push to the # repository, but GitHub Pages will not rebuild the website in response to such diff --git a/tests/wpt/web-platform-tests/user-timing/mark-measure-return-objects.any.js b/tests/wpt/web-platform-tests/user-timing/mark-measure-return-objects.any.js index fa45388d7b11..bb15c5839818 100644 --- a/tests/wpt/web-platform-tests/user-timing/mark-measure-return-objects.any.js +++ b/tests/wpt/web-platform-tests/user-timing/mark-measure-return-objects.any.js @@ -8,7 +8,7 @@ async_test(function (t) { async_test(function (t) { self.performance.clearMeasures(); const measure = self.performance.measure("measure2", - { startTime: 12, endTime:23 }); + { start: 12, end: 23 }); assert_true(measure instanceof PerformanceMeasure); t.done(); }, "L3: performance.measure(name, param1) should return an entry."); diff --git a/tests/wpt/web-platform-tests/user-timing/measure-with-dict.any.js b/tests/wpt/web-platform-tests/user-timing/measure-with-dict.any.js index 99a2fe4d7984..95160fea8941 100644 --- a/tests/wpt/web-platform-tests/user-timing/measure-with-dict.any.js +++ b/tests/wpt/web-platform-tests/user-timing/measure-with-dict.any.js @@ -30,10 +30,12 @@ async_test(function (t) { { entryType: "measure", name: "measure15", detail: null, startTime: timeStamp1, duration: timeStamp2 - timeStamp1 }, { entryType: "measure", name: "measure16", detail: null, startTime: timeStamp1 }, { entryType: "measure", name: "measure17", detail: { customInfo: 159 }, startTime: timeStamp3, duration: timeStamp2 - timeStamp3 }, - { entryType: "measure", name: "measure18", detail: null, startTime: 0 }, - { entryType: "measure", name: "measure19", detail: null, startTime: 0 }, + { entryType: "measure", name: "measure18", detail: null, startTime: timeStamp1, duration: timeStamp2 - timeStamp1 }, + { entryType: "measure", name: "measure19", detail: null, startTime: timeStamp1, duration: timeStamp2 - timeStamp1 }, { entryType: "measure", name: "measure20", detail: null, startTime: 0 }, - { entryType: "measure", name: "measure21", detail: null, startTime: 0 }]; + { entryType: "measure", name: "measure21", detail: null, startTime: 0 }, + { entryType: "measure", name: "measure22", detail: null, startTime: 0 }, + { entryType: "measure", name: "measure23", detail: null, startTime: 0 }]; const observer = new PerformanceObserver( t.step_func(function (entryList, obs) { measureEntries = @@ -80,11 +82,15 @@ async_test(function (t) { self.performance.measure("measure16", { start: 'mark1', end: undefined, detail: null })); returnedEntries.push( self.performance.measure("measure17", { start: timeStamp3, end: 'mark2', detail: { customInfo: 159 }})); + returnedEntries.push( + self.performance.measure("measure18", { start: timeStamp1, duration: timeStamp2 - timeStamp1 })); + returnedEntries.push( + self.performance.measure("measure19", { duration: timeStamp2 - timeStamp1, end: timeStamp2 })); // {}, null, undefined, invalid-dict passed to startOrOptions are interpreted as start time being 0. - returnedEntries.push(self.performance.measure("measure18", {}, 'mark1')); - returnedEntries.push(self.performance.measure("measure19", null, 'mark1')); - returnedEntries.push(self.performance.measure("measure20", undefined, 'mark1')); - returnedEntries.push(self.performance.measure("measure21", { invalidDict:1 }, 'mark1')); + returnedEntries.push(self.performance.measure("measure20", {}, 'mark1')); + returnedEntries.push(self.performance.measure("measure21", null, 'mark1')); + returnedEntries.push(self.performance.measure("measure22", undefined, 'mark1')); + returnedEntries.push(self.performance.measure("measure23", { invalidDict:1 }, 'mark1')); checkEntries(returnedEntries, expectedEntries); }, "measure entries' detail and start/end are customizable"); diff --git a/tests/wpt/web-platform-tests/user-timing/measure_exception.html b/tests/wpt/web-platform-tests/user-timing/measure_exception.html index 8783ff7e2267..df674d931f48 100644 --- a/tests/wpt/web-platform-tests/user-timing/measure_exception.html +++ b/tests/wpt/web-platform-tests/user-timing/measure_exception.html @@ -27,6 +27,8 @@

Description

test_method_throw_exception('performance.measure("Exception5", "ExistMark", "NonExistMark1")', 'SYNTAX_ERR'); test_method_throw_exception('performance.measure("Exception6", "NonExistMark1", "NonExistMark2")', 'SYNTAX_ERR'); test_method_throw_exception('performance.measure("Exception7", "redirectStart")', 'INVALID_ACCESS_ERR'); +test_method_throw_exception('performance.measure("Exception8", {"detail": "non-empty"})', TypeError()); +test_method_throw_exception('performance.measure("Exception9", {"start": 1, "duration": 2, "end": 3})', TypeError()); diff --git a/tests/wpt/web-platform-tests/user-timing/structured-serialize-detail.any.js b/tests/wpt/web-platform-tests/user-timing/structured-serialize-detail.any.js index 55cbd9246f9c..0c4be9a3bcb0 100644 --- a/tests/wpt/web-platform-tests/user-timing/structured-serialize-detail.any.js +++ b/tests/wpt/web-platform-tests/user-timing/structured-serialize-detail.any.js @@ -30,14 +30,14 @@ test(function() { test(function() { performance.clearMeasures(); const detail = { randomInfo: 123 } - const measureEntry = performance.measure("A", { detail }); + const measureEntry = performance.measure("A", { start: 0, detail }); assert_not_equals(measureEntry.detail, detail); }, "The detail property in the measure method should be structured-clone."); test(function() { performance.clearMeasures(); const detail = { randomInfo: 123 } - const measureEntry = performance.measure("A", { detail }); + const measureEntry = performance.measure("A", { start: 0, detail }); assert_equals(measureEntry.detail, measureEntry.detail); }, "The detail property in the measure method should be the same reference."); @@ -51,7 +51,7 @@ test(function() { performance.clearMeasures(); const detail = { unserializable: Symbol() }; assert_throws("DataCloneError", ()=>{ - performance.measure("A", { detail }); + performance.measure("A", { start: 0, detail }); }, "Trying to structured-serialize a Symbol."); }, "Measure: Throw an exception when the detail property cannot be structured-serialized."); diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js index 7b14797d962d..3c1750f1f266 100644 --- a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js +++ b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js @@ -1305,7 +1305,7 @@ const gCSSProperties = { 'text-emphasis-style': { // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-emphasis-style types: [ - { type: 'discrete', options: [ [ 'filled circle', 'open dot' ] ] } + { type: 'discrete', options: [ [ 'circle', 'open dot' ] ] } ] }, 'text-indent': { diff --git a/tests/wpt/web-platform-tests/web-nfc/NDEFMessage_constructor.https.html b/tests/wpt/web-platform-tests/web-nfc/NDEFMessage_constructor.https.html index 73bbb4f8ab51..5be4571493ad 100644 --- a/tests/wpt/web-platform-tests/web-nfc/NDEFMessage_constructor.https.html +++ b/tests/wpt/web-platform-tests/web-nfc/NDEFMessage_constructor.https.html @@ -3,7 +3,7 @@ - + - + - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader.https.html index 3032b652edfb..4488097d6ebe 100644 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReader.https.html +++ b/tests/wpt/web-platform-tests/web-nfc/NFCReader.https.html @@ -5,9 +5,7 @@ - -
- + diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options.https.html new file mode 100644 index 000000000000..ebda3859834c --- /dev/null +++ b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options.https.html @@ -0,0 +1,160 @@ + + +Web NFC: NFCReader option tests + + + + + + diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_mediaType-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_mediaType-manual.https.html deleted file mode 100644 index faaf8f39a77f..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_mediaType-manual.https.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Web NFC Test: NFCReader NFCReaderOptions mediaType test - - - - - - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_empty-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_empty-manual.https.html deleted file mode 100644 index 995072b260d8..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_empty-manual.https.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Web NFC Test: write and read empty records - - - - - - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_json-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_json-manual.https.html deleted file mode 100644 index 4120bc72f308..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_json-manual.https.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Web NFC Test: write and read json records - - - - - - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_opaque-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_opaque-manual.https.html deleted file mode 100644 index 94ded3e8a0fc..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_opaque-manual.https.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Web NFC Test: write and read opaque records - - - - - - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_text-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_text-manual.https.html deleted file mode 100644 index 72ca3e70d430..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_text-manual.https.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Web NFC Test: write and read text records - - - - - - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_url-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_url-manual.https.html deleted file mode 100644 index af57610c285a..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_url-manual.https.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Web NFC Test: write and read url records - - - - - - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_url-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_url-manual.https.html deleted file mode 100644 index aa0e72b089a1..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_url-manual.https.html +++ /dev/null @@ -1,34 +0,0 @@ - - -Web NFC Test: NFCReader NFCReaderOptions url test - - - - - - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReadingEvent_constructor.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReadingEvent_constructor.https.html index 172b0a619c2b..c2f9cef6e505 100644 --- a/tests/wpt/web-platform-tests/web-nfc/NFCReadingEvent_constructor.https.html +++ b/tests/wpt/web-platform-tests/web-nfc/NFCReadingEvent_constructor.https.html @@ -3,7 +3,7 @@ - + diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCWriter_push.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCWriter_push.https.html index 0b804615930b..33471a18d8e1 100644 --- a/tests/wpt/web-platform-tests/web-nfc/NFCWriter_push.https.html +++ b/tests/wpt/web-platform-tests/web-nfc/NFCWriter_push.https.html @@ -5,10 +5,7 @@ - - -
- + diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCWriter_push_signal-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCWriter_push_signal-manual.https.html deleted file mode 100644 index f45d0bbbd498..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/NFCWriter_push_signal-manual.https.html +++ /dev/null @@ -1,45 +0,0 @@ - - -Web NFC Test: NFCWriter signal test - - - - - - - - -

Tap an NFC tag to the test device with NFC support.

- -

Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/README.md b/tests/wpt/web-platform-tests/web-nfc/README.md new file mode 100644 index 000000000000..8ae597e36fd1 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-nfc/README.md @@ -0,0 +1,28 @@ +The `nfc-helpers.js` requires an implementation of +the `WebNFCTest` interfaces, which should emulate platform Web NFC backends. + +The `WebNFCTest` interface is defined as: + +``` + class NFCTestChromium { + initialize(); // Sets up the testing environment. + async reset(); // Frees the resources. + getMockNFC(); // Returns `MockNFC` interface. + }; + + class MockNFC { + setHWStatus(number status); // Sets the hardware status. + setCompatibility(NDEFCompatibility compatibility); // Sets NDEF accepted compatible devices + setReadingMessage(NDEFMessageInit message, NDEFCompatibility compatibility); // Sets message that is used to deliver NFC reading updates with a specific NDEFCompatibility. + setPendingPushCompleted(boolean result); // Sets if the pending push is completed. + setPushShouldTimeout(boolean result); // Sets flag to trigger the pending push to timeout. + pushedMessage(); // Gets the pushed `NDEFMessageSource`. + pushOptions(); // Gets the pushed `NFCPushOptions`. + }; +``` + +The Chromium implementation of the `WebNFCTest` interface is located in +[nfc-mock.js](../resources/chromium/nfc-mock.js). + +Other browser vendors should provide their own implementations of +the `WebNFCTest` interfaces. diff --git a/tests/wpt/web-platform-tests/web-nfc/nfc_hw_disabled-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/nfc_hw_disabled-manual.https.html deleted file mode 100644 index bb2cd42f1e65..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/nfc_hw_disabled-manual.https.html +++ /dev/null @@ -1,37 +0,0 @@ - - -Web NFC Test: NFC HW Disabled - - - - - - - -

Precondition

-
    -
  1. - Disable the NFC module or run test on a device without NFC module. -
  2. -
- -
- - diff --git a/tests/wpt/web-platform-tests/web-nfc/nfc_insecure_context.html b/tests/wpt/web-platform-tests/web-nfc/nfc_insecure_context.html index 0e5764e6ebca..f883f0473b7c 100644 --- a/tests/wpt/web-platform-tests/web-nfc/nfc_insecure_context.html +++ b/tests/wpt/web-platform-tests/web-nfc/nfc_insecure_context.html @@ -5,7 +5,6 @@ -

Note

  1. diff --git a/tests/wpt/web-platform-tests/web-nfc/nfc_push_ArrayBuffer-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/nfc_push_ArrayBuffer-manual.https.html deleted file mode 100644 index 90a356f9b264..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/nfc_push_ArrayBuffer-manual.https.html +++ /dev/null @@ -1,38 +0,0 @@ - - -Web NFC Test: push ArrayBuffer message - - - - - - - - -

    Tap an NFC tag to the test device with NFC support.

    - -

    Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

    - -
    - - diff --git a/tests/wpt/web-platform-tests/web-nfc/nfc_push_DOMString-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/nfc_push_DOMString-manual.https.html deleted file mode 100644 index 15e1da50fb3a..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/nfc_push_DOMString-manual.https.html +++ /dev/null @@ -1,36 +0,0 @@ - - -Web NFC Test: push DOMString message - - - - - - - - -

    Tap an NFC tag to the test device with NFC support.

    - -

    Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.

    - -
    - - diff --git a/tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js b/tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js new file mode 100644 index 000000000000..fc72fa2de89f --- /dev/null +++ b/tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js @@ -0,0 +1,206 @@ +'use strict'; +// These tests rely on the User Agent providing an implementation of +// platform nfc backends. +// +// In Chromium-based browsers this implementation is provided by a polyfill +// in order to reduce the amount of test-only code shipped to users. To enable +// these tests the browser must be run with these options: +// +// --enable-blink-features=MojoJS,MojoJSTest +let loadChromiumResources = Promise.resolve().then(() => { + if (!window.MojoInterfaceInterceptor) { + // Do nothing on non-Chromium-based browsers or when the Mojo bindings are + // not present in the global namespace. + return; + } + + let chain = Promise.resolve(); + [ + '/gen/layout_test_data/mojo/public/js/mojo_bindings.js', + '/gen/services/device/public/mojom/nfc.mojom.js', + '/resources/chromium/nfc-mock.js', + ].forEach(path => { + let script = document.createElement('script'); + script.src = path; + script.async = false; + chain = chain.then(() => new Promise(resolve => { + script.onload = resolve; + })); + document.head.appendChild(script); + }); + + return chain; +}); + +async function initialize_nfc_tests() { + if (typeof WebNFCTest === 'undefined') { + await loadChromiumResources; + } + assert_true( + typeof WebNFCTest !== 'undefined', + 'WebNFC testing interface is not available.' + ); + let NFCTest = new WebNFCTest(); + await NFCTest.initialize(); + return NFCTest; +} + +function nfc_test(func, name, properties) { + promise_test(async t => { + let NFCTest = await initialize_nfc_tests(); + let mockTest = NFCTest.getMockNFC(); + try { + await func(t, mockTest); + } finally { + await NFCTest.reset(); + }; + }, name, properties); +} + +const test_text_data = 'Test text data.'; +const test_text_byte_array = new TextEncoder('utf-8').encode(test_text_data); +const test_number_data = 42; +const test_json_data = {level: 1, score: 100, label: 'Game'}; +const test_url_data = 'https://w3c.github.io/web-nfc/'; +const test_message_origin = 'https://127.0.0.1:8443'; +const test_buffer_data = new ArrayBuffer(test_text_byte_array.length); +const test_buffer_view = + new Uint8Array(test_buffer_data).set(test_text_byte_array); +const fake_tag_serial_number = 'c0:45:00:02'; + +const NFCHWStatus = {}; +// OS-level NFC setting is ON +NFCHWStatus.ENABLED = 1; +// no NFC chip +NFCHWStatus.NOT_SUPPORTED = NFCHWStatus.ENABLED + 1; +// OS-level NFC setting OFF +NFCHWStatus.DISABLED = NFCHWStatus.NOT_SUPPORTED + 1; + +function createMessage(records) { + if (records !== undefined) { + let message = {}; + message.records = records; + return message; + } +} + +function createRecord(recordType, mediaType, data) { + let record = {}; + if (recordType !== undefined) + record.recordType = recordType; + if (mediaType !== undefined) + record.mediaType = mediaType; + if (data !== undefined) + record.data = data; + return record; +} + +function createTextRecord(text) { + return createRecord('text', 'text/plain', text); +} + +function createJsonRecord(json) { + return createRecord('json', 'application/json', json); +} + +function createOpaqueRecord(buffer) { + return createRecord('opaque', 'application/octet-stream', buffer); +} + +function createUrlRecord(url) { + return createRecord('url', 'text/plain', url); +} + +function createNFCPushOptions(target, timeout, ignoreRead, compatibility) { + return { target, timeout, ignoreRead, compatibility}; +} + +// Compares NDEFMessageSource that was provided to the API +// (e.g. NFCWriter.push), and NDEFMessage that was received by the +// mock NFC service. +function assertNDEFMessagesEqual(providedMessage, receivedMessage) { + // If simple data type is passed, e.g. String or ArrayBuffer, convert it + // to NDEFMessage before comparing. + // https://w3c.github.io/web-nfc/#dom-ndefmessagesource + let provided = providedMessage; + if (providedMessage instanceof ArrayBuffer) + provided = createMessage([createOpaqueRecord(providedMessage)]); + else if (typeof providedMessage === 'string') + provided = createMessage([createTextRecord(providedMessage)]); + + assert_equals(provided.records.length, receivedMessage.data.length, + 'NDEFMessages must have same number of NDEFRecords'); + + // Compare contents of each individual NDEFRecord + for (let i = 0; i < provided.records.length; ++i) + compareNDEFRecords(provided.records[i], receivedMessage.data[i]); +} + +// Used to compare two WebNFC messages, one that is provided to mock NFC +// service and another that is received from NFCWriter.onreading() EventHandler. +function assertWebNDEFMessagesEqual(a, b) { + if (b.url) assert_equals(a.url, b.url); + assert_equals(a.records.length, b.records.length); + for(let i in a.records) { + let recordA = a.records[i]; + let recordB = b.records[i]; + assert_equals(recordA.recordType, recordB.recordType); + assert_equals(recordA.mediaType, recordB.mediaType); + if (recordA.data() == null) { + assert_true(recordB.data == null); + } else if (recordA.data() instanceof ArrayBuffer) { + assert_array_equals(new Uint8Array(recordA.data()), + new Uint8Array(recordB.data)); + } else if (typeof recordA.data() === 'object') { + assert_object_equals(recordA.data(), recordB.data); + } else if (typeof recordA.data() === 'number' + || typeof recordA.data() === 'string') { + assert_true(recordA.data() == recordB.data); + } + } +} + +function testNFCReaderOptions(message, readOptions, unmatchedReadOptions, desc) { + nfc_test(async (t, mockNFC) => { + const reader1 = new NFCReader(unmatchedReadOptions); + const reader2 = new NFCReader(readOptions); + + mockNFC.setReadingMessage(message, readOptions.compatibility); + + // Reading from unmatched reader will not be triggered + reader1.onreading = t.unreached_func("reading event should not be fired."); + reader1.start(); + + const readerWatcher = new EventWatcher(t, reader2, ["reading", "error"]); + + const promise = readerWatcher.wait_for("reading").then(event => { + reader1.stop(); + reader2.stop(); + assertWebNDEFMessagesEqual(event.message, message); + }); + // NFCReader#start() asynchronously dispatches the onreading event. + reader2.start(); + await promise; + }, desc); +} + +function testReadingMultiMessages(message, readOptions, unmatchedMessage, + unmatchedCompatibility, desc) { + nfc_test(async (t, mockNFC) => { + const reader = new NFCReader(readOptions); + const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]); + + const promise = readerWatcher.wait_for("reading").then(event => { + reader.stop(); + assertWebNDEFMessagesEqual(event.message, message); + }); + // NFCReader#start() asynchronously dispatches the onreading event. + reader.start(); + + // Unmatched message will not be read + mockNFC.setReadingMessage(unmatchedMessage, unmatchedCompatibility); + mockNFC.setReadingMessage(message); + + await promise; + }, desc); +} diff --git a/tests/wpt/web-platform-tests/web-nfc/resources/nfc_help.js b/tests/wpt/web-platform-tests/web-nfc/resources/nfc_help.js deleted file mode 100644 index 67fd5af381c9..000000000000 --- a/tests/wpt/web-platform-tests/web-nfc/resources/nfc_help.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; - -const test_text_data = "Test text data."; -const test_text_byte_array = new TextEncoder('utf-8').encode(test_text_data); -const test_number_data = 42; -const test_json_data = {level: 1, score: 100, label: 'Game'}; -const test_url_data = "https://w3c.github.io/web-nfc"; -const test_buffer_data = new ArrayBuffer(test_text_byte_array.length); -const test_buffer_view = new Uint8Array(test_buffer_data).set(test_text_byte_array); - -function noop() {}; - -function createMessage(records) { - if (records !== undefined) { - let message = {}; - message.records = records; - return message; - } -} - -function createRecord(recordType, mediaType, data) { - let record = {}; - if (recordType !== undefined) { - record.recordType = recordType; - } - if (mediaType !== undefined) { - record.mediaType = mediaType; - } - if (data !== undefined) { - record.data = data; - } - return record; -} - -function createTextRecord(text) { - return createRecord('text', 'text/plain', text); -} - -function createJsonRecord(json) { - return createRecord('json', 'application/json', json); -} - -function createOpaqueRecord(buffer) { - return createRecord('opaque', 'application/octet-stream', buffer); -} - -function createUrlRecord(url) { - return createRecord('url', 'text/plain', url); -} - -function assertWebNDEFMessagesEqual(a, b) { - if (b.url) assert_equals(a.url, `${location.origin}${b.url}`); - assert_equals(a.records.length, b.records.length); - for(let i in a.records) { - let recordA = a.records[i]; - let recordB = b.records[i]; - assert_equals(recordA.recordType, recordB.recordType); - assert_equals(recordA.mediaType, recordB.mediaType); - if (recordA.data() instanceof ArrayBuffer) { - assert_array_equals(new Uint8Array(recordA.data()), - new Uint8Array(recordB.data())); - } else if (typeof recordA.data() === 'object') { - assert_object_equals(recordA.data(), recordB.data()); - } else if (typeof recordA.data() === 'number' - || typeof recordA.data() === 'string') { - assert_true(recordA.data() == recordB.data()); - } - } -} - -function testNFCReaderOptions(pushedMessage, readOptions, unacceptableReadOptions, desc) { - promise_test(async t => { - const writer = new NFCWriter(); - const reader1 = new NFCReader(unacceptableReadOptions); - const reader2 = new NFCReader(readOptions); - await writer.push(pushedMessage); - - reader1.onreading = t.unreached_func("reading event should not be fired."); - reader1.start(); - - const readerWatcher = new EventWatcher(t, reader2, ["reading", "error"]); - reader2.start(); - const event = await readerWatcher.wait_for("reading"); - assertWebNDEFMessagesEqual(event.message, pushedMessage); - }, desc); -}