aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock118
-rw-r--r--components/compositing/Cargo.toml2
-rw-r--r--components/config/Cargo.toml2
-rw-r--r--components/constellation/pipeline.rs27
-rw-r--r--components/debugger/Cargo.toml2
-rw-r--r--components/layout/display_list/webrender_helpers.rs1
-rw-r--r--components/layout_thread/lib.rs5
-rw-r--r--components/layout_thread_2020/lib.rs5
-rw-r--r--components/layout_traits/lib.rs1
-rw-r--r--components/malloc_size_of/Cargo.toml2
-rw-r--r--components/net/Cargo.toml5
-rw-r--r--components/net/data_loader.rs2
-rw-r--r--components/net_traits/Cargo.toml5
-rw-r--r--components/net_traits/lib.rs38
-rw-r--r--components/script/Cargo.toml5
-rw-r--r--components/script/dom/document.rs2
-rwxr-xr-xcomponents/script/dom/htmlformelement.rs42
-rw-r--r--components/script/dom/htmliframeelement.rs1
-rw-r--r--components/script/dom/windowproxy.rs1
-rw-r--r--components/script/script_thread.rs6
-rw-r--r--components/script_layout_interface/message.rs1
-rw-r--r--components/script_traits/Cargo.toml2
-rw-r--r--components/script_traits/lib.rs4
-rw-r--r--components/url/Cargo.toml3
-rw-r--r--components/url/lib.rs20
-rw-r--r--components/url/origin.rs10
-rw-r--r--components/webdriver_server/Cargo.toml4
-rw-r--r--etc/taskcluster/decision_task.py2
-rw-r--r--ports/glutin/Cargo.toml2
-rw-r--r--ports/glutin/headed_window.rs2
-rw-r--r--python/servo/build_commands.py2
-rw-r--r--servo-tidy.toml1
-rw-r--r--support/hololens/ServoApp/Servo.cpp2
-rw-r--r--tests/wpt/metadata/MANIFEST.json2315
-rw-r--r--tests/wpt/metadata/css/css-align/parsing/gap-computed.html.ini34
-rw-r--r--tests/wpt/metadata/css/css-align/parsing/gap-valid.html.ini28
-rw-r--r--tests/wpt/metadata/css/css-paint-api/custom-property-animation-on-main-thread.https.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-paint-api/one-custom-property-animation.https.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-paint-api/two-custom-property-animation.https.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-text-decor/parsing/text-decoration-valid.html.ini21
-rw-r--r--tests/wpt/metadata/css/css-transforms/animation/composited-transform.html.ini4
-rw-r--r--tests/wpt/metadata/css/css-transitions/CSSTransition-effect.tentative.html.ini3
-rw-r--r--tests/wpt/metadata/css/css-transitions/parsing/transition-timing-function-computed.html.ini13
-rw-r--r--tests/wpt/metadata/css/css-values/max-length-percent-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-values/min-length-percent-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/cssom-view/matchMedia-display-none-iframe.html.ini2
-rw-r--r--tests/wpt/metadata/fetch/content-type/response.window.js.ini14
-rw-r--r--tests/wpt/metadata/fetch/content-type/script.window.js.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini4
-rw-r--r--tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini4
-rw-r--r--tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini4
-rw-r--r--tests/wpt/metadata/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html.ini4
-rw-r--r--tests/wpt/metadata/html/cross-origin-embedder-policy/blob.https.html.ini19
-rw-r--r--tests/wpt/metadata/html/cross-origin-embedder-policy/data.https.html.ini4
-rw-r--r--tests/wpt/metadata/html/cross-origin-embedder-policy/none.https.html.ini4
-rw-r--r--tests/wpt/metadata/html/cross-origin-embedder-policy/require-corp.https.html.ini25
-rw-r--r--tests/wpt/metadata/html/cross-origin-embedder-policy/sandbox.https.html.ini5
-rw-r--r--tests/wpt/metadata/html/cross-origin-embedder-policy/srcdoc.https.html.ini5
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/coep-navigate-popup.https.html.ini37
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/coep-redirect.https.html.ini19
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/coep.https.html.ini25
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/coop-navigated-popup.https.html.ini4
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/coop-sandbox.https.html.ini4
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/popup-none.https.html.ini55
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.ini55
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-origin.https.html.ini55
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.ini55
-rw-r--r--tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-site.https.html.ini55
-rw-r--r--tests/wpt/metadata/html/dom/interfaces.https.html.ini21
-rw-r--r--tests/wpt/metadata/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html.ini4
-rw-r--r--tests/wpt/metadata/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html.ini2
-rw-r--r--tests/wpt/metadata/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/interactive-elements/the-details-element/toggleEvent.html.ini7
-rw-r--r--tests/wpt/metadata/html/syntax/parsing/DOMContentLoaded-defer.html.ini4
-rw-r--r--tests/wpt/metadata/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini4
-rw-r--r--tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini3
-rw-r--r--tests/wpt/metadata/url/a-element-origin-xhtml.xhtml.ini5
-rw-r--r--tests/wpt/metadata/url/a-element-origin.html.ini4
-rw-r--r--tests/wpt/metadata/url/a-element-xhtml.xhtml.ini9
-rw-r--r--tests/wpt/metadata/url/a-element.html.ini9
-rw-r--r--tests/wpt/metadata/url/toascii.window.js.ini210
-rw-r--r--tests/wpt/metadata/url/url-constructor.html.ini9
-rw-r--r--tests/wpt/metadata/url/url-origin.html.ini8
-rw-r--r--tests/wpt/metadata/url/url-setters.html.ini12
-rw-r--r--tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini1
-rw-r--r--tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini3
-rw-r--r--tests/wpt/metadata/webxr/xrBoundedReferenceSpace_updates.https.html.ini2
-rw-r--r--tests/wpt/metadata/workers/WorkerGlobalScope-close.html.ini4
-rw-r--r--tests/wpt/web-platform-tests/.azure-pipelines.yml10
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.js14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.tentative.https.html8
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.js16
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.tentative.https.html8
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002-ref.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-001.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-002.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-003.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-align/parsing/gap-computed.html35
-rw-r--r--tests/wpt/web-platform-tests/css/css-align/parsing/gap-invalid.html21
-rw-r--r--tests/wpt/web-platform-tests/css/css-align/parsing/gap-valid.html26
-rw-r--r--tests/wpt/web-platform-tests/css/css-box/parsing/padding-invalid.html11
-rw-r--r--tests/wpt/web-platform-tests/css/css-box/parsing/padding-valid.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/parsing/display-invalid.html54
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/parsing/display-valid.html93
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/inline-flex-min-content-height.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-block-list-marker-ref.html62
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-block-list-marker.html63
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-block-list-ref.html61
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-block-list.html62
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-list-marker-ref.html51
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-list-marker.html63
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-list-ref.html49
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-list-with-table-child-ref.html40
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-list-with-table-child.html44
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/inline-list.html62
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-001-ref.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-001.html14
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-002-ref.html10
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-002.html17
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-003.html16
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-004-ref.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-004.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-005.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-breaking-nobackground-004-ref.html72
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-breaking-nobackground-004.html55
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-nested-balancing-003-ref.html41
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-nested-balancing-003.html36
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/custom-property-animation-on-main-thread.https.html58
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/one-custom-property-animation-ref.html14
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/one-custom-property-animation.https.html60
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/two-custom-property-animation-ref.html14
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/two-custom-property-animation.https.html76
-rw-r--r--tests/wpt/web-platform-tests/css/css-pseudo/first-letter-of-html-root-crash-ref.html3
-rw-r--r--tests/wpt/web-platform-tests/css/css-pseudo/first-letter-of-html-root-crash.html16
-rw-r--r--tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-computed.html25
-rw-r--r--tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-invalid.html24
-rw-r--r--tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-valid.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-001-ref.html37
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-001.html39
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-002-ref.html43
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-002.html51
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-003-ref.html46
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-003.html56
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-004-ref.html49
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-004.html62
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-005-ref.html52
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/block-ruby-005.html62
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/root-block-ruby.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/root-ruby-ref.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/css/css-ruby/root-ruby.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/css/css-tables/table-cell-overflow-auto-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-tables/table-cell-overflow-auto.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/inheritance.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-invalid.html3
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-valid.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-computed.html31
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-invalid.html20
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-valid.html22
-rw-r--r--tests/wpt/web-platform-tests/css/css-text/shaping/reference/shaping-014-ref.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-text/shaping/shaping-014.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/animation/composited-transform.html38
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/CSSTransition-effect.tentative.html38
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/parsing/transition-timing-function-computed.html (renamed from tests/wpt/web-platform-tests/css/css-animations/parsing/transition-timing-function-computed.html)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/parse.tentative.html10
-rw-r--r--tests/wpt/web-platform-tests/css/css-typed-om/width-by-max-px-em.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-typed-om/width-by-min-px-em.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-values/max-length-percent-001.html18
-rw-r--r--tests/wpt/web-platform-tests/css/css-values/min-length-percent-001.html18
-rw-r--r--tests/wpt/web-platform-tests/element-timing/toJSON.html47
-rw-r--r--tests/wpt/web-platform-tests/event-timing/toJSON.html43
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html100
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/README.md1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html44
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html20
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html21
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html79
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html138
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html17
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers2
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-none.sub.html (renamed from tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_null.sub.html)0
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html (renamed from tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_anonymous.sub.html)0
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/script-factory.js23
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/sandbox.https.html40
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/sandbox.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html21
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/README.md11
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html62
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers2
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html67
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html.headers2
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html43
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html.headers2
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html29
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https.html22
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https.html.headers (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin.tentative.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html18
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-none.https.html (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_null.tentative.html)5
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html15
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html)3
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin.https.html (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin.tentative.html)3
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html)3
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.headers (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site.https.html (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site.tentative.html)3
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site.https.html.headers (renamed from tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site.tentative.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/common.js36
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/coop-coep.py35
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html10
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener/common.sub.js28
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener/resources/coop_window.py10
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener/resources/postback.sub.html13
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html18
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html219
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html103
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_anonymous.sub.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html18
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/resources/nothing.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/resources/nothing.txt.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html18
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html54
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/interfaces.https.html1
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.html32
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.worker.js24
-rw-r--r--tests/wpt/web-platform-tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html74
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html29
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html24
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html23
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html24
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html50
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/parsing-addresses.tentative.html11
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/parsing-schema.tentative.html11
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/parsing-scope-keys.tentative.html11
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/parsing-specifier-keys.tentative.html11
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resolving-builtins.tentative.html11
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resolving-not-yet-implemented.tentative.html11
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resolving-scopes.tentative.html11
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resolving.tentative.html11
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/helpers/parsing.js50
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-addresses.js351
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-schema.js139
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-scope-keys.js145
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/parsing-specifier-keys.js159
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-builtins.js158
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-not-yet-implemented.js47
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/resolving-scopes.js230
-rw-r--r--tests/wpt/web-platform-tests/import-maps/imported/resources/resolving.js (renamed from tests/wpt/web-platform-tests/import-maps/resources/resolving.js)102
-rw-r--r--tests/wpt/web-platform-tests/import-maps/resources/jest-test-helper.js (renamed from tests/wpt/web-platform-tests/import-maps/resolving.tentative.html)61
-rw-r--r--tests/wpt/web-platform-tests/interfaces/element-timing.idl1
-rw-r--r--tests/wpt/web-platform-tests/interfaces/event-timing.idl1
-rw-r--r--tests/wpt/web-platform-tests/interfaces/largest-contentful-paint.idl1
-rw-r--r--tests/wpt/web-platform-tests/interfaces/layout-instability.idl1
-rw-r--r--tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl98
-rw-r--r--tests/wpt/web-platform-tests/largest-contentful-paint/first-letter-background.html48
-rw-r--r--tests/wpt/web-platform-tests/largest-contentful-paint/observe-after-untrusted-scroll.html2
-rw-r--r--tests/wpt/web-platform-tests/largest-contentful-paint/toJSON.html42
-rw-r--r--tests/wpt/web-platform-tests/layout-instability/toJSON.html42
-rw-r--r--tests/wpt/web-platform-tests/lint.whitelist4
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006-ref.html74
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006.html79
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007-ref.html42
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007.html50
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008.html33
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009-ref.html21
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009.html27
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010-ref.html44
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010.html51
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity-ref.html163
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity.html168
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/inheritance.html21
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-computed.html24
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-invalid.html18
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-valid.html23
-rw-r--r--tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001.html18
-rw-r--r--tests/wpt/web-platform-tests/referrer-policy/generic/referrer-policy-test-case.sub.js15
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js415
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/lib/README.md2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js2239
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.js10
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/DocumentOrShadowRoot-activeElement.html92
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-negative.html34
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html37
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html36
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html35
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html37
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html37
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero.html35
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/focus/resources/shadow-utils.js79
-rw-r--r--tests/wpt/web-platform-tests/sms/README.md3
-rw-r--r--tests/wpt/web-platform-tests/streams/readable-streams/patched-global.any.js32
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/accumulate-values-width-animation.html110
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/additive-from-to-width-animation.html61
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/additive-type-by-animation.html275
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/additive-values-width-animation.html83
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-by.html70
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-by.html71
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-to.html71
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-to.html70
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-values.html70
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-color-calcMode-discrete.html63
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-color-fill-currentColor.html63
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-color-fill-from-by.html63
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-color-transparent.html53
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-css-xml-attributeType.html88
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-currentColor.html63
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-dynamic-update-attributeName.html71
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-elem-02-t-drt.html183
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-elem-14-t-drt.html140
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-elem-15-t-drt.html136
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-elem-16-t-drt.html136
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-elem-17-t-drt.html136
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-elem-18-t-drt.html137
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-elem-19-t-drt.html136
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-end-attribute-numeric-precision.html57
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-fill-freeze-with-repeatDur.html47
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-from-to-keyTimes.html60
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-gradient-transform.html103
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-inherit-css-property.html69
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-insert-begin.html59
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-insert-no-begin.html58
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-keySplines.html75
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/animate-marker-orient-from-angle-to-angle.html104
-rw-r--r--tests/wpt/web-platform-tests/svg/animations/syncbase-remove-add-while-running.html44
-rw-r--r--tests/wpt/web-platform-tests/tools/ci/manifest_build.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/ci/tests/test_update_pr_preview.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/ci/update_pr_preview.py2
-rwxr-xr-xtests/wpt/web-platform-tests/tools/ci/website_build.sh2
-rw-r--r--tests/wpt/web-platform-tests/user-timing/mark-measure-return-objects.any.js2
-rw-r--r--tests/wpt/web-platform-tests/user-timing/measure-with-dict.any.js20
-rw-r--r--tests/wpt/web-platform-tests/user-timing/measure_exception.html2
-rw-r--r--tests/wpt/web-platform-tests/user-timing/structured-serialize-detail.any.js6
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js2
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NDEFMessage_constructor.https.html2
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NDEFRecord_constructor.https.html2
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader-manual.https.html64
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader.https.html117
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader_options.https.html160
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader_options_mediaType-manual.https.html31
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_empty-manual.https.html31
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_json-manual.https.html31
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_opaque-manual.https.html31
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_text-manual.https.html31
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_url-manual.https.html31
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReader_options_url-manual.https.html34
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCReadingEvent_constructor.https.html4
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCWriter_push.https.html181
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/NFCWriter_push_signal-manual.https.html45
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/README.md28
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/nfc_hw_disabled-manual.https.html37
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/nfc_insecure_context.html1
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/nfc_push_ArrayBuffer-manual.https.html38
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/nfc_push_DOMString-manual.https.html36
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js206
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/resources/nfc_help.js86
379 files changed, 14696 insertions, 3070 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9c0b0652d9e..a62b52321f8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -414,7 +414,7 @@ dependencies = [
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"offscreen_gl_context 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pixels 0.0.1",
- "raqote 0.6.1-alpha.0 (git+https://github.com/jrmuizel/raqote)",
+ "raqote 0.6.2-alpha.0 (git+https://github.com/jrmuizel/raqote)",
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
"webrender 0.60.0 (git+https://github.com/servo/webrender)",
@@ -611,7 +611,7 @@ dependencies = [
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"gleam 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -732,7 +732,7 @@ dependencies = [
[[package]]
name = "crc32fast"
-version = "1.1.2"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -900,7 +900,7 @@ version = "0.0.1"
dependencies = [
"crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "ws 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2114,7 +2114,7 @@ dependencies = [
[[package]]
name = "image"
-version = "0.21.0"
+version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2124,10 +2124,9 @@ dependencies = [
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "png 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tiff 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2533,7 +2532,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2744,7 +2743,7 @@ dependencies = [
"string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.60.0 (git+https://github.com/servo/webrender)",
"xml5ever 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3085,6 +3084,7 @@ dependencies = [
"msg 0.0.1",
"net_traits 0.0.1",
"openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pixels 0.0.1",
"profile_traits 0.0.1",
"rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3100,10 +3100,10 @@ dependencies = [
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-openssl 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.60.0 (git+https://github.com/servo/webrender)",
- "ws 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -3127,7 +3127,7 @@ dependencies = [
"http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper_serde 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3136,6 +3136,7 @@ dependencies = [
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1",
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pixels 0.0.1",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_arc 0.1.1",
@@ -3143,7 +3144,7 @@ dependencies = [
"servo_url 0.0.1",
"std_test_override 0.0.1",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.60.0 (git+https://github.com/servo/webrender)",
]
@@ -3455,7 +3456,7 @@ dependencies = [
[[package]]
name = "peek-poke"
version = "0.2.0"
-source = "git+https://github.com/servo/webrender#9e35bec12890c1136607ff218789f20d956adb81"
+source = "git+https://github.com/servo/webrender#cdfafba1709a2634c612032fd3b456a62a10391f"
dependencies = [
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"peek-poke-derive 0.2.0 (git+https://github.com/servo/webrender)",
@@ -3464,7 +3465,7 @@ dependencies = [
[[package]]
name = "peek-poke-derive"
version = "0.2.0"
-source = "git+https://github.com/servo/webrender#9e35bec12890c1136607ff218789f20d956adb81"
+source = "git+https://github.com/servo/webrender#cdfafba1709a2634c612032fd3b456a62a10391f"
dependencies = [
"proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3560,13 +3561,13 @@ dependencies = [
[[package]]
name = "png"
-version = "0.14.0"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)",
"inflate 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -3769,13 +3770,13 @@ dependencies = [
[[package]]
name = "raqote"
-version = "0.6.1-alpha.0"
-source = "git+https://github.com/jrmuizel/raqote#4b9ae1986e3211d788dacc0a58ce4d5734dbdb44"
+version = "0.6.2-alpha.0"
+source = "git+https://github.com/jrmuizel/raqote#2d9a0fbb419d10e066fb49e121a45fce1e1f2abe"
dependencies = [
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"font-kit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lyon_geom 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "png 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sw-composite 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"typed-arena 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -3925,11 +3926,6 @@ dependencies = [
]
[[package]]
-name = "safe-transmute"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "safemem"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3994,7 +3990,7 @@ dependencies = [
"http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper_serde 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4016,6 +4012,7 @@ dependencies = [
"net_traits 0.0.1",
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4048,7 +4045,7 @@ dependencies = [
"tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"typetag 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4143,7 +4140,7 @@ dependencies = [
"servo_url 0.0.1",
"style_traits 0.0.1",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.60.0 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1",
@@ -4243,7 +4240,7 @@ dependencies = [
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4500,7 +4497,7 @@ dependencies = [
"servo_geometry 0.0.1",
"servo_url 0.0.1",
"std_test_override 0.0.1",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -4565,8 +4562,7 @@ dependencies = [
"servo_rand 0.0.1",
"to_shmem 0.0.1",
"to_shmem_derive 0.0.1",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -5010,7 +5006,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "tiff"
-version = "0.2.1"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -5408,15 +5404,7 @@ dependencies = [
"idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "url_serde"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -5589,7 +5577,7 @@ dependencies = [
"crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"keyboard-types 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -5602,7 +5590,7 @@ dependencies = [
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
"servo_url 0.0.1",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -5610,7 +5598,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.60.0"
-source = "git+https://github.com/servo/webrender#9e35bec12890c1136607ff218789f20d956adb81"
+source = "git+https://github.com/servo/webrender#cdfafba1709a2634c612032fd3b456a62a10391f"
dependencies = [
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -5626,7 +5614,7 @@ dependencies = [
"freetype 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -5651,7 +5639,7 @@ dependencies = [
[[package]]
name = "webrender_api"
version = "0.60.0"
-source = "git+https://github.com/servo/webrender#9e35bec12890c1136607ff218789f20d956adb81"
+source = "git+https://github.com/servo/webrender#cdfafba1709a2634c612032fd3b456a62a10391f"
dependencies = [
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -5673,7 +5661,7 @@ dependencies = [
[[package]]
name = "webrender_build"
version = "0.0.1"
-source = "git+https://github.com/servo/webrender#9e35bec12890c1136607ff218789f20d956adb81"
+source = "git+https://github.com/servo/webrender#cdfafba1709a2634c612032fd3b456a62a10391f"
dependencies = [
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -5839,7 +5827,7 @@ dependencies = [
[[package]]
name = "wr_malloc_size_of"
version = "0.0.1"
-source = "git+https://github.com/servo/webrender#9e35bec12890c1136607ff218789f20d956adb81"
+source = "git+https://github.com/servo/webrender#cdfafba1709a2634c612032fd3b456a62a10391f"
dependencies = [
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -5856,7 +5844,6 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.18 (git+https://github.com/servo/mio.git?branch=servo)",
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -5864,6 +5851,24 @@ dependencies = [
]
[[package]]
+name = "ws"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.18 (git+https://github.com/servo/mio.git?branch=servo)",
+ "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "x11"
version = "2.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6006,7 +6011,7 @@ dependencies = [
"checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
"checksum core-text 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d95a72b5e50e549969dd88eff3047495fe5b8c6f028635442c2b708be707e669"
"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
-"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
+"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b"
"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
@@ -6125,7 +6130,7 @@ dependencies = [
"checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa"
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
-"checksum image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "52fb0666a1273dac46f9725aa4859bcd5595fc3554cf3495051b4de8db745e7d"
+"checksum image 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "663a975007e0b49903e2e8ac0db2c432c465855f2d65f17883ba1476e85f0b42"
"checksum immeta 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7371aa3c98fad60de2d9b517e2e1ed45593c32b0c77249310fa507749a2a318b"
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
"checksum inflate 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6f53b811ee8e2057ccf9643ca6b4277de90efaf5e61e55fd5254576926bb4245"
@@ -6236,7 +6241,7 @@ dependencies = [
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum plane-split 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68a117c887fbcd9af8dfc1b8b12ee19ba9dec0b2a91d0a9d2bd9114e459f9c78"
-"checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"
+"checksum png 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8422b27bb2c013dd97b9aef69e161ce262236f49aaf46a0489011c8ff0264602"
"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
"checksum proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1dd4172a1e1f96f709341418f49b11ea6c2d95d53dca08c0f74cbd332d9cf3"
@@ -6254,7 +6259,7 @@ dependencies = [
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
-"checksum raqote 0.6.1-alpha.0 (git+https://github.com/jrmuizel/raqote)" = "<none>"
+"checksum raqote 0.6.2-alpha.0 (git+https://github.com/jrmuizel/raqote)" = "<none>"
"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4"
"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
@@ -6271,7 +6276,6 @@ dependencies = [
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rusttype 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20"
-"checksum safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9604873ffe1980bc1f179103704a65c8aca141c248d9e52b7af95ff10578166e"
"checksum safemem 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e133ccc4f4d1cd4f89cc8a7ff618287d56dc7f638b8e38fc32c5fdcadc339dd5"
"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
@@ -6334,7 +6338,7 @@ dependencies = [
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5920e77802b177479ab5795767fa48e68f61b2f516c2ac0041e2978dd8efe483"
"checksum threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59f6d3eff89920113dac9db44dde461d71d01e88a5b57b258a0466c32b5d7fe1"
-"checksum tiff 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a2cc6c4fd13cb1cfd20abdb196e794ceccb29371855b7e7f575945f920a5b3c2"
+"checksum tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b7c2cfc4742bd8a32f2e614339dd8ce30dbcf676bb262bd63a2327bc5df57d"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d79833ca2c493c726ea6a7b651ba0ff8a790add5156cd11bf3743f346005c0c8"
"checksum tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6e93c78d23cc61aa245a8acd2c4a79c4d7fa7fb5c3ca90d5737029f043a84895"
@@ -6374,7 +6378,6 @@ dependencies = [
"checksum unwind-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bd1c4a6d1cfe0072924d1b1d4ca6faa211c95056666979d7ef1bab4cd206057f"
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
-"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
"checksum urlencoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3df3561629a8bb4c57e5a2e4c43348d9e29c7c29d9b1c4c1f47166deca8f37ed"
"checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
@@ -6409,6 +6412,7 @@ dependencies = [
"checksum wio 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5"
"checksum wr_malloc_size_of 0.0.1 (git+https://github.com/servo/webrender)" = "<none>"
"checksum ws 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec91ea61b83ce033c43c06c52ddc7532f465c0153281610d44c58b74083aee1a"
+"checksum ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6f5bb86663ff4d1639408410f50bf6050367a8525d644d49a6894cd618a631"
"checksum x11 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5c4ac579b5d324dc4add02312b5d0e3e0218521e2d5779d526ac39ee4bb171"
"checksum x11-clipboard 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d8617c6185c96e5fcf57ff156496d73c9c82b7f09a5fea21b518dd32c10e2e05"
"checksum x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)" = "940586acb859ea05c53971ac231685799a7ec1dee66ac0bccc0e6ad96e06b4e3"
diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml
index 26cfa152dad..25cb2754276 100644
--- a/components/compositing/Cargo.toml
+++ b/components/compositing/Cargo.toml
@@ -21,7 +21,7 @@ embedder_traits = {path = "../embedder_traits"}
euclid = "0.20"
gfx_traits = {path = "../gfx_traits"}
gleam = {version = "0.6", optional = true}
-image = "0.21"
+image = "0.22"
ipc-channel = "0.11"
libc = "0.2"
keyboard-types = "0.4.3"
diff --git a/components/config/Cargo.toml b/components/config/Cargo.toml
index 568d2acb92b..274c4cc4492 100644
--- a/components/config/Cargo.toml
+++ b/components/config/Cargo.toml
@@ -25,7 +25,7 @@ serde_derive = "1.0"
serde_json = "1.0"
servo_geometry = {path = "../geometry"}
servo_url = {path = "../url"}
-url = "1.2"
+url = "2.0"
servo_config_plugins = { path = "../config_plugins" }
[dev-dependencies]
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index 43c6a13524f..5182110f3a5 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -9,7 +9,7 @@ use canvas_traits::webgl::WebGLPipeline;
use compositing::compositor_thread::Msg as CompositorMsg;
use compositing::CompositionPipeline;
use compositing::CompositorProxy;
-use crossbeam_channel::Sender;
+use crossbeam_channel::{unbounded, Sender};
use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
use embedder_traits::EventLoopWaker;
use euclid::{Scale, Size2D};
@@ -218,9 +218,6 @@ impl Pipeline {
// probably requires a general low-memory strategy.
let (pipeline_chan, pipeline_port) = ipc::channel().expect("Pipeline main chan");
- let (layout_content_process_shutdown_chan, layout_content_process_shutdown_port) =
- ipc::channel().expect("Pipeline layout content shutdown chan");
-
let window_size = WindowSizeData {
initial_viewport: state.window_size,
device_pixel_ratio: state.device_pixel_ratio,
@@ -237,7 +234,6 @@ impl Pipeline {
load_data: state.load_data.clone(),
window_size: window_size,
pipeline_port: pipeline_port,
- content_process_shutdown_chan: Some(layout_content_process_shutdown_chan),
};
if let Err(e) =
@@ -275,9 +271,6 @@ impl Pipeline {
script_to_devtools_chan
});
- let (script_content_process_shutdown_chan, script_content_process_shutdown_port) =
- ipc::channel().expect("Pipeline script content process shutdown chan");
-
let mut unprivileged_pipeline_content = UnprivilegedPipelineContent {
id: state.id,
browsing_context_id: state.browsing_context_id,
@@ -306,10 +299,6 @@ impl Pipeline {
prefs: prefs::pref_map().iter().collect(),
pipeline_port: pipeline_port,
pipeline_namespace_id: state.pipeline_namespace_id,
- layout_content_process_shutdown_chan: layout_content_process_shutdown_chan,
- layout_content_process_shutdown_port: layout_content_process_shutdown_port,
- script_content_process_shutdown_chan: script_content_process_shutdown_chan,
- script_content_process_shutdown_port: script_content_process_shutdown_port,
webrender_api_sender: state.webrender_api_sender,
webrender_document: state.webrender_document,
webgl_chan: state.webgl_chan,
@@ -515,10 +504,6 @@ pub struct UnprivilegedPipelineContent {
prefs: HashMap<String, PrefValue>,
pipeline_port: IpcReceiver<LayoutControlMsg>,
pipeline_namespace_id: PipelineNamespaceId,
- layout_content_process_shutdown_chan: IpcSender<()>,
- layout_content_process_shutdown_port: IpcReceiver<()>,
- script_content_process_shutdown_chan: IpcSender<()>,
- script_content_process_shutdown_port: IpcReceiver<()>,
webrender_api_sender: webrender_api::RenderApiSender,
webrender_document: webrender_api::DocumentId,
webgl_chan: Option<WebGLPipeline>,
@@ -545,6 +530,7 @@ impl UnprivilegedPipelineContent {
self.script_chan.clone(),
self.load_data.url.clone(),
);
+ let (content_process_shutdown_chan, content_process_shutdown_port) = unbounded();
let layout_thread_busy_flag = Arc::new(AtomicBool::new(false));
let layout_pair = STF::create(
InitialScriptState {
@@ -567,7 +553,7 @@ impl UnprivilegedPipelineContent {
devtools_chan: self.devtools_chan,
window_size: self.window_size,
pipeline_namespace_id: self.pipeline_namespace_id,
- content_process_shutdown_chan: self.script_content_process_shutdown_chan,
+ content_process_shutdown_chan: content_process_shutdown_chan,
webgl_chan: self.webgl_chan,
webvr_chan: self.webvr_chan,
webxr_registry: self.webxr_registry,
@@ -605,7 +591,6 @@ impl UnprivilegedPipelineContent {
self.font_cache_thread,
self.time_profiler_chan,
self.mem_profiler_chan,
- Some(self.layout_content_process_shutdown_chan),
self.webrender_api_sender,
self.webrender_document,
paint_time_metrics,
@@ -624,8 +609,10 @@ impl UnprivilegedPipelineContent {
);
if wait_for_completion {
- let _ = self.script_content_process_shutdown_port.recv();
- let _ = self.layout_content_process_shutdown_port.recv();
+ match content_process_shutdown_port.recv() {
+ Ok(()) => {},
+ Err(_) => error!("Script-thread shut-down unexpectedly"),
+ }
}
}
diff --git a/components/debugger/Cargo.toml b/components/debugger/Cargo.toml
index 1e7ed26fedd..3d0e542b209 100644
--- a/components/debugger/Cargo.toml
+++ b/components/debugger/Cargo.toml
@@ -14,4 +14,4 @@ crate_type = ["rlib"]
[dependencies]
crossbeam-channel = "0.3"
log = "0.4"
-ws = "0.8"
+ws = "0.9"
diff --git a/components/layout/display_list/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs
index 37232dda832..a27979a3189 100644
--- a/components/layout/display_list/webrender_helpers.rs
+++ b/components/layout/display_list/webrender_helpers.rs
@@ -230,6 +230,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
raster_space: RasterSpace::Screen,
// TODO(pcwalton): Enable picture caching?
cache_tiles: false,
+ is_backdrop_root: false,
},
};
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index 2febabce08b..887c31f4657 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -306,7 +306,6 @@ impl LayoutThreadFactory for LayoutThread {
font_cache_thread: FontCacheThread,
time_profiler_chan: profile_time::ProfilerChan,
mem_profiler_chan: profile_mem::ProfilerChan,
- content_process_shutdown_chan: Option<IpcSender<()>>,
webrender_api_sender: webrender_api::RenderApiSender,
webrender_document: webrender_api::DocumentId,
paint_time_metrics: PaintTimeMetrics,
@@ -383,9 +382,6 @@ impl LayoutThreadFactory for LayoutThread {
Msg::CollectReports,
);
}
- if let Some(content_process_shutdown_chan) = content_process_shutdown_chan {
- let _ = content_process_shutdown_chan.send(());
- }
})
.expect("Thread spawning failed");
}
@@ -951,7 +947,6 @@ impl LayoutThread {
self.font_cache_thread.clone(),
self.time_profiler_chan.clone(),
self.mem_profiler_chan.clone(),
- info.content_process_shutdown_chan,
self.webrender_api.clone_sender(),
self.webrender_document,
info.paint_time_metrics,
diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs
index 3f6c2e6f8d5..82919fa75c1 100644
--- a/components/layout_thread_2020/lib.rs
+++ b/components/layout_thread_2020/lib.rs
@@ -243,7 +243,6 @@ impl LayoutThreadFactory for LayoutThread {
font_cache_thread: FontCacheThread,
time_profiler_chan: profile_time::ProfilerChan,
mem_profiler_chan: profile_mem::ProfilerChan,
- content_process_shutdown_chan: Option<IpcSender<()>>,
webrender_api_sender: webrender_api::RenderApiSender,
webrender_document: webrender_api::DocumentId,
paint_time_metrics: PaintTimeMetrics,
@@ -312,9 +311,6 @@ impl LayoutThreadFactory for LayoutThread {
Msg::CollectReports,
);
}
- if let Some(content_process_shutdown_chan) = content_process_shutdown_chan {
- let _ = content_process_shutdown_chan.send(());
- }
})
.expect("Thread spawning failed");
}
@@ -819,7 +815,6 @@ impl LayoutThread {
self.font_cache_thread.clone(),
self.time_profiler_chan.clone(),
self.mem_profiler_chan.clone(),
- info.content_process_shutdown_chan,
self.webrender_api.clone_sender(),
self.webrender_document,
info.paint_time_metrics,
diff --git a/components/layout_traits/lib.rs b/components/layout_traits/lib.rs
index a37e8943125..cfb824f6c98 100644
--- a/components/layout_traits/lib.rs
+++ b/components/layout_traits/lib.rs
@@ -43,7 +43,6 @@ pub trait LayoutThreadFactory {
font_cache_thread: FontCacheThread,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
- content_process_shutdown_chan: Option<IpcSender<()>>,
webrender_api_sender: webrender_api::RenderApiSender,
webrender_document: webrender_api::DocumentId,
paint_time_metrics: PaintTimeMetrics,
diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml
index 3de67f45abb..cee59ed2c73 100644
--- a/components/malloc_size_of/Cargo.toml
+++ b/components/malloc_size_of/Cargo.toml
@@ -41,7 +41,7 @@ smallvec = "0.6"
string_cache = { version = "0.7", optional = true }
thin-slice = "0.1.0"
time = { version = "0.1.17", optional = true }
-url = { version = "1.2", optional = true }
+url = { version = "2.0", optional = true }
webrender_api = { git = "https://github.com/servo/webrender", features = ["ipc"], optional = true }
xml5ever = { version = "0.14", optional = true }
void = "1.0.2"
diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml
index e979db00765..b2bcbc0d7bf 100644
--- a/components/net/Cargo.toml
+++ b/components/net/Cargo.toml
@@ -42,6 +42,7 @@ mime_guess = "2.0.0-alpha.6"
msg = {path = "../msg"}
net_traits = {path = "../net_traits"}
openssl = "0.10"
+percent-encoding = "2.0"
pixels = {path = "../pixels"}
profile_traits = {path = "../profile_traits"}
rayon = "1"
@@ -55,10 +56,10 @@ tokio = "0.1"
tokio-timer = "0.2"
threadpool = "1.0"
time = "0.1.17"
-url = "1.2"
+url = "2.0"
uuid = {version = "0.7", features = ["v4"]}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
-ws = { version = "0.8", features = ["ssl"] }
+ws = { version = "0.9", features = ["ssl"] }
[dev-dependencies]
std_test_override = { path = "../std_test_override" }
diff --git a/components/net/data_loader.rs b/components/net/data_loader.rs
index 31f32837a75..02e271cb49c 100644
--- a/components/net/data_loader.rs
+++ b/components/net/data_loader.rs
@@ -4,8 +4,8 @@
use base64;
use mime::Mime;
+use percent_encoding::percent_decode;
use servo_url::ServoUrl;
-use url::percent_encoding::percent_decode;
use url::Position;
pub enum DecodeError {
diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml
index 56aacf38197..4604e7cb8aa 100644
--- a/components/net_traits/Cargo.toml
+++ b/components/net_traits/Cargo.toml
@@ -20,7 +20,7 @@ headers = "0.2"
http = "0.1"
hyper = "0.12"
hyper_serde = "0.11"
-piston_image = {package = "image", version = "0.21"}
+piston_image = {package = "image", version = "0.22"}
ipc-channel = "0.11"
lazy_static = "1"
log = "0.4"
@@ -29,13 +29,14 @@ malloc_size_of_derive = "0.1"
mime = "0.3"
msg = {path = "../msg"}
num-traits = "0.2"
+percent-encoding = "2.0"
pixels = {path = "../pixels"}
serde = "1.0"
servo_arc = {path = "../servo_arc"}
servo_config = {path = "../config"}
servo_url = {path = "../url"}
time = "0.1"
-url = "1.2"
+url = "2.0"
uuid = {version = "0.7", features = ["v4", "serde"]}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs
index b30ed9e6877..1f3bf88ba58 100644
--- a/components/net_traits/lib.rs
+++ b/components/net_traits/lib.rs
@@ -14,8 +14,6 @@ extern crate malloc_size_of;
extern crate malloc_size_of_derive;
#[macro_use]
extern crate serde;
-#[macro_use]
-extern crate url;
use crate::filemanager_thread::FileManagerThreadMsg;
use crate::request::{Request, RequestBuilder};
@@ -35,7 +33,6 @@ use msg::constellation_msg::HistoryStateId;
use servo_url::ServoUrl;
use std::error::Error;
use time::precise_time_ns;
-use url::percent_encoding;
pub mod blob_url_store;
pub mod filemanager_thread;
@@ -656,14 +653,29 @@ pub fn trim_http_whitespace(mut slice: &[u8]) -> &[u8] {
}
pub fn http_percent_encode(bytes: &[u8]) -> String {
- define_encode_set! {
- // This encode set is used for HTTP header values and is defined at
- // https://tools.ietf.org/html/rfc5987#section-3.2
- pub HTTP_VALUE = [percent_encoding::SIMPLE_ENCODE_SET] | {
- ' ', '"', '%', '\'', '(', ')', '*', ',', '/', ':', ';', '<', '-', '>', '?',
- '[', '\\', ']', '{', '}'
- }
- }
-
- url::percent_encoding::percent_encode(bytes, HTTP_VALUE).to_string()
+ // This encode set is used for HTTP header values and is defined at
+ // https://tools.ietf.org/html/rfc5987#section-3.2
+ const HTTP_VALUE: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
+ .add(b' ')
+ .add(b'"')
+ .add(b'%')
+ .add(b'\'')
+ .add(b'(')
+ .add(b')')
+ .add(b'*')
+ .add(b',')
+ .add(b'/')
+ .add(b':')
+ .add(b';')
+ .add(b'<')
+ .add(b'-')
+ .add(b'>')
+ .add(b'?')
+ .add(b'[')
+ .add(b'\\')
+ .add(b']')
+ .add(b'{')
+ .add(b'}');
+
+ percent_encoding::percent_encode(bytes, HTTP_VALUE).to_string()
}
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index 2473dba7c9c..872ffcab926 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -58,7 +58,7 @@ html5ever = "0.23"
http = "0.1"
hyper = "0.12"
hyper_serde = "0.11"
-image = "0.21"
+image = "0.22"
indexmap = "1.0.2"
ipc-channel = "0.11"
itertools = "0.8"
@@ -79,6 +79,7 @@ msg = {path = "../msg"}
net_traits = {path = "../net_traits"}
num-traits = "0.2"
parking_lot = "0.8"
+percent-encoding = "2.0"
phf = "0.7"
pixels = {path = "../pixels"}
profile_traits = {path = "../profile_traits"}
@@ -107,7 +108,7 @@ tendril = {version = "0.4.1", features = ["encoding_rs"]}
time = "0.1.12"
typetag = "0.1"
unicode-segmentation = "1.1.0"
-url = "1.6"
+url = "2.0"
utf-8 = "0.7"
uuid = {version = "0.7", features = ["v4"]}
xml5ever = {version = "0.14"}
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index c9c9a1156bc..e6cd5468e98 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -133,6 +133,7 @@ use net_traits::CookieSource::NonHTTP;
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
use net_traits::{FetchResponseMsg, IpcSend, ReferrerPolicy};
use num_traits::ToPrimitive;
+use percent_encoding::percent_decode;
use profile_traits::ipc as profile_ipc;
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType};
use ref_slice::ref_slice;
@@ -163,7 +164,6 @@ use style::shared_lock::SharedRwLock as StyleSharedRwLock;
use style::str::{split_html_space_chars, str_join};
use style::stylesheet_set::DocumentStylesheetSet;
use style::stylesheets::{Origin, OriginSet, Stylesheet};
-use url::percent_encoding::percent_decode;
use url::Host;
use uuid::Uuid;
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 603ebf69f56..b09804e397c 100755
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -63,8 +63,6 @@ use std::borrow::ToOwned;
use std::cell::Cell;
use style::attr::AttrValue;
use style::str::split_html_space_chars;
-use url::form_urlencoded::Serializer;
-use url::UrlQuery;
#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)]
pub struct GenerationId(u32);
@@ -463,13 +461,12 @@ impl HTMLFormElement {
) {
let charset = encoding.name();
- self.set_encoding_override(load_data.url.as_mut_url().query_pairs_mut())
- .clear()
- .extend_pairs(
- form_data
- .into_iter()
- .map(|field| (field.name.clone(), field.replace_value(charset))),
- );
+ self.set_url_query_pairs(
+ &mut load_data.url,
+ form_data
+ .iter()
+ .map(|field| (&*field.name, field.replace_value(charset))),
+ );
self.plan_to_navigate(load_data, target);
}
@@ -492,13 +489,12 @@ impl HTMLFormElement {
.typed_insert(ContentType::from(mime::APPLICATION_WWW_FORM_URLENCODED));
let mut url = load_data.url.clone();
- self.set_encoding_override(url.as_mut_url().query_pairs_mut())
- .clear()
- .extend_pairs(
- form_data
- .into_iter()
- .map(|field| (field.name.clone(), field.replace_value(charset))),
- );
+ self.set_url_query_pairs(
+ &mut url,
+ form_data
+ .iter()
+ .map(|field| (&*field.name, field.replace_value(charset))),
+ );
url.query().unwrap_or("").to_string().into_bytes()
},
@@ -521,13 +517,17 @@ impl HTMLFormElement {
self.plan_to_navigate(load_data, target);
}
- fn set_encoding_override<'a>(
+ fn set_url_query_pairs<'a>(
&self,
- mut serializer: Serializer<UrlQuery<'a>>,
- ) -> Serializer<UrlQuery<'a>> {
+ url: &mut servo_url::ServoUrl,
+ pairs: impl Iterator<Item = (&'a str, String)>,
+ ) {
let encoding = self.pick_encoding();
- serializer.custom_encoding_override(move |s| encoding.encode(s).0);
- serializer
+ url.as_mut_url()
+ .query_pairs_mut()
+ .encoding_override(Some(&|s| encoding.encode(s).0))
+ .clear()
+ .extend_pairs(pairs);
}
/// [Planned navigation](https://html.spec.whatwg.org/multipage/#planned-navigation)
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index fbeaf14cdf4..a3a246c4edc 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -198,7 +198,6 @@ impl HTMLIFrameElement {
opener: None,
load_data: load_data,
pipeline_port: pipeline_receiver,
- content_process_shutdown_chan: None,
window_size: WindowSizeData {
initial_viewport: {
let rect = self.upcast::<Node>().bounding_content_box_or_zero();
diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs
index 79b93792ce5..d64975a78b9 100644
--- a/components/script/dom/windowproxy.rs
+++ b/components/script/dom/windowproxy.rs
@@ -303,7 +303,6 @@ impl WindowProxy {
opener: Some(self.browsing_context_id),
load_data: load_data,
pipeline_port: pipeline_receiver,
- content_process_shutdown_chan: None,
window_size: window.window_size(),
};
let constellation_msg = ScriptMsg::ScriptNewAuxiliary(load_info, pipeline_sender);
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 06442d3042a..8347113791e 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -123,6 +123,7 @@ use net_traits::{
Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming, ResourceThreads,
ResourceTimingType,
};
+use percent_encoding::percent_decode;
use profile_traits::mem::{self as profile_mem, OpaqueSender, ReportsChan};
use profile_traits::time::{self as profile_time, profile, ProfilerCategory};
use script_layout_interface::message::{self, LayoutThreadInit, Msg, ReflowGoal};
@@ -160,7 +161,6 @@ use std::time::{Duration, SystemTime};
use style::dom::OpaqueNode;
use style::thread_state::{self, ThreadState};
use time::{at_utc, get_time, precise_time_ns, Timespec};
-use url::percent_encoding::percent_decode;
use url::Position;
use webrender_api::units::LayoutPixel;
use webrender_api::{DocumentId, RenderApiSender};
@@ -612,7 +612,7 @@ pub struct ScriptThread {
timer_event_chan: Sender<TimerEvent>,
timer_event_port: Receiver<TimerEvent>,
- content_process_shutdown_chan: IpcSender<()>,
+ content_process_shutdown_chan: Sender<()>,
/// <https://html.spec.whatwg.org/multipage/#microtask-queue>
microtask_queue: Rc<MicrotaskQueue>,
@@ -2276,7 +2276,6 @@ impl ScriptThread {
load_data,
window_size,
pipeline_port,
- content_process_shutdown_chan,
} = new_layout_info;
let layout_pair = unbounded();
@@ -2294,7 +2293,6 @@ impl ScriptThread {
constellation_chan: self.layout_to_constellation_chan.clone(),
script_chan: self.control_chan.clone(),
image_cache: self.image_cache.clone(),
- content_process_shutdown_chan: content_process_shutdown_chan,
paint_time_metrics: PaintTimeMetrics::new(
new_pipeline_id,
self.time_profiler_chan.clone(),
diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs
index c6d9710541f..01a589d53cb 100644
--- a/components/script_layout_interface/message.rs
+++ b/components/script_layout_interface/message.rs
@@ -225,7 +225,6 @@ pub struct LayoutThreadInit {
pub constellation_chan: IpcSender<ConstellationMsg>,
pub script_chan: IpcSender<ConstellationControlMsg>,
pub image_cache: Arc<dyn ImageCache>,
- pub content_process_shutdown_chan: Option<IpcSender<()>>,
pub paint_time_metrics: PaintTimeMetrics,
pub layout_is_busy: Arc<AtomicBool>,
}
diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml
index bd1011daad2..46e4bff40ee 100644
--- a/components/script_traits/Cargo.toml
+++ b/components/script_traits/Cargo.toml
@@ -37,7 +37,7 @@ servo_atoms = {path = "../atoms"}
servo_url = {path = "../url"}
style_traits = {path = "../style_traits", features = ["servo"]}
time = "0.1.12"
-url = "1.2"
+url = "2.0"
webdriver = "0.40"
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webvr_traits = {path = "../webvr_traits"}
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 5aac6b47e5e..790c49eff94 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -219,8 +219,6 @@ pub struct NewLayoutInfo {
pub window_size: WindowSizeData,
/// A port on which layout can receive messages from the pipeline.
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
- /// A shutdown channel so that layout can tell the content process to shut down when it's done.
- pub content_process_shutdown_chan: Option<IpcSender<()>>,
}
/// When a pipeline is closed, should its browsing context be discarded too?
@@ -651,7 +649,7 @@ pub struct InitialScriptState {
/// The ID of the pipeline namespace for this script thread.
pub pipeline_namespace_id: PipelineNamespaceId,
/// A ping will be sent on this channel once the script thread shuts down.
- pub content_process_shutdown_chan: IpcSender<()>,
+ pub content_process_shutdown_chan: Sender<()>,
/// A channel to the WebGL thread used in this pipeline.
pub webgl_chan: Option<WebGLPipeline>,
/// A channel to the webvr thread, if available.
diff --git a/components/url/Cargo.toml b/components/url/Cargo.toml
index 1a59812e071..d766316cd1f 100644
--- a/components/url/Cargo.toml
+++ b/components/url/Cargo.toml
@@ -17,6 +17,5 @@ to_shmem = { path = "../to_shmem" }
to_shmem_derive = { path = "../to_shmem_derive" }
serde = {version = "1.0", features = ["derive"]}
servo_rand = {path = "../rand"}
-url = "1.2"
-url_serde = {version = "0.2"}
+url = {version = "2.0", features = ["serde"]}
uuid = {version = "0.7", features = ["v4", "serde"]}
diff --git a/components/url/lib.rs b/components/url/lib.rs
index bb7c1fa4e35..1c27c069ae6 100644
--- a/components/url/lib.rs
+++ b/components/url/lib.rs
@@ -30,7 +30,7 @@ use url::{Position, Url};
pub use url::Host;
-#[derive(Clone, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
+#[derive(Clone, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize)]
pub struct ServoUrl(#[ignore_malloc_size_of = "Arc"] Arc<Url>);
impl ToShmem for ServoUrl {
@@ -222,21 +222,3 @@ impl From<Url> for ServoUrl {
ServoUrl::from_url(url)
}
}
-
-impl serde::Serialize for ServoUrl {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: serde::Serializer,
- {
- url_serde::serialize(&*self.0, serializer)
- }
-}
-
-impl<'de> serde::Deserialize<'de> for ServoUrl {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- url_serde::deserialize(deserializer).map(Self::from_url)
- }
-}
diff --git a/components/url/origin.rs b/components/url/origin.rs
index c0174c38e1f..1878e85a9d8 100644
--- a/components/url/origin.rs
+++ b/components/url/origin.rs
@@ -14,15 +14,7 @@ pub enum ImmutableOrigin {
Opaque(OpaqueOrigin),
/// Consists of the URL's scheme, host and port
- Tuple(
- String,
- #[serde(
- deserialize_with = "url_serde::deserialize",
- serialize_with = "url_serde::serialize"
- )]
- Host,
- u16,
- ),
+ Tuple(String, Host, u16),
}
impl ImmutableOrigin {
diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml
index 0bb7f68a8c4..7fd9e7dae69 100644
--- a/components/webdriver_server/Cargo.toml
+++ b/components/webdriver_server/Cargo.toml
@@ -16,7 +16,7 @@ cookie = "0.11"
crossbeam-channel = "0.3"
euclid = "0.20"
hyper = "0.12"
-image = "0.21"
+image = "0.22"
ipc-channel = "0.11"
keyboard-types = "0.4.3"
log = "0.4"
@@ -29,6 +29,6 @@ serde_json = "1"
script_traits = {path = "../script_traits"}
servo_config = {path = "../config"}
servo_url = {path = "../url"}
-url = "1.2"
+url = "2.0"
uuid = {version = "0.7", features = ["v4"]}
webdriver = "0.40"
diff --git a/etc/taskcluster/decision_task.py b/etc/taskcluster/decision_task.py
index de947985bc7..2d73448eaeb 100644
--- a/etc/taskcluster/decision_task.py
+++ b/etc/taskcluster/decision_task.py
@@ -907,7 +907,7 @@ def magicleap_nightly():
env -u DYLD_LIBRARY_PATH ./mach package --magicleap --release
./mach upload-nightly magicleap --secret-from-taskcluster
""")
- .with_artifacts("repo/target/magicleap/aarch64-linux-android/release/Servo2D.mpk")
+ .with_artifacts("repo/target/magicleap/aarch64-linux-android/release/Servo.mpk")
.find_or_create("build.magicleap_nightly." + CONFIG.task_id())
)
diff --git a/ports/glutin/Cargo.toml b/ports/glutin/Cargo.toml
index 591d6d93c56..c4e8b386800 100644
--- a/ports/glutin/Cargo.toml
+++ b/ports/glutin/Cargo.toml
@@ -64,7 +64,7 @@ webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] }
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
-image = "0.21"
+image = "0.22"
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
osmesa-sys = "0.1.2"
diff --git a/ports/glutin/headed_window.rs b/ports/glutin/headed_window.rs
index 082f344badb..039d18e3d7a 100644
--- a/ports/glutin/headed_window.rs
+++ b/ports/glutin/headed_window.rs
@@ -675,7 +675,7 @@ fn load_icon(icon_bytes: &[u8]) -> Icon {
let (width, height) = image.dimensions();
let mut rgba = Vec::with_capacity((width * height) as usize * 4);
for (_, _, pixel) in image.pixels() {
- rgba.extend_from_slice(&pixel.to_rgba().data);
+ rgba.extend_from_slice(&pixel.to_rgba().0);
}
(rgba, width, height)
};
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py
index 76d75a0673b..dbd5e2d905c 100644
--- a/python/servo/build_commands.py
+++ b/python/servo/build_commands.py
@@ -756,7 +756,7 @@ class MachCommands(CommandBase):
target_arch = target.split('-')[0]
if target_arch == "aarch64":
arch = "arm64"
- elif target_arch == "x64":
+ elif target_arch == "x86_64":
arch = "x64"
else:
print("ERROR: We do not have openxr_loader DLLs for %s" % target_arch)
diff --git a/servo-tidy.toml b/servo-tidy.toml
index cedd07f2711..648dde549c4 100644
--- a/servo-tidy.toml
+++ b/servo-tidy.toml
@@ -50,6 +50,7 @@ packages = [
"scopeguard",
"unicase",
"url", # https://github.com/servo/servo/pull/23838
+ "ws",
]
# Files that are ignored for all tidy and lint checks.
files = [
diff --git a/support/hololens/ServoApp/Servo.cpp b/support/hololens/ServoApp/Servo.cpp
index afe72c2d2af..43350aa54be 100644
--- a/support/hololens/ServoApp/Servo.cpp
+++ b/support/hololens/ServoApp/Servo.cpp
@@ -32,7 +32,7 @@ Servo::Servo(GLsizei width, GLsizei height, ServoDelegate &aDelegate)
: mWindowHeight(height), mWindowWidth(width), mDelegate(aDelegate) {
capi::CInitOptions o;
- o.args = NULL;
+ o.args = "--pref dom.webxr.enabled";
o.url = "https://servo.org";
o.width = mWindowWidth;
o.height = mWindowHeight;
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index e6d7c8291ce..b460cc44e7a 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-opener/new_window_same_origin.tentative.html.headers": [
+ "html/cross-origin-embedder-policy/require-corp.https.html.headers": [
[]
],
- "html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html.headers": [
+ "html/cross-origin-embedder-policy/resources/blob-url-factory.html": [
[]
],
- "html/cross-origin-opener/new_window_same_site.tentative.html.headers": [
+ "html/cross-origin-embedder-policy/resources/blob-url-factory.html.headers": [
[]
],
- "html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html.headers": [
+ "html/cross-origin-embedder-policy/resources/navigate-none.sub.html": [
[]
],
- "html/cross-origin-opener/resources/coop_window.py": [
+ "html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html": [
[]
],
- "html/cross-origin-opener/resources/postback.sub.html": [
+ "html/cross-origin-embedder-policy/resources/navigate-require-corp.sub.html.headers": [
[]
],
- "html/cross-origin-opener/resources/window.sub.html": [
+ "html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt": [
[]
],
- "html/cross-origin-opener/resources/window.sub.html.headers": [
+ "html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt.headers": [
[]
],
- "html/cross-origin/anonymous.tentative.html.headers": [
+ "html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt": [
[]
],
- "html/cross-origin/null.tentative.html.headers": [
+ "html/cross-origin-embedder-policy/resources/nothing-same-origin-corp.txt.headers": [
[]
],
- "html/cross-origin/resources/navigate_anonymous.sub.html": [
+ "html/cross-origin-embedder-policy/resources/script-factory.js": [
[]
],
- "html/cross-origin/resources/navigate_anonymous.sub.html.headers": [
+ "html/cross-origin-embedder-policy/sandbox.https.html.headers": [
[]
],
- "html/cross-origin/resources/navigate_null.sub.html": [
+ "html/cross-origin-embedder-policy/srcdoc.https.html.headers": [
[]
],
- "html/cross-origin/resources/navigate_usecredentials.sub.html": [
+ "html/cross-origin-opener-policy/README.md": [
[]
],
- "html/cross-origin/resources/navigate_usecredentials.sub.html.headers": [
+ "html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers": [
[]
],
- "html/cross-origin/resources/nothing.txt": [
+ "html/cross-origin-opener-policy/coep-redirect.https.html.headers": [
[]
],
- "html/cross-origin/resources/nothing.txt.headers": [
+ "html/cross-origin-opener-policy/coep.https.html.headers": [
[]
],
- "html/cross-origin/resources/popup_and_close.sub.html": [
+ "html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers": [
[]
],
- "html/cross-origin/resources/popup_and_close.sub.html.headers": [
+ "html/cross-origin-opener-policy/coop-sandbox.https.html.headers": [
[]
],
- "html/cross-origin/usecredentials.tentative.html.headers": [
+ "html/cross-origin-opener-policy/no-https.html.headers": [
+ []
+ ],
+ "html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers": [
+ []
+ ],
+ "html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.headers": [
+ []
+ ],
+ "html/cross-origin-opener-policy/popup-same-origin.https.html.headers": [
+ []
+ ],
+ "html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.headers": [
+ []
+ ],
+ "html/cross-origin-opener-policy/popup-same-site.https.html.headers": [
+ []
+ ],
+ "html/cross-origin-opener-policy/resources/common.js": [
+ []
+ ],
+ "html/cross-origin-opener-policy/resources/coop-coep.py": [
+ []
+ ],
+ "html/cross-origin-opener-policy/resources/postback.html": [
+ []
+ ],
+ "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-embedder-policy/blob.https.html",
+ {}
+ ]
+ ],
+ "html/cross-origin-embedder-policy/data.https.html": [
[
- "html/cross-origin-opener/new_window_null.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/non-initial-about-blank.https.html": [
[
- "html/cross-origin-opener/new_window_same_origin.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/none.https.html": [
[
- "html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.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-embedder-policy/sandbox.https.html",
{}
]
],
- "html/cross-origin-opener/new_window_same_site.tentative.html": [
+ "html/cross-origin-embedder-policy/srcdoc.https.html": [
[
- "html/cross-origin-opener/new_window_same_site.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-opener-policy/coep-navigate-popup.https.html": [
[
- "html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html",
+ "html/cross-origin-opener-policy/coep-navigate-popup.https.html",
{}
]
],
- "html/cross-origin/anonymous.tentative.html": [
+ "html/cross-origin-opener-policy/coep-redirect.https.html": [
[
- "html/cross-origin/anonymous.tentative.html",
- {
- "timeout": "long"
- }
+ "html/cross-origin-opener-policy/coep-redirect.https.html",
+ {}
]
],
- "html/cross-origin/null.tentative.html": [
+ "html/cross-origin-opener-policy/coep.https.html": [
[
- "html/cross-origin/null.tentative.html",
- {
- "timeout": "long"
- }
+ "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/usecredentials.tentative.html": [
+ "html/cross-origin-opener-policy/coop-sandbox.https.html": [
[
- "html/cross-origin/usecredentials.tentative.html",
+ "html/cross-origin-opener-policy/coop-sandbox.https.html",
+ {}
+ ]
+ ],
+ "html/cross-origin-opener-policy/no-https.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/imported/parsing-schema.tentative.html": [
+ [
+ "import-maps/imported/parsing-schema.tentative.html",
{}
]
],
- "import-maps/resolving.tentative.html": [
+ "import-maps/imported/parsing-scope-keys.tentative.html": [
[
- "import-maps/resolving.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-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/anonymous.tentative.html": [
- "ef9b9bb7b878a738c8f7e377d4cfe62b41dfea7f",
+ "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/resources/popup_and_close.sub.html.headers": [
- "a76b601291ec4323da4469a0e09d62c84f81efc3",
+ "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/usecredentials.tentative.html": [
- "55c0f2235db27ad119d652782141de68f5de62a6",
+ "html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html": [
+ "18ee909d1865567706674b75b40a6615ef75908c",
"testharness"
],
- "html/cross-origin/usecredentials.tentative.html.headers": [
- "a84d3782037e7a0573f3b621941e293560792628",
+ "html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.headers": [
+ "ab7b28948150ff64101ef080b0d9c7cc9a6a34d2",
+ "support"
+ ],
+ "html/cross-origin-opener-policy/popup-same-site.https.html": [
+ "9a0db2765daeb445a892a8ece7347c6b97f24917",
+ "testharness"
+ ],
+ "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/resolving.tentative.html": [
- "f2b09a7ae02422c8f6fd3f8dad1f9b8d52a43831",
+ "import-maps/imported/resolving-scopes.tentative.html": [
+ "4985249f4e2951965ad78321208ee08eca8617fa",
+ "testharness"
+ ],
+ "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 00000000000..77d70251f90
--- /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 00000000000..61c7e78a818
--- /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 00000000000..2460e466ee2
--- /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 00000000000..46b6997ba48
--- /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 00000000000..2c201848a38
--- /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 b153c32c44e..6a2d6c0ede6 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 00000000000..a8bac605c98
--- /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 09cab11e134..37478df2204 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 00000000000..5a41ca5ad57
--- /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 00000000000..d9ddfa2bf68
--- /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 00000000000..e70af2a782f
--- /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 e6e1f29e274..00000000000
--- 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 032451b7dfa..a70942e359e 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 @@
[<iframe>: separate response Content-Type: */* text/html]
expected: FAIL
- [<iframe>: combined response Content-Type: text/html;" text/plain]
- expected: FAIL
-
[<iframe>: combined response Content-Type: */* text/html]
expected: FAIL
- [<iframe>: separate response Content-Type: text/html */*]
- expected: FAIL
-
- [<iframe>: combined response Content-Type: text/html */*;charset=gbk]
- expected: FAIL
-
- [<iframe>: combined response Content-Type: text/html;" \\" text/plain]
- expected: FAIL
-
- [<iframe>: combined response Content-Type: text/html;x=" text/plain]
+ [<iframe>: combined response Content-Type: text/html */*]
expected: FAIL
diff --git a/tests/wpt/metadata/fetch/content-type/script.window.js.ini b/tests/wpt/metadata/fetch/content-type/script.window.js.ini
index c7413d589dc..d2df9b78483 100644
--- a/tests/wpt/metadata/fetch/content-type/script.window.js.ini
+++ b/tests/wpt/metadata/fetch/content-type/script.window.js.ini
@@ -56,9 +56,3 @@
[separate text/javascript x/x]
expected: FAIL
- [separate text/javascript;charset=windows-1252 error text/javascript]
- expected: FAIL
-
- [separate text/javascript;charset=windows-1252 text/javascript]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini b/tests/wpt/metadata/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini
index 8fb86a1ad58..4aa76db6401 100644
--- a/tests/wpt/metadata/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini
+++ b/tests/wpt/metadata/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini
@@ -1,6 +1,8 @@
[scroll-restoration-fragment-scrolling-cross-origin.html]
type: testharness
- expected: TIMEOUT
[Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation]
expected: TIMEOUT
+ [Precedence of scroll restoration mode over fragment scrolling in cross-origin history traversal]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini
deleted file mode 100644
index 385376c7321..00000000000
--- a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[traverse_the_history_4.html]
- [Multiple history traversals, last would be aborted]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini
deleted file mode 100644
index dc2e45516de..00000000000
--- a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_5.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[traverse_the_history_5.html]
- [Multiple history traversals, last would be aborted]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html.ini b/tests/wpt/metadata/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html.ini
new file mode 100644
index 00000000000..16fa2c5cfc1
--- /dev/null
+++ b/tests/wpt/metadata/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html.ini
@@ -0,0 +1,4 @@
+[creating_browsing_context_test_01.html]
+ [first argument: absolute url]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-embedder-policy/blob.https.html.ini b/tests/wpt/metadata/html/cross-origin-embedder-policy/blob.https.html.ini
new file mode 100644
index 00000000000..1b1c0ac9822
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-embedder-policy/blob.https.html.ini
@@ -0,0 +1,19 @@
+[blob.https.html]
+ [Cross-Origin-Embedder-Policy and blob: URL from https://web-platform.test:8443 in subframe via subframe]
+ expected: FAIL
+
+ [Cross-Origin-Embedder-Policy and blob: URL from https://web-platform.test:8443 in subframe via navigate]
+ expected: FAIL
+
+ [Cross-Origin-Embedder-Policy and blob: URL from https://www1.web-platform.test:8443 in subframe via subframe]
+ expected: FAIL
+
+ [Cross-Origin-Embedder-Policy and blob: URL from https://not-web-platform.test:8443 in subframe via navigate]
+ expected: FAIL
+
+ [Cross-Origin-Embedder-Policy and blob: URL from https://not-web-platform.test:8443 in subframe via subframe]
+ expected: FAIL
+
+ [Cross-Origin-Embedder-Policy and blob: URL from https://www1.web-platform.test:8443 in subframe via navigate]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-embedder-policy/data.https.html.ini b/tests/wpt/metadata/html/cross-origin-embedder-policy/data.https.html.ini
new file mode 100644
index 00000000000..6af04961841
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-embedder-policy/data.https.html.ini
@@ -0,0 +1,4 @@
+[data.https.html]
+ [Cross-Origin-Embedder-Policy and data: URLs]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-embedder-policy/none.https.html.ini b/tests/wpt/metadata/html/cross-origin-embedder-policy/none.https.html.ini
new file mode 100644
index 00000000000..183bf9ed764
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-embedder-policy/none.https.html.ini
@@ -0,0 +1,4 @@
+[none.https.html]
+ ["require-corp" top-level noopener popup: navigating to "none" should succeed]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-embedder-policy/require-corp.https.html.ini b/tests/wpt/metadata/html/cross-origin-embedder-policy/require-corp.https.html.ini
new file mode 100644
index 00000000000..636d78750b0
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-embedder-policy/require-corp.https.html.ini
@@ -0,0 +1,25 @@
+[require-corp.https.html]
+ ["require-corp" top-level: creating a noopener "none" popup should succeed]
+ expected: FAIL
+
+ ["require-corp" top-level: fetch() to response without CORP should fail]
+ expected: FAIL
+
+ ["require-corp" top-level (as noopener popup): navigating to "none" should succeed]
+ expected: FAIL
+
+ ["require-corp" top-level (as popup with opener set to null): navigating to "none" should succeed]
+ expected: FAIL
+
+ ["require-corp" top-level: navigating a frame to "none" should fail]
+ expected: FAIL
+
+ ["require-corp" top-level: navigating a frame from "require-corp" to "none" should fail]
+ expected: FAIL
+
+ ["require-corp" top-level: creating a "none" popup should succeed.]
+ expected: FAIL
+
+ ["require-corp" top-level (as popup): navigating to "none" should succeed]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-embedder-policy/sandbox.https.html.ini b/tests/wpt/metadata/html/cross-origin-embedder-policy/sandbox.https.html.ini
new file mode 100644
index 00000000000..496af1bb86a
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-embedder-policy/sandbox.https.html.ini
@@ -0,0 +1,5 @@
+[sandbox.https.html]
+ expected: TIMEOUT
+ [Cross-Origin-Embedder-Policy and sandbox]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/html/cross-origin-embedder-policy/srcdoc.https.html.ini b/tests/wpt/metadata/html/cross-origin-embedder-policy/srcdoc.https.html.ini
new file mode 100644
index 00000000000..834da2f8e62
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-embedder-policy/srcdoc.https.html.ini
@@ -0,0 +1,5 @@
+[srcdoc.https.html]
+ expected: TIMEOUT
+ [Cross-Origin-Embedder-Policy and srcdoc]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/coep-navigate-popup.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/coep-navigate-popup.https.html.ini
new file mode 100644
index 00000000000..3ca2b83d464
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/coep-navigate-popup.https.html.ini
@@ -0,0 +1,37 @@
+[coep-navigate-popup.https.html]
+ [Popup navigating to same-origin with coop unsafe-inherit/coep]
+ expected: FAIL
+
+ [Popup navigating to same-origin with no coop/coep]
+ expected: FAIL
+
+ [Popup navigating to same-origin with coop unsafe-inherit/no coep]
+ expected: FAIL
+
+ [Popup navigating to same-site with no coop/coep]
+ expected: FAIL
+
+ [Popup navigating to same-origin with coop/no coep]
+ expected: FAIL
+
+ [Popup navigating to same-origin with coop/coep]
+ expected: FAIL
+
+ [Popup navigating to same-origin with no coop/no coep]
+ expected: FAIL
+
+ [Popup navigating to same-site with coop unsafe-inherit/coep]
+ expected: FAIL
+
+ [Popup navigating to same-site with coop/no coep]
+ expected: FAIL
+
+ [Popup navigating to same-site with no coop/no coep]
+ expected: FAIL
+
+ [Popup navigating to same-site with coop unsafe-inherit/no coep]
+ expected: FAIL
+
+ [Popup navigating to same-site with coop/coep]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/coep-redirect.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/coep-redirect.https.html.ini
new file mode 100644
index 00000000000..337e99fbdf3
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/coep-redirect.https.html.ini
@@ -0,0 +1,19 @@
+[coep-redirect.https.html]
+ [Redirect from coop unsafe-inherit/coep to coop unsafe-inherit/coep]
+ expected: FAIL
+
+ [Redirect from coop/coep to coop/coep]
+ expected: FAIL
+
+ [Redirect from coop unsafe-inherit/coep to coop/coep]
+ expected: FAIL
+
+ [Redirect from no coop/no coep to coop/coep]
+ expected: FAIL
+
+ [Redirect from coop/no coep to coop/coep]
+ expected: FAIL
+
+ [Redirect from coop/coep to no coop/coep]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/coep.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/coep.https.html.ini
new file mode 100644
index 00000000000..18df3214980
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/coep.https.html.ini
@@ -0,0 +1,25 @@
+[coep.https.html]
+ [Same-site popup with coop/coep]
+ expected: FAIL
+
+ [Same-origin popup with coop unsafe-inherit/coep]
+ expected: FAIL
+
+ [Same-origin popup without coep]
+ expected: FAIL
+
+ [Same-site popup with coop unsafe-inherit/coep]
+ expected: FAIL
+
+ [Same-site popup with coop unsafe-inherit without coep]
+ expected: FAIL
+
+ [Same-origin popup with coop unsafe-inherit without coep]
+ expected: FAIL
+
+ [Same-origin popup with coop/coep]
+ expected: FAIL
+
+ [Same-site popup without coep]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/coop-navigated-popup.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/coop-navigated-popup.https.html.ini
new file mode 100644
index 00000000000..f1d7d792d31
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/coop-navigated-popup.https.html.ini
@@ -0,0 +1,4 @@
+[coop-navigated-popup.https.html]
+ [Open a popup to a document without COOP, then navigate it to a document with]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/coop-sandbox.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/coop-sandbox.https.html.ini
new file mode 100644
index 00000000000..a9152adbcf9
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/coop-sandbox.https.html.ini
@@ -0,0 +1,4 @@
+[coop-sandbox.https.html]
+ [Sandboxed Cross-Origin-Opener-Policy popup should result in a network error]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/popup-none.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-none.https.html.ini
new file mode 100644
index 00000000000..1df11b41340
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-none.https.html.ini
@@ -0,0 +1,55 @@
+[popup-none.https.html]
+ [none document opening popup to https://web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [none document opening popup to https://web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [none document opening popup to https://www1.web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [none document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [none document opening popup to https://www1.web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [none document opening popup to https://web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [none document opening popup to https://web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [none document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [none document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [none document opening popup to https://web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [none document opening popup to https://web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [none document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [none document opening popup to https://not-web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [none document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [none document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [none document opening popup to https://not-web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [none document opening popup to https://not-web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [none document opening popup to https://not-web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.ini
new file mode 100644
index 00000000000..5282e919e11
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.ini
@@ -0,0 +1,55 @@
+[popup-same-origin-unsafe-allow-outgoing.https.html]
+ [same-origin_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-origin_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-origin.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-origin.https.html.ini
new file mode 100644
index 00000000000..22920edfe2c
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-origin.https.html.ini
@@ -0,0 +1,55 @@
+[popup-same-origin.https.html]
+ [same-origin document opening popup to https://not-web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-origin document opening popup to https://web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-origin document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://not-web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://not-web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://www1.web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://not-web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://www1.web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-origin document opening popup to https://web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-origin document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.ini
new file mode 100644
index 00000000000..09d242037a2
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.ini
@@ -0,0 +1,55 @@
+[popup-same-site-unsafe-allow-outgoing.https.html]
+ [same-site_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://not-web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-site_unsafe-allow-outgoing document opening popup to https://www1.web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-site.https.html.ini b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-site.https.html.ini
new file mode 100644
index 00000000000..6d2a5b3bed9
--- /dev/null
+++ b/tests/wpt/metadata/html/cross-origin-opener-policy/popup-same-site.https.html.ini
@@ -0,0 +1,55 @@
+[popup-same-site.https.html]
+ [same-site document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site document opening popup to https://www1.web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-site document opening popup to https://web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site document opening popup to https://web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-site document opening popup to https://not-web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-site document opening popup to https://web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-site document opening popup to https://not-web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-site document opening popup to https://www1.web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-site document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site document opening popup to https://not-web-platform.test:8443 with COOP: ""]
+ expected: FAIL
+
+ [same-site document opening popup to https://web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-site document opening popup to https://not-web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
+ [same-site document opening popup to https://www1.web-platform.test:8443 with COOP: "jibberish"]
+ expected: FAIL
+
+ [same-site document opening popup to https://www1.web-platform.test:8443 with COOP: "same-origin"]
+ expected: FAIL
+
+ [same-site document opening popup to https://not-web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-site document opening popup to https://web-platform.test:8443 with COOP: "same-site"]
+ expected: FAIL
+
+ [same-site document opening popup to https://web-platform.test:8443 with COOP: "same-site unsafe-allow-outgoing"]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/dom/interfaces.https.html.ini b/tests/wpt/metadata/html/dom/interfaces.https.html.ini
index c1ce887cc10..becd9b9ee8a 100644
--- a/tests/wpt/metadata/html/dom/interfaces.https.html.ini
+++ b/tests/wpt/metadata/html/dom/interfaces.https.html.ini
@@ -10709,3 +10709,24 @@
[SVGElement interface: attribute onformdata]
expected: FAIL
+ [DOMStringList interface: calling item(unsigned long) on location.ancestorOrigins with too few arguments must throw TypeError]
+ expected: FAIL
+
+ [DOMStringList interface: calling contains(DOMString) on location.ancestorOrigins with too few arguments must throw TypeError]
+ expected: FAIL
+
+ [DOMStringList interface: location.ancestorOrigins must inherit property "contains(DOMString)" with the proper type]
+ expected: FAIL
+
+ [Stringification of location.ancestorOrigins]
+ expected: FAIL
+
+ [DOMStringList interface: location.ancestorOrigins must inherit property "item(unsigned long)" with the proper type]
+ expected: FAIL
+
+ [DOMStringList must be primary interface of location.ancestorOrigins]
+ expected: FAIL
+
+ [DOMStringList interface: location.ancestorOrigins must inherit property "length" with the proper type]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html.ini b/tests/wpt/metadata/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html.ini
new file mode 100644
index 00000000000..56f24be109c
--- /dev/null
+++ b/tests/wpt/metadata/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html.ini
@@ -0,0 +1,4 @@
+[tabindex-getter.html]
+ [HTML Test: tabIndex getter return value]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html.ini b/tests/wpt/metadata/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html.ini
new file mode 100644
index 00000000000..98d846b3207
--- /dev/null
+++ b/tests/wpt/metadata/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-2.html.ini
@@ -0,0 +1,2 @@
+[select-1-block-size-001-2.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html.ini b/tests/wpt/metadata/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html.ini
new file mode 100644
index 00000000000..bb0fb8e3daf
--- /dev/null
+++ b/tests/wpt/metadata/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html.ini
@@ -0,0 +1,2 @@
+[select-1-block-size-001.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini b/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini
index 702af61a3c4..127392316de 100644
--- a/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini
+++ b/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini
@@ -1,11 +1,7 @@
[form-submission-algorithm.html]
- expected: TIMEOUT
[If form's firing submission events is true, then return; 'submit' event]
expected: FAIL
[If form's firing submission events is true, then return; 'invalid' event]
expected: FAIL
- [Cannot navigate (after constructing the entry list)]
- expected: TIMEOUT
-
diff --git a/tests/wpt/metadata/html/semantics/interactive-elements/the-details-element/toggleEvent.html.ini b/tests/wpt/metadata/html/semantics/interactive-elements/the-details-element/toggleEvent.html.ini
deleted file mode 100644
index 9e522297c94..00000000000
--- a/tests/wpt/metadata/html/semantics/interactive-elements/the-details-element/toggleEvent.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[toggleEvent.html]
- [Calling open twice on 'details' fires only one toggle event]
- expected: FAIL
-
- [Setting open=true to opened 'details' element should not fire a toggle event at the 'details' element]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/syntax/parsing/DOMContentLoaded-defer.html.ini b/tests/wpt/metadata/html/syntax/parsing/DOMContentLoaded-defer.html.ini
new file mode 100644
index 00000000000..a9677391662
--- /dev/null
+++ b/tests/wpt/metadata/html/syntax/parsing/DOMContentLoaded-defer.html.ini
@@ -0,0 +1,4 @@
+[DOMContentLoaded-defer.html]
+ [The end: DOMContentLoaded and defer scripts]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini b/tests/wpt/metadata/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini
index 034d9baebfa..496bad988c6 100644
--- a/tests/wpt/metadata/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini
+++ b/tests/wpt/metadata/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/promise-rejection-events.html.ini
@@ -1,5 +1,4 @@
[promise-rejection-events.html]
- expected: TIMEOUT
[delayed handling: delaying handling rejected promise created from createImageBitmap will cause both events to fire]
expected: FAIL
@@ -9,6 +8,3 @@
[no unhandledrejection/rejectionhandled: rejection handler attached synchronously to a promise created from createImageBitmap]
expected: FAIL
- [rejectionhandled is dispatched from a queued task, and not immediately]
- expected: TIMEOUT
-
diff --git a/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini b/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini
index 99a24216c88..7725b118e9d 100644
--- a/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini
+++ b/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini
@@ -12,3 +12,6 @@
[Verifies the resolution of entry.startTime is at least 5 microseconds.]
expected: TIMEOUT
+ [Verifies the resolution of performance.now() is at least 5 microseconds.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/url/a-element-origin-xhtml.xhtml.ini b/tests/wpt/metadata/url/a-element-origin-xhtml.xhtml.ini
deleted file mode 100644
index cc2702303bc..00000000000
--- a/tests/wpt/metadata/url/a-element-origin-xhtml.xhtml.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[a-element-origin-xhtml.xhtml]
- type: testharness
- [Parsing origin: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/url/a-element-origin.html.ini b/tests/wpt/metadata/url/a-element-origin.html.ini
deleted file mode 100644
index 467203dcd45..00000000000
--- a/tests/wpt/metadata/url/a-element-origin.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[a-element-origin.html]
- type: testharness
- [Parsing origin: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
diff --git a/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini b/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini
index c4ca103fea6..f35b1ed99f5 100644
--- a/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini
+++ b/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini
@@ -42,9 +42,6 @@
[Parsing: <////x/> against <sc://x/>]
expected: FAIL
- [Parsing: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
[Parsing: <file:\\\\//> against <about:blank>]
expected: FAIL
@@ -132,15 +129,9 @@
[Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>]
expected: FAIL
- [Parsing: <http://host/?'> against <about:blank>]
- expected: FAIL
-
[Parsing: <sc://ñ> against <about:blank>]
expected: FAIL
- [Parsing: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
[Parsing: <sc://ñ#x> against <about:blank>]
expected: FAIL
diff --git a/tests/wpt/metadata/url/a-element.html.ini b/tests/wpt/metadata/url/a-element.html.ini
index c970ed63dfd..826c2c5db2f 100644
--- a/tests/wpt/metadata/url/a-element.html.ini
+++ b/tests/wpt/metadata/url/a-element.html.ini
@@ -42,9 +42,6 @@
[Parsing: <////x/> against <sc://x/>]
expected: FAIL
- [Parsing: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
[Parsing: <file:\\\\//> against <about:blank>]
expected: FAIL
@@ -132,15 +129,9 @@
[Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>]
expected: FAIL
- [Parsing: <http://host/?'> against <about:blank>]
- expected: FAIL
-
[Parsing: <sc://ñ> against <about:blank>]
expected: FAIL
- [Parsing: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
[Parsing: <sc://ñ#x> against <about:blank>]
expected: FAIL
diff --git a/tests/wpt/metadata/url/toascii.window.js.ini b/tests/wpt/metadata/url/toascii.window.js.ini
index 307733c5a20..7bd325547f0 100644
--- a/tests/wpt/metadata/url/toascii.window.js.ini
+++ b/tests/wpt/metadata/url/toascii.window.js.ini
@@ -1,191 +1,23 @@
[toascii.window.html]
type: testharness
- [aa-- (using URL)]
- expected: FAIL
-
- [aa-- (using URL.host)]
- expected: FAIL
-
- [aa-- (using URL.hostname)]
- expected: FAIL
-
- [aa-- (using <a>)]
- expected: FAIL
-
- [aa-- (using <a>.host)]
- expected: FAIL
-
- [aa-- (using <a>.hostname)]
- expected: FAIL
-
- [aa-- (using <area>)]
- expected: FAIL
-
- [a†-- (using URL)]
- expected: FAIL
-
- [a†-- (using URL.host)]
- expected: FAIL
-
- [a†-- (using URL.hostname)]
- expected: FAIL
-
- [a†-- (using <a>)]
- expected: FAIL
-
- [a†-- (using <a>.host)]
- expected: FAIL
-
- [a†-- (using <a>.hostname)]
- expected: FAIL
-
- [a†-- (using <area>)]
- expected: FAIL
-
[a†-- (using <area>.host)]
expected: FAIL
[a†-- (using <area>.hostname)]
expected: FAIL
- [-x (using URL)]
- expected: FAIL
-
- [-x (using URL.host)]
- expected: FAIL
-
- [-x (using URL.hostname)]
- expected: FAIL
-
- [-x (using <a>)]
- expected: FAIL
-
- [-x (using <a>.host)]
- expected: FAIL
-
- [-x (using <a>.hostname)]
- expected: FAIL
-
- [-x (using <area>)]
- expected: FAIL
-
- [-† (using URL)]
- expected: FAIL
-
- [-† (using URL.host)]
- expected: FAIL
-
- [-† (using URL.hostname)]
- expected: FAIL
-
- [-† (using <a>)]
- expected: FAIL
-
- [-† (using <a>.host)]
- expected: FAIL
-
- [-† (using <a>.hostname)]
- expected: FAIL
-
- [-† (using <area>)]
- expected: FAIL
-
[-† (using <area>.host)]
expected: FAIL
[-† (using <area>.hostname)]
expected: FAIL
- [-x.xn--nxa (using URL)]
- expected: FAIL
-
- [-x.xn--nxa (using URL.host)]
- expected: FAIL
-
- [-x.xn--nxa (using URL.hostname)]
- expected: FAIL
-
- [-x.xn--nxa (using <a>)]
- expected: FAIL
-
- [-x.xn--nxa (using <a>.host)]
- expected: FAIL
-
- [-x.xn--nxa (using <a>.hostname)]
- expected: FAIL
-
- [-x.xn--nxa (using <area>)]
- expected: FAIL
-
- [-x.β (using URL)]
- expected: FAIL
-
- [-x.β (using URL.host)]
- expected: FAIL
-
- [-x.β (using URL.hostname)]
- expected: FAIL
-
- [-x.β (using <a>)]
- expected: FAIL
-
- [-x.β (using <a>.host)]
- expected: FAIL
-
- [-x.β (using <a>.hostname)]
- expected: FAIL
-
- [-x.β (using <area>)]
- expected: FAIL
-
[-x.β (using <area>.host)]
expected: FAIL
[-x.β (using <area>.hostname)]
expected: FAIL
- [x-.xn--nxa (using URL)]
- expected: FAIL
-
- [x-.xn--nxa (using URL.host)]
- expected: FAIL
-
- [x-.xn--nxa (using URL.hostname)]
- expected: FAIL
-
- [x-.xn--nxa (using <a>)]
- expected: FAIL
-
- [x-.xn--nxa (using <a>.host)]
- expected: FAIL
-
- [x-.xn--nxa (using <a>.hostname)]
- expected: FAIL
-
- [x-.xn--nxa (using <area>)]
- expected: FAIL
-
- [x-.β (using URL)]
- expected: FAIL
-
- [x-.β (using URL.host)]
- expected: FAIL
-
- [x-.β (using URL.hostname)]
- expected: FAIL
-
- [x-.β (using <a>)]
- expected: FAIL
-
- [x-.β (using <a>.host)]
- expected: FAIL
-
- [x-.β (using <a>.hostname)]
- expected: FAIL
-
- [x-.β (using <area>)]
- expected: FAIL
-
[x-.β (using <area>.host)]
expected: FAIL
@@ -291,54 +123,12 @@
[xn--a-yoc (using <area>.hostname)]
expected: FAIL
- [ශ්‍රී (using URL)]
- expected: FAIL
-
- [ශ්‍රී (using URL.host)]
- expected: FAIL
-
- [ශ්‍රී (using URL.hostname)]
- expected: FAIL
-
- [ශ්‍රී (using <a>)]
- expected: FAIL
-
- [ශ්‍රී (using <a>.host)]
- expected: FAIL
-
- [ශ්‍රී (using <a>.hostname)]
- expected: FAIL
-
- [ශ්‍රී (using <area>)]
- expected: FAIL
-
[ශ්‍රී (using <area>.host)]
expected: FAIL
[ශ්‍රී (using <area>.hostname)]
expected: FAIL
- [نامه‌ای (using URL)]
- expected: FAIL
-
- [نامه‌ای (using URL.host)]
- expected: FAIL
-
- [نامه‌ای (using URL.hostname)]
- expected: FAIL
-
- [نامه‌ای (using <a>)]
- expected: FAIL
-
- [نامه‌ای (using <a>.host)]
- expected: FAIL
-
- [نامه‌ای (using <a>.hostname)]
- expected: FAIL
-
- [نامه‌ای (using <area>)]
- expected: FAIL
-
[نامه‌ای (using <area>.host)]
expected: FAIL
diff --git a/tests/wpt/metadata/url/url-constructor.html.ini b/tests/wpt/metadata/url/url-constructor.html.ini
index e3ffc72c5ca..888abb477ab 100644
--- a/tests/wpt/metadata/url/url-constructor.html.ini
+++ b/tests/wpt/metadata/url/url-constructor.html.ini
@@ -42,9 +42,6 @@
[Parsing: <////x/> against <sc://x/>]
expected: FAIL
- [Parsing: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
[Parsing: <file:\\\\//> against <about:blank>]
expected: FAIL
@@ -123,15 +120,9 @@
[Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>]
expected: FAIL
- [Parsing: <http://host/?'> against <about:blank>]
- expected: FAIL
-
[Parsing: <sc://ñ> against <about:blank>]
expected: FAIL
- [Parsing: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
[Parsing: <sc://ñ#x> against <about:blank>]
expected: FAIL
diff --git a/tests/wpt/metadata/url/url-origin.html.ini b/tests/wpt/metadata/url/url-origin.html.ini
deleted file mode 100644
index 5d0f79285e8..00000000000
--- a/tests/wpt/metadata/url/url-origin.html.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[url-origin.html]
- type: testharness
- [Origin parsing: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
- [Origin parsing: <https://faß.ExAmPlE/> against <about:blank>]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/url/url-setters.html.ini b/tests/wpt/metadata/url/url-setters.html.ini
index 0e3dd0c62f9..2a8973c4905 100644
--- a/tests/wpt/metadata/url/url-setters.html.ini
+++ b/tests/wpt/metadata/url/url-setters.html.ini
@@ -663,12 +663,6 @@
[<area>: Setting <sc://x/>.host = 'ß']
expected: FAIL
- [URL: Setting <https://x/>.host = 'ß' IDNA Nontransitional_Processing]
- expected: FAIL
-
- [<a>: Setting <https://x/>.host = 'ß' IDNA Nontransitional_Processing]
- expected: FAIL
-
[<area>: Setting <https://x/>.host = 'ß' IDNA Nontransitional_Processing]
expected: FAIL
@@ -972,9 +966,6 @@
[<area>: Setting <http://example.net>.password = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
expected: FAIL
- [<a>: Setting <https://x/>.host = 'ß' IDNA Nontransitional_Processing]
- expected: FAIL
-
[<a>: Setting <a:/>.hash = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' Simple percent-encoding; nuls, tabs, and newlines are removed]
expected: FAIL
@@ -1038,9 +1029,6 @@
[<area>: Setting <a:/>.hash = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' Simple percent-encoding; nuls, tabs, and newlines are removed]
expected: FAIL
- [URL: Setting <https://x/>.host = 'ß' IDNA Nontransitional_Processing]
- expected: FAIL
-
[<area>: Setting <ssh://me@example.net>.protocol = 'http' Can’t switch from non-special scheme to special]
expected: FAIL
diff --git a/tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini b/tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini
index 66bd350083b..a56bad443a2 100644
--- a/tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini
+++ b/tests/wpt/metadata/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html.ini
@@ -1,4 +1,5 @@
[realtimeanalyser-fft-scaling.html]
+ expected: TIMEOUT
[X 2048-point FFT peak position is not equal to 64. Got 0.]
expected: FAIL
diff --git a/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini b/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini
index 6395762198b..2a05ceb67fa 100644
--- a/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini
+++ b/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini
@@ -197,3 +197,6 @@
[X SNR (21.44080528729615 dB) is not greater than or equal to 65.737. Got 21.44080528729615.]
expected: FAIL
+ [X Stitched sine-wave buffers at sample rate 43800 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...\] with an element-wise tolerance of {"absoluteThreshold":0.0038986,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[30\]\t9.4836157560348511e-1\t9.5236867666244507e-1\t4.0071010589599609e-3\t4.2075103446311962e-3\t3.8985999999999999e-3\n\t[31\]\t9.2646563053131104e-1\t9.3139332532882690e-1\t4.9276947975158691e-3\t5.2906700783754857e-3\t3.8985999999999999e-3\n\t[32\]\t9.0087991952896118e-1\t9.0675884485244751e-1\t5.8789253234863281e-3\t6.4834496590358351e-3\t3.8985999999999999e-3\n\t[33\]\t8.7170630693435669e-1\t8.7856203317642212e-1\t6.8557262420654297e-3\t7.8033490899654511e-3\t3.8985999999999999e-3\n\t[34\]\t8.3906102180480957e-1\t8.4691369533538818e-1\t7.8526735305786133e-3\t9.2721059699818163e-3\t3.8985999999999999e-3\n\t...and 31037 more errors.\n\tMax AbsError of 9.8276454210281372e-1 at index of 39267.\n\t[39267\]\t-4.4464776011506507e-25\t-9.8276454210281372e-1\t9.8276454210281372e-1\t1.0000000000000000e+0\t3.8985999999999999e-3\n\tMax RelError of 3.3137802965303198e+0 at index of 1253.\n\t[1253\]\t-4.3022233992815018e-2\t-9.9732093513011932e-3\t3.3049024641513824e-2\t3.3137802965303198e+0\t3.8985999999999999e-3\n]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/webxr/xrBoundedReferenceSpace_updates.https.html.ini b/tests/wpt/metadata/webxr/xrBoundedReferenceSpace_updates.https.html.ini
index 6ff00c31bef..27f6c5ed7a2 100644
--- a/tests/wpt/metadata/webxr/xrBoundedReferenceSpace_updates.https.html.ini
+++ b/tests/wpt/metadata/webxr/xrBoundedReferenceSpace_updates.https.html.ini
@@ -1,5 +1,5 @@
[xrBoundedReferenceSpace_updates.https.html]
- expected: TIMEOUT
+ expected: ERROR
['XRBoundedReferenceSpace updates properly when the changes are applied]
expected: TIMEOUT
diff --git a/tests/wpt/metadata/workers/WorkerGlobalScope-close.html.ini b/tests/wpt/metadata/workers/WorkerGlobalScope-close.html.ini
deleted file mode 100644
index fe8654e447c..00000000000
--- a/tests/wpt/metadata/workers/WorkerGlobalScope-close.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[WorkerGlobalScope-close.html]
- [Test sending a message after closing.]
- expected: FAIL
-
diff --git a/tests/wpt/web-platform-tests/.azure-pipelines.yml b/tests/wpt/web-platform-tests/.azure-pipelines.yml
index 3bd94f97b22..4a4e9c7ff5e 100644
--- a/tests/wpt/web-platform-tests/.azure-pipelines.yml
+++ b/tests/wpt/web-platform-tests/.azure-pipelines.yml
@@ -1,6 +1,7 @@
# This is the configuration file for Azure Pipelines, used to run tests on
# macOS. Documentation to help understand this setup:
# https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema
+# https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers
# https://docs.microsoft.com/en-us/azure/devops/pipelines/process/multiple-phases
# https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates
# https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables
@@ -10,13 +11,20 @@
# project is required:
# - The "Build pull requests from forks of this repository" setting must be
# enabled: https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/github#validate-contributions-from-forks
-# - A scheduled build needs to be set up for one of the epochs/* branches.
# - Self-hosted agents for Windows 10 are used:
# - 'Hosted Windows Client' is the latest Windows 10
# - 'Hosted Windows Client Next' is Windows 10 Insider Preview
# Documention for the setup of these agents:
# https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows
+schedules:
+- cron: "15 */6 * * *"
+ displayName: Every six hours
+ branches:
+ include:
+ - epochs/six_hourly
+ always: true
+
jobs:
# The affected tests jobs are unconditional for speed, as most PRs have one or
# more affected tests: https://github.com/web-platform-tests/wpt/issues/13936.
diff --git a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.js b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.js
index 31e644d50b2..258441921bf 100644
--- a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.js
+++ b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.js
@@ -19,23 +19,25 @@ self.addEventListener('install', (event) => {
});
// Resolves when the service worker receives the 'activate' event.
-const kServiceWorkerActivatedPromise = new Promise(resolve => {
+const kServiceWorkerActivatedPromise = new Promise((resolve) => {
self.addEventListener('activate', event => { resolve(); });
});
+const kCookieChangeReceivedPromise = new Promise((resolve) => {
+ self.addEventListener('cookiechange', (event) => {
+ resolve(event);
+ });
+});
+
promise_test(async testCase => {
await kServiceWorkerActivatedPromise;
- const cookie_change_received_promise = new Promise((resolve) => {
- self.oncookiechange = (event) => { resolve(event); };
- });
-
await cookieStore.set('cookie-name', 'cookie-value');
testCase.add_cleanup(async () => {
await cookieStore.delete('cookie-name');
});
- const event = await cookie_change_received_promise;
+ const event = await kCookieChangeReceivedPromise;
assert_equals(event.type, 'cookiechange');
assert_equals(event.changed.length, 1);
assert_equals(event.changed[0].name, 'cookie-name');
diff --git a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.tentative.https.html
index 8f9255b4649..ee9713e933b 100644
--- a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.tentative.https.html
@@ -11,11 +11,11 @@
(async () => {
const scope = 'scope';
- let registration = await navigator.serviceWorker.getRegistration(scope);
- if (registration)
- await registration.unregister();
- registration = await navigator.serviceWorker.register(
+ const registration = await navigator.serviceWorker.register(
'serviceworker_cookieStore_subscriptions_eventhandler_attribute.js', {scope});
+ add_completion_callback(() => {
+ registration.unregister();
+ });
fetch_tests_from_worker(registration.installing);
})();
diff --git a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.js b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.js
index 3d07c86492e..bd37b9be1ee 100644
--- a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.js
+++ b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.js
@@ -19,19 +19,19 @@ self.addEventListener('install', (event) => {
});
// Resolves when the service worker receives the 'activate' event.
-const kServiceWorkerActivatedPromise = new Promise(resolve => {
+const kServiceWorkerActivatedPromise = new Promise((resolve) => {
self.addEventListener('activate', event => { resolve(); });
});
+const kCookieChangeReceivedPromise = new Promise((resolve) => {
+ self.addEventListener('cookiechange', (event) => {
+ resolve(event);
+ });
+});
+
promise_test(async testCase => {
await kServiceWorkerActivatedPromise;
- const cookie_change_received_promise = new Promise((resolve) => {
- self.addEventListener('cookiechange', (event) => {
- resolve(event);
- });
- });
-
await cookieStore.set('another-cookie-name', 'cookie-value');
testCase.add_cleanup(async () => {
await cookieStore.delete('another-cookie-name');
@@ -41,7 +41,7 @@ promise_test(async testCase => {
await cookieStore.delete('cookie-name');
});
- const event = await cookie_change_received_promise;
+ const event = await kCookieChangeReceivedPromise;
assert_equals(event.type, 'cookiechange');
assert_equals(event.changed.length, 1);
assert_equals(event.changed[0].name, 'cookie-name');
diff --git a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.tentative.https.html
index ea70a1efcd0..b8ad46a5710 100644
--- a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.tentative.https.html
@@ -10,11 +10,11 @@
(async () => {
const scope = 'scope';
- let registration = await navigator.serviceWorker.getRegistration(scope);
- if (registration)
- await registration.unregister();
- registration = await navigator.serviceWorker.register(
+ const registration = await navigator.serviceWorker.register(
'serviceworker_cookieStore_subscriptions_mismatch.js', {scope});
+ add_completion_callback(() => {
+ registration.unregister();
+ });
fetch_tests_from_worker(registration.installing);
})();
diff --git a/tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002-ref.xht b/tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002-ref.xht
index e872737b1ca..6b449157053 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002-ref.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002-ref.xht
@@ -15,6 +15,7 @@
font: 3.75em/0.4 serif;
margin-left: 1em;
text-decoration: underline;
+ text-decoration-skip-ink: none;
}
span
diff --git a/tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002.xht b/tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002.xht
index 28b38f31e28..09b0b4ed5f8 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/text/text-decoration-va-length-002.xht
@@ -21,6 +21,7 @@
font: 3.75em/0.4 serif;
margin-left: 1em;
text-decoration: underline;
+ text-decoration-skip-ink: none;
}
span#wrapper
@@ -49,4 +50,4 @@
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-001.html b/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-001.html
index 881bb18446e..7ce3b69f6b5 100644
--- a/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-001.html
+++ b/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-001.html
@@ -29,7 +29,7 @@
test(
function(){
var target = document.getElementById("target");
- assert_equals(getComputedStyle(target).gap, "50px 50px");
+ assert_equals(getComputedStyle(target).gap, "50px");
assert_equals(getComputedStyle(target).rowGap, "50px");
assert_equals(getComputedStyle(target).columnGap, "50px");
}, "gap is interpolable");
diff --git a/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-002.html b/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-002.html
index 44d8c70b3a8..6056aad6740 100644
--- a/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-002.html
+++ b/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-002.html
@@ -28,7 +28,7 @@
test(
function(){
var target = document.getElementById("target");
- assert_equals(getComputedStyle(target).gap, "100px 100px");
+ assert_equals(getComputedStyle(target).gap, "100px");
assert_equals(getComputedStyle(target).rowGap, "100px");
assert_equals(getComputedStyle(target).columnGap, "100px");
}, "gap: normal is not interpolable");
diff --git a/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-003.html b/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-003.html
index c047946fb7f..2ec4551acb7 100644
--- a/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-003.html
+++ b/tests/wpt/web-platform-tests/css/css-align/gaps/gap-animation-003.html
@@ -27,7 +27,7 @@
test(
function(){
var target = document.getElementById("target");
- assert_equals(getComputedStyle(target).gap, "100px 100px");
+ assert_equals(getComputedStyle(target).gap, "100px");
assert_equals(getComputedStyle(target).rowGap, "100px");
assert_equals(getComputedStyle(target).columnGap, "100px");
}, "Default gap is not interpolable");
diff --git a/tests/wpt/web-platform-tests/css/css-align/parsing/gap-computed.html b/tests/wpt/web-platform-tests/css/css-align/parsing/gap-computed.html
new file mode 100644
index 00000000000..b93b2378136
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-align/parsing/gap-computed.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Box Alignment Level 3: getComputedStyle().gap</title>
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-gap">
+<meta name="assert" content="gap computed value is a pair of keyword or <length-percentage> values.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+<style>
+ #target {
+ font-size: 40px;
+ }
+</style>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("gap", "normal");
+test_computed_value("gap", "10px");
+test_computed_value("gap", "20%");
+test_computed_value("gap", "calc(20% + 10px)");
+test_computed_value("gap", "calc(-0.5em + 10px)", "0px");
+test_computed_value("gap", "calc(0.5em + 10px)", "30px");
+
+test_computed_value("gap", "normal 10px");
+test_computed_value("gap", "10px 20%");
+test_computed_value("gap", "20% calc(20% + 10px)");
+test_computed_value("gap", "calc(20% + 10px) normal");
+
+test_computed_value("gap", "calc(-0.5em + 10px) calc(0.5em + 10px)", "0px 30px");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-align/parsing/gap-invalid.html b/tests/wpt/web-platform-tests/css/css-align/parsing/gap-invalid.html
new file mode 100644
index 00000000000..c2eae8f7aad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-align/parsing/gap-invalid.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Box Alignment Level 3: parsing gap with invalid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-gap">
+<meta name="assert" content="gap supports only the grammar '<row-gap> <column-gap>?'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value("gap", "auto");
+test_invalid_value("gap", "-10px");
+
+test_invalid_value("gap", "10px 20% 30px");
+test_invalid_value("gap", "normal 10px normal");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-align/parsing/gap-valid.html b/tests/wpt/web-platform-tests/css/css-align/parsing/gap-valid.html
new file mode 100644
index 00000000000..3104e3fbbdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-align/parsing/gap-valid.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Box Alignment Level 3: parsing gap with valid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-gap">
+<meta name="assert" content="row-gap supports the full grammar '<row-gap> <column-gap>?'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("gap", "normal normal", "normal");
+test_valid_value("gap", "10px 10px", "10px");
+test_valid_value("gap", "20% 20%", "20%");
+test_valid_value("gap", "calc(20% + 10px) calc(20% + 10px)", "calc(20% + 10px)");
+
+test_valid_value("gap", "normal 10px");
+test_valid_value("gap", "10px 20%");
+test_valid_value("gap", "20% calc(20% + 10px)");
+test_valid_value("gap", "calc(20% + 10px) 0px");
+test_valid_value("gap", "0px normal");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-box/parsing/padding-invalid.html b/tests/wpt/web-platform-tests/css/css-box/parsing/padding-invalid.html
index e995ac616a1..3e3a560c2f7 100644
--- a/tests/wpt/web-platform-tests/css/css-box/parsing/padding-invalid.html
+++ b/tests/wpt/web-platform-tests/css/css-box/parsing/padding-invalid.html
@@ -3,9 +3,9 @@
<head>
<meta charset="utf-8">
<title>CSS basic box model: parsing padding with invalid values</title>
-<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-box-3/#propdef-padding">
-<meta name="assert" content="padding supports only the grammar '<length>{1,4}'.">
+<meta name="assert" content="padding supports only the grammar '<length-percentage>{1,4}'.">
+<meta name="assert" content="Negative values are invalid.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
@@ -23,12 +23,7 @@ test_invalid_value("padding-bottom", "10px 20px calc(2em + 3ex) auto");
test_invalid_value("padding-bottom-left", "10px 20px");
test_invalid_value("padding-top", "-10px");
-
-// The following are not yet rejected by browsers:
-test_invalid_value("padding", "20%");
-test_invalid_value("padding", "10px 20% 30% 40px");
-test_invalid_value("padding-right", "20%");
-test_invalid_value("padding-right", "calc(2em + 3%)");
+test_invalid_value("padding-right", "-20%");
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-box/parsing/padding-valid.html b/tests/wpt/web-platform-tests/css/css-box/parsing/padding-valid.html
index ba3c3a7fd4a..0d3d51e86bb 100644
--- a/tests/wpt/web-platform-tests/css/css-box/parsing/padding-valid.html
+++ b/tests/wpt/web-platform-tests/css/css-box/parsing/padding-valid.html
@@ -3,9 +3,8 @@
<head>
<meta charset="utf-8">
<title>CSS basic box model: parsing padding with valid values</title>
-<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-box-3/#propdef-padding">
-<meta name="assert" content="padding supports the full grammar '<length>{1,4}'.">
+<meta name="assert" content="padding supports the full grammar '<length-percentage>{1,4}'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
@@ -20,6 +19,11 @@ test_valid_value("padding-top", "10px");
test_valid_value("padding-right", "20px");
test_valid_value("padding-bottom", "30px");
test_valid_value("padding-left", "40px");
+
+test_valid_value("padding", "20%");
+test_valid_value("padding", "10px 20% 30% 40px");
+test_valid_value("padding-right", "20%");
+test_valid_value("padding-right", "calc(2em + 3%)");
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/parsing/display-invalid.html b/tests/wpt/web-platform-tests/css/css-display/parsing/display-invalid.html
index 70516ad4901..7c4054747e2 100644
--- a/tests/wpt/web-platform-tests/css/css-display/parsing/display-invalid.html
+++ b/tests/wpt/web-platform-tests/css/css-display/parsing/display-invalid.html
@@ -16,6 +16,60 @@
<script>
test_invalid_value("display", "grid inline-grid");
test_invalid_value("display", "none grid");
+test_invalid_value("display", "none flow");
+test_invalid_value("display", "none ruby");
+test_invalid_value("display", "none flow-root");
+test_invalid_value("display", "none list-item");
+test_invalid_value("display", "contents list-item");
+test_invalid_value("display", "list-item contents");
+test_invalid_value("display", "flow flow");
+test_invalid_value("display", "block block");
+test_invalid_value("display", "flow flow-root");
+test_invalid_value("display", "flow-root flow-root");
+test_invalid_value("display", "block inline");
+test_invalid_value("display", "flex ruby");
+test_invalid_value("display", "ruby flex");
+test_invalid_value("display", "inline inline");
+test_invalid_value("display", "flex flex");
+test_invalid_value("display", "grid flex");
+test_invalid_value("display", "ruby grid");
+test_invalid_value("display", "flex grid");
+test_invalid_value("display", "grid table");
+test_invalid_value("display", "table flex");
+test_invalid_value("display", "flex table");
+test_invalid_value("display", "ruby table");
+test_invalid_value("display", "table table");
+test_invalid_value("display", "table flow-root");
+test_invalid_value("display", "flow-root ruby");
+test_invalid_value("display", "list-item list-item");
+test_invalid_value("display", "list-item table");
+test_invalid_value("display", "flex list-item");
+test_invalid_value("display", "list-item grid");
+test_invalid_value("display", "flow flow list-item");
+test_invalid_value("display", "grid flow list-item");
+test_invalid_value("display", "flow list-item flow");
+test_invalid_value("display", "block list-item block");
+test_invalid_value("display", "list-item flow-root flow");
+test_invalid_value("display", "list-item block block");
+test_invalid_value("display", "list-item block list-item");
+test_invalid_value("display", "list-item flow-root list-item");
+test_invalid_value("display", "list-item flow-root block list-item");
+test_invalid_value("display", "list-item block flow-root list-item");
+test_invalid_value("display", "block list-item flow-root list-item");
+test_invalid_value("display", "flow-root list-item block list-item");
+test_invalid_value("display", "list-item ruby");
+test_invalid_value("display", "ruby list-item");
+test_invalid_value("display", "ruby ruby");
+test_invalid_value("display", "ruby flow");
+test_invalid_value("display", "flow ruby");
+test_invalid_value("display", "ruby flow-root");
+test_invalid_value("display", "grid ruby");
+test_invalid_value("display", "table ruby");
+test_invalid_value("display", "table-row flow");
+test_invalid_value("display", "flow table-row");
+test_invalid_value("display", "table-row-group flow-root");
+test_invalid_value("display", "flex table-row-group");
+
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/parsing/display-valid.html b/tests/wpt/web-platform-tests/css/css-display/parsing/display-valid.html
index efa48350a62..ecd57511422 100644
--- a/tests/wpt/web-platform-tests/css/css-display/parsing/display-valid.html
+++ b/tests/wpt/web-platform-tests/css/css-display/parsing/display-valid.html
@@ -35,6 +35,99 @@ test_valid_value("display", "table-column");
test_valid_value("display", "table-cell");
test_valid_value("display", "table-caption");
test_valid_value("display", "none");
+
+// https://drafts.csswg.org/css-display/#the-display-properties
+test_valid_value("display", "run-in");
+test_valid_value("display", "flow", "block");
+test_valid_value("display", "flow-root");
+test_valid_value("display", "ruby");
+
+test_valid_value("display", "flow list-item", "list-item");
+test_valid_value("display", "list-item flow", "list-item");
+test_valid_value("display", "flow-root list-item", "flow-root list-item");
+test_valid_value("display", "list-item flow-root", "flow-root list-item");
+
+test_valid_value("display", "block flow", "block");
+test_valid_value("display", "flow block", "block");
+test_valid_value("display", "flow-root block", "flow-root");
+test_valid_value("display", "block flow-root", "flow-root");
+test_valid_value("display", "flex block", "flex");
+test_valid_value("display", "block flex", "flex");
+test_valid_value("display", "grid block", "grid");
+test_valid_value("display", "block grid", "grid");
+test_valid_value("display", "table block", "table");
+test_valid_value("display", "block table", "table");
+test_valid_value("display", "block ruby", "block ruby");
+test_valid_value("display", "ruby block", "block ruby");
+test_valid_value("display", "block list-item", "list-item");
+test_valid_value("display", "list-item block", "list-item");
+test_valid_value("display", "flow block list-item", "list-item");
+test_valid_value("display", "block flow list-item", "list-item");
+test_valid_value("display", "flow list-item block", "list-item");
+test_valid_value("display", "block list-item flow", "list-item");
+test_valid_value("display", "list-item block flow", "list-item");
+test_valid_value("display", "list-item flow block", "list-item");
+test_valid_value("display", "flow-root block list-item", "flow-root list-item");
+test_valid_value("display", "block flow-root list-item", "flow-root list-item");
+test_valid_value("display", "flow-root list-item block", "flow-root list-item");
+test_valid_value("display", "block list-item flow-root", "flow-root list-item");
+test_valid_value("display", "list-item block flow-root", "flow-root list-item");
+test_valid_value("display", "list-item flow-root block", "flow-root list-item");
+
+test_valid_value("display", "inline flow", "inline");
+test_valid_value("display", "flow inline", "inline");
+test_valid_value("display", "flow-root inline", "inline-block");
+test_valid_value("display", "inline flow-root", "inline-block");
+test_valid_value("display", "flex inline", "inline-flex");
+test_valid_value("display", "inline flex", "inline-flex");
+test_valid_value("display", "grid inline", "inline-grid");
+test_valid_value("display", "inline grid", "inline-grid");
+test_valid_value("display", "table inline", "inline-table");
+test_valid_value("display", "inline table", "inline-table");
+test_valid_value("display", "inline ruby", "ruby");
+test_valid_value("display", "ruby inline", "ruby");
+test_valid_value("display", "inline list-item", "inline list-item");
+test_valid_value("display", "list-item inline", "inline list-item");
+test_valid_value("display", "flow inline list-item", "inline list-item");
+test_valid_value("display", "inline flow list-item", "inline list-item");
+test_valid_value("display", "flow list-item inline", "inline list-item");
+test_valid_value("display", "inline list-item flow", "inline list-item");
+test_valid_value("display", "list-item inline flow", "inline list-item");
+test_valid_value("display", "list-item flow inline", "inline list-item");
+test_valid_value("display", "flow-root inline list-item", "inline flow-root list-item");
+test_valid_value("display", "inline flow-root list-item", "inline flow-root list-item");
+test_valid_value("display", "flow-root list-item inline", "inline flow-root list-item");
+test_valid_value("display", "inline list-item flow-root", "inline flow-root list-item");
+test_valid_value("display", "list-item inline flow-root", "inline flow-root list-item");
+test_valid_value("display", "list-item flow-root inline", "inline flow-root list-item");
+
+test_valid_value("display", "run-in flow", "run-in");
+test_valid_value("display", "flow run-in", "run-in");
+test_valid_value("display", "flow-root run-in", "run-in flow-root");
+test_valid_value("display", "run-in flow-root", "run-in flow-root");
+test_valid_value("display", "flex run-in", "run-in flex");
+test_valid_value("display", "run-in flex", "run-in flex");
+test_valid_value("display", "grid run-in", "run-in grid");
+test_valid_value("display", "run-in grid", "run-in grid");
+test_valid_value("display", "table run-in", "run-in table");
+test_valid_value("display", "run-in table", "run-in table");
+test_valid_value("display", "run-in ruby", "run-in ruby");
+test_valid_value("display", "ruby run-in", "run-in ruby");
+test_valid_value("display", "run-in list-item", "run-in list-item");
+test_valid_value("display", "list-item run-in", "run-in list-item");
+test_valid_value("display", "flow run-in list-item", "run-in list-item");
+test_valid_value("display", "run-in flow list-item", "run-in list-item");
+test_valid_value("display", "flow list-item run-in", "run-in list-item");
+test_valid_value("display", "run-in list-item flow", "run-in list-item");
+test_valid_value("display", "list-item run-in flow", "run-in list-item");
+test_valid_value("display", "list-item flow run-in", "run-in list-item");
+test_valid_value("display", "flow-root run-in list-item", "run-in flow-root list-item");
+test_valid_value("display", "run-in flow-root list-item", "run-in flow-root list-item");
+test_valid_value("display", "flow-root list-item run-in", "run-in flow-root list-item");
+test_valid_value("display", "run-in list-item flow-root", "run-in flow-root list-item");
+test_valid_value("display", "list-item run-in flow-root", "run-in flow-root list-item");
+test_valid_value("display", "list-item flow-root run-in", "run-in flow-root list-item");
+
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/inline-flex-min-content-height.html b/tests/wpt/web-platform-tests/css/css-flexbox/inline-flex-min-content-height.html
new file mode 100644
index 00000000000..b84b9afc0b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/inline-flex-min-content-height.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Flexbox Layout Test: Atomic inline Flexible Box with height: min-content</title>
+<link rel="help" href="https://drafts.csswg.org/css-sizing/#valdef-width-min-content">
+<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
+<meta name=assert content="This test checks that height: min-content computes to 'auto' for atomic inline level flexible box.">
+<style>
+ #flexbox {
+ background-color: green;
+ display: inline-flex;
+ height: min-content;
+ }
+</style>
+<p>Test passes if there is a filled green square.</p>
+<div id="flexbox">
+ <div id="item">
+ <div style="width:100px; height:100px;"></div>
+ </div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-marker-ref.html b/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-marker-ref.html
new file mode 100644
index 00000000000..6a36181107e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-marker-ref.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<head>
+ <meta charset="utf-8">
+ <title>CSS Reference: inline flow-root list-item with ::marker</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+html,body {
+ color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+ol,ul,li { margin:0; padding:0; }
+body { margin-left: 40px; }
+
+li { border: 1px solid; display: list-item; }
+li::marker { content: counters(list-item, ".") " "; }
+
+.wrap { width: 22ch; }
+.m { width: -webkit-min-content; width: min-content; }
+ib { display:inline-block; }
+</style>
+</head>
+<body>
+
+<div class="wrap">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li class=m>B</li>
+
+<ol>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<ib><li class=m>B</li></ib>
+<ib><li class=m>C</li></ib>
+</ol>
+
+<ol style="display:inline">
+<ib><li>A A A A A A A A A A A A A A A A A A A A </li></ib>
+<ib><li class=m>B</li></ib>
+<ib><li class=m>C</li></ib>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol>
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li class=m>b</li>
+</ol></li>
+<li class=m>C</li>
+</ol>
+
+<ul>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol style="display:inline">
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li class=m>b</li>
+</ol></li>
+<li class=m>C</li>
+</ul>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-marker.html b/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-marker.html
new file mode 100644
index 00000000000..73a163fa9db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-marker.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<head>
+ <meta charset="utf-8">
+ <title>CSS Test: inline flow-root list-item with ::marker</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <link rel="help" href="https://drafts.csswg.org/css-lists-3/#marker-pseudo">
+ <link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1105868">
+ <link rel="match" href="inline-block-list-marker-ref.html">
+<style>
+html,body {
+ color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+ol,ul,li { margin:0; padding:0; }
+body { margin-left: 40px; }
+
+li { display: inline flow-root list-item; border: 1px solid; }
+li::marker { content: counters(list-item, ".") " "; }
+.wrap { width: 22ch; }
+</style>
+</head>
+<body>
+
+<div class="wrap">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+
+<ol>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+<li>C</li>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+<li>C</li>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol>
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li>b</li>
+</ol></li>
+<li>C</li>
+</ol>
+
+<ul>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol style="display:inline">
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li>b</li>
+</ol></li>
+<li>C</li>
+</ul>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-ref.html b/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-ref.html
new file mode 100644
index 00000000000..41b8504e4df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-block-list-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<head>
+ <meta charset="utf-8">
+ <title>CSS Reference: inline flow-root list-item</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+html,body {
+ color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+ol,ul,li { margin:0; padding:0; }
+body { margin-left: 40px; }
+
+li { border: 1px solid; display: list-item; }
+
+.wrap { width: 22ch; }
+.m { width: -webkit-min-content; width: min-content; }
+ib { display:inline-block; }
+</style>
+</head>
+<body>
+
+<div class="wrap">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li class=m>B</li>
+
+<ol>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<ib><li class=m>B</li></ib>
+<ib><li class=m>C</li></ib>
+</ol>
+
+<ol style="display:inline">
+<ib><li>A A A A A A A A A A A A A A A A A A A A </li></ib>
+<ib><li class=m>B</li></ib>
+<ib><li class=m>C</li></ib>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol>
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li class=m>b</li>
+</ol></li>
+<li class=m>C</li>
+</ol>
+
+<ul>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol style="display:inline">
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li class=m>b</li>
+</ol></li>
+<li class=m>C</li>
+</ul>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-block-list.html b/tests/wpt/web-platform-tests/css/css-lists/inline-block-list.html
new file mode 100644
index 00000000000..52220ae4241
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-block-list.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<head>
+ <meta charset="utf-8">
+ <title>CSS Test: inline flow-root list-item</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <link rel="help" href="https://drafts.csswg.org/css-lists-3/#declaring-a-list-item">
+ <link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1105868">
+ <link rel="match" href="inline-block-list-ref.html">
+<style>
+html,body {
+ color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+ol,ul,li { margin:0; padding:0; }
+body { margin-left: 40px; }
+
+li { border: 1px solid; display: inline flow-root list-item; }
+.wrap { width: 22ch; }
+</style>
+</head>
+<body>
+
+<div class="wrap">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+
+<ol>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+<li>C</li>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+<li>C</li>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol>
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li>b</li>
+</ol></li>
+<li>C</li>
+</ol>
+
+<ul>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol style="display:inline">
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li>b</li>
+</ol></li>
+<li>C</li>
+</ul>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-list-marker-ref.html b/tests/wpt/web-platform-tests/css/css-lists/inline-list-marker-ref.html
new file mode 100644
index 00000000000..e5a3c2e490a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-list-marker-ref.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<head>
+ <meta charset="utf-8">
+ <title>CSS Reference: inline list-item with ::marker</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+ol,ul,li { margin:0; padding:0; }
+body { margin-left: 40px; }
+
+span { border: 1px solid; }
+.wrap { width: 22ch; }
+ib { display:inline-block; }
+</style>
+</head>
+<body>
+
+<div class="wrap">
+<span>1 A A A A A A A A A A A A A A A A A A A A </span><span>2 B</span>
+
+<ol>
+<span>1 A A A A A A A A A A A A A A A A A A A A </span><span>2 B</span>
+<span>3 C</span>
+</ol>
+
+<ol style="display:inline">
+<span>1 A A A A A A A A A A A A A A A A A A A A </span><span>2 B</span>
+<span>3 C</span>
+</ol>
+
+<ol style="display:inline">
+<span>1 A A A A A A A A A A A A A A A A A A A A </span><span>2 B<ol>
+<span>2.1 a a a a a a a a a a a a a a a a a a a a </span><span>2.2 b</span>
+</ol></span>
+<span>3 C</span>
+</ol>
+
+<ul>
+<span>1 A A A A A A A A A A A A A A A A A A A A </span><span>2 B
+<ol style="display:inline"><span>2.1 a a a a a a a a a a a a a a a a a a a a </span><span>2.2 b</span>
+</ol></span><span>3 C</span>
+</ul>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-list-marker.html b/tests/wpt/web-platform-tests/css/css-lists/inline-list-marker.html
new file mode 100644
index 00000000000..3535f22ce2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-list-marker.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<head>
+ <meta charset="utf-8">
+ <title>CSS Test: inline list-item with ::marker</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <link rel="help" href="https://drafts.csswg.org/css-lists-3/#marker-pseudo">
+ <link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1105868">
+ <link rel="match" href="inline-list-marker-ref.html">
+<style>
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+ol,ul,li { margin:0; padding:0; }
+body { margin-left: 40px; }
+
+li { display: inline list-item; border: 1px solid; }
+li::marker { content: counters(list-item, ".") " "; }
+.wrap { width: 22ch; }
+</style>
+</head>
+<body>
+
+<div class="wrap">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+
+<ol>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+<li>C</li>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+<li>C</li>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol>
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li>b</li>
+</ol></li>
+<li>C</li>
+</ol>
+
+<ul>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol style="display:inline">
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li>b</li>
+</ol></li>
+<li>C</li>
+</ul>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-list-ref.html b/tests/wpt/web-platform-tests/css/css-lists/inline-list-ref.html
new file mode 100644
index 00000000000..ae1570a9703
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-list-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<head>
+ <meta charset="utf-8">
+ <title>CSS Reference: inline list-item</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+html,body {
+ color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+ol,ul,li { margin:0; padding:0; }
+body { margin-left: 40px; }
+
+span { border: 1px solid; }
+li { display: list-item; list-style-position: inside; }
+
+.wrap { width: 22ch; }
+ib { display:inline-block; }
+</style>
+</head>
+<body>
+
+<div class="wrap">
+<span><ib><li>A</li></ib> A A A A A A A A A A A A A A A A A A A </span><span><ib><li value=2></li></ib>B</span>
+
+<ol>
+<span><ib><li>A</li></ib> A A A A A A A A A A A A A A A A A A A </span><span><ib><li>B</li></ib></span>
+<span><ib><li>C</li></ib></span>
+</ol>
+
+<ol style="display:inline">
+<span><ib><li>A</li></ib> A A A A A A A A A A A A A A A A A A A </span><span><ib><li>B</li></ib></span>
+<span><ib><li>C</li></ib></span></ol><ol style="display:inline">
+<span><ib><li>A</li></ib> A A A A A A A A A A A A A A A A A A A </span><span><ib><li></li></ib>B<ol>
+<span><ib><li>a</li></ib> a a a a a a a a a a a a a a a a a a a </span><span><ib><li>b</li></ib></span>
+</ol></li></ib></span>
+<span><ib><li>C</li></ib></span>
+</ol>
+
+<ul>
+<span><ib><li>A</li></ib> A A A A A A A A A A A A A A A A A A A </span><span><ib><li></li></ib><br>B <ol style="display:inline"><span><ib><li>a</li></ib> a a a a a a a a a a a a a a a a a a a </span><span><ib><li>b</li></ib></span>
+</ol></span><span><ib><li>C</li></ib></span>
+</ul>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-list-with-table-child-ref.html b/tests/wpt/web-platform-tests/css/css-lists/inline-list-with-table-child-ref.html
new file mode 100644
index 00000000000..c35f640b226
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-list-with-table-child-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Reference: table boxes inside inline list-items</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <style>
+html,body {
+ color:black; background-color:white; font:16px/1 monospace;
+}
+
+.l1 { display: inline list-item; }
+.l2 { display: inline flow-root list-item; }
+
+span {
+ border: 1px solid;
+}
+
+div { background: blue; }
+ </style>
+</head>
+<body>
+
+A<span class="l1">B<div style="display:inline-table">T</div>C</span>
+A<span class="l1">B<div style="display:inline-table">T</div>C</span>
+A<span class="l1">B<div style="display:inline-table">T</div>C</span>
+A<span class="l1">B<x><div style="display:inline-table">T</div></x>C</span>
+A<span class="l1">B<x style="display:block"><div style="display:inline-table">T</div></x>C</span>
+
+A<span class="l2">B<div style="display:table">T</div>C</span>
+A<span class="l2">B<div style="display:table">T</div>C</span>
+A<span class="l2">B<div style="display:table">T</div>C</span>
+A<span class="l2">B<x><div style="display:inline-table">T</div></x>C</span>
+A<span class="l2">B<x style="display:block"><div style="display:table">T</div></x>C</span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-list-with-table-child.html b/tests/wpt/web-platform-tests/css/css-lists/inline-list-with-table-child.html
new file mode 100644
index 00000000000..0b897ec1da1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-list-with-table-child.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>CSS Test: table boxes inside inline list-items</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <link rel="help" href="https://drafts.csswg.org/css-tables-3/#ref-for-inline-table②">
+ <link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1105868">
+ <link rel="match" href="inline-list-with-table-child-ref.html">
+ <style>
+html,body {
+ color:black; background-color:white; font:16px/1 monospace;
+}
+
+.l1 { display: inline list-item; }
+.l2 { display: inline flow-root list-item; }
+
+span {
+ border: 1px solid;
+}
+
+div { background: blue; }
+ </style>
+</head>
+<body>
+
+A<span class="l1">B<div style="display:table-cell">T</div>C</span>
+A<span class="l1">B<div style="display:table-row">T</div>C</span>
+A<span class="l1">B<div style="display:table-row-group">T</div>C</span>
+A<span class="l1">B<div style="display:inline-table">T</div>C</span>
+A<span class="l1">B<div style="display:table">T</div>C</span>
+
+A<span class="l2">B<div style="display:table-cell">T</div>C</span>
+A<span class="l2">B<div style="display:table-row">T</div>C</span>
+A<span class="l2">B<div style="display:table-row-group">T</div>C</span>
+A<span class="l2">B<div style="display:inline-table">T</div>C</span>
+A<span class="l2">B<div style="display:table">T</div>C</span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/inline-list.html b/tests/wpt/web-platform-tests/css/css-lists/inline-list.html
new file mode 100644
index 00000000000..f4b48230e1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/inline-list.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<head>
+ <meta charset="utf-8">
+ <title>CSS Test: inline list-item</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <link rel="help" href="https://drafts.csswg.org/css-lists-3/#declaring-a-list-item">
+ <link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1105868">
+ <link rel="match" href="inline-list-ref.html">
+<style>
+html,body {
+ color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+ol,ul,li { margin:0; padding:0; }
+body { margin-left: 40px; }
+
+li { border: 1px solid; display: inline list-item; }
+.wrap { width: 22ch; }
+</style>
+</head>
+<body>
+
+<div class="wrap">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+
+<ol>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+<li>C</li>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B</li>
+<li>C</li>
+</ol>
+
+<ol style="display:inline">
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol>
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li>b</li>
+</ol></li>
+<li>C</li>
+</ol>
+
+<ul>
+<li>A A A A A A A A A A A A A A A A A A A A </li>
+<li>B<ol style="display:inline">
+<li>a a a a a a a a a a a a a a a a a a a a </li>
+<li>b</li>
+</ol></li>
+<li>C</li>
+</ul>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-001-ref.html b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-001-ref.html
new file mode 100644
index 00000000000..7b5c5d86087
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-001-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<ol>
+ <li value=3>three
+ <li value=6>six
+ <li value=5>five
+</ol>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-001.html b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-001.html
new file mode 100644
index 00000000000..616d7ccc66b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-001.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>Interaction of ol reversed and list-item value</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1573907">
+<link rel="help" href="https://html.spec.whatwg.org/#attr-ol-reversed">
+<link rel="help" href="https://html.spec.whatwg.org/#ordinal-value">
+<link rel="author" title="L. David Baron" href="https://dbaron.org/">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="match" href="li-value-reversed-001-ref.html">
+<ol reversed>
+ <li>three
+ <li value=6>six
+ <li>five
+</ol>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-002-ref.html b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-002-ref.html
new file mode 100644
index 00000000000..71c187d3069
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-002-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<ol>
+ <li value=6>six
+ <li value=5>five
+ <li value=7>seven
+ <li value=6>six
+ <li value=10>ten
+ <li value=9>nine
+</ol>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-002.html b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-002.html
new file mode 100644
index 00000000000..0c89ad21222
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-002.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>Interaction of ol reversed and list-item value</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1573907">
+<link rel="help" href="https://html.spec.whatwg.org/#attr-ol-reversed">
+<link rel="help" href="https://html.spec.whatwg.org/#ordinal-value">
+<link rel="author" title="L. David Baron" href="https://dbaron.org/">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="match" href="li-value-reversed-002-ref.html">
+<ol reversed>
+ <li>six
+ <li>five
+ <li value=7>seven
+ <li>six
+ <li value=10>ten
+ <li>nine
+</ol>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-003.html b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-003.html
new file mode 100644
index 00000000000..6e4d3d5f1ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-003.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Interaction of ol reversed and list-item value</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1573907">
+<link rel="help" href="https://html.spec.whatwg.org/#attr-ol-reversed">
+<link rel="help" href="https://html.spec.whatwg.org/#ordinal-value">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="match" href="li-value-reversed-002-ref.html">
+<ol reversed>
+ <li>six
+ <li>five
+ <li style="counter-set: list-item 7">seven
+ <li style="counter-increment: list-item -1">six
+ <li style="counter-set: list-item 10; counter-increment: list-item 1">ten
+ <li>nine
+</ol>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-004-ref.html b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-004-ref.html
new file mode 100644
index 00000000000..da95a042cfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-004-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<ol>
+ <li value=2>two
+ <div></div>
+ <li value=0>zero
+</ol>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-004.html b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-004.html
new file mode 100644
index 00000000000..48ac24a6a2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-004.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>Non-list items with explicit list-item counter increments don't increment the ol reversed start value</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1573907">
+<link rel="help" href="https://html.spec.whatwg.org/#attr-ol-reversed">
+<link rel="help" href="https://html.spec.whatwg.org/#ordinal-value">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="match" href="li-value-reversed-004-ref.html">
+<ol reversed>
+ <li>two
+ <div style="counter-increment: list-item -1"></div>
+ <li>zero
+</ol>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-005.html b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-005.html
new file mode 100644
index 00000000000..84f017b4992
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/li-value-reversed-005.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>Non-list items with explicit list-item counter increments don't increment the ol reversed start value</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1573907">
+<link rel="help" href="https://html.spec.whatwg.org/#attr-ol-reversed">
+<link rel="help" href="https://html.spec.whatwg.org/#ordinal-value">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="match" href="li-value-reversed-004-ref.html">
+<ol reversed>
+ <li>two
+ <div style="counter-increment: list-item 1; counter-set: list-item 1"></div>
+ <li>zero
+</ol>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-breaking-nobackground-004-ref.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-breaking-nobackground-004-ref.html
new file mode 100644
index 00000000000..2245fae043e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-breaking-nobackground-004-ref.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<title>CSS Test Reference: breaking of a multicolumn</title>
+<meta charset="utf-8">
+<link rel="author" title="L. David Baron" href="https://dbaron.org/">
+<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
+<link rel="author" title="Mozilla" href="https://mozilla.org/">
+<style>
+
+.outer {
+ height: 125px;
+ width: 800px;
+ background: rgba(0, 0, 255, 0.3);
+ position: relative;
+}
+
+.inner {
+ height: 100px;
+ width: 86px;
+ font: 16px/1.25 sans-serif;
+ position: absolute;
+ top: 0;
+}
+
+.border-bottom {
+ height: 25px;
+ width: 188px;
+ background: green;
+ position: absolute;
+ top: 100px;
+}
+
+.lefthalf {
+ border-right: 2px solid fuchsia;
+ padding-right: 7px;
+}
+
+.righthalf {
+ padding-left: 7px;
+}
+
+</style>
+
+<div class="outer">
+ <div class="inner lefthalf" style="left: 0">
+ AAAAA<br>
+ BBBBB<br>
+ CCCCC<br>
+ DDDDD<br>
+ EEEEE
+ </div>
+ <div class="inner righthalf" style="left: 95px">
+ FFFFF<br>
+ GGGGG<br>
+ HHHHH<br>
+ IIIII<br>
+ JJJJJ
+ </div>
+ <div class="border-bottom" style="left: 0"></div>
+ <div class="inner lefthalf" style="left: 204px">
+ KKKKK<br>
+ LLLLL<br>
+ MMMMM<br>
+ NNNNN
+ </div>
+ <div class="inner righthalf" style="left: 299px">
+ OOOOO<br>
+ PPPPP<br>
+ QQQQQ<br>
+ </div>
+ <div class="border-bottom" style="left: 204px;"></div>
+ <div class="border-bottom" style="left: 408px"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-breaking-nobackground-004.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-breaking-nobackground-004.html
new file mode 100644
index 00000000000..7b810423c91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-breaking-nobackground-004.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<title>CSS Test: breaking of a multicolumn</title>
+<meta charset="utf-8">
+<link rel="author" title="L. David Baron" href="https://dbaron.org/">
+<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
+<link rel="author" title="Mozilla" href="https://mozilla.org/">
+<link rel="help" href="https://drafts.csswg.org/css-multicol/#column-gaps-and-rules">
+<link rel="help" href="https://drafts.csswg.org/css-multicol/#cf">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/2309">
+<link rel="help" href="https://drafts.csswg.org/css-break/#break-decoration">
+<link rel="match" href="multicol-breaking-nobackground-004-ref.html">
+<style>
+
+.outer {
+ height: 125px;
+ column-fill: auto;
+ width: 800px;
+ column-count: 4;
+ column-gap: 16px;
+ background: rgba(0, 0, 255, 0.3);
+}
+
+.inner {
+ column-count: 2;
+ column-rule: 2px solid fuchsia;
+ column-gap: 16px;
+ font: 16px/1.25 sans-serif;
+ border: solid green;
+ border-width: 0 0 25px 0;
+ box-decoration-break: clone;
+}
+
+</style>
+
+<div class="outer">
+ <div class="inner" style="height: 300px">
+ AAAAA<br>
+ BBBBB<br>
+ CCCCC<br>
+ DDDDD<br>
+ EEEEE<br>
+ FFFFF<br>
+ GGGGG<br>
+ HHHHH<br>
+ IIIII<br>
+ JJJJJ<br>
+ KKKKK<br>
+ LLLLL<br>
+ MMMMM<br>
+ NNNNN<br>
+ OOOOO<br>
+ PPPPP<br>
+ QQQQQ
+ </div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-nested-balancing-003-ref.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-nested-balancing-003-ref.html
new file mode 100644
index 00000000000..573afe683fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-nested-balancing-003-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <title>CSS Multi-column Layout Test Reference: Test the column rules' block-size with nested balancing multicol container</title>
+ <link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+
+ <style>
+ .outer {
+ column-count: 2;
+ column-rule: 6px solid black;
+ column-fill: auto;
+ width: 400px;
+ height: 250px;
+ }
+ .inner {
+ column-count: 2;
+ column-rule: 3px solid gray;
+ column-fill: auto;
+ height: 200px;
+ }
+ .inner-block {
+ background-color: lightblue;
+ height: 400px;
+ }
+ .space {
+ height: 50px;
+ }
+ </style>
+
+ <article class="outer">
+ <article class="inner">
+ <div class="inner-block"></div>
+ </article>
+ <div class="space"></div>
+ <article class="inner">
+ <div class="inner-block"></div>
+ </article>
+ <div class="space"></div>
+ </article>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-nested-balancing-003.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-nested-balancing-003.html
new file mode 100644
index 00000000000..3dea42550e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-nested-balancing-003.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <title>CSS Multi-column Layout Test: Test the column rules' block-size with nested balancing multicol container</title>
+ <link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+ <link rel="help" href="https://drafts.csswg.org/css-multicol-1/#cf">
+ <link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-gaps-and-rules">
+ <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/2309">
+ <link rel="match" href="multicol-rule-nested-balancing-003-ref.html">
+ <meta name="assert" content="This test verifies that the column-rules are extended to the content block-end edges of their corresponding inner and outer multicol container.">
+
+ <style>
+ .outer {
+ column-count: 2;
+ column-rule: 6px solid black;
+ width: 400px;
+ height: 250px;
+ }
+ .inner {
+ column-count: 2;
+ column-rule: 3px solid gray;
+ height: 400px;
+ }
+ .inner-block {
+ background-color: lightblue;
+ height: 800px;
+ }
+ </style>
+
+ <article class="outer">
+ <article class="inner">
+ <div class="inner-block"></div>
+ </article>
+ </article>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/custom-property-animation-on-main-thread.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/custom-property-animation-on-main-thread.https.html
new file mode 100644
index 00000000000..13ccf3fc273
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/custom-property-animation-on-main-thread.https.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="one-custom-property-animation-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+ animation: expand 5s;
+}
+@keyframes expand {
+ 0% { --foo: 0; }
+ 0.01% { --foo: 50; }
+ 99% { --foo: 50; }
+ 100% { --foo: 100; }
+}
+
+#canvas-geometry {
+ background-color: blue;
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ let fooValue = parseFloat(properties.get('--foo').toString());
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, fooValue, fooValue);
+ }
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+</script>
+
+<script>
+// The test is designed to make sure that when the custom property animation is
+// running on the compositor thread, we are getting the right value.
+// The "importWorkletAndTerminateTestAfterAsyncPaint" has the logic to rAF
+// two frames before taking a screenshot. So the animation is designed to
+// be stable after two frames. That is, the 0.01% of 5s is much less than
+// two frames, and thus after two frames, the value of --foo should be stable.
+importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/one-custom-property-animation-ref.html b/tests/wpt/web-platform-tests/css/css-paint-api/one-custom-property-animation-ref.html
new file mode 100644
index 00000000000..c221aa0e89d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/one-custom-property-animation-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'blue';
+context.fillRect(0, 0, 100, 100);
+context.fillStyle = 'green';
+context.fillRect(0, 0, 50, 50);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/one-custom-property-animation.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/one-custom-property-animation.https.html
new file mode 100644
index 00000000000..1675bba1696
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/one-custom-property-animation.https.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="one-custom-property-animation-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+ animation: expand 5s;
+ /* TODO(crbug.com/987969): the will-change: transform should not be needed. */
+ will-change: transform;
+}
+@keyframes expand {
+ 0% { --foo: 0; }
+ 0.01% { --foo: 50; }
+ 99% { --foo: 50; }
+ 100% { --foo: 100; }
+}
+
+#canvas-geometry {
+ background-color: blue;
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo']; }
+ paint(ctx, geom, properties) {
+ let fooValue = parseFloat(properties.get('--foo').toString());
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, fooValue, fooValue);
+ }
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+</script>
+
+<script>
+// The test is designed to make sure that when the custom property animation is
+// running on the compositor thread, we are getting the right value.
+// The "importWorkletAndTerminateTestAfterAsyncPaint" has the logic to rAF
+// two frames before taking a screenshot. So the animation is designed to
+// be stable after two frames. That is, the 0.01% of 5s is much less than
+// two frames, and thus after two frames, the value of --foo should be stable.
+importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/two-custom-property-animation-ref.html b/tests/wpt/web-platform-tests/css/css-paint-api/two-custom-property-animation-ref.html
new file mode 100644
index 00000000000..1acef69f941
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/two-custom-property-animation-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="100" height="100"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = 'blue';
+context.fillRect(0, 0, 100, 100);
+context.fillStyle = '#9876c8';
+context.fillRect(0, 0, 50, 50);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/two-custom-property-animation.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/two-custom-property-animation.https.html
new file mode 100644
index 00000000000..392b5291f92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/two-custom-property-animation.https.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="two-custom-property-animation-ref.html">
+<style>
+.container {
+ width: 100px;
+ height: 100px;
+ animation: expand 5s, clr 5s;
+ /* TODO(crbug.com/987969): the will-change: transform should not be needed. */
+ will-change: transform;
+}
+@keyframes expand {
+ 0% { --foo: 0; }
+ 0.01% { --foo: 50; }
+ 99% { --foo: 50; }
+ 100% { --foo: 100; }
+}
+@keyframes clr {
+ 0% { --bar: 0; }
+ 0.01% { --bar: 200; }
+ 99% { --bar: 200; }
+ 100% { --bar: 255; }
+}
+
+#canvas-geometry {
+ background-color: blue;
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ static get inputProperties() { return ['--foo', '--bar']; }
+ paint(ctx, geom, properties) {
+ let fooValue = parseFloat(properties.get('--foo').toString());
+ let barValue = parseFloat(properties.get('--bar').toString());
+ let barString = barValue.toString(16);
+ if (barString.length == 1)
+ barString = '0' + barString;
+ ctx.fillStyle = '#9876' + barString;
+ ctx.fillRect(0, 0, fooValue, fooValue);
+ }
+});
+</script>
+
+<script>
+CSS.registerProperty({
+ name: '--foo',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+CSS.registerProperty({
+ name: '--bar',
+ syntax: '<number>',
+ initialValue: '0',
+ inherits: false
+});
+</script>
+
+<script>
+// The test is designed to make sure that when the custom property animation is
+// running on the compositor thread, we are getting the right value.
+// The "importWorkletAndTerminateTestAfterAsyncPaint" has the logic to rAF
+// two frames before taking a screenshot. So the animation is designed to
+// be stable after two frames. That is, the 0.01% of 5s is much less than
+// two frames, and thus after two frames, the value of --foo should be stable.
+importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-pseudo/first-letter-of-html-root-crash-ref.html b/tests/wpt/web-platform-tests/css/css-pseudo/first-letter-of-html-root-crash-ref.html
new file mode 100644
index 00000000000..f63dd580aa8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-pseudo/first-letter-of-html-root-crash-ref.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<title>CSS Test Reference</title>
+<body style="margin:0">PASS</body>
diff --git a/tests/wpt/web-platform-tests/css/css-pseudo/first-letter-of-html-root-crash.html b/tests/wpt/web-platform-tests/css/css-pseudo/first-letter-of-html-root-crash.html
new file mode 100644
index 00000000000..4233dd1dc35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-pseudo/first-letter-of-html-root-crash.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>CSS Test: ::first-letter of html root element crash in combination with removal of body</title>
+<link rel="help" href="https://crbug.com/993764">
+<link rel="match" href="first-letter-of-html-root-crash-ref.html">
+<style id="sheet">
+ html::first-letter { font-size: initial }
+</style>FAIL
+<script>
+ const sel = window.getSelection();
+ sel.selectAllChildren(document.documentElement);
+ const range = sel.getRangeAt(0);
+ document.body.remove();
+ document.documentElement.appendChild(document.createTextNode("PASS"));
+ document.documentElement.offsetTop;
+ range.surroundContents(sheet);
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-computed.html b/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-computed.html
new file mode 100644
index 00000000000..4153645dddf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-computed.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Rhythmic Sizing: getComputedStyle().lineHeightStep</title>
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#propdef-line-height-step">
+<meta name="assert" content="line-height-step computed value is an absolute length.">
+<meta name="assert" content="line-height-step is not negative.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+<style>
+ #target {
+ font-size: 40px;
+ }
+</style>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("line-height-step", "calc(10px + 0.5em)", "30px");
+test_computed_value("line-height-step", "calc(10px - 0.5em)", "0px");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-invalid.html b/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-invalid.html
new file mode 100644
index 00000000000..e2049057f1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-invalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Rhythmic Sizing: parsing line-height-step with invalid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#propdef-line-height-step">
+<meta name="assert" content="line-height-step supports only the grammar '<length>'.">
+<meta name="assert" content="line-height-step rejects negative lengths.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value("line-height-step", "auto");
+test_invalid_value("line-height-step", "normal");
+
+test_invalid_value("line-height-step", "10");
+test_invalid_value("line-height-step", "10px 20px");
+test_invalid_value("line-height-step", "-1px");
+test_invalid_value("line-height-step", "4%");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-valid.html b/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-valid.html
new file mode 100644
index 00000000000..ea47a636786
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-rhythm/parsing/line-height-step-valid.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Rhythmic Sizing: parsing line-height-step with valid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-rhythm/#propdef-line-height-step">
+<meta name="assert" content="line-height-step supports the full grammar '<length>'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("line-height-step", "0", "0px");
+test_valid_value("line-height-step", "1px");
+test_valid_value("line-height-step", "calc(2em + 3ex)");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-001-ref.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-001-ref.html
new file mode 100644
index 00000000000..b8d851fb532
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-001-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>CSS Ruby Reference: basic 'block ruby' layout.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+.b { background: lightblue; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+.columns {
+ columns: 3 auto;
+ column-rule: 1px;
+ background: lightgrey;
+ height: 2em;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+}
+.w { white-space: nowrap; width:2.5em; }
+</style>
+A<div class=b><ruby>べ<rt>る</rt></ruby></div>B
+A<div class="mbp b"><ruby>べ<rt>る</rt></ruby></div>B
+<div class=columns>A<div class="mbp b"><ruby>べ<rt>る</rt> べ<rt>る</rt> べ<rt>る</rt> べ<rt>る</rt> べ<rt>る</rt></ruby></div>B</div>
+<div style="width:2.5em; border:1px solid; text-align: center">
+ <p><div class="w b"><ruby><rb>一<rb>二<rb>三<rb>四<rb>五<rb>六<rb>七<rb>八</ruby></div></p>
+ <p><div class="w b"><ruby><rbc>一</rbc><rbc>二</rbc><rbc>三</rbc><rbc>四</rbc><rbc>五</rbc><rbc>六</rbc><rbc>七</rbc><rbc>八</rbc></ruby></div></p>
+</div>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-001.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-001.html
new file mode 100644
index 00000000000..f6a058807c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-001.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>CSS Ruby Test: basic 'block ruby' layout.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#ruby-layout">
+<link rel="match" href="block-ruby-001-ref.html">
+<style>
+ruby { display: block ruby; background: lightblue; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+.columns {
+ columns: 3 auto;
+ column-rule: 1px;
+ background: lightgrey;
+ height: 2em;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+}
+</style>
+A<ruby>べ<rt>る</rt></ruby>B
+A<ruby class=mbp>べ<rt>る</rt></ruby>B
+<div class=columns>A<ruby class=mbp>べ<rt>る</rt> べ<rt>る</rt> べ<rt>る</rt> べ<rt>る</rt> べ<rt>る</rt></ruby>B</div>
+<div style="width:2.5em; border:1px solid; text-align: center">
+ <p><ruby><rb>一<rb>二<rb>三<rb>四<rb>五<rb>六<rb>七<rb>八</ruby></p>
+ <p><ruby><rbc>一</rbc><rbc>二</rbc><rbc>三</rbc><rbc>四</rbc><rbc>五</rbc><rbc>六</rbc><rbc>七</rbc><rbc>八</rbc></ruby></p>
+</div>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-002-ref.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-002-ref.html
new file mode 100644
index 00000000000..a4d26153da6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-002-ref.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>Reference: blockification/inlinification of 'display:ruby/block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+div,span { background: lightblue; }
+ruby { display: ruby; }
+rbb { display: ruby; background: lightblue; }
+grid { display: grid; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+}
+rtc {
+ display: ruby-text-container;
+ unicode-bidi: isolate;
+}
+</style>
+<grid>A<div><ruby>べ<rt>る</rt></ruby></div>B</grid>
+<grid>A<div class=mbp><ruby>べ<rt>る</rt></ruby></div>B</grid>
+<grid>A
+ <div><ruby>べ<rt>る</rt></ruby></div>
+ <div><ruby><rbc>一</rbc><rbc>二</rbc><rbc>三</rbc><rbc>四</rbc><rbc>五</rbc><rbc>六</rbc><rbc>七</rbc><rbc>八</rbc></ruby></div>
+B
+</grid>
+<span><ruby>べ<rt><rbb>る</rbb></rt></ruby></span>
+<span><ruby>べ<rbc><rbb>る</rbb></rbc></ruby></span>
+<span><ruby>べ<rtc><rbb>る</rbb></rtc></ruby></span>
+<span><ruby>べ<rbb>る</rbb></ruby></span>
+
+<pre>block ruby, block ruby, block ruby, block ruby, ruby, ruby, ruby, ruby, ruby, ruby, ruby, ruby, </pre>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-002.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-002.html
new file mode 100644
index 00000000000..73fbc3015bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-002.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>CSS Ruby Test: blockification/inlinification of 'display:ruby/block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#box-fixup">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#inlinify">
+<link rel="match" href="block-ruby-002-ref.html">
+<style>
+ruby { display: ruby; background: lightblue; }
+rbb { display: block ruby; background: lightblue; }
+grid { display: grid; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+}
+rtc {
+ display: ruby-text-container;
+ unicode-bidi: isolate;
+}
+</style>
+<grid>A<ruby>べ<rt>る</rt></ruby>B</grid>
+<grid>A<ruby class=mbp>べ<rt>る</rt></ruby>B</grid>
+<grid>A
+ <ruby>べ<rt>る</rt></ruby>
+ <ruby><rbc>一</rbc><rbc>二</rbc><rbc>三</rbc><rbc>四</rbc><rbc>五</rbc><rbc>六</rbc><rbc>七</rbc><rbc>八</rbc></ruby>
+B
+</grid>
+<ruby>べ<rt><rbb>る</rbb></rt></ruby>
+<ruby>べ<rbc><rbb>る</rbb></rbc></ruby>
+<ruby>べ<rtc><rbb>る</rbb></rtc></ruby>
+<ruby>べ<rbb>る</rbb></ruby>
+
+<pre></pre>
+<script>
+let ruby = Array.prototype.slice.call(document.querySelectorAll('ruby,rbb'));
+let result = ruby.map(e => window.getComputedStyle(e).display + ', ').reduce((s, t) => s + t, "");
+document.querySelector('pre').appendChild(document.createTextNode(result));
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-003-ref.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-003-ref.html
new file mode 100644
index 00000000000..b89f33cfdae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-003-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>Reference: Text node insertion in 'display:ruby/block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+html,body {
+ color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
+}
+
+ruby { display: ruby; background: lightblue; }
+rbb { display: block ruby; background: lightblue; }
+grid { display: grid; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+}
+rtc {
+ display: ruby-text-container;
+ unicode-bidi: isolate;
+}
+</style>
+
+<ruby class=mbp>X<rt>る</rt></ruby>
+<grid>A<ruby class=mbp>X<rt>る</rt></ruby>B</grid>
+<grid>A<ruby class=mbp>X<rt>る</rt></ruby>B</grid>
+<grid>A<ruby>X<rt>る</rt></ruby><ruby>X<rbc></rbc></ruby>B</grid>
+<grid>A<ruby>X</ruby><ruby>X<rbc><rt>る</rt></rbc></ruby>B</grid>
+<ruby>X<rt><rbb>Xる</rbb></rt></ruby>
+<ruby>X<rbc><rbb>Xる</rbb></rbc></ruby>
+<ruby>X<rtc><rbb>Xる</rbb></rtc></ruby>
+<rbb class=mbp>X</rbb>
+<rbb class=mbp>X<rt>る</rt></rbb>
+<rbb class=mbp>X<rb>X</rb></rbb>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-003.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-003.html
new file mode 100644
index 00000000000..861ba8352ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-003.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>CSS Ruby Test: Text node insertion in 'display:ruby/block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#box-fixup">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#inlinify">
+<link rel="match" href="block-ruby-003-ref.html">
+<style>
+html,body {
+ color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
+}
+
+ruby { display: ruby; background: lightblue; }
+rbb { display: block ruby; background: lightblue; }
+grid { display: grid; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+}
+rtc {
+ display: ruby-text-container;
+ unicode-bidi: isolate;
+}
+</style>
+
+<ruby class=mbp><rt>る</rt></ruby>
+<grid>A<ruby class=mbp><rt>る</rt></ruby>B</grid>
+<grid>A<ruby class=mbp><rt>る</rt></ruby>B</grid>
+<grid>A<ruby><rt>る</rt></ruby><ruby><rbc></rbc></ruby>B</grid>
+<grid>A<ruby></ruby><ruby><rbc><rt>る</rt></rbc></ruby>B</grid>
+<ruby><rt><rbb>る</rbb></rt></ruby>
+<ruby><rbc><rbb>る</rbb></rbc></ruby>
+<ruby><rtc><rbb>る</rbb></rtc></ruby>
+<rbb class=mbp></rbb>
+<rbb class=mbp><rt>る</rt></rbb>
+<rbb class=mbp><rb>X</rb></rbb>
+
+<script>
+document.body.getClientRects();
+let s = "X";
+let ruby = Array.prototype.slice.call(document.querySelectorAll('ruby,rbb'));
+ruby.forEach(function(e){ e.insertBefore(document.createTextNode(s),e.firstChild); e.offsetHeight;});
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-004-ref.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-004-ref.html
new file mode 100644
index 00000000000..879609f4daf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-004-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>Reference: RT append in 'display:ruby/block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+html,body {
+ color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
+}
+
+ruby { display: ruby; background: lightblue; }
+rbb { display: block ruby; background: lightblue; }
+grid { display: grid; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+ font-size: 200%;
+}
+rtc {
+ display: ruby-text-container;
+ unicode-bidi: isolate;
+ ruby-position: under;
+}
+</style>
+
+<rt>る</rt>
+<ruby class=mbp>X<rt>る</rt></ruby>
+<grid>A<ruby class=mbp><rt>る</rt></ruby>B</grid>
+<grid>A<ruby class=mbp>X<rt>る</rt></ruby>B</grid>
+<grid>A<ruby>X<rt>る</rt></ruby><ruby><rbc></rbc><rt>る</rt></ruby>B</grid>
+<grid>A<ruby><rt>る</rt></ruby><ruby><rbc>X</rbc><rt>る</rt></ruby>B</grid>
+<ruby><rt><rbb>X<rt>る</rt></rbb></rt><rt>る</rt></ruby>
+<ruby><rbc><rbb>X<rt>る</rt></rbb></rbc><rt>る</rt></ruby>
+<ruby><rtc><rbb>X<rt>る</rt></rbb></rtc><rt>る</rt></ruby>
+<rbb class=mbp><rt>る</rt></rbb>
+<rbb class=mbp>X<rt>る</rt></rbb>
+<rbb class=mbp><rb>X</rb><rt>る</rt></rbb>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-004.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-004.html
new file mode 100644
index 00000000000..fcddc1dbda2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-004.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>CSS Ruby Test: RT append in 'display:ruby/block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#box-fixup">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#inlinify">
+<link rel="match" href="block-ruby-004-ref.html">
+<style>
+html,body {
+ color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
+}
+
+ruby { display: ruby; background: lightblue; }
+rbb { display: block ruby; background: lightblue; }
+rbbr { display: block ruby; background: lightblue; }
+grid { display: grid; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+ font-size: 200%;
+}
+rtc {
+ display: ruby-text-container;
+ unicode-bidi: isolate;
+ ruby-position: under;
+}
+</style>
+
+
+<rt>る</rt>
+<ruby class=mbp>X</ruby>
+<grid>A<ruby class=mbp></ruby>B</grid>
+<grid>A<ruby class=mbp>X</ruby>B</grid>
+<grid>A<ruby>X</ruby><ruby><rbc></rbc></ruby>B</grid>
+<grid>A<ruby></ruby><ruby><rbc>X</rbc></ruby>B</grid>
+<ruby><rt><rbb>X</rbb></rt></ruby>
+<ruby><rbc><rbb>X</rbb></rbc></ruby>
+<ruby><rtc><rbb>X</rbb></rtc></ruby>
+<rbb class=mbp></rbb>
+<rbb class=mbp>X</rbb>
+<rbb class=mbp><rb>X</rb></rbb>
+
+<script>
+document.body.getClientRects();
+let rt = document.querySelector('rt');
+let ruby = Array.prototype.slice.call(document.querySelectorAll('ruby,rbb'));
+ruby.forEach(function(e){ let n = rt.cloneNode(true); e.appendChild(n); e.offsetHeight;});
+</script>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-005-ref.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-005-ref.html
new file mode 100644
index 00000000000..a7f9353b590
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-005-ref.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>Reference: DIV append in 'display:ruby/block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+html,body {
+ color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
+}
+
+rbb, ruby { background:lightblue; text-overflow:ellipses; }
+ruby { display: ruby; }
+rbb { display: block ruby; }
+grid { display: grid; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+ font-size: 200%;
+}
+rtc {
+ display: ruby-text-container;
+ unicode-bidi: isolate;
+ ruby-position: under;
+}
+x { display:block; width:3em; overflow:hidden; background:lightblue; }
+</style>
+
+<div>zzzzzzzzzzzz</div>
+<ruby class=mbp>X<div>zzzzzzzzzzzz</div></ruby>
+<grid>A<x class=mbp><rbb><div>zzzzzzzzzzzz</div></rbb></x>B</grid>
+<grid>A<x class=mbp><rbb>X<div>zzzzzzzzzzzz</div></rbb></x>B</grid>
+<grid>A<x><rbb>X<div>zzzzzzzzzzzz</div></rbb></x><x><rbb><rbc></rbc><div>zzzzzzzzzzzz</div></rbb></x>B</grid>
+<grid>A<x><rbb><div>zzzzzzzzzzzz</div></rbb></x><x><rbb><rbc>X</rbc><div>zzzzzzzzzzzz</div></rbb></x>B</grid>
+<ruby><rt><ruby>X<div>zzzzzzzzzzzz</div></ruby></rt><div>zzzzzzzzzzzz</div></ruby>
+<ruby><rbc><ruby>X<div>zzzzzzzzzzzz</div></ruby></rbc><div>zzzzzzzzzzzz</div></ruby>
+<ruby><rtc><ruby>X<div>zzzzzzzzzzzz</div></ruby></rtc><div>zzzzzzzzzzzz</div></ruby>
+<x class=mbp><rbb><div>zzzzzzzzzzzz</div></rbb></x>
+<x class=mbp><rbb>X<div>zzzzzzzzzzzz</div></rbb></x>
+<x class=mbp><rbb><rt>X</rt><div>zzzzzzzzzzzz</div></rbb></x>
+<x class=mbp><rbb><rb>X</rb><div>zzzzzzzzzzzz</div></rbb></x>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-005.html b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-005.html
new file mode 100644
index 00000000000..8750b63d995
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/block-ruby-005.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja">
+<meta charset="utf-8">
+<title>CSS Ruby Test: DIV append in 'display:ruby/block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#box-fixup">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#inlinify">
+<link rel="match" href="block-ruby-005-ref.html">
+<style>
+html,body {
+ color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
+}
+
+rbb, ruby { background:lightblue; text-overflow:ellipses; overflow:hidden; width:3em; }
+ruby { display: ruby; }
+rbb { display: block ruby; }
+grid { display: grid; }
+.mbp {
+ margin: 1px 3px 5px 7px;
+ padding: 3px 5px 7px 1px;
+ border-width: 3px 1px 7px 5px;
+ border-style: solid;
+}
+rbc {
+ display: ruby-base-container;
+ unicode-bidi: isolate;
+ font-size: 200%;
+}
+rtc {
+ display: ruby-text-container;
+ unicode-bidi: isolate;
+ ruby-position: under;
+}
+</style>
+
+<div>zzzzzzzzzzzz</div>
+<ruby class=mbp>X</ruby>
+<grid>A<ruby class=mbp></ruby>B</grid>
+<grid>A<ruby class=mbp>X</ruby>B</grid>
+<grid>A<ruby>X</ruby><ruby><rbc></rbc></ruby>B</grid>
+<grid>A<ruby></ruby><ruby><rbc>X</rbc></ruby>B</grid>
+<ruby><rt><rbb>X</rbb></rt></ruby>
+<ruby><rbc><rbb>X</rbb></rbc></ruby>
+<ruby><rtc><rbb>X</rbb></rtc></ruby>
+<rbb class=mbp></rbb>
+<rbb class=mbp>X</rbb>
+<rbb class=mbp><rt>X</rt></rbb>
+<rbb class=mbp><rb>X</rb></rbb>
+
+<script>
+document.body.getClientRects();
+let div = document.querySelector('div');
+let ruby = Array.prototype.slice.call(document.querySelectorAll('ruby,rbb'));
+ruby.forEach(function(e){ let n = div.cloneNode(true); e.appendChild(n); e.offsetHeight;});
+</script>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/root-block-ruby.xhtml b/tests/wpt/web-platform-tests/css/css-ruby/root-block-ruby.xhtml
new file mode 100644
index 00000000000..51ac507c3be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/root-block-ruby.xhtml
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja" xmlns="http://www.w3.org/1999/xhtml">
+<meta charset="utf-8"/>
+<title>CSS Ruby Test: :root element with 'display:block ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"/>
+<link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display"/>
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#box-fixup"/>
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#inlinify"/>
+<link rel="match" href="root-ruby-ref.xhtml"/>
+<style>
+:root { display: block ruby; }
+rbc {
+ display: ruby-base-container;
+}
+rtc {
+ display: ruby-text-container;
+}
+</style>
+べ
+<rtc>
+ <rt>る</rt>
+</rtc>
+<rbc>
+ <rb>A</rb>
+ <rb>B</rb>
+</rbc>
+
+<pre></pre>
+<script>
+let ruby = Array.prototype.slice.call(document.querySelectorAll(':root'));
+let result = ruby.map(e => window.getComputedStyle(e).display + ', ').reduce((s, t) => s + t, "");
+document.querySelector('pre').appendChild(document.createTextNode(result));
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/root-ruby-ref.xhtml b/tests/wpt/web-platform-tests/css/css-ruby/root-ruby-ref.xhtml
new file mode 100644
index 00000000000..9edd7e3601d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/root-ruby-ref.xhtml
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja" xmlns="http://www.w3.org/1999/xhtml">
+<meta charset="utf-8"/>
+<title>Reference: :root element with 'display:ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"/>
+<style>
+rbc {
+ display: ruby-base-container;
+}
+rtc {
+ display: ruby-text-container;
+}
+</style>
+<ruby>べ
+<rtc>
+ <rt>る</rt>
+</rtc>
+<rbc>
+ <rb>A</rb>
+ <rb>B</rb>
+</rbc>
+
+<pre>block ruby, </pre>
+</ruby></html>
diff --git a/tests/wpt/web-platform-tests/css/css-ruby/root-ruby.xhtml b/tests/wpt/web-platform-tests/css/css-ruby/root-ruby.xhtml
new file mode 100644
index 00000000000..4b78690dd4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-ruby/root-ruby.xhtml
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+<html lang="ja" xmlns="http://www.w3.org/1999/xhtml">
+<meta charset="utf-8"/>
+<title>CSS Ruby Test: :root element with 'display:ruby'.</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"/>
+<link rel="help" href="https://drafts.csswg.org/css-display/#propdef-display"/>
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#box-fixup"/>
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#inlinify"/>
+<link rel="match" href="root-ruby-ref.xhtml"/>
+<style>
+:root { display: ruby; }
+rbc {
+ display: ruby-base-container;
+}
+rtc {
+ display: ruby-text-container;
+}
+</style>
+べ
+<rtc>
+ <rt>る</rt>
+</rtc>
+<rbc>
+ <rb>A</rb>
+ <rb>B</rb>
+</rbc>
+
+<pre></pre>
+<script>
+let ruby = Array.prototype.slice.call(document.querySelectorAll(':root'));
+let result = ruby.map(e => window.getComputedStyle(e).display + ', ').reduce((s, t) => s + t, "");
+document.querySelector('pre').appendChild(document.createTextNode(result));
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-tables/table-cell-overflow-auto-ref.html b/tests/wpt/web-platform-tests/css/css-tables/table-cell-overflow-auto-ref.html
new file mode 100644
index 00000000000..18163de3032
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-tables/table-cell-overflow-auto-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; border: solid;">
+ <div style="display: table-cell; max-width: 100px; height: 100px; background: green; overflow-x: scroll; vertical-align: top;">
+ <div style="width: 120px; height: 50px; background: hotpink;"></div>
+ </div>
+</div>
+<br>
+<div style="width: 100px; height: 100px; border: solid;">
+ <div style="display: table-cell; max-width: 100px; height: 100px; background: green; overflow-x: scroll; vertical-align: middle;">
+ <div style="width: 120px; height: 50px; background: hotpink;"></div>
+ </div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-tables/table-cell-overflow-auto.html b/tests/wpt/web-platform-tests/css/css-tables/table-cell-overflow-auto.html
new file mode 100644
index 00000000000..6b688561b91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-tables/table-cell-overflow-auto.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-tables-3/#row-layout">
+<link rel="match" href="table-cell-overflow-auto-ref.html">
+<meta name="assert" content="horizontal scrollbars show up on table-cells with overflowing content and overflow:auto, vertical-align: middle/top" />
+<div style="width: 100px; height: 100px; border: solid;">
+ <div style="display: table-cell; max-width: 100px; height: 100px; background: green; overflow-x: auto; vertical-align: top;">
+ <div style="width: 120px; height: 50px; background: hotpink;"></div>
+ </div>
+</div>
+<br>
+<div style="width: 100px; height: 100px; border: solid;">
+ <div style="display: table-cell; max-width: 100px; height: 100px; background: green; overflow-x: auto; vertical-align: middle;">
+ <div style="width: 120px; height: 50px; background: hotpink;"></div>
+ </div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/inheritance.html b/tests/wpt/web-platform-tests/css/css-text-decor/inheritance.html
index b106343742e..9ee65b4e592 100644
--- a/tests/wpt/web-platform-tests/css/css-text-decor/inheritance.html
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/inheritance.html
@@ -26,7 +26,7 @@ assert_not_inherited('text-decoration-line', 'none', 'line-through');
assert_not_inherited('text-decoration-style', 'solid', 'dashed');
assert_inherited('text-emphasis-color', 'rgba(2, 3, 4, 0.5)', 'rgba(42, 53, 64, 0.75)');
assert_inherited('text-emphasis-position', 'over right', 'under left');
-assert_inherited('text-emphasis-style', 'none', 'filled triangle');
+assert_inherited('text-emphasis-style', 'none', 'triangle');
assert_inherited('text-shadow', 'none', 'rgba(42, 53, 64, 0.75) 10px 20px 0px');
assert_inherited('text-underline-position', 'auto', 'under');
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-invalid.html b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-invalid.html
index 90095c0114f..9cba2423206 100644
--- a/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-invalid.html
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-invalid.html
@@ -7,9 +7,6 @@
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<script>
-test_invalid_value("text-decoration", "auto");
-test_invalid_value("text-decoration", "1px");
-
test_invalid_value("text-decoration", "double overline underline dotted");
test_invalid_value("text-decoration", "red line-through green");
test_invalid_value("text-decoration", "overline blue underline");
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-valid.html b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-valid.html
index 1c1aef3ff00..fd12ab4dc31 100644
--- a/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-valid.html
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-decoration-valid.html
@@ -9,12 +9,18 @@
<script>
test_valid_value("text-decoration", "none");
test_valid_value("text-decoration", "line-through");
-test_valid_value("text-decoration", "solid");
-test_valid_value("text-decoration", "currentcolor");
+test_valid_value("text-decoration", "solid", "none");
+test_valid_value("text-decoration", "currentcolor", "none");
+test_valid_value("text-decoration", "auto", "none");
+test_valid_value("text-decoration", "from-font");
+test_valid_value("text-decoration", "10px");
test_valid_value("text-decoration", "double overline underline", "underline overline double");
test_valid_value("text-decoration", "underline overline line-through red");
test_valid_value("text-decoration", "rgba(10, 20, 30, 0.4) dotted", "dotted rgba(10, 20, 30, 0.4)");
-
+test_valid_value("text-decoration", "overline green from-font");
test_valid_value("text-decoration", "underline dashed green");
+test_valid_value("text-decoration", "underline auto", "underline");
+test_valid_value("text-decoration", "line-through 20px");
+test_valid_value("text-decoration", "overline 3em");
</script>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-computed.html b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-computed.html
new file mode 100644
index 00000000000..a90738d825f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-computed.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Decoration Test: getComputedStyle().textShadow</title>
+<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property">
+<meta name="assert" content="text-shadow computed value is none or a list, each item a color and lengths.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+<style>
+ #target {
+ font-size: 40px;
+ color: blue;
+ }
+</style>
+<div id="target"></div>
+<script>
+'use strict';
+const red = 'rgb(255, 0, 0)';
+const lime = 'rgb(0, 255, 0)';
+const currentColor = 'rgb(0, 0, 255)';
+
+test_computed_value("text-shadow", "none");
+
+test_computed_value("text-shadow", "10px 20px", currentColor + " 10px 20px 0px");
+test_computed_value("text-shadow", "red 10px 20px 30px", red + " 10px 20px 30px");
+test_computed_value("text-shadow", "calc(0.5em + 10px) calc(0.5em + 10px) calc(0.5em + 10px)", currentColor + " 30px 30px 30px");
+test_computed_value("text-shadow", "calc(-0.5em + 10px) calc(-0.5em + 10px) calc(-0.5em + 10px)", currentColor + " -10px -10px 0px");
+
+test_computed_value("text-shadow", "10px 20px, 30px 40px", currentColor + " 10px 20px 0px, " + currentColor + " 30px 40px 0px");
+test_computed_value("text-shadow", "lime 10px 20px 30px, red 40px 50px", lime + " 10px 20px 30px, " + red + " 40px 50px 0px");
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-invalid.html b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-invalid.html
new file mode 100644
index 00000000000..dfaa4a5b48b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-invalid.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Decoration Test: Parsing text-shadow with invalid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property">
+<meta name="assert" content="text-shadow supports only the grammar 'none | [ <color>? && <length>{2,3} ]#'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+test_invalid_value("text-shadow", "auto");
+
+test_invalid_value("text-shadow", "10px 20px -30px");
+
+test_invalid_value("text-shadow", "10px");
+test_invalid_value("text-shadow", "10px 20px 30px 40px");
+test_invalid_value("text-shadow", "red 10px 20px blue");
+test_invalid_value("text-shadow", "10% 20px");
+test_invalid_value("text-shadow", "10px 20% 30px");
+test_invalid_value("text-shadow", "lime 10px 20px 30%");
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-valid.html b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-valid.html
new file mode 100644
index 00000000000..cbf9df54790
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/parsing/text-shadow-valid.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Decoration Test: Parsing text-shadow with valid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property">
+<meta name="assert" content="text-shadow supports the full grammar 'none | [ <color>? && <length>{2,3} ]#'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+test_valid_value("text-shadow", "none");
+
+test_valid_value("text-shadow", "10px 20px");
+test_valid_value("text-shadow", "10px 20px 30px");
+test_valid_value("text-shadow", "calc(1em + 2px) calc(3em + 4px) calc(5em + 6px)");
+test_valid_value("text-shadow", "-10px 20px 30px");
+test_valid_value("text-shadow", "10px -20px 30px");
+test_valid_value("text-shadow", "rgb(255, 0, 0) 10px 20px");
+test_valid_value("text-shadow", "10px 20px 30px lime", "lime 10px 20px 30px");
+
+test_valid_value("text-shadow", "10px 20px, 30px 40px");
+test_valid_value("text-shadow", "lime 10px 20px 30px, blue 40px 50px");
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-text/shaping/reference/shaping-014-ref.html b/tests/wpt/web-platform-tests/css/css-text/shaping/reference/shaping-014-ref.html
index f32ae1c23ec..6555baf1c74 100644
--- a/tests/wpt/web-platform-tests/css/css-text/shaping/reference/shaping-014-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-text/shaping/reference/shaping-014-ref.html
@@ -9,7 +9,7 @@
src: url('/fonts/noto/NotoNaskhArabic-regular.woff2') format('woff2');
}
.test, .ref { border: 1px solid #02D7F6; margin: 20px; padding: 10px; width: 3em; font-size: 120px; font-family: "csstest_noto"; }
-.styled { text-decoration: underline; }
+.styled { text-decoration: underline; text-decoration-skip-ink: none; }
</style>
<link rel=mismatch href="shaping-014-sanity-ref.html">
</head>
diff --git a/tests/wpt/web-platform-tests/css/css-text/shaping/shaping-014.html b/tests/wpt/web-platform-tests/css/css-text/shaping/shaping-014.html
index 01e80c35f2f..b817f2c0947 100644
--- a/tests/wpt/web-platform-tests/css/css-text/shaping/shaping-014.html
+++ b/tests/wpt/web-platform-tests/css/css-text/shaping/shaping-014.html
@@ -14,7 +14,7 @@
}
.test, .ref { border: 1px solid #02D7F6; margin: 20px; padding: 10px; width: 3em; font-size: 120px; font-family: "csstest_noto"; }
/* the CSS above is not part of the test */
-.styled { text-decoration: underline; }
+.styled { text-decoration: underline; text-decoration-skip-ink: none; }
</style>
</head>
<body>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/animation/composited-transform.html b/tests/wpt/web-platform-tests/css/css-transforms/animation/composited-transform.html
new file mode 100644
index 00000000000..182321b9d30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/animation/composited-transform.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Composition of transform animations</title>
+<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#combining-transform-lists">
+<meta name="assert" content="transform animations should composite correctly">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="target"><div>
+
+<script>
+test(() => {
+ var anim1 = target.animate(
+ { transform: [ 'translateX(0)', 'translateX(100px)' ]},
+ 1000
+ );
+ var anim2 = target.animate(
+ { transform: [ 'translateY(0)', 'translateY(100px)' ]},
+ {duration: 1000, composite: 'add'}
+ );
+
+ anim1.pause();
+ anim2.pause();
+
+ anim1.currentTime = 200;
+ anim2.currentTime = 800;
+
+ // The computation here should be:
+ // underlying_value = 'translateX(0)' --> 'translateX(100px)' @ 0.2
+ // = 'translateX(20px)'
+ // final_value = 0.2 * ('translateX(20px) translateY(0)') +
+ // 0.8 * ('translateX(20px) translateY(100px)')
+ // = 'translateX(20px) translateY(80px)'
+ // = 'matrix(1, 0, 0, 1, 20, 80)'
+ assert_equals(getComputedStyle(target).transform, 'matrix(1, 0, 0, 1, 20, 80)')
+}, 'An additive transform animation on-top of a replace transform animation ' +
+ 'should composite correctly');
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/CSSTransition-effect.tentative.html b/tests/wpt/web-platform-tests/css/css-transitions/CSSTransition-effect.tentative.html
index a6153b33171..41bd23eb531 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/CSSTransition-effect.tentative.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/CSSTransition-effect.tentative.html
@@ -10,6 +10,12 @@
<script>
'use strict';
+function singleFrame() {
+ return new Promise((resolve, reject) => {
+ requestAnimationFrame(resolve);
+ });
+}
+
test(t => {
const div = addDiv(t);
div.style.left = '0px';
@@ -87,6 +93,38 @@ promise_test(async t => {
assert_equals(getComputedStyle(div).left, '0px');
}, 'After setting a transition\'s effect to null, a new transition can be started');
+// This is a regression test for https://crbug.com/992668, where Chromium would
+// crash if the running transition's effect was set to null and the transition
+// was interrupted before it could finish due to the null effect.
+promise_test(async t => {
+ const div = addDiv(t);
+ div.style.left = '0px';
+
+ div.style.transition = 'left 100s';
+ getComputedStyle(div).left;
+ div.style.left = '100px';
+
+ assert_equals(div.getAnimations().length, 1);
+
+ const transition = div.getAnimations()[0];
+ await transition.ready;
+
+ // The transition needs to have a non-zero currentTime for the interruption
+ // reversal logic to apply.
+ await singleFrame();
+ assert_not_equals(transition.currentTime, 0);
+ assert_not_equals(getComputedStyle(div).left, '0px');
+
+ // Without yielding to the rendering loop, set the current transition's
+ // effect to null and interrupt the transition. This should work correctly.
+ transition.effect = null;
+ div.style.left = '0px';
+
+ // Yield to the rendering loop. This should not crash.
+ await singleFrame();
+}, 'After setting a transition\'s effect to null, it should be possible to '
+ + 'interrupt that transition');
+
promise_test(async t => {
const div = addDiv(t);
div.style.left = '0px';
diff --git a/tests/wpt/web-platform-tests/css/css-animations/parsing/transition-timing-function-computed.html b/tests/wpt/web-platform-tests/css/css-transitions/parsing/transition-timing-function-computed.html
index 9834dfdbf0d..9834dfdbf0d 100644
--- a/tests/wpt/web-platform-tests/css/css-animations/parsing/transition-timing-function-computed.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/parsing/transition-timing-function-computed.html
diff --git a/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/parse.tentative.html b/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/parse.tentative.html
index 80e4f44b3a0..98384b6fcc5 100644
--- a/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/parse.tentative.html
+++ b/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/parse.tentative.html
@@ -27,4 +27,14 @@ test(() => {
assert_style_value_equals(new CSSUnitValue(1, 'px'), CSSNumericValue.parse(' 1px '));
}, 'Parsing ignores surrounding spaces');
+test(() => {
+ const expected = new CSSMathMin(CSS.px(10), CSS.percent(10));
+ assert_style_value_equals(expected, CSSNumericValue.parse('min(10px, 10%)'));
+}, 'Parsing min() is successful');
+
+test(() => {
+ const expected = new CSSMathMax(CSS.px(10), CSS.percent(10));
+ assert_style_value_equals(expected, CSSNumericValue.parse('max(10px, 10%)'));
+}, 'Parsing max() is successful');
+
</script>
diff --git a/tests/wpt/web-platform-tests/css/css-typed-om/width-by-max-px-em.html b/tests/wpt/web-platform-tests/css/css-typed-om/width-by-max-px-em.html
new file mode 100644
index 00000000000..2aac59b7074
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-typed-om/width-by-max-px-em.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-typed-om-1/#stylevalue-subclasses">
+<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="'width' can be set with a CSSMathMax object.">
+<style>
+#target { font-size: 10px; background-color: green; height: 100px; }
+</style>
+<p>Test passes if there is a filled green square.</p>
+<div id=target></div>
+<script>
+const width = new CSSMathMax(CSS.em(10), CSS.px(90));
+const target = document.querySelector('#target');
+target.attributeStyleMap.set('width', width);
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-typed-om/width-by-min-px-em.html b/tests/wpt/web-platform-tests/css/css-typed-om/width-by-min-px-em.html
new file mode 100644
index 00000000000..615cb15708c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-typed-om/width-by-min-px-em.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-typed-om-1/#stylevalue-subclasses">
+<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
+<meta name="assert" content="'width' can be set with a CSSMathMin object.">
+<style>
+#target { font-size: 10px; background-color: green; height: 100px; }
+</style>
+<p>Test passes if there is a filled green square.</p>
+<div id=target></div>
+<script>
+const width = new CSSMathMin(CSS.em(10), CSS.px(110));
+const target = document.querySelector('#target');
+target.attributeStyleMap.set('width', width);
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-values/max-length-percent-001.html b/tests/wpt/web-platform-tests/css/css-values/max-length-percent-001.html
new file mode 100644
index 00000000000..ffb6c27db27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-values/max-length-percent-001.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS values: max() between pixel and percentage values</title>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
+<link rel="match" href="reference/200-200-green.html">
+<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
+<style>
+html, body { margin: 0px; padding: 0px; }
+#parent { width: 400px; }
+#target {
+ width: max(100px, 25% + 100px, 150px + 10%);
+ height: 200px;
+ background: green;
+}
+</style>
+<div id=parent>
+ <div id=target></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-values/min-length-percent-001.html b/tests/wpt/web-platform-tests/css/css-values/min-length-percent-001.html
new file mode 100644
index 00000000000..73069ecfe1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-values/min-length-percent-001.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS values: min() between pixel and percentage values</title>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
+<link rel="match" href="reference/200-200-green.html">
+<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
+<style>
+html, body { margin: 0px; padding: 0px; }
+#parent { width: 400px; }
+#target {
+ width: min(300px, 25% + 100px, 50px + 50%);
+ height: 200px;
+ background: green;
+}
+</style>
+<div id=parent>
+ <div id=target></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/element-timing/toJSON.html b/tests/wpt/web-platform-tests/element-timing/toJSON.html
new file mode 100644
index 00000000000..d9889347081
--- /dev/null
+++ b/tests/wpt/web-platform-tests/element-timing/toJSON.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: toJSON</title>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<img elementtiming='img' src="resources/square100.png"/>
+<script>
+ async_test(function (t) {
+ if (!window.PerformanceElementTiming) {
+ assert_unreached("PerformanceElementTiming is not implemented");
+ }
+ const observer = new PerformanceObserver(
+ t.step_func_done(function(entryList) {
+ assert_equals(entryList.getEntries().length, 1);
+ const entry = entryList.getEntries()[0];
+ assert_equals(typeof(entry.toJSON), 'function');
+ const json = entry.toJSON();
+ assert_equals(typeof(json), 'object');
+ const keys = [
+ // PerformanceEntry
+ 'name',
+ 'entryType',
+ 'startTime',
+ 'duration',
+ // PerformanceElementTiming
+ 'renderTime',
+ 'loadTime',
+ 'intersectionRect',
+ 'identifier',
+ 'naturalWidth',
+ 'naturalHeight',
+ 'id',
+ 'element',
+ 'url',
+ ];
+ for (const key of keys) {
+ assert_equals(json[key], entry[key],
+ 'PerformanceElementTiming ${key} entry does not match its toJSON value');
+ }
+ })
+ );
+ observer.observe({type: 'element', buffered: true});
+ }, 'Test toJSON() in PerformanceElementTiming.');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/event-timing/toJSON.html b/tests/wpt/web-platform-tests/event-timing/toJSON.html
new file mode 100644
index 00000000000..05a7ba76319
--- /dev/null
+++ b/tests/wpt/web-platform-tests/event-timing/toJSON.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Event Timing: toJSON</title>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<script src=resources/event-timing-test-utils.js></script>
+<button id='button'>Generate a 'click' event</button>
+<script>
+ async_test(function (t) {
+ if (!window.PerformanceEventTiming) {
+ assert_unreached("PerformanceEventTiming is not implemented");
+ }
+ const observer = new PerformanceObserver(
+ t.step_func_done(function(entryList) {
+ const entry = entryList.getEntries()[0];
+ assert_equals(typeof(entry.toJSON), 'function');
+ const json = entry.toJSON();
+ assert_equals(typeof(json), 'object');
+ const keys = [
+ // PerformanceEntry
+ 'name',
+ 'entryType',
+ 'startTime',
+ 'duration',
+ // PerformanceEventTiming
+ 'processingStart',
+ 'processingEnd',
+ 'cancelable',
+ ];
+ for (const key of keys) {
+ assert_equals(json[key], entry[key],
+ 'PerformanceEventTiming ${key} entry does not match its toJSON value');
+ }
+ })
+ );
+ observer.observe({type: 'event'});
+ clickAndBlockMain('button');
+ }, 'Test toJSON() in PerformanceEventTiming.');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html
index 7d9a31d0d40..4b81c7c44f9 100644
--- a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html
@@ -11,57 +11,63 @@
}
</style>
<div id="log"></div>
-<iframe></iframe>
<script>
'use strict';
- // The test does the following navigation steps for iframe
- // 1. load page-with-fragment.html#fragment
- // 2. load blank1
- // 3. go back to page-with-fragment.html
- async_test(function(t) {
- var iframe = document.querySelector('iframe');
- var hostInfo = get_host_info();
- var basePath = location.pathname.substring(0, location.pathname.lastIndexOf('/'));
- var localURL = hostInfo.HTTP_ORIGIN + basePath + '/resources/page-with-fragment.html#fragment';
- var remoteURL = hostInfo.HTTP_REMOTE_ORIGIN + basePath + "/resources/blank1.html"
+ var next;
+ function frameOnload() {
+ if (next) {
+ next();
+ dump("next \n");
+ } else {
+ dump("no next \n");
+ // The test does the following navigation steps for iframe
+ // 1. load page-with-fragment.html#fragment
+ // 2. load blank1
+ // 3. go back to page-with-fragment.html
+ async_test(function(t) {
+ var iframe = document.querySelector('iframe');
+ var hostInfo = get_host_info();
+ var basePath = location.pathname.substring(0, location.pathname.lastIndexOf('/'));
+ var localURL = hostInfo.HTTP_ORIGIN + basePath + '/resources/page-with-fragment.html#fragment';
+ var remoteURL = hostInfo.HTTP_REMOTE_ORIGIN + basePath + "/resources/blank1.html"
- var steps = [
- function() {
- iframe.src = 'resources/page-with-fragment.html#fragment';
- }, function() {
- assert_equals(iframe.contentWindow.location.href, localURL, 'should be on page-with-fragment page');
- // wait one animation frame to ensure layout is run and fragment scrolling is complete
- iframe.contentWindow.requestAnimationFrame(function() {
- assert_equals(iframe.contentWindow.scrollY, 800, 'should scroll to fragment');
+ var steps = [
+ function() {
+ assert_equals(iframe.contentWindow.location.href, localURL, 'should be on page-with-fragment page');
+ // wait one animation frame to ensure layout is run and fragment scrolling is complete
+ iframe.contentWindow.requestAnimationFrame(function() {
+ assert_approx_equals(iframe.contentWindow.scrollY, 800, 5, 'should scroll to fragment');
- iframe.contentWindow.history.scrollRestoration = 'manual';
- assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual');
- setTimeout(next, 0);
- });
- }, function() {
- // navigate to a new page from a different origin
- iframe.src = remoteURL;
- }, function() {
- // going back causes the iframe to traverse back
- history.back();
- }, function() {
- // coming back from history, scrollRestoration should be set to manual and respected
- assert_equals(iframe.contentWindow.location.href, localURL, 'should be back on page-with-fragment page');
- iframe.contentWindow.requestAnimationFrame(t.step_func_done(function() {
- assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value');
- assert_equals(iframe.contentWindow.scrollX, 0, 'should not scroll to fragment');
- assert_equals(iframe.contentWindow.scrollY, 0, 'should not scroll to fragment');
- }));
- }
- ];
-
- var stepCount = 0;
- var next = t.step_func(function() {
- steps[stepCount++]();
- });
+ iframe.contentWindow.history.scrollRestoration = 'manual';
+ assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual');
+ setTimeout(next, 0);
+ });
+ }, function() {
+ // navigate to a new page from a different origin
+ iframe.src = remoteURL;
+ }, function() {
+ // going back causes the iframe to traverse back
+ history.back();
+ }, function() {
+ // coming back from history, scrollRestoration should be set to manual and respected
+ assert_equals(iframe.contentWindow.location.href, localURL, 'should be back on page-with-fragment page');
+ iframe.contentWindow.requestAnimationFrame(t.step_func_done(function() {
+ assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value');
+ assert_equals(iframe.contentWindow.scrollX, 0, 'should not scroll to fragment');
+ assert_equals(iframe.contentWindow.scrollY, 0, 'should not scroll to fragment');
+ }));
+ }
+ ];
- iframe.onload = next;
- next();
- }, 'Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation');
+ var stepCount = 0;
+ next = t.step_func(function() {
+ steps[stepCount++]();
+ });
+ next();
+ }, 'Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation');
+ }
+ }
</script>
+<iframe src="resources/page-with-fragment.html#fragment" onload="frameOnload()"></iframe>
+
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 00000000000..16179eb0133
--- /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 00000000000..aa4cf969d9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/blob.https.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/common/utils.js"></script>
+<div id=log></div>
+<script>
+const origins = get_host_info();
+[
+ {
+ "origin": origins.HTTPS_ORIGIN,
+ "crossOrigin": origins.HTTPS_REMOTE_ORIGIN
+ },
+ {
+ "origin": origins.HTTPS_REMOTE_ORIGIN,
+ "crossOrigin": origins.HTTPS_NOTSAMESITE_ORIGIN
+ },
+ {
+ "origin": origins.HTTPS_NOTSAMESITE_ORIGIN,
+ "crossOrigin": origins.HTTPS_ORIGIN
+ }
+].forEach(({ origin, crossOrigin }) => {
+ ["subframe", "navigate"].forEach(variant => {
+ async_test(t => {
+ const id = token();
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => { frame.remove(); });
+ const path = new URL("resources/blob-url-factory.html", window.location).pathname;
+ frame.src = `${origin}${path}?id=${id}&variant=${variant}&crossOrigin=${crossOrigin}`;
+ window.addEventListener("message", t.step_func(({ data }) => {
+ if (data.id !== id) {
+ return;
+ }
+ assert_equals(data.origin, origin);
+ assert_true(data.sameOriginNoCORPSuccess, "Same-origin without CORP did not succeed");
+ assert_true(data.crossOriginNoCORPFailure, "Cross-origin without CORP did not fail");
+ t.done();
+ }));
+ document.body.append(frame);
+ }, `Cross-Origin-Embedder-Policy and blob: URL from ${origin} in subframe via ${variant}`);
+ });
+});
+</script>
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 00000000000..6604450991a
--- /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 00000000000..c34f1336c8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/data.https.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/script-factory.js"></script>
+<div id=log></div>
+<script>
+async_test(t => {
+ window.addEventListener("message", t.step_func_done(({ data }) => {
+ assert_equals(data.id, "");
+ assert_equals(data.origin, "null");
+ assert_false(data.sameOriginNoCORPSuccess); // This is effectively a no-op for this test
+ assert_true(data.crossOriginNoCORPFailure, "Cross-origin without CORP did not fail");
+ }));
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ frame.src = `data:text/html,${createScript("null", window.origin)}`;
+ document.body.append(frame);
+}, "Cross-Origin-Embedder-Policy and data: URLs");
+</script>
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 00000000000..6604450991a
--- /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 00000000000..7fed1fe5819
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/non-initial-about-blank.https.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(t => {
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ let i = 0;
+ frame.onload = t.step_func(() => {
+ i++;
+ assert_equals(frame.contentDocument.URL, "about:blank");
+ frame.src = "about:blank";
+ if (i == 2) {
+ t.done();
+ }
+ });
+ document.body.append(frame);
+}, "Cross-Origin-Embedder-Policy and about:blank");
+</script>
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 00000000000..6604450991a
--- /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 00000000000..b1bb6fefc6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/none.https.html
@@ -0,0 +1,79 @@
+<!doctype html>
+<meta name="timeout" content="long">
+<title>Cross-Origin-Embedder-Policy header and nested navigable resource without such header</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/utils.js></script> <!-- Use token() to allow running tests in parallel -->
+<div id=log></div>
+<script>
+async_test(t => {
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ frame.onload = t.step_func_done(() => {
+ assert_not_equals(frame.contentDocument, null);
+ });
+ frame.src = "/common/blank.html";
+ document.body.append(frame);
+ assert_equals(frame.contentDocument.body.localName, "body");
+}, `"none" top-level: navigating a frame to "none" should succeed`);
+
+async_test(t => {
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ const blank = "/common/blank.html";
+ let firstNavOk = false;
+ frame.onload = t.step_func(() => {
+ if (!firstNavOk) {
+ assert_not_equals(frame.contentDocument, null);
+ firstNavOk = true;
+ } else {
+ assert_not_equals(frame.contentDocument, null);
+ assert_equals(frame.contentWindow.location.pathname, blank);
+ t.done();
+ }
+ });
+ frame.src = `resources/navigate-require-corp.sub.html?to=${blank}`;
+ document.body.append(frame);
+ assert_equals(frame.contentDocument.body.localName, "body");
+}, `"none" top-level: navigating a frame from "require-corp" to "none" should succeed`);
+
+async_test(t => {
+ const w = window.open(`resources/navigate-none.sub.html?to=navigate-require-corp.sub.html`, "window_name");
+ t.add_cleanup(() => w.close());
+
+ t.step_timeout(() => {
+ w.history.back();
+ t.step_timeout(() => {
+ assert_not_equals(w.document, null);
+ t.done();
+ }, 500);
+ }, 500);
+}, `"none" top-level: navigating a frame back from "require-corp" should succeed`);
+
+async_test(t => {
+ let pageLoaded = false;
+ const bc = new BroadcastChannel(token());
+ let finished = false;
+ bc.onmessage = t.step_func((event) => {
+ pageLoaded = true;
+ let payload = event.data;
+ assert_equals(payload, "loaded");
+ });
+
+ const bc2 = new BroadcastChannel(token());
+ bc2.onmessage = t.step_func((event) => {
+ finished = true;
+ let payload = event.data;
+ assert_equals(payload, "loaded");
+ });
+
+ const win = window.open(`resources/navigate-require-corp.sub.html?channelName=${bc.name}&to=navigate-none.sub.html?channelName=${bc2.name}`, "_blank", "noopener");
+ assert_equals(win, null);
+
+ t.step_timeout(() => {
+ assert_true(pageLoaded);
+ assert_true(finished);
+ t.done();
+ }, 500);
+}, `"require-corp" top-level noopener popup: navigating to "none" should succeed`);
+</script>
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 00000000000..43c44cffd64
--- /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 00000000000..0bd6aab7295
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/require-corp.https.html
@@ -0,0 +1,138 @@
+<!doctype html>
+<meta name="timeout" content="long">
+<title>Cross-Origin-Embedder-Policy header and nested navigable resource without such header</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/common/utils.js"></script> <!-- Use token() to allow running tests in parallel -->
+<div id=log></div>
+<script>
+async_test(t => {
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ t.step_timeout(() => {
+ // Make sure the iframe didn't load. See https://github.com/whatwg/html/issues/125 for why a
+ // timeout is used here. Long term all network error handling should be similar and have a
+ // reliable event.
+ assert_equals(frame.contentDocument, null);
+ t.done();
+ }, 500);
+ frame.src = "/common/blank.html";
+ document.body.append(frame);
+ assert_equals(frame.contentDocument.body.localName, "body");
+}, `"require-corp" top-level: navigating a frame to "none" should fail`);
+
+async_test(t => {
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ const bc = new BroadcastChannel(token());
+ bc.onmessage = t.step_func((event) => {
+ assert_not_equals(frame.contentDocument, null);
+ let payload = event.data;
+ assert_equals(payload, "loaded");
+ t.step_timeout(() => {
+ assert_equals(frame.contentDocument, null);
+ t.done();
+ }, 500);
+ });
+ frame.src = `resources/navigate-require-corp.sub.html?channelName=${bc.name}&to=/common/blank.html`;
+ document.body.append(frame);
+ assert_equals(frame.contentDocument.body.localName, "body");
+}, `"require-corp" top-level: navigating a frame from "require-corp" to "none" should fail`);
+
+async_test(t => {
+ let pageLoaded = false;
+ const bc = new BroadcastChannel(token());
+ let finished = false;
+ bc.onmessage = t.step_func((event) => {
+ let payload = event.data;
+ assert_equals(payload, "loaded");
+ pageLoaded = true;
+ });
+
+ const bc2 = new BroadcastChannel(token());
+ bc2.onmessage = t.step_func_done((event) => {
+ let payload = event.data;
+ assert_equals(payload, "loaded");
+ assert_equals(pageLoaded, true);
+ });
+
+ const win = window.open(`resources/navigate-none.sub.html?channelName=${bc.name}&to=navigate-none.sub.html?channelName=${bc2.name}`, "_blank", "noopener");
+ assert_equals(win, null);
+}, `"require-corp" top-level: creating a noopener "none" popup should succeed`);
+
+async_test(t => {
+ let pageLoaded = false;
+ const bc = new BroadcastChannel(token());
+ bc.onmessage = t.step_func_done((event) => {
+ pageLoaded = true;
+ let payload = event.data;
+ assert_equals(payload, "loaded");
+ });
+
+ const win = window.open(`resources/navigate-none.sub.html?channelName=${bc.name}&to=/common/blank.html`, "_blank");
+ t.add_cleanup(() => win.close());
+ t.step_timeout(() => {
+ assert_equals(pageLoaded, true);
+ t.done();
+ }, 500);
+}, `"require-corp" top-level: creating a "none" popup should succeed.`);
+
+[
+ {
+ "name": "",
+ "title": "as popup"
+ },
+ {
+ "name": "noopener",
+ "title": "as noopener popup"
+ },
+ {
+ "name": "clear opener",
+ "title": "as popup with opener set to null"
+ }
+].forEach(({name, title}) => {
+ async_test(t => {
+ let pageLoaded = false;
+ const bc = new BroadcastChannel(token());
+ bc.onmessage = t.step_func(event => {
+ pageLoaded = true;
+ const payload = event.data;
+ assert_equals(payload, "loaded");
+ });
+
+ const bc2 = new BroadcastChannel(token());
+ bc2.onmessage = t.step_func_done(event => {
+ const payload = event.data;
+ assert_equals(payload, "loaded");
+ assert_equals(pageLoaded, true);
+ });
+
+ let clearOpener = "";
+ if (name === "clear opener") {
+ clearOpener = "&clearOpener=true"
+ }
+
+ let noopener = undefined;
+ if (name === "noopener") {
+ noopener = "noopener"
+ }
+
+ const win = window.open(`resources/navigate-require-corp.sub.html?channelName=${bc.name}${clearOpener}&to=navigate-none.sub.html?channelName=${bc2.name}`, "_blank", noopener);
+ if (name === "noopener") {
+ assert_equals(win, null);
+ } else {
+ t.add_cleanup(() => win.close());
+ }
+ }, `"require-corp" top-level (${title}): navigating to "none" should succeed`);
+});
+
+promise_test(async t => {
+ const response = await fetch(get_host_info().HTTPS_REMOTE_ORIGIN+"/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt", {mode: "no-cors"});
+ assert_equals(response.type, "opaque");
+}, `"require-corp" top-level: fetch() to CORP: cross-origin response should succeed`);
+
+promise_test(t => {
+ return promise_rejects(t, new TypeError(), fetch(get_host_info().HTTPS_REMOTE_ORIGIN+"/common/blank.html", {mode: "no-cors"}));
+}, `"require-corp" top-level: fetch() to response without CORP should fail`);
+</script>
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 00000000000..6604450991a
--- /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 00000000000..7d90aacd8bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/blob-url-factory.html
@@ -0,0 +1,17 @@
+<body>
+<script src="script-factory.js"></script>
+<script>
+const query = new URLSearchParams(window.location.search);
+const id = query.get("id");
+const variant = query.get("variant");
+const parent = (variant === "subframe") ? "parent.parent" : "parent";
+const blob = new Blob([createScript(window.origin, query.get("crossOrigin"), parent, id)], { type: "text/html" });
+const blobURL = URL.createObjectURL(blob);
+if (variant === "subframe") {
+ const frame = document.createElement("iframe");
+ frame.src = blobURL;
+ document.body.append(frame);
+} else {
+ window.location = blobURL;
+}
+</script>
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 00000000000..4e798cd9f5d
--- /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
index 1008f70ff12..1008f70ff12 100644
--- 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
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
index d4b38bc1a10..d4b38bc1a10 100644
--- 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
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 00000000000..6604450991a
--- /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 00000000000..e61d8ee36c9
--- /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 00000000000..1b88136c01c
--- /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 00000000000..b9ba801f78e
--- /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 00000000000..30ddeac2e7a
--- /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 00000000000..9db75522602
--- /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 <script> element that is useful for blob/data/srcdoc-style tests.
+
+function createScript(sameOrigin, crossOrigin, parent="parent", id="") {
+ return `<script>
+const data = { id: "${id}",
+ origin: window.origin,
+ sameOriginNoCORPSuccess: false,
+ crossOriginNoCORPFailure: false };
+function record(promise, token, expectation) {
+ return promise.then(() => data[token] = expectation, () => data[token] = !expectation);
+}
+
+const records = [
+ record(fetch("${crossOrigin}/common/blank.html", { mode: "no-cors" }), "crossOriginNoCORPFailure", false)
+];
+
+if ("${sameOrigin}" !== "null") {
+ records.push(record(fetch("${sameOrigin}/common/blank.html", { mode: "no-cors" }), "sameOriginNoCORPSuccess", true));
+}
+
+Promise.all(records).then(() => window.${parent}.postMessage(data, "*"));
+<\/script>`;
+}
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/sandbox.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/sandbox.https.html
new file mode 100644
index 00000000000..1e3f80a9186
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/sandbox.https.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<div id=log></div>
+<script>
+async_test(t => {
+ window.addEventListener("message", t.step_func_done(({ data }) => {
+ assert_equals(data.origin, "null");
+ assert_true(data.sameOriginWithoutCORP, "Request to same-origin resource without CORP did not fail");
+ assert_true(data.sameOriginWithSameOriginCORP, "Request to same-origin resource with same-origin CORP did not fail");
+ assert_true(data.sameOriginWithCrossOriginCORP, "Request to same-origin resource with cross-origin CORP did not succeed");
+ assert_true(data.crossOriginWithCrossOriginCORP, "Request to cross-origin resource with cross-origin CORP did not succeed");
+ }));
+
+ const origins = get_host_info();
+ const frame = document.createElement("iframe");
+ const nothingCrossOriginCORP = new URL("resources/nothing-cross-origin-corp.txt", window.location).pathname;
+ const nothingSameOriginCORP = new URL("resources/nothing-same-origin-corp.txt", window.location).pathname;
+ frame.sandbox = "allow-scripts";
+ frame.srcdoc = `<script>
+const data = { sameOriginWithoutCORP: false,
+ sameOriginWithSameOriginCORP: false,
+ sameOriginWithCrossOriginCORP: false,
+ crossOriginWithCrossOriginCORP: false,
+ origin: self.origin };
+function record(promise, token, expectation) {
+ return promise.then(() => data[token] = expectation, () => data[token] = !expectation);
+}
+Promise.all([
+ record(fetch("/common/blank.html", { mode: "no-cors" }), "sameOriginWithoutCORP", false),
+ record(fetch("${nothingSameOriginCORP}", { mode: "no-cors" }), "sameOriginWithSameOriginCORP", false),
+ record(fetch("${nothingCrossOriginCORP}", { mode: "no-cors" }), "sameOriginWithCrossOriginCORP", true),
+ record(fetch("${origins.HTTPS_NOTSAMESITE_ORIGIN}${nothingCrossOriginCORP}", { mode: "no-cors" }), "crossOriginWithCrossOriginCORP", true)
+]).then(() => parent.postMessage(data, "*"));
+<\/script>`;
+ document.body.append(frame);
+}, "Cross-Origin-Embedder-Policy and sandbox");
+</script>
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 00000000000..6604450991a
--- /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 00000000000..3fbba961b27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/srcdoc.https.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/script-factory.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<div id=log></div>
+<script>
+async_test(t => {
+ window.addEventListener("message", t.step_func_done(({ data }) => {
+ assert_equals(data.id, "");
+ assert_equals(data.origin, window.origin);
+ assert_true(data.sameOriginNoCORPSuccess, "Same-origin without CORP did not succeed");
+ assert_true(data.crossOriginNoCORPFailure, "Cross-origin without CORP did not fail");
+ }));
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ frame.srcdoc = createScript(window.origin, get_host_info().HTTPS_NOTSAMESITE_ORIGIN);
+ document.body.append(frame);
+}, "Cross-Origin-Embedder-Policy and srcdoc");
+</script>
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 00000000000..6604450991a
--- /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 00000000000..3f080c82d25
--- /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 00000000000..717122b4b2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: a navigating popup</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/common.js"></script>
+<script>
+[
+ {
+ "title": "coop/coep",
+ "coop": "same-origin",
+ "coep": "require-corp",
+ "opener": true
+ },
+ {
+ "title": "no coop/coep",
+ "coop": "",
+ "coep": "require-corp",
+ "opener": false
+ },
+ {
+ "title": "coop/no coep",
+ "coop": "same-origin",
+ "coep": "",
+ "opener": false
+ },
+ {
+ "title": "no coop/no coep",
+ "coop": "",
+ "coep": "",
+ "opener": false
+ },
+ {
+ "title": "coop unsafe-inherit/coep",
+ "coop": "unsafe-inherit",
+ "coep": "require-corp",
+ "opener": true
+ },
+ {
+ "title": "coop unsafe-inherit/no coep",
+ "coop": "unsafe-inherit",
+ "coep": "",
+ "opener": false
+ }
+].forEach(variant => {
+ ["same-origin", "same-site"].forEach(site => {
+ const title = `Popup navigating to ${site} with ${variant.title}`;
+ const channel = title.replace(/ /g,"-");
+ const navigateHost = site === "same-origin" ? SAME_ORIGIN : SAME_SITE;
+ const navigateURL = `${navigateHost.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=${variant.coop}&coep=${variant.coep}&channel=${channel}`;
+ const opener = site === "same-origin" ? variant.opener : false;
+
+ async_test(t => {
+ // For each test we open a COOP: same-origin/COEP: require-corp document in a popup and then
+ // navigate that to either a same-origin or same-site document whose COOP and COEP are set as
+ // per the top-most array. We then verify that this document has the correct opener for its
+ // specific setup.
+ url_test(t, `${SAME_ORIGIN.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=same-origin&coep=require-corp&navigate=${encodeURIComponent(navigateURL)}`, channel, opener);
+ }, title);
+ });
+});
+</script>
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 00000000000..63b60e490f4
--- /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 00000000000..73f07ddef88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep-redirect.https.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: redirects</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/common.js"></script>
+<script>
+const coopCOEPPath = new URL("resources/coop-coep.py", window.location).pathname;
+
+[
+ {
+ "title": "coop/coep to coop/coep",
+ "redirectCOOP": "same-origin",
+ "redirectCOEP": "require-corp",
+ "coop": "same-origin",
+ "coep": "require-corp",
+ "opener": true
+ },
+ {
+ "title": "coop/coep to no coop/coep",
+ "redirectCOOP": "same-origin",
+ "redirectCOEP": "require-corp",
+ "coop": "",
+ "coep": "require-corp",
+ "opener": false
+ },
+ {
+ "title": "no coop/no coep to coop/coep",
+ "redirectCOOP": "",
+ "redirectCOEP": "",
+ "coop": "same-origin",
+ "coep": "require-corp",
+ "opener": false
+ },
+ {
+ "title": "coop/no coep to coop/coep",
+ "redirectCOOP": "same-origin",
+ "redirectCOEP": "",
+ "coop": "same-origin",
+ "coep": "require-corp",
+ "opener": false
+ },
+ {
+ "title": "coop unsafe-inherit/coep to coop/coep",
+ "redirectCOOP": "unsafe-inherit",
+ "redirectCOEP": "require-corp",
+ "coop": "same-origin",
+ "coep": "require-corp",
+ "opener": true
+ },
+ {
+ "title": "coop unsafe-inherit/coep to coop unsafe-inherit/coep",
+ "redirectCOOP": "unsafe-inherit",
+ "redirectCOEP": "require-corp",
+ "coop": "unsafe-inherit",
+ "coep": "require-corp",
+ "opener": true
+ }
+].forEach(variant => {
+ const title = `Redirect from ${variant.title}`;
+ async_test(t => {
+ const channel = title.replace(/ /g,"-");
+ const redirectLocation = `${SAME_ORIGIN.origin}${coopCOEPPath}?coop=${variant.coop}&coep=${variant.coep}&channel=${channel}`;
+ url_test(t, `${SAME_ORIGIN.origin}${coopCOEPPath}?coop=${variant.redirectCOOP}&coep=${variant.redirectCOEP}&redirect=${encodeURIComponent(redirectLocation)}`, channel, variant.opener);
+ }, title);
+});
+</script>
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 00000000000..63b60e490f4
--- /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 00000000000..1c04ed30dd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coep.https.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/common.js"></script>
+<script>
+[
+ {
+ "title": "popup with coop/coep",
+ "coop": "same-origin",
+ "coep": "require-corp",
+ "opener": true
+ },
+ {
+ "title": "popup with coop unsafe-inherit/coep",
+ "coop": "unsafe-inherit",
+ "coep": "require-corp",
+ "opener": true
+ },
+ {
+ "title": "popup with coop unsafe-inherit without coep",
+ "coop": "unsafe-inherit",
+ "coep": "",
+ "opener": false
+ },
+ {
+ "title": "popup without coep",
+ "coop": "same-origin",
+ "coep": "",
+ "opener": false
+ }
+].forEach(variant => {
+ async_test(t => {
+ coop_coep_test(t, SAME_ORIGIN, variant.coop, variant.coep, variant.title.replace(/ /g,"-"), variant.opener);
+ }, `Same-origin ${variant.title}`);
+
+ // This seems useful to test, CROSS_SITE is probably too redundant though.
+ async_test(t => {
+ coop_coep_test(t, SAME_SITE, variant.coop, variant.coep, `same-site-${variant.title.replace(/ /g,"-")}`, false);
+ }, `Same-site ${variant.title}`);
+});
+</script>
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 00000000000..63b60e490f4
--- /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 00000000000..0b51512c221
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>Cross-Origin-Opener-Policy: a navigated popup</title>
+<!-- In particular this is different from coep-navigate-popup.https.html as this document initiates
+ the navigation (and uses unsafe-allow-outgoing and no COEP as without that it cannot be
+ observed). COOP should work identically, but implementations might have used the wrong
+ authority. -->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/utils.js"></script> <!-- Use token() to allow running tests in parallel -->
+<script>
+async_test(t => {
+ const noCOOP = "/common/blank.html";
+ const popupName = token();
+ const popup = window.open(noCOOP, popupName);
+ t.add_cleanup(() => popup.close());
+ popup.onload = t.step_func(() => {
+ assert_equals(popup.name, popupName);
+ assert_equals(new URL(popup.document.URL).pathname, noCOOP);
+ const channel = new BroadcastChannel(token());
+ channel.onmessage = t.step_func_done(event => {
+ const payload = event.data;
+ assert_equals(payload.name, "");
+ assert_false(payload.opener);
+ });
+ const coop = `resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}`;
+ popup.location = coop;
+ });
+}, "Open a popup to a document without COOP, then navigate it to a document with");
+</script>
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
index a19f4400cea..a19f4400cea 100644
--- 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
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 00000000000..e471b1eda2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>Sandboxed Cross-Origin-Opener-Policy popup should result in a network error</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/utils.js"></script> <!-- Use token() to allow running tests in parallel -->
+<div id=log>
+<script>
+async_test(t => {
+ const frame = document.createElement("iframe");
+ const channel = new BroadcastChannel(token());
+ channel.onmessage = t.unreached_func("A COOP popup was created from a sandboxed frame");
+ t.add_cleanup(() => frame.remove());
+ frame.sandbox = "allow-popups allow-scripts allow-same-origin";
+ frame.srcdoc = `<script>
+const popup = window.open("resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}");
+<\/script>`;
+ document.body.append(frame);
+ t.step_timeout(() => {
+ t.done()
+ }, 500);
+});
+</script>
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
index 46ad58d83bf..46ad58d83bf 100644
--- 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
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 00000000000..da9efdce777
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/no-https.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta name="timeout" content="long">
+<title>Cross-Origin-Opener-Policy requires secure contexts</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+async_test(t => {
+ const popup = window.open("/common/blank.html");
+ assert_equals(window, popup.opener);
+
+ t.step_timeout(() => {
+ assert_false(popup.closed);
+ assert_equals(popup.location.pathname, "/common/blank.html");
+ popup.close();
+ t.done();
+ }, 500);
+}, "Cross-Origin-Opener-Policy only works over secure contexts");
+</script>
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 00000000000..46ad58d83bf
--- /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
index 35a42fd2f09..62633457d3f 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 @@
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
-
-<script src="common.sub.js"></script>
+<script src="resources/common.js"></script>
<div id=log></div>
<script>
@@ -33,6 +32,6 @@ let tests = [
[CROSS_ORIGIN, "same-origin unsafe-allow-outgoing", false],
];
-run_coop_tests("null", tests);
+run_coop_tests("none", tests);
</script>
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 00000000000..65ec3b26aa0
--- /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 @@
+<!doctype html>
+<title>Cross-Origin-Opener-Policy: about:blank</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+async_test(t => {
+ const popup = window.open("resources/coop-coep.py?coop=same-origin&coep=&navigate=about:blank");
+ assert_equals(window, popup.opener);
+ t.step_timeout(() => {
+ assert_equals(popup.location.href, "about:blank");
+ popup.close();
+ t.done();
+ }, 500);
+}, "Navigating a popup to about:blank");
+</script>
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 00000000000..46ad58d83bf
--- /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
index bbd55130d7a..2f8ebc3be3f 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 @@
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
-
-<script src="common.sub.js"></script>
+<script src="resources/common.js"></script>
<div id=log></div>
<script>
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.headers
new file mode 100644
index 00000000000..a19f4400cea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin-unsafe-allow-outgoing.https.html.headers
@@ -0,0 +1 @@
+Cross-Origin-Opener-Policy: same-origin unsafe-allow-outgoing
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin.tentative.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin.https.html
index 6bbb37cafca..964011ff762 100644
--- a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_origin.tentative.html
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin.https.html
@@ -3,8 +3,7 @@
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
-
-<script src="common.sub.js"></script>
+<script src="resources/common.js"></script>
<div id=log></div>
<script>
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin.https.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin.https.html.headers
new file mode 100644
index 00000000000..46ad58d83bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-origin.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_site_unsafe_allow_outgoing.tentative.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html
index d81506f434b..18ee909d186 100644
--- a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html
@@ -3,8 +3,7 @@
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
-
-<script src="common.sub.js"></script>
+<script src="resources/common.js"></script>
<div id=log></div>
<script>
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.headers
index ab7b2894815..ab7b2894815 100644
--- a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site_unsafe_allow_outgoing.tentative.html.headers
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site-unsafe-allow-outgoing.https.html.headers
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site.tentative.html b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site.https.html
index e1efac12d02..9a0db2765da 100644
--- a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site.tentative.html
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site.https.html
@@ -3,8 +3,7 @@
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
-
-<script src="common.sub.js"></script>
+<script src="resources/common.js"></script>
<div id=log></div>
<script>
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site.tentative.html.headers b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site.https.html.headers
index 34bd099a302..34bd099a302 100644
--- a/tests/wpt/web-platform-tests/html/cross-origin-opener/new_window_same_site.tentative.html.headers
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/popup-same-site.https.html.headers
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/common.js b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/common.js
new file mode 100644
index 00000000000..b60093f1c62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/common.js
@@ -0,0 +1,36 @@
+const SAME_ORIGIN = {origin: get_host_info().HTTPS_ORIGIN, name: "SAME_ORIGIN"};
+const SAME_SITE = {origin: get_host_info().HTTPS_REMOTE_ORIGIN, name: "SAME_SITE"};
+const CROSS_ORIGIN = {origin: get_host_info().HTTPS_NOTSAMESITE_ORIGIN, name: "CROSS_ORIGIN"}
+
+function url_test(t, url, channelName, hasOpener) {
+ const bc = new BroadcastChannel(channelName);
+ bc.onmessage = t.step_func_done(event => {
+ const payload = event.data;
+ assert_equals(payload.name, hasOpener ? channelName : "");
+ assert_equals(payload.opener, hasOpener);
+ });
+
+ const w = window.open(url, channelName);
+
+ // w will be closed by its postback iframe. When out of process,
+ // window.close() does not work.
+ t.add_cleanup(() => w.close());
+}
+
+function coop_coep_test(t, host, coop, coep, channelName, hasOpener) {
+ url_test(t, `${host.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=${encodeURIComponent(coop)}&coep=${coep}&channel=${channelName}`, channelName, hasOpener);
+}
+
+function coop_test(t, host, coop, channelName, hasOpener) {
+ coop_coep_test(t, host, coop, "", channelName, hasOpener);
+}
+
+function run_coop_tests(documentCOOPValueTitle, testArray) {
+ for (const test of tests) {
+ async_test(t => {
+ coop_test(t, test[0], test[1],
+ `${mainTest}_to_${test[0].name}_${test[1].replace(/ /g,"-")}`,
+ test[2]);
+ }, `${documentCOOPValueTitle} document opening popup to ${test[0].origin} with COOP: "${test[1]}"`);
+ }
+}
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/coop-coep.py b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/coop-coep.py
new file mode 100644
index 00000000000..8b12341be73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/coop-coep.py
@@ -0,0 +1,35 @@
+def main(request, response):
+ coop = request.GET.first("coop")
+ coep = request.GET.first("coep")
+ redirect = request.GET.first("redirect", None)
+ if coop != "":
+ response.headers.set("Cross-Origin-Opener-Policy", coop)
+ if coep != "":
+ response.headers.set("Cross-Origin-Embedder-Policy", coep)
+
+ if redirect != None:
+ response.status = 302
+ response.headers.set("Location", redirect)
+ return
+
+ # This uses an <iframe> as BroadcastChannel is same-origin bound.
+ response.content = """
+<!doctype html>
+<meta charset=utf-8>
+<script src="/common/get-host-info.sub.js"></script>
+<iframe></iframe>
+<script>
+ const navigate = new URL(location).searchParams.get("navigate");
+ if (navigate !== null) {
+ self.location = navigate;
+ } else {
+ const iframe = document.querySelector("iframe");
+ iframe.onload = () => {
+ const payload = { name: self.name, opener: !!self.opener };
+ iframe.contentWindow.postMessage(payload, "*");
+ };
+ const channelName = new URL(location).searchParams.get("channel");
+ iframe.src = `${get_host_info().HTTPS_ORIGIN}/html/cross-origin-opener-policy/resources/postback.html?channel=${channelName}`;
+ }
+</script>
+"""
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 00000000000..cf3c93bbe1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-opener-policy/resources/postback.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf-8>
+<script>
+const channelName = new URL(location).searchParams.get("channel");
+const bc = new BroadcastChannel(channelName);
+window.addEventListener("message", event => {
+ bc.postMessage(event.data);
+ window.parent.close();
+});
+</script>
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 00000000000..6604450991a
--- /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 a73a95aba86..00000000000
--- 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 b24d6d55a9a..00000000000
--- 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 ee08bab4d55..00000000000
--- a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/postback.sub.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-
-<script>
-
-let channelName = new URL(location).searchParams.get("channel");
-let bc = new BroadcastChannel(channelName);
-window.addEventListener("message", (event) => {
- bc.postMessage(event.data);
- window.parent.close();
-}, false);
-
-</script>
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 524efe2588d..00000000000
--- a/tests/wpt/web-platform-tests/html/cross-origin-opener/resources/window.sub.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-
-<script src="/common/get-host-info.sub.js"></script>
-
-<script type="text/javascript">
-
- window.addEventListener('load', function() {
- let iframe = document.createElement("iframe");
- iframe.onload = () => {
- let payload = { name: self.name, opener: !!self.opener };
- iframe.contentWindow.postMessage(payload, "*");
- };
- let channelName = new URL(location).searchParams.get("channel");
- iframe.src = `${get_host_info().HTTP_ORIGIN}/html/cross-origin-opener/resources/postback.sub.html?channel=${channelName}`;
- document.body.appendChild(iframe);
- });
-</script>
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 34bd099a302..00000000000
--- 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 ef9b9bb7b87..00000000000
--- a/tests/wpt/web-platform-tests/html/cross-origin/anonymous.tentative.html
+++ /dev/null
@@ -1,219 +0,0 @@
-<!doctype html>
-<meta name="timeout" content="long">
-<title>Cross-Origin header and nested navigable resource without such header</title>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src="/common/get-host-info.sub.js"></script>
-<div id=log></div>
-<script>
-async_test(t => {
- const frame = document.createElement("iframe");
- t.step_timeout(() => {
- // Make sure the iframe didn't load.
- assert_equals(frame.contentDocument, null);
- t.done();
- }, 500);
- frame.src = "/common/blank.html";
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with anonymous policy: navigating a frame to a null policy should fail.");
-
-async_test(t => {
- const frame = document.createElement("iframe");
-
- const CHANNEL_NAME = "frame-anon-to-blank";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- bc.onmessage = t.step_func((event) => {
- assert_not_equals(frame.contentDocument, null);
- let payload = event.data;
- assert_equals(payload, "loaded");
- t.step_timeout(() => {
- assert_equals(frame.contentDocument, null, "Navigation to null policy should fail");
- t.done();
- }, 1500);
- });
-
- frame.src = `resources/navigate_anonymous.sub.html?channelName=${CHANNEL_NAME}&to=/common/blank.html`;
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with anonymous policy: navigating a frame from an anonymous policy to a null policy should fail.");
-
-
-async_test(t => {
- const frame = document.createElement("iframe");
-
- const CHANNEL_NAME = "frame-usecredentials-to-blank";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- bc.onmessage = t.step_func((event) => {
- assert_not_equals(frame.contentDocument, null);
- let payload = event.data;
- assert_equals(payload, "loaded");
- t.step_timeout(() => {
- assert_equals(frame.contentDocument, null, "Navigation to null policy should fail");
- t.done();
- }, 1500);
- });
- frame.src = `resources/navigate_usecredentials.sub.html?channelName=${CHANNEL_NAME}&to=/common/blank.html`;
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with anonymous policy: navigating a frame from a use-credentials policy to a null policy should fail.");
-
-async_test(t => {
- let pageLoaded = false;
- const CHANNEL_NAME = "anon-null-window-noopener";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- let finished = false;
- bc.onmessage = t.step_func((event) => {
- let payload = event.data;
- assert_equals(payload, "loaded");
- pageLoaded = true;
- });
-
- const SECOND_CHANNEL = "anon-null-window-noopener-second";
- let bc2 = new BroadcastChannel(SECOND_CHANNEL);
- bc2.onmessage = t.step_func_done((event) => {
- let payload = event.data;
- assert_equals(payload, "loaded");
- assert_equals(pageLoaded, true, "Opening a null window (noopener) from anon window should work");
- });
-
- let win = window.open(`resources/navigate_null.sub.html?channelName=${CHANNEL_NAME}&to=navigate_null.sub.html?channelName=${SECOND_CHANNEL}`, "_blank", "noopener");
-}, "Top-level with anonymous policy: creating a noopener popup with null policy should work.");
-
-async_test(t => {
- let pageLoaded = false;
- const CHANNEL_NAME = "anon-null-window";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- bc.onmessage = t.step_func_done((event) => {
- pageLoaded = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- let win = window.open(`resources/navigate_null.sub.html?channelName=${CHANNEL_NAME}&to=/common/blank.html`, "_blank");
- t.add_cleanup(() => win.close());
- t.step_timeout(() => {
- assert_equals(pageLoaded, false, "Opening a null window from anon window should fail");
- t.done();
- }, 500);
-}, "Top-level with anonymous policy: creating a popup with null policy should fail.");
-
-async_test(t => {
- let pageLoaded = false;
- const CHANNEL_NAME = "anon-null-top-navigation";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- bc.onmessage = t.step_func((event) => {
- pageLoaded = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- const SECOND_CHANNEL = "anon-null-top-navigation-final";
- let bc2 = new BroadcastChannel(SECOND_CHANNEL);
- bc2.onmessage = t.step_func_done((event) => {
- let payload = event.data;
- assert_equals(payload, "loaded");
- assert_equals(pageLoaded, true, "Opening a null window (noopener) from anon window should work");
- });
-
- let win = window.open(`resources/navigate_anonymous.sub.html?channelName=${CHANNEL_NAME}&to=navigate_null.sub.html?channelName=${SECOND_CHANNEL}`, "_blank", "noopener");
-
-}, "Top-level noopener with anonymous policy: navigating to a different policy should work");
-
-promise_test(t => {
- let host_info = get_host_info();
- return fetch(host_info.HTTP_REMOTE_ORIGIN+"/html/cross-origin/resources/nothing.txt",
- {"mode": "no-cors", "method": "GET", "headers":{}}).then(r => {
- assert_equals(r.type, "cors", "type should have been changed to cors");
- });
-}, "Fetch policy: anonymous policy no-cors fetches should be changed to cors");
-
-
-async_test(t => {
- let pageLoaded = false;
- const CHANNEL_NAME = "anon-null-window";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- bc.onmessage = t.step_func_done((event) => {
- pageLoaded = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- const SECOND_CHANNEL = "anon-null-window-second";
- let navigated = false;
- let bc2 = new BroadcastChannel(SECOND_CHANNEL);
- bc2.onmessage = t.step_func((event) => {
- navigated = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- let win = window.open(`resources/navigate_anonymous.sub.html?channelName=${CHANNEL_NAME}&to=navigate_null.sub.html?channelName=${SECOND_CHANNEL}`, "_blank");
- t.add_cleanup(() => win.close());
- t.step_timeout(() => {
- assert_equals(pageLoaded, true, "Opening the popup window from anon window should work");
- assert_equals(navigated, false, "Navigating the popup to a null policy should fail");
- t.done();
- }, 500);
-}, "Top-level popup with anonymous policy: Navigating the popup to a null policy should fail.");
-
-async_test(t => {
- let pageLoaded = false;
- const CHANNEL_NAME = "anon-null-window";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- bc.onmessage = t.step_func_done((event) => {
- pageLoaded = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- const SECOND_CHANNEL = "anon-null-window-second";
- let navigated = false;
- let bc2 = new BroadcastChannel(SECOND_CHANNEL);
- bc2.onmessage = t.step_func((event) => {
- navigated = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- let win = window.open(`resources/navigate_anonymous.sub.html?clearOpener=true&channelName=${CHANNEL_NAME}&to=navigate_null.sub.html?channelName=${SECOND_CHANNEL}`, "_blank");
- t.add_cleanup(() => win.close());
- t.step_timeout(() => {
- assert_equals(pageLoaded, true, "Opening the popup window from anon window should work");
- assert_equals(navigated, false, "Navigating the popup to a null policy should fail");
- t.done();
- }, 500);
-}, "Top-level popup with anonymous policy: Navigating the popup to a null policy should fail. (even when we clear the opener)");
-
-async_test(t => {
- let popupLoaded = false;
- const CHANNEL_NAME = "anon-null-window-no-opener";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- bc.onmessage = t.step_func_done((event) => {
- let payload = event.data;
- if (payload == "loaded") {
- t.step_timeout(() => {
- assert_equals(popupLoaded, true, "Opening the popup window (noopener) from anon window should work");
- assert_equals(navigated, false, "Navigating the popup to a null policy should fail");
- t.done();
- }, 500);
- } else if (payload == "popup-loaded") {
- popupLoaded = true;
- } else {
- assert_unreached(`unexpected payload ${payload}`);
- }
- });
-
- const SECOND_CHANNEL = "anon-null-window-second-popup";
- let navigated = false;
- let bc2 = new BroadcastChannel(SECOND_CHANNEL);
- bc2.onmessage = t.step_func((event) => {
- navigated = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- let win = window.open(`resources/popup_and_close.sub.html?channelName=${CHANNEL_NAME}&to=navigate_null.sub.html?channelName=${SECOND_CHANNEL}`, "_blank", "noopener");
-}, "Top-level popup with anonymous policy: Navigating the popup to a null policy should fail. (even opener window is closed)");
-
-</script>
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 a76b601291e..00000000000
--- 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 ae871c4a273..00000000000
--- a/tests/wpt/web-platform-tests/html/cross-origin/null.tentative.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!doctype html>
-<meta name="timeout" content="long">
-<title>Cross-Origin header and nested navigable resource without such header</title>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src="/common/get-host-info.sub.js"></script>
-<div id=log></div>
-<script>
-async_test(t => {
- const frame = document.createElement("iframe");
- frame.onload = t.step_func_done(() => {
- assert_not_equals(frame.contentDocument, null, "The frame should actually load");
- });
- frame.src = "/common/blank.html";
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with null policy: navigating a frame to a null policy should work.");
-
-async_test(t => {
- const frame = document.createElement("iframe");
- let firstNavOk = false;
- frame.onload = t.step_func(() => {
- assert_not_equals(frame.contentDocument, null);
- firstNavOk = true;
- });
- t.step_timeout(() => {
- assert_equals(firstNavOk, true, "The initial load should work");
- assert_not_equals(frame.contentDocument, null, "Navigation to null policy should fail");
- t.done();
- }, 500);
- frame.src = "resources/navigate_anonymous.sub.html?to=/common/blank.html";
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with null policy: parent policy should apply to frame navigation from use-credentials policy to a null. Should succeed.");
-
-async_test(t => {
- const frame = document.createElement("iframe");
- let firstNavOk = false;
- frame.onload = t.step_func(() => {
- assert_not_equals(frame.contentDocument, null);
- firstNavOk = true;
- });
- t.step_timeout(() => {
- assert_equals(firstNavOk, true, "The initial load should work");
- assert_not_equals(frame.contentDocument, null, "Navigation to null policy should fail");
- t.done();
- }, 500);
- frame.src = "resources/navigate_anonymous.sub.html?to=/common/blank.html";
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with null policy: parent policy should apply to frame navigation from anonymous policy to a null. Should succeed.");
-
-async_test(t => {
- let w = window.open(`resources/navigate_null.sub.html?to=navigate_anonymous.sub.html`, "window_name");
-
- t.add_cleanup(() => w.close());
-
- t.step_timeout(() => {
- w.history.back();
- t.step_timeout(() => {
- assert_not_equals(w.document, null);
- t.done();
- }, 500);
- }, 500);
-}, "Top-level with null policy: navigating a frame back from a blocked page should work.");
-
-async_test(t => {
- let pageLoaded = false;
- const CHANNEL_NAME = "usecredentials-null-top-navigation";
- let bc = new BroadcastChannel(CHANNEL_NAME);
- let finished = false;
- bc.onmessage = t.step_func((event) => {
- pageLoaded = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- const SECOND_CHANNEL = "usecredentials-null-top-navigation-final";
- let bc2 = new BroadcastChannel(SECOND_CHANNEL);
- bc2.onmessage = t.step_func((event) => {
- finished = true;
- let payload = event.data;
- assert_equals(payload, "loaded");
- });
-
- let win = window.open(`resources/navigate_usecredentials.sub.html?channelName=${CHANNEL_NAME}&to=navigate_null.sub.html?channelName=${SECOND_CHANNEL}`, "_blank", "noopener");
-
- t.step_timeout(() => {
- assert_equals(pageLoaded, true, "Opening a null window (noopener) from usecredentials window should work");
- assert_equals(finished, true, "Navigating a top level window out of an usecredentials policy should work");
- t.done();
- }, 500);
-}, "Top-level noopener popup with use-credentials policy: navigating to a different (null) policy should work");
-
-promise_test(t => {
- let host_info = get_host_info();
- return fetch(host_info.HTTP_REMOTE_ORIGIN+"/html/cross-origin/resources/nothing.txt",
- {"mode": "no-cors", "method": "GET", "headers":{}}).then(r => {
- assert_equals(r.type, "opaque", "type should be opaque for cross origin fetch");
- });
-}, "Fetch policy: null policy should not affect the no-cors mode");
-
-</script>
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 fd34f127d55..00000000000
--- 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 a76b601291e..00000000000
--- 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 1008f70ff12..00000000000
--- a/tests/wpt/web-platform-tests/html/cross-origin/resources/navigate_usecredentials.sub.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!doctype html>
-<script>
- let current = new URL(window.location.href);
- let navigateTo = current.searchParams.get("to");
- let channelName = current.searchParams.get("channelName");
- current.search = "";
- if (navigateTo) {
- let next = new URL(navigateTo, current);
- setTimeout(() => {
- window.location = next.href;
- }, 50);
- }
-
- if (channelName) {
- let bc = new BroadcastChannel(channelName);
- bc.postMessage("loaded");
- }
-</script>
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 a84d3782037..00000000000
--- 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 9dafe9be209..00000000000
--- 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 cb762eff806..00000000000
--- 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 2489fa8d247..00000000000
--- a/tests/wpt/web-platform-tests/html/cross-origin/resources/popup_and_close.sub.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!doctype html>
-<script>
- let current = new URL(window.location.href);
- let navigateTo = current.searchParams.get("to");
- let channelName = current.searchParams.get("channelName");
- let secondChannel = current.searchParams.get("secondChannel");
-
- if (channelName) {
- let bc = new BroadcastChannel(channelName);
- bc.postMessage("popup-loaded");
- }
-
- let win = window.open(`navigate_anonymous.sub.html?channelName=${channelName}&to=navigate_null.sub.html?channelName=${secondChannel}`, "_blank");
-
- setTimeout(() => {
- window.close();
- }, 10);
-</script>
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 a76b601291e..00000000000
--- 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 55c0f2235db..00000000000
--- a/tests/wpt/web-platform-tests/html/cross-origin/usecredentials.tentative.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!doctype html>
-<meta name="timeout" content="long">
-<title>Cross-Origin header and nested navigable resource without such header</title>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<div id=log></div>
-<script>
-async_test(t => {
- const frame = document.createElement("iframe");
- t.step_timeout(() => {
- // Make sure the iframe didn't load.
- assert_equals(frame.contentDocument, null);
- t.done();
- }, 500);
- frame.src = "/common/blank.html";
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with use-credentials policy: navigating a frame to a null policy should fail.");
-
-async_test(t => {
- const frame = document.createElement("iframe");
- let firstNavOk = false;
- frame.onload = t.step_func(() => {
- assert_not_equals(frame.contentDocument, null);
- firstNavOk = true;
- });
- t.step_timeout(() => {
- assert_equals(firstNavOk, true, "The initial load should work");
- assert_equals(frame.contentDocument, null, "Navigation to null policy should fail");
- t.done();
- }, 500);
- frame.src = "resources/navigate_usecredentials.sub.html?to=/common/blank.html";
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with use-credentials policy: navigating a frame from a use-credentials policy to a null policy should fail");
-
-async_test(t => {
- const frame = document.createElement("iframe");
- let firstNavOk = false;
- frame.onload = t.step_func(() => {
- assert_not_equals(frame.contentDocument, null);
- firstNavOk = true;
- });
- t.step_timeout(() => {
- assert_equals(firstNavOk, true, "The initial load should work");
- assert_equals(frame.contentDocument, null, "Navigation to null policy should fail");
- t.done();
- }, 500);
- frame.src = "resources/navigate_anonymous.sub.html?to=/common/blank.html";
- document.body.append(frame);
- assert_equals(frame.contentDocument.body.localName, "body");
-}, "Top-level with use-credentials policy: navigating a frame from an anonymous policy to a null policy should fail.");
-
-</script>
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 a84d3782037..00000000000
--- 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 7745e4c68e2..0d3f1160d28 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 @@ idl_test(
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 e991e19f059..00000000000
--- a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/domstringlist-interface.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>DOMStringList IDL tests</title>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/WebIDLParser.js></script>
-<script src=/resources/idlharness.js></script>
-
-<h1>DOMStringList IDL tests</h1>
-<div id=log></div>
-
-<script>
-"use strict";
-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: ['location.ancestorOrigins'],
- });
-
- idlArray.test();
- t.done();
- });
-});
-</script>
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 e957b9e9b50..00000000000
--- 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 00000000000..773739804b3
--- /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 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: tabIndex getter return value</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#dom-tabindex">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<input>
+<input type="hidden">
+<button>button</button>
+<button disabled>button</button>
+<button hidden>button</button>
+<a>a</a>
+<a href="#">a</a>
+<svg><a>svg a</a></svg>
+<svg><a>svg a</a></svg>
+<link id="nohref">
+<textarea></textarea>
+<select><optgroup><option>option</option></optgroup></select>
+<select multiple></select>
+<iframe width="10" height="10"></iframe>
+<embed width="10" height="10"></embed>
+<object width="10" height="10"></object>
+<span></span>
+<div></div>
+<details><summary>summary</summary><summary id="secondsummary">second summary</summary>details</details>
+<div id="hostDelegatesFocus"></div>
+<div id="hostNonDelegatesFocus"></div>
+<script>
+document.getElementById("hostDelegatesFocus").attachShadow({ mode: "open", delegatesFocus: true });
+document.getElementById("hostNonDelegatesFocus").attachShadow({ mode: "open", delegatesFocus: false });
+const defaultList = [
+ ["input", 0],
+ ["input[type='hidden']", 0],
+ ["button", 0],
+ ["button[disabled]", 0],
+ ["button[hidden]", 0],
+ ["a", 0],
+ ["a[href]", 0],
+ ["svg a", 0],
+ ["textarea", 0],
+ ["select", 0],
+ ["select[multiple]", 0],
+ ["option", -1],
+ ["optgroup", -1],
+ ["iframe", 0],
+ ["embed", -1],
+ ["object", 0],
+ ["span", -1],
+ ["div", -1],
+ ["link#nohref", -1],
+ ["link[href]", -1],
+ ["details", -1],
+ ["summary", 0],
+ ["summary#secondsummary", -1],
+ ["#hostDelegatesFocus", -1],
+ ["#hostNonDelegatesFocus", -1],
+];
+const tabIndexValue = [-1, 0, 1];
+for (const entry of defaultList) {
+ const element = document.querySelector(entry[0]);
+ test(() => {
+ assert_equals(element.tabIndex, entry[1]);
+ }, entry[0] + ".tabIndex should return " + entry[1] + " by default");
+ for (const setValue of tabIndexValue ) {
+ test(() => {
+ element.setAttribute("tabindex", setValue);
+ assert_equals(element.tabIndex, setValue);
+ }, entry[0] + ".tabIndex should return " + setValue + " when set to " + setValue);
+ }
+}
+</script>
+</body>
+
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 00000000000..5f03a761dc8
--- /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 @@
+<!doctype html>
+<title>Select block size when line-height is specified</title>
+<!--
+ FIXME: This is just a copy of select-1-block-size-001.html, but if I move the
+ <link rel="match"> in this file to select-1-block-size-001-ref.html (which is
+ the "right" way to do this), fuzzy annotations do not work.
+-->
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1571764">
+<link rel="match" href="select-1-block-size-001-ref-2.html">
+<style>
+select {
+ -webkit-appearance: none;
+ appearance: none;
+
+ background: black;
+ color: black;
+
+ line-height: 100px;
+ width: 100px;
+
+ border: 0;
+ border-radius: 0;
+ padding: 0;
+}
+</style>
+<select></select>
+<select><option>A</option></select>
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 00000000000..385c2a75d42
--- /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 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1571764">
+<style>
+div {
+ -webkit-appearance: none;
+ appearance: none;
+
+ background: black;
+ color: black;
+
+ line-height: 100px;
+ width: 100px;
+
+ border: 0;
+ padding: 0;
+
+ display: inline-block;
+}
+</style>
+<div>A</div>
+<div>A</div>
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 00000000000..ad504846dfa
--- /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 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1571764">
+<style>
+button {
+ -webkit-appearance: none;
+ appearance: none;
+
+ background: black;
+ color: black;
+
+ line-height: 100px;
+ width: 100px;
+
+ border: 0;
+ border-radius: 0;
+ padding: 0;
+}
+</style>
+<button>A</button>
+<button>A</button>
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 00000000000..5dc0fc15dc5
--- /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 @@
+<!doctype html>
+<title>Select block size when line-height is specified</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1571764">
+<link rel="match" href="select-1-block-size-001-ref.html">
+<style>
+select {
+ -webkit-appearance: none;
+ appearance: none;
+
+ background: black;
+ color: black;
+
+ line-height: 100px;
+ width: 100px;
+
+ border: 0;
+ border-radius: 0;
+ padding: 0;
+}
+</style>
+<select></select>
+<select><option>A</option></select>
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 3a9d1d9b583..00000000000
--- a/tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8" />
-<title>idlharness test</title>
-<link rel="author" title="Kensaku Komatsu" href="mailto:kensaku.komatsu@gmail.com" />
-<link rel="help" href="http://www.w3.org/TR/animation-timing/#definitions"/>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-</head>
-<body>
-<h1>idlharness test</h1>
-<p>This test validates the WebIDL included in the Timing control for script-based animations specification.</p>
-
-<pre id='untested_idl' style='display:none'>
-[Global=Window, Exposed=Window]
-interface Window {
-};
-</pre>
-
-<pre id='idl'>
-partial interface Window {
- long requestAnimationFrame(FrameRequestCallback callback);
- void cancelAnimationFrame(long handle);
-};
-
-callback FrameRequestCallback = void (DOMHighResTimeStamp time);
-</pre>
-
-<script>
-
-(function() {
- var idl_array = new IdlArray();
-
- idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
- idl_array.add_idls(document.getElementById("idl").textContent);
-
- idl_array.add_objects({Window: ["window"]});
-
- idl_array.test();
-})();
-
-</script>
-
-<div id="log"></div>
-
-</body>
-</html>
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 00000000000..ddb3b724bb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/import-maps/imported/parsing-addresses.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/jest-test-helper.js"></script>
+<script type="module" src="resources/helpers/parsing.js"></script>
+
+<!--
+Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-addresses.js
+-->
+<script type="module" src="resources/parsing-addresses.js"></script>
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 00000000000..6b7c0e5b0eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/import-maps/imported/parsing-schema.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/jest-test-helper.js"></script>
+<script type="module" src="resources/helpers/parsing.js"></script>
+
+<!--
+Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-schema.js
+-->
+<script type="module" src="resources/parsing-schema.js"></script>
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 00000000000..601ac37720d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/import-maps/imported/parsing-scope-keys.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/jest-test-helper.js"></script>
+<script type="module" src="resources/helpers/parsing.js"></script>
+
+<!--
+Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-scope-keys.js
+-->
+<script type="module" src="resources/parsing-scope-keys.js"></script>
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 00000000000..dd547f01d1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/import-maps/imported/parsing-specifier-keys.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/jest-test-helper.js"></script>
+<script type="module" src="resources/helpers/parsing.js"></script>
+
+<!--
+Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-specifier-keys.js
+-->
+<script type="module" src="resources/parsing-specifier-keys.js"></script>
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 00000000000..c1395c175c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/import-maps/imported/resolving-builtins.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/jest-test-helper.js"></script>
+<script type="module" src="resources/helpers/parsing.js"></script>
+
+<!--
+Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving-builtins.js
+-->
+<script type="module" src="resources/resolving-builtins.js"></script>
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 00000000000..7db5f29f892
--- /dev/null
+++ b/tests/wpt/web-platform-tests/import-maps/imported/resolving-not-yet-implemented.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/jest-test-helper.js"></script>
+<script type="module" src="resources/helpers/parsing.js"></script>
+
+<!--
+Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving-not-yet-implemented.js
+-->
+<script type="module" src="resources/resolving-not-yet-implemented.js"></script>
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 00000000000..4985249f4e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/import-maps/imported/resolving-scopes.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/jest-test-helper.js"></script>
+<script type="module" src="resources/helpers/parsing.js"></script>
+
+<!--
+Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving-scopes.js
+-->
+<script type="module" src="resources/resolving-scopes.js"></script>
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 00000000000..339026259b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/import-maps/imported/resolving.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/jest-test-helper.js"></script>
+<script type="module" src="resources/helpers/parsing.js"></script>
+
+<!--
+Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving.js
+-->
+<script type="module" src="resources/resolving.js"></script>
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 00000000000..5c22f6de710
--- /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 00000000000..0f5fc73506b
--- /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 00000000000..695034533c7
--- /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 00000000000..cd1d9b34890
--- /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 00000000000..9eb423a19eb
--- /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 00000000000..a9383df843d
--- /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 00000000000..93d782fdad8
--- /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 00000000000..ca19a668406
--- /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
index 0409962e4d7..29ee31ccbc9 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
index f2b09a7ae02..86556ed3dd9 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 @@
-<!DOCTYPE html>
-<html>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// Hacky glue code to run Jest-based tests as WPT tests.
+// TODO(https://github.com/WICG/import-maps/issues/170): Consider better ways
+// to write and run tests.
+
setup({allow_uncaught_exception : true});
-// Hacky glue code to run Jest-based tests as WPT tests.
-// Only supports resolving.js.
+const exports = {};
+
function require(name) {
- return {
+ return Object.assign({
'URL': URL,
'parseFromString': parseFromString,
- 'resolve': resolve
- };
+ 'resolve': resolve,
+ 'BUILT_IN_MODULE_SCHEME': 'std'
+ }, exports);
}
function expect(v) {
return {
toMatchURL: expected => assert_equals(v, expected),
- toThrow: expected => assert_throws(expected(), v)
+ toThrow: expected => {
+ if (expected.test && expected.test('not yet implemented')) {
+ // We override /not yet implemented/ expectation.
+ assert_throws(TypeError(), v);
+ } else {
+ assert_throws(expected(), v);
+ }
+ },
+ toEqual: expected => {
+ if (v.localName === 'iframe') {
+ // `v` is the result of parseFromString(), and thus toEqual() is
+ // expected to compare parsed import maps.
+ // We sort keys when stringifying for normalization.
+ const actualParsedImportMap = JSON.parse(
+ internals.getParsedImportMap(v.contentDocument));
+ assert_equals(
+ JSON.stringify(actualParsedImportMap,
+ Object.keys(actualParsedImportMap).sort()),
+ JSON.stringify(expected.imports,
+ Object.keys(expected.imports).sort())
+ );
+ } else {
+ assert_object_equals(v, expected);
+ }
+ }
};
}
+expect.toMatchURL = expected => expected;
+
+const test_harness_test = test;
+test = it;
+
let current_message = '';
function describe(message, f) {
const old = current_message;
@@ -38,7 +67,7 @@ function it(message, f) {
current_message += ' / ';
}
current_message += message;
- test(t => t.step_func(f)(), current_message);
+ test_harness_test(t => t.step_func(f)(), current_message);
current_message = old;
}
@@ -71,11 +100,3 @@ function resolve(specifier, map, baseURL) {
baseURL,
map.contentDocument);
}
-
-</script>
-
-<!--
-resolving.js is
-https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving.js
--->
-<script type="module" src="resources/resolving.js"></script>
diff --git a/tests/wpt/web-platform-tests/interfaces/element-timing.idl b/tests/wpt/web-platform-tests/interfaces/element-timing.idl
index dc3b886cfe5..cf56426fb6e 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 c6790e16e3d..e8475d31922 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 f16a7ff812c..d2c69c47575 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 1bacea77bce..c46151a923d 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 48ebc187bc4..e92533a226e 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 00000000000..19544c8edee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/largest-contentful-paint/first-letter-background.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Largest Contentful Paint: observe element with background image in its first letter</title>
+<body>
+<style>
+#target::first-letter {
+ background-image: url('/images/black-rectangle.png');
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<script>
+ let beforeRender = performance.now();
+ async_test(function (t) {
+ if (!window.LargestContentfulPaint) {
+ assert_unreached("LargestContentfulPaint is not implemented");
+ }
+ const observer = new PerformanceObserver(
+ t.step_func(function(entryList) {
+ entryList.getEntries().forEach(entry => {
+ // If we happen to get a text entry due to text happening before the image, return.
+ if (entry.url === '')
+ return;
+ assert_equals(entry.entryType, 'largest-contentful-paint');
+ assert_greater_than_equal(entry.renderTime, beforeRender,
+ '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, entry.renderTime, 'startTime should equal renderTime');
+ assert_equals(entry.duration, 0);
+ assert_greater_than_equal(entry.size, 0);
+ assert_equals(entry.id, 'target');
+ const pathname = window.location.origin + '/images/black-rectangle.png';
+ assert_equals(entry.url, pathname);
+ assert_greater_than(entry.loadTime, beforeRender,
+ 'The load timestamp should occur after script starts running.');
+ assert_less_than(entry.loadTime, entry.renderTime,
+ 'The load timestamp should occur before the render timestamp.')
+ assert_equals(entry.element, document.getElementById('target'));
+ t.done();
+ })
+ }));
+ observer.observe({entryTypes: ['largest-contentful-paint']});
+ }, 'Largest Contentful Paint: first-letter is observable.');
+</script>
+<div id='target'>A</div>
+</body>
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 abe753fc14a..b551e7632b5 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 00000000000..7defcce1b6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/largest-contentful-paint/toJSON.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Largest Contentful Paint: toJSON</title>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<p>Text!</p>
+<script>
+ async_test(function (t) {
+ if (!window.LargestContentfulPaint) {
+ assert_unreached("LargestContentfulPaint is not implemented");
+ }
+ const observer = new PerformanceObserver(
+ t.step_func_done(function(entryList) {
+ const entry = entryList.getEntries()[0];
+ assert_equals(typeof(entry.toJSON), 'function');
+ const json = entry.toJSON();
+ assert_equals(typeof(json), 'object');
+ const keys = [
+ // PerformanceEntry
+ 'name',
+ 'entryType',
+ 'startTime',
+ 'duration',
+ // LargestContentfulPaint
+ 'renderTime',
+ 'loadTime',
+ 'size',
+ 'id',
+ 'url',
+ 'element',
+ ];
+ for (const key of keys) {
+ assert_equals(json[key], entry[key],
+ 'LargestContentfulPaint ${key} entry does not match its toJSON value');
+ }
+ })
+ );
+ observer.observe({type: 'largest-contentful-paint', buffered: true});
+ }, 'Test toJSON() in LargestContentfulPaint.');
+</script>
+</body>
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 00000000000..3d39d623e13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/layout-instability/toJSON.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Layout Instability: toJSON</title>
+<body>
+<style>
+#myDiv { position: relative; width: 300px; height: 100px; }
+</style>
+<div id='myDiv'></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ async_test(function (t) {
+ if (!window.LayoutShift)
+ assert_unreached('LayoutShift entries are not supported');
+ const observer = new PerformanceObserver(
+ t.step_func_done(function(entryList) {
+ const entry = entryList.getEntries()[0];
+ assert_equals(typeof(entry.toJSON), 'function');
+ const json = entry.toJSON();
+ assert_equals(typeof(json), 'object');
+ const keys = [
+ // PerformanceEntry
+ 'name',
+ 'entryType',
+ 'startTime',
+ 'duration',
+ // LayoutShift
+ 'value',
+ 'hadRecentInput',
+ 'lastInputTime',
+ ];
+ for (const key of keys) {
+ assert_equals(json[key], entry[key],
+ 'LayoutShift ${key} entry does not match its toJSON value');
+ }
+ })
+ );
+ observer.observe({type: 'layout-shift'});
+ document.getElementById('myDiv').style = "top: 60px";
+ }, 'Test toJSON() in LayoutShift.');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/lint.whitelist b/tests/wpt/web-platform-tests/lint.whitelist
index c344c3a8344..669038166ab 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 00000000000..39e6dabdfb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006-ref.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>RTL mtable and mtable with frame</title>
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math, math * {
+ font: 25px Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math>
+ <mtable>
+ <mtr>
+ <mtd>
+ <mtext>É</mtext>
+ </mtd>
+ <mtd>
+ <mtext>p</mtext>
+ </mtd>
+ <mtd>
+ <mtext>X</mtext>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd>
+ <mtext>pÉ</mtext>
+ </mtd>
+ <mtd>
+ <mtext>XÉ</mtext>
+ </mtd>
+ <mtd>
+ <mtext>Xp</mtext>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+
+ <p>
+ <math>
+ <mtable frame="solid">
+ <mtr>
+ <mtd>
+ <mtext>É</mtext>
+ </mtd>
+ <mtd>
+ <mtext>p</mtext>
+ </mtd>
+ <mtd>
+ <mtext>X</mtext>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd>
+ <mtext>pÉ</mtext>
+ </mtd>
+ <mtd>
+ <mtext>XÉ</mtext>
+ </mtd>
+ <mtd>
+ <mtext>Xp</mtext>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..904e7d3fed8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-006.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>RTL mtable and mtable with frame</title>
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#attributes-common-to-html-and-mathml-elements">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#css-styling">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#tabular-math">
+ <meta name="assert" content="Verify RTL math table renders the same as the column mirrored.">
+ <link rel="match" href="direction-006-ref.html">
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math, math * {
+ font: 25px Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math dir="rtl">
+ <mtable>
+ <mtr>
+ <mtd>
+ <mtext>X</mtext>
+ </mtd>
+ <mtd>
+ <mtext>p</mtext>
+ </mtd>
+ <mtd>
+ <mtext>É</mtext>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd>
+ <mtext>Xp</mtext>
+ </mtd>
+ <mtd>
+ <mtext>XÉ</mtext>
+ </mtd>
+ <mtd>
+ <mtext>pÉ</mtext>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+
+ <p>
+ <math dir="rtl">
+ <mtable frame="solid">
+ <mtr>
+ <mtd>
+ <mtext>X</mtext>
+ </mtd>
+ <mtd>
+ <mtext>p</mtext>
+ </mtd>
+ <mtd>
+ <mtext>É</mtext>
+ </mtd>
+ </mtr>
+ <mtr>
+ <mtd>
+ <mtext>Xp</mtext>
+ </mtd>
+ <mtd>
+ <mtext>XÉ</mtext>
+ </mtd>
+ <mtd>
+ <mtext>pÉ</mtext>
+ </mtd>
+ </mtr>
+ </mtable>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..5c77395f200
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007-ref.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>mo and embellished mrow/munderover (lspace=1em rspace=2em)</title>
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math, math * {
+ font: 25px/1 Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math>
+ <mtext>p</mtext><mo lspace="2em" rspace="1em">X</mo><mtext>p</mtext>
+ </math>
+ </p>
+
+ <p>
+ <math>
+ <mtext>p</mtext>
+ <mrow><mo lspace="2em" rspace="1em">X</mo></mrow>
+ <mtext>p</mtext>
+ </math>
+ </p>
+
+ <p>
+ <math>
+ <mtext>p</mtext>
+ <munderover>
+ <mo lspace="2em" rspace="1em">X</mo>
+ <mtext>É</mtext>
+ <mtext>É</mtext>
+ </munderover>
+ <mtext>p</mtext>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..7137e2640fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-007.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>mo and embellished mrow/munderover (lspace=1em rspace=2em)</title>
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#attributes-common-to-html-and-mathml-elements">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#css-styling">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#embellished-operators">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-fence-separator-or-accent-mo">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#horizontally-group-sub-expressions-mrow">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#underscripts-and-overscripts-munder-mover-munderover">
+ <meta name="assert" content="Verify that the lspace/rspace on an mo or an embellished mrow/munderover element are switched in RTL mode">
+ <link rel="match" href="direction-007-ref.html">
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math, math * {
+ font: 25px/1 Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math dir="rtl">
+ <mtext>p</mtext><mo lspace="1em" rspace="2em">X</mo><mtext>p</mtext>
+ </math>
+ </p>
+
+ <p>
+ <math dir="rtl">
+ <mtext>p</mtext>
+ <mrow><mo lspace="1em" rspace="2em">X</mo></mrow>
+ <mtext>p</mtext>
+ </math>
+ </p>
+
+ <p>
+ <math dir="rtl">
+ <mtext>p</mtext>
+ <munderover>
+ <mo lspace="1em" rspace="2em">X</mo>
+ <mtext>É</mtext>
+ <mtext>É</mtext>
+ </munderover>
+ <mtext>p</mtext>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..492fa9539ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>embellished mfrac (lspace=1em rspace=2em)</title>
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math, math * {
+ font: 25px/1 Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math>
+ <mtext>p</mtext>
+ <mfrac>
+ <mo lspace="2em" rspace="1em">X</mo>
+ <mtext>É</mtext>
+ </mfrac>
+ <mtext>p</mtext>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..5c98b074100
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-008.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>embellished mfrac (lspace=1em rspace=2em)</title>
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#attributes-common-to-html-and-mathml-elements">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#css-styling">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#fractions-mfrac">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#embellished-operators">
+ <meta name="assert" content="Verify that the lspace/rspace on an embellished mfrac element are switched in RTL mode">
+ <link rel="match" href="direction-008-ref.html">
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math, math * {
+ font: 25px/1 Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math dir="rtl">
+ <mtext>p</mtext>
+ <mfrac>
+ <mo lspace="1em" rspace="2em">X</mo>
+ <mtext>É</mtext>
+ </mfrac>
+ <mtext>p</mtext>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..7ed4796814a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>RTL ms lquote="X" rquote="p"</title>
+ <style>
+ math {
+ font: 25px/1 Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math>
+ <ms lquote="p" rquote="X">É</ms>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..bf8caf16aed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-009.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>RTL ms lquote="X" rquote="p"</title>
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#attributes-common-to-html-and-mathml-elements">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#css-styling">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#string-literal-ms">
+ <meta name="assert" content="Verify that a RTL ms element renders the same as if its left and right quotes were switched.">
+ <link rel="match" href="direction-009-ref.html">
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math {
+ font: 25px/1 Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math dir="rtl">
+ <ms lquote="X" rquote="p">É</ms>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..4f595ed49f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010-ref.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>dir="rtl" VS direction: rtl on math/mrow/mstyle</title>
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math {
+ font: 25px/1 Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math style="direction: rtl">
+ <mtext>X</mtext>
+ <mtext>p</mtext>
+ <mtext>É</mtext>
+ </math>
+ </p>
+
+ <p>
+ <math>
+ <mrow style="direction: rtl">
+ <mtext>X</mtext>
+ <mtext>p</mtext>
+ <mtext>É</mtext>
+ </mrow>
+ </math>
+ </p>
+
+ <p>
+ <math>
+ <mstyle mathcolor="blue" style="direction: rtl">
+ <mtext>X</mtext>
+ <mtext>p</mtext>
+ <mtext>É</mtext>
+ </mstyle>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..6dc095ac1fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-010.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>dir="rtl" VS direction: rtl on math/mrow/mstyle</title>
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#attributes-common-to-html-and-mathml-elements">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#css-styling">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#horizontally-group-sub-expressions-mrow">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#style-change-mstyle">
+ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#the-top-level-math-element">
+ <meta name="assert" content="Verify that math, mrow and mstyle with a dir=rtl attribute render the same as CSS direction right-to-left.">
+ <link rel="match" href="direction-010-ref.html">
+ <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+ <style>
+ math {
+ font: 25px/1 Ahem;
+ }
+ </style>
+ </head>
+ <body>
+
+ <p>
+ <math dir="rtl">
+ <mtext>X</mtext>
+ <mtext>p</mtext>
+ <mtext>É</mtext>
+ </math>
+ </p>
+
+ <p>
+ <math>
+ <mrow dir="rtl">
+ <mtext>X</mtext>
+ <mtext>p</mtext>
+ <mtext>É</mtext>
+ </mrow>
+ </math>
+ </p>
+
+ <p>
+ <math>
+ <mstyle mathcolor="blue" dir="rtl">
+ <mtext>X</mtext>
+ <mtext>p</mtext>
+ <mtext>É</mtext>
+ </mstyle>
+ </math>
+ </p>
+
+ </body>
+</html>
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 00000000000..28d9acc1f4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity-ref.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant case sensitivity</title>
+<style>
+ @font-face {
+ font-family: mathvariant-bold-fraktur;
+ src: url("/fonts/math/mathvariant-bold-fraktur.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold;
+ src: url("/fonts/math/mathvariant-bold.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-italic;
+ src: url("/fonts/math/mathvariant-bold-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-sans-serif;
+ src: url("/fonts/math/mathvariant-bold-sans-serif.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-script;
+ src: url("/fonts/math/mathvariant-bold-script.woff");
+ }
+ @font-face {
+ font-family: mathvariant-double-struck;
+ src: url("/fonts/math/mathvariant-double-struck.woff");
+ }
+ @font-face {
+ font-family: mathvariant-fraktur;
+ src: url("/fonts/math/mathvariant-fraktur.woff");
+ }
+ @font-face {
+ font-family: mathvariant-initial;
+ src: url("/fonts/math/mathvariant-initial.woff");
+ }
+ @font-face {
+ font-family: mathvariant-italic;
+ src: url("/fonts/math/mathvariant-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-looped;
+ src: url("/fonts/math/mathvariant-looped.woff");
+ }
+ @font-face {
+ font-family: mathvariant-monospace;
+ src: url("/fonts/math/mathvariant-monospace.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif-bold-italic;
+ src: url("/fonts/math/mathvariant-sans-serif-bold-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif;
+ src: url("/fonts/math/mathvariant-sans-serif.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif-italic;
+ src: url("/fonts/math/mathvariant-sans-serif-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-script;
+ src: url("/fonts/math/mathvariant-script.woff");
+ }
+ @font-face {
+ font-family: mathvariant-stretched;
+ src: url("/fonts/math/mathvariant-stretched.woff");
+ }
+ @font-face {
+ font-family: mathvariant-tailed;
+ src: url("/fonts/math/mathvariant-tailed.woff");
+ }
+</style>
+<body>
+ <p>
+ <math style="font-family: mathvariant-bold-fraktur">
+ <mtext>&#x1D56C;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold">
+ <mtext>&#x1D400;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-italic">
+ <mtext>&#x1D468;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-sans-serif">
+ <mtext>&#x1D5D4;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-script">
+ <mtext>&#x1D4D0;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-double-struck">
+ <mtext>&#x1D538;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-fraktur">
+ <mtext>&#x1D504;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-initial">
+ <mtext>&#x1EE30;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-italic">
+ <mtext>&#x1D434;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-looped">
+ <mtext>&#x1EE90;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-monospace">
+ <mtext>&#x1D670;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif-bold-italic">
+ <mtext>&#x1D63C;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif">
+ <mtext>&#x1D5A0;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif-italic">
+ <mtext>&#x1D608;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-script">
+ <mtext>&#x1D49C;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-stretched">
+ <mtext>&#x1EE70;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-tailed">
+ <mtext>&#x1EE52;</mtext>
+ </math>
+ </p>
+</body>
+</html>
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 00000000000..0d3e706d961
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-case-sensitivity.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8"/>
+<title>mathvariant case sensitivity</title>
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#css-styling">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#the-mathvariant-attribute">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#new-text-transform-values">
+<link rel="match" href="mathvariant-case-sensitivity-ref.html"/>
+<meta name="assert" content="Verify that mathvariant value is case insensitive">
+<style>
+ @font-face {
+ font-family: mathvariant-bold-fraktur;
+ src: url("/fonts/math/mathvariant-bold-fraktur.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold;
+ src: url("/fonts/math/mathvariant-bold.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-italic;
+ src: url("/fonts/math/mathvariant-bold-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-sans-serif;
+ src: url("/fonts/math/mathvariant-bold-sans-serif.woff");
+ }
+ @font-face {
+ font-family: mathvariant-bold-script;
+ src: url("/fonts/math/mathvariant-bold-script.woff");
+ }
+ @font-face {
+ font-family: mathvariant-double-struck;
+ src: url("/fonts/math/mathvariant-double-struck.woff");
+ }
+ @font-face {
+ font-family: mathvariant-fraktur;
+ src: url("/fonts/math/mathvariant-fraktur.woff");
+ }
+ @font-face {
+ font-family: mathvariant-initial;
+ src: url("/fonts/math/mathvariant-initial.woff");
+ }
+ @font-face {
+ font-family: mathvariant-italic;
+ src: url("/fonts/math/mathvariant-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-looped;
+ src: url("/fonts/math/mathvariant-looped.woff");
+ }
+ @font-face {
+ font-family: mathvariant-monospace;
+ src: url("/fonts/math/mathvariant-monospace.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif-bold-italic;
+ src: url("/fonts/math/mathvariant-sans-serif-bold-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif;
+ src: url("/fonts/math/mathvariant-sans-serif.woff");
+ }
+ @font-face {
+ font-family: mathvariant-sans-serif-italic;
+ src: url("/fonts/math/mathvariant-sans-serif-italic.woff");
+ }
+ @font-face {
+ font-family: mathvariant-script;
+ src: url("/fonts/math/mathvariant-script.woff");
+ }
+ @font-face {
+ font-family: mathvariant-stretched;
+ src: url("/fonts/math/mathvariant-stretched.woff");
+ }
+ @font-face {
+ font-family: mathvariant-tailed;
+ src: url("/fonts/math/mathvariant-tailed.woff");
+ }
+</style>
+<body>
+ <p>
+ <math style="font-family: mathvariant-bold-fraktur">
+ <mtext mathvariant="BoLd-fRaKtUr">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold">
+ <mtext mathvariant="BoLd">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-italic">
+ <mtext mathvariant="BoLd-iTaLiC">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-sans-serif">
+ <mtext mathvariant="BoLd-sAnS-SeRiF">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-bold-script">
+ <mtext mathvariant="BoLd-sCrIpT">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-double-struck">
+ <mtext mathvariant="DoUbLe-sTrUcK">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-fraktur">
+ <mtext mathvariant="FrAkTuR">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-initial">
+ <mtext mathvariant="InItIaL">&#x641;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-italic">
+ <mtext mathvariant="ItAlIc">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-looped">
+ <mtext mathvariant="LoOpEd">&#x641;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-monospace">
+ <mtext mathvariant="MoNoSpAcE">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif-bold-italic">
+ <mtext mathvariant="SaNs-sErIf-bOlD-ItAlIc">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif">
+ <mtext mathvariant="SaNs-sErIf">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-sans-serif-italic">
+ <mtext mathvariant="SaNs-sErIf-iTaLiC">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-script">
+ <mtext mathvariant="ScRiPt">&#x41;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-stretched">
+ <mtext mathvariant="StReTcHeD">&#x641;</mtext>
+ </math>
+ </p>
+ <p>
+ <math style="font-family: mathvariant-tailed">
+ <mtext mathvariant="TaIlEd">&#x642;</mtext>
+ </math>
+ </p>
+</body>
+</html>
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 00000000000..0bf39bcb4dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/inheritance.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Inheritance of touch-action</title>
+<link rel="help" href="https://w3c.github.io/pointerevents/#the-touch-action-css-property">
+<meta name="assert" content="touch-action does not inherit.">
+<meta name="assert" content="touch-action initial value is auto.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/inheritance-testcommon.js"></script>
+</head>
+<body>
+<div id="container">
+ <div id="target"></div>
+</div>
+<script>
+assert_not_inherited('touch-action', 'auto', 'none');
+</script>
+</body>
+</html>
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 00000000000..59255bec455
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-computed.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Pointer Events: getComputedStyle().touchAction</title>
+<link rel="help" href="https://w3c.github.io/pointerevents/#the-touch-action-css-property">
+<meta name="assert" content="touch-action computed value is as specified.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("touch-action", "auto");
+test_computed_value("touch-action", "none");
+test_computed_value("touch-action", "manipulation");
+
+test_computed_value("touch-action", "pan-x");
+test_computed_value("touch-action", "pan-y");
+test_computed_value("touch-action", "pan-x pan-y");
+</script>
+</body>
+</html>
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 00000000000..979dc252d3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-invalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Pointer Events: parsing touch-action with invalid values</title>
+<link rel="help" href="https://w3c.github.io/pointerevents/#the-touch-action-css-property">
+<meta name="assert" content="touch-action supports only the grammar 'auto | none | [ pan-x || pan-y ] | manipulation'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value("touch-action", "auto none");
+test_invalid_value("touch-action", "manipulation pan-x");
+test_invalid_value("touch-action", "pan-y pan-x pan-y");
+</script>
+</body>
+</html>
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 00000000000..9bb5d023edc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/parsing/touch-action-valid.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Pointer Events: parsing touch-action with valid values</title>
+<link rel="help" href="https://w3c.github.io/pointerevents/#the-touch-action-css-property">
+<meta name="assert" content="touch-action supports the full grammar 'auto | none | [ pan-x || pan-y ] | manipulation'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("touch-action", "auto");
+test_valid_value("touch-action", "none");
+test_valid_value("touch-action", "manipulation");
+
+// [ pan-x || pan-y ]
+test_valid_value("touch-action", "pan-x");
+test_valid_value("touch-action", "pan-y");
+test_valid_value("touch-action", "pan-y pan-x", "pan-x pan-y");
+</script>
+</body>
+</html>
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 00000000000..46a4d7d156f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001-ref.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<div>Prevent quirky dl margin from messing up with us</div>
+<dl>
+ <dd>One</dd>
+ <dl>Two</dl>
+</dl>
+<dd>Three</dd><dd>Four</dd>
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 00000000000..96fc76f08f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks/dd-dl-firefox-001.html
@@ -0,0 +1,18 @@
+<!-- quirks -->
+<title>dd and dl don't have weird text-indent quirks</title>
+<link rel="match" href="dd-dl-firefox-001-ref.html">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=782551">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<style>
+ /* Firefox used to (sometimes) implement dd indentation in quirks mode via
+ the ::before pseudo-element; this rule should do nothing in compliant
+ browsers */
+ dd::before { content: "" }
+</style>
+<div>Prevent quirky dl margin from messing up with us</div>
+<dl>
+ <dd>One</dd>
+ <dl>Two</dl>
+</dl>
+<dd>Three</dd><dd>Four</dd>
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 0c0f3819530..d1cb469b3df 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 00000000000..83bd6b8a0de
--- /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 3f9d75f57ba..1bd583269d2 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 9cb975a8bb3..900694b095d 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,496 +154,502 @@ __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);
+ function callback() {
+ const callback = consume("callback");
+ if (!callback) return;
+ 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);
}
- 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;
- }
+ function interface_(opts) {
+ const base = consume("interface");
+ if (!base) return;
+ 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;
+ }
- 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);
- }
+ function partial() {
+ const partial = consume("partial");
+ if (!partial) return;
+ return _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__["Dictionary"].parse(tokeniser, { partial }) ||
+ interface_({ partial }) ||
+ _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__["Namespace"].parse(tokeniser, { partial }) ||
+ error("Partial doesn't apply to anything");
}
- 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;
- }
+ function definition() {
+ return callback() ||
+ interface_() ||
+ partial() ||
+ _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);
+ }
- get type() {
- return "callback";
+ function definitions() {
+ if (!source.length) return [];
+ const defs = [];
+ while (true) {
+ 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");
+ break;
+ }
+ def.extAttrs = ea;
+ defs.push(def);
}
- get name() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
+ const eof = consume("eof");
+ if (options.concrete) {
+ defs.push(eof);
}
+ return defs;
}
+ const res = definitions();
+ if (tokeniser.position < source.length) error("Unrecognised tokens");
+ return res;
+}
- function callback() {
- const callback = consume("callback");
- if (!callback) return;
- const tok = consume("interface");
- if (tok) {
- return Interface.parse(tok, { callback });
- }
- return CallbackFunction.parse(callback);
+function parse(str, options = {}) {
+ 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);
+}
- 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);
- }
- }
+/***/ }),
+/* 2 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
- 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;
- }
+"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__(3);
- 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`);
+// 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
+};
- return ret;
- }
+const stringTypes = [
+ "ByteString",
+ "DOMString",
+ "USVString"
+];
- get type() {
- return this.tokens.base.value;
- }
- get readonly() {
- return !!this.tokens.readonly;
- }
- }
+const argumentNameKeywords = [
+ "async",
+ "attribute",
+ "callback",
+ "const",
+ "deleter",
+ "dictionary",
+ "enum",
+ "getter",
+ "includes",
+ "inherit",
+ "interface",
+ "iterable",
+ "maplike",
+ "namespace",
+ "partial",
+ "required",
+ "setlike",
+ "setter",
+ "static",
+ "stringifier",
+ "typedef",
+ "unrestricted"
+];
- function inheritance() {
- const colon = consume(":");
- if (!colon) {
- return {};
+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);
+
+const punctuations = [
+ "(",
+ ")",
+ ",",
+ "...",
+ ":",
+ ";",
+ "<",
+ "=",
+ ">",
+ "?",
+ "[",
+ "]",
+ "{",
+ "}"
+];
+
+/**
+ * @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;
+
+ if (/[\t\n\r ]/.test(nextChar)) {
+ result = attemptTokenMatch("whitespace", { noFlushTrivia: true });
+ } else if (nextChar === '/') {
+ result = attemptTokenMatch("comment", { noFlushTrivia: true });
}
- 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());
+ 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");
}
- 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");
+ if (result === -1) {
+ result = attemptTokenMatch("identifier");
+ const token = tokens[tokens.length - 1];
+ if (result !== -1 && nonRegexTerminals.includes(token.value)) {
+ token.type = token.value;
}
- mem.extAttrs = ea;
- instance.members.push(mem);
}
+ } else if (nextChar === '"') {
+ result = attemptTokenMatch("string");
}
- 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;
+ 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;
}
- 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";
+ // 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;
}
- class Mixin extends Container {
- static parse(base, { partial } = {}) {
- const tokens = { partial, base };
- tokens.mixin = consume("mixin");
- if (!tokens.mixin) {
- return;
+ // remaining trivia as eof
+ tokens.push({
+ type: "eof",
+ value: "",
+ trivia
+ });
+
+ 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 Container.parse(new Mixin({ source, tokens }), {
- type: "interface mixin",
- allowedMembers: [
- [Constant.parse],
- [stringifier],
- [Attribute.parse, { noInherit: true }],
- [Operation.parse, { regular: true }]
- ]
- });
+ return re.lastIndex;
}
+ return -1;
+ }
+}
- get type() {
- return "interface mixin";
- }
+class Tokeniser {
+ /**
+ * @param {string} idl
+ */
+ constructor(idl) {
+ this.source = tokenise(idl);
+ this.position = 0;
}
- function interface_(opts) {
- const base = consume("interface");
- if (!base) return;
- const ret = Mixin.parse(base, opts) ||
- Interface.parse(base, opts) ||
- error("Interface has no proper body");
- return ret;
+ /**
+ * @param {string} message
+ */
+ error(message) {
+ throw new WebIDLParseError(Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["syntaxError"])(this.source, this.position, this.current, message));
}
- 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 }]
- ]
- });
- }
+ /**
+ * @param {string} type
+ */
+ probe(type) {
+ return this.source.length > this.position && this.source[this.position].type === type;
+ }
- get type() {
- return "namespace";
+ /**
+ * @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;
}
}
- function partial() {
- const partial = consume("partial");
- if (!partial) return;
- return Dictionary.parse({ partial }) ||
- interface_({ partial }) ||
- Namespace.parse({ partial }) ||
- error("Partial doesn't apply to anything");
+ /**
+ * @param {number} position
+ */
+ unconsume(position) {
+ this.position = position;
}
+}
- 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],
- ]
- });
- }
+class WebIDLParseError extends Error {
+ constructor({ message, bareMessage, context, line, sourceName, input, tokens }) {
+ super(message);
- get type() {
- return "dictionary";
- }
+ 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;
}
+}
- 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);
+/***/ }),
+/* 3 */
+/***/ (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];
+}
+
+/**
+ * @typedef {object} WebIDL2ErrorOptions
+ * @property {"error" | "warning"} level
+ *
+ * @param {string} message error message
+ * @param {"Syntax" | "Validation"} kind error type
+ * @param {WebIDL2ErrorOptions} [options]
+ */
+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);
+ }
+
+ function tokensToText(inputs, { precedes } = {}) {
+ const text = inputs.map(t => t.trivia + t.value).join("");
+ const nextToken = source[position];
+ if (nextToken.type === "eof") {
+ return text;
}
- get required() {
- return !!this.tokens.required;
+ if (precedes) {
+ return text + nextToken.trivia;
}
+ return text.slice(nextToken.trivia.length);
}
- 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;
- }
+ 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;
- get type() {
- return "typedef";
- }
- get name() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
+ 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 {string} message error message
+ */
+function syntaxError(source, position, current, message) {
+ return error(source, position, current, message, "Syntax");
+}
+
+/**
+ * @param {string} message error message
+ * @param {WebIDL2ErrorOptions} [options]
+ */
+function validationError(source, token, current, message, options) {
+ return error(source, token.index, current, message, "Validation", options);
+}
+
+
+/***/ }),
+/* 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
+ */
+ static parse(tokeniser) {
+ const value = tokeniser.consume("string");
+ if (value) {
+ return new EnumValue({ source: tokeniser.source, tokens: { 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();
+ get type() {
+ return "enum-value";
}
+ get value() {
+ return super.value.slice(1, -1);
+ }
+}
- function definitions() {
- if (!source.length) return [];
- const defs = [];
- while (true) {
- const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__["ExtendedAttributes"].parse(tokeniser);
- const def = definition();
- if (!def) {
- if (ea.length) error("Stray extended attributes");
- break;
- }
- def.extAttrs = ea;
- defs.push(def);
+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;
}
- const eof = consume("eof");
- if (options.concrete) {
- defs.push(eof);
+ 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");
}
- return defs;
+ 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;
}
- const res = definitions();
- if (tokeniser.position < source.length) error("Unrecognised tokens");
- return res;
-}
-function parse(str, options = {}) {
- const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_1__["Tokeniser"](str);
- return parseByTokens(tokeniser, options);
+ get type() {
+ return "enum";
+ }
+ get name() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
+ }
}
/***/ }),
-/* 2 */
+/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -651,10 +663,15 @@ __webpack_require__.r(__webpack_exports__);
/* 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__, "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);
+
+
@@ -809,17 +826,33 @@ function return_type(tokeniser, typeName) {
}
}
+/**
+ * @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;
+}
+
/***/ }),
-/* 3 */
+/* 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__(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 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);
+
+
@@ -965,11 +998,37 @@ class Type extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
].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);
+ }
+ }
+ }
}
/***/ }),
-/* 4 */
+/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -1001,346 +1060,89 @@ class Base {
/***/ }),
-/* 5 */
+/* 8 */
/***/ (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"
-];
-
-const argumentNameKeywords = [
- "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",
- "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 = [
- "(",
- ")",
- ",",
- "...",
- ":",
- ";",
- "<",
- "=",
- ">",
- "?",
- "[",
- "]",
- "{",
- "}"
-];
-
+/* 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; });
/**
- * @param {string} str
+ * Yields direct references to dictionary within union.
*/
-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 });
+function* dictionaryWithinUnion(subtypes, defs) {
+ for (const subtype of subtypes) {
+ const def = defs.unique.get(subtype.idlType);
+ if (def && def.type === "dictionary") {
+ yield subtype;
}
+ }
+}
- 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");
- }
- 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");
+/**
+ * @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;
}
-
- 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;
+ 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;
}
}
-
- // other as the last try
- if (result === -1) {
- result = attemptTokenMatch("other");
- }
- if (result === -1) {
- throw new Error("Token stream not progressing");
+ if (def.type === "dictionary") {
+ return idlType;
}
- lastCharIndex = result;
- index += 1;
}
-
- // remaining trivia as eof
- tokens.push({
- type: "eof",
- value: "",
- trivia
- });
-
- 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);
+ for (const subtype of idlType.subtype) {
+ const result = idlTypeIncludesDictionary(subtype, defs);
if (result) {
- tokens.push({ type, value: result[0], trivia, line, index });
- if (!noFlushTrivia) {
- trivia = "";
+ if (subtype.union) {
+ return result;
}
- return re.lastIndex;
- }
- return -1;
- }
-}
-
-class Tokeniser {
- /**
- * @param {string} idl
- */
- constructor(idl) {
- this.source = tokenise(idl);
- this.position = 0;
- }
-
- /**
- * @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;
- }
-
- /**
- * @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;
- }
- }
-
- /**
- * @param {number} position
- */
- unconsume(position) {
- this.position = position;
- }
-}
-
-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;
- }
-}
-
-
-/***/ }),
-/* 6 */
-/***/ (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];
-}
-
-/**
- * @param {string} message error message
- * @param {"Syntax" | "Validation"} type error type
- */
-function error(source, position, current, message, type) {
- /**
- * @param {number} count
- */
- function sliceTokens(count) {
- return count > 0 ?
- source.slice(position, position + count) :
- source.slice(Math.max(position + count, 0), position);
- }
-
- function tokensToText(inputs, { precedes } = {}) {
- const text = inputs.map(t => t.trivia + t.value).join("");
- const nextToken = source[position];
- if (nextToken.type === "eof") {
- return text;
+ return subtype;
}
- if (precedes) {
- return text + nextToken.trivia;
- }
- return text.slice(nextToken.trivia.length);
}
-
- 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
+ * @return true if the idlType directly references a typedef.
*/
-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;
+function referencesTypedef(idlType, defs) {
+ const result = defs.unique.get(idlType.idlType);
+ return result && result.type === "typedef";
}
/***/ }),
-/* 7 */
+/* 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__(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 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);
+
+
@@ -1372,6 +1174,9 @@ class Argument extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
return ret;
}
+ get type() {
+ return "argument";
+ }
get optional() {
return !!this.tokens.optional;
}
@@ -1381,18 +1186,32 @@ class Argument extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
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);
+ }
+ }
+ }
}
/***/ }),
-/* 8 */
+/* 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__(4);
-/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
@@ -1435,15 +1254,17 @@ class Default extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/***/ }),
-/* 9 */
+/* 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__(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 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);
+
@@ -1487,6 +1308,7 @@ class SimpleExtendedAttribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Bas
const name = tokeniser.consume("identifier");
if (name) {
return new SimpleExtendedAttribute({
+ source: tokeniser.source,
tokens: { name },
params: ExtendedAttributeParameters.parse(tokeniser)
});
@@ -1519,6 +1341,19 @@ class SimpleExtendedAttribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Bas
}
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);
+ }
+ }
}
// Note: we parse something simpler than the official syntax. It's all that ever
@@ -1530,7 +1365,7 @@ class ExtendedAttributes extends _array_base_js__WEBPACK_IMPORTED_MODULE_1__["Ar
static parse(tokeniser) {
const tokens = {};
tokens.open = tokeniser.consume("[");
- if (!tokens.open) return [];
+ 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,
@@ -1545,11 +1380,17 @@ class ExtendedAttributes extends _array_base_js__WEBPACK_IMPORTED_MODULE_1__["Ar
}
return ret;
}
+
+ *validate(defs) {
+ for (const extAttr of this) {
+ yield* extAttr.validate(defs);
+ }
+ }
}
/***/ }),
-/* 10 */
+/* 12 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -1567,13 +1408,13 @@ class ArrayBase extends Array {
/***/ }),
-/* 11 */
+/* 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__(4);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
class Token extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
@@ -1597,85 +1438,147 @@ class Token extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/***/ }),
-/* 12 */
+/* 14 */
/***/ (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__, "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 EnumValue extends _token_js__WEBPACK_IMPORTED_MODULE_1__["Token"] {
+class Operation extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/**
- * @param {import("../tokeniser").Tokeniser} tokeniser
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
*/
- static parse(tokeniser) {
- const value = tokeniser.consume("string");
- if (value) {
- return new EnumValue({ source: tokeniser.source, tokens: { value } });
+ 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;
+ }
}
+ 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;
}
get type() {
- return "enum-value";
+ return "operation";
}
- get value() {
- return super.value.slice(1, -1);
+ 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;
+ }
+
+ *validate(defs) {
+ if (this.idlType) {
+ yield* this.idlType.validate(defs);
+ }
+ for (const argument of this.arguments) {
+ yield* argument.validate(defs);
+ }
}
}
-class Enum extends _base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
+
+/***/ }),
+/* 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 {import("../tokeniser").Tokeniser} tokeniser
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
*/
- static parse(tokeniser) {
- const tokens = {};
- tokens.base = tokeniser.consume("enum");
+ 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");
+ }
+ 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;
}
- 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");
+ 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.termination = tokeniser.consume(";") || tokeniser.error("No semicolon after enum");
+ 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 "enum";
+ 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_0__["unescape"])(this.tokens.name.value);
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value);
+ }
+
+ *validate(defs) {
+ yield* this.idlType.validate(defs);
}
}
/***/ }),
-/* 13 */
+/* 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__(4);
-/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
@@ -1712,7 +1615,647 @@ class Includes extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/***/ }),
-/* 14 */
+/* 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);
+
+
+
+class Typedef extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ 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;
+ }
+
+ get type() {
+ return "typedef";
+ }
+ get name() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value);
+ }
+
+ *validate(defs) {
+ yield* this.idlType.validate(defs);
+ }
+}
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* 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);
+
+
+
+class CallbackFunction extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
+ */
+ 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;
+ }
+
+ get type() {
+ return "callback";
+ }
+ get name() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value);
+ }
+
+ *validate(defs) {
+ yield* this.idlType.validate(defs);
+ }
+}
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* 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);
+
+
+
+
+
+
+
+
+
+/**
+ * @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, 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 type() {
+ return "interface";
+ }
+
+ *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);
+ }
+ }
+}
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* 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);
+
+
+
+
+/**
+ * @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 };
+}
+
+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);
+ }
+ }
+ }
+ }
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* 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 Constant extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
+ */
+ static parse(tokeniser) {
+ 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 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);
+ }
+}
+
+
+/***/ }),
+/* 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.js").Tokeniser} tokeniser
+ */
+ static 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;
+ }
+
+ 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 this.tokens.base.value;
+ }
+ get readonly() {
+ return !!this.tokens.readonly;
+ }
+ get async() {
+ return !!this.tokens.async;
+ }
+}
+
+
+/***/ }),
+/* 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);
+ }
+ }
+
+ 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 getOperations(i) {
+ return i.members
+ .filter(({type}) => type === "operation");
+ }
+}
+
+
+/***/ }),
+/* 24 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* 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";
+ }
+}
+
+
+/***/ }),
+/* 25 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* 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 Dictionary extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ 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 type() {
+ return "dictionary";
+ }
+}
+
+
+/***/ }),
+/* 26 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* 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 Field extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser) {
+ 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 "field";
+ }
+ 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);
+ }
+}
+
+
+/***/ }),
+/* 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, { partial } = {}) {
+ const tokens = { partial };
+ tokens.base = tokeniser.consume("namespace");
+ if (!tokens.base) {
+ return;
+ }
+ 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 }]
+ ]
+ });
+ }
+
+ get type() {
+ return "namespace";
+ }
+
+ *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);
+ }
+}
+
+
+/***/ }),
+/* 28 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* 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 CallbackInterface extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser, callback, { partial = null } = {}) {
+ const tokens = { callback };
+ tokens.base = tokeniser.consume("interface");
+ if (!tokens.base) {
+ return;
+ }
+ 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 "callback interface";
+ }
+}
+
+
+/***/ }),
+/* 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,16 +2570,34 @@ 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();
@@ -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 3f89881c043..f1997bd824e 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 00000000000..20456b057e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/DocumentOrShadowRoot-activeElement.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: DocumentOrShadowRoot.activeElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<body>
+<script>
+function createChildAndFocus(focusParent) {
+ const focused = document.createElement("div");
+ focused.tabIndex = 0;
+ focusParent.appendChild(focused);
+ focused.focus();
+ return focused;
+}
+
+test(() => {
+ const host = document.createElement("div");
+ const shadowRoot = host.attachShadow({ mode: "open" });
+ document.body.appendChild(host);
+
+ const focused = createChildAndFocus(shadowRoot);
+ assert_equals(document.activeElement, host);
+ assert_equals(shadowRoot.activeElement, focused);
+}, "activeElement on document & shadow root when focused element is in the shadow tree");
+
+test(() => {
+ const host = document.createElement("div");
+ const shadowRoot = host.attachShadow({ mode: "open" });
+ document.body.appendChild(host);
+
+ const focused = createChildAndFocus(document.body);
+ assert_equals(document.activeElement, focused);
+ assert_equals(shadowRoot.activeElement, null);
+}, "activeElement on document & shadow root when focused element is in the document");
+
+test(() => {
+ const host = document.createElement("div");
+ const shadowRoot = host.attachShadow({ mode: "open" });
+ shadowRoot.appendChild(document.createElement("slot"));
+ document.body.appendChild(host);
+
+ // Child of |host|, will be slotted to the slot in |shadowRoot|.
+ const focused = createChildAndFocus(host);
+ assert_equals(document.activeElement, focused);
+ assert_equals(shadowRoot.activeElement, null);
+}, "activeElement on document & shadow root when focused element is slotted");
+
+test(() => {
+ const host = document.createElement("div");
+ const shadowRoot = host.attachShadow({ mode: "open" });
+ document.body.appendChild(host);
+ const neighborHost = document.createElement("div");
+ const neighborShadowRoot = neighborHost.attachShadow({ mode: "open" });
+ document.body.appendChild(neighborHost);
+
+ const focused = createChildAndFocus(shadowRoot);
+ assert_equals(document.activeElement, host);
+ assert_equals(shadowRoot.activeElement, focused);
+ assert_equals(neighborShadowRoot.activeElement, null);
+}, "activeElement on a neighboring host when focused element is in another shadow tree");
+
+test(() => {
+ const host = document.createElement("div");
+ const shadowRoot = host.attachShadow({ mode: "open" });
+ document.body.appendChild(host);
+ const nestedHost = document.createElement("div");
+ const nestedShadowRoot = nestedHost.attachShadow({ mode: "open" });
+ shadowRoot.appendChild(nestedHost);
+
+ const focused = createChildAndFocus(nestedShadowRoot);
+ assert_equals(document.activeElement, host);
+ assert_equals(shadowRoot.activeElement, nestedHost);
+ assert_equals(nestedShadowRoot.activeElement, focused);
+}, "activeElement when focused element is in a nested shadow tree");
+
+test(() => {
+ const host = document.createElement("div");
+ const shadowRoot = host.attachShadow({ mode: "open" });
+ document.body.appendChild(host);
+ const nestedHost = document.createElement("div");
+ const nestedShadowRoot = nestedHost.attachShadow({ mode: "open" });
+ shadowRoot.appendChild(nestedHost);
+
+ const focused = createChildAndFocus(shadowRoot);
+ assert_equals(document.activeElement, host);
+ assert_equals(shadowRoot.activeElement, focused);
+ assert_equals(nestedShadowRoot.activeElement, null);
+}, "activeElement when focused element is in a parent shadow tree");
+</script>
+</body>
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 00000000000..ab25ea829bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-negative.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - the sequential focus navigation order with shadow dom and negative tabindex in shadow scope</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/shadow-utils.js"></script>
+<body>
+<script>
+// Structure:
+// <div #aboveHost tabindex=0>
+// <div #host tabindex=0>
+// #shadowRoot
+// <div #aboveSlot tabindex=-1>
+// <slot #slotAbove tabindex=-1>
+// (slotted) <div #slottedAbove tabindex=-1>
+// <slot #slotBelow tabindex=-1>
+// (slotted) <div #slottedBelow tabindex=-1>
+// <div #belowSlot tabindex=-1>
+// <div #belowHost tabindex=0>
+
+promise_test(() => {
+ let elementsInFlatTreeOrder;
+ let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
+ elementsInFlatTreeOrder = prepareDOM(document.body, false);
+ setTabIndex(elementsInFlatTreeOrder, -1);
+ setTabIndex([aboveHost, host, belowHost], 0);
+ resetFocus();
+ return assertFocusOrder([aboveHost, host, belowHost]);
+}, "Order when all elements in shadow tree has negative tabindex");
+</script>
+</body>
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 00000000000..3c9e70867c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0 except for one of the slot</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/shadow-utils.js"></script>
+<body>
+<script>
+// Structure:
+// <div #aboveHost tabindex=0>
+// <div #host tabindex=0>
+// #shadowRoot
+// <div #aboveSlot tabindex=0>
+// <slot #slotAbove tabindex=0>
+// (slotted) <div #slottedAbove tabindex=0>
+// <slot #slotBelow tabindex=1>
+// (slotted) <div #slottedBelow tabindex=0>
+// <div #belowSlot tabindex=0>
+// <div #belowHost tabindex=0>
+
+promise_test(() => {
+ let elementsInFlatTreeOrder;
+ let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
+ elementsInFlatTreeOrder = prepareDOM(document.body, false);
+ setTabIndex(elementsInFlatTreeOrder, 0);
+ slotBelow.tabIndex = 1;
+ resetFocus();
+ // Focus should move first according to flat tree order to #aboveHost and #host, then into #host's focus scope.
+ // It will then move to #slottedBelow because #slotBelow has tabindex=1 (though we actually won't focus on the slot),
+ // and then back to #host's focus scope again, finally getting out to the document focus scope.
+ return assertFocusOrder([aboveHost, host, slottedBelow, aboveSlot, slottedAbove, belowSlot, belowHost]);
+}, "Order when all tabindex=0, except for one slot that has tabindex=1");
+</script>
+</body>
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 00000000000..875e5b6814a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - the sequential focus navigation order with shadow dom with varying tabindex values</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/shadow-utils.js"></script>
+<body>
+<script>
+// Structure:
+// <div #aboveHost tabindex=3>
+// <div #host tabindex=3>
+// #shadowRoot
+// <div #aboveSlot tabindex=2>
+// <slot #slotAbove tabindex=1>
+// (slotted) <div #slottedAbove tabindex=4>
+// <slot #slotBelow tabindex=1>
+// (slotted) <div #slottedBelow tabindex=4>
+// <div #belowSlot tabindex=2>
+// <div #belowHost tabindex=3>
+
+promise_test(() => {
+ let elementsInFlatTreeOrder;
+ let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
+ elementsInFlatTreeOrder = prepareDOM(document.body, false);
+ setTabIndex([slotAbove, slotBelow], 1);
+ setTabIndex([aboveSlot, belowSlot], 2);
+ setTabIndex([aboveHost, host, belowHost], 3);
+ setTabIndex([slottedAbove, slottedBelow], 4);
+ resetFocus();
+ return assertFocusOrder([aboveHost, host, slottedAbove, slottedBelow, aboveSlot, belowSlot, belowHost]);
+}, "Order with various tabindex values");
+</script>
+</body>
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 00000000000..b491c7d237c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - the sequential focus navigation order with shadow dom and negative host tabindex</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/shadow-utils.js"></script>
+<body>
+<script>
+// Structure:
+// <div #aboveHost tabindex=0>
+// <div #host tabindex=-1>
+// #shadowRoot
+// <div #aboveSlot tabindex=0>
+// <slot #slotAbove tabindex=0>
+// (slotted) <div #slottedAbove tabindex=0>
+// <slot #slotBelow tabindex=0>
+// (slotted) <div #slottedBelow tabindex=0>
+// <div #belowSlot tabindex=0>
+// <div #belowHost tabindex=0>
+
+promise_test(() => {
+ let elementsInFlatTreeOrder;
+ let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
+ elementsInFlatTreeOrder = prepareDOM(document.body, false);
+ setTabIndex(elementsInFlatTreeOrder, 0);
+ host.tabIndex = -1;
+ resetFocus();
+ // Focus willl only move within the focus navigation scope of the document (not going to get into #host).
+ return assertFocusOrder([aboveHost, belowHost]);
+}, "Order when all tabindex=0 except for host, which has tabindex=-1");
+</script>
+</body>
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 00000000000..f2572614771
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - the sequential focus navigation order with shadow dom and non-focusable host</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/shadow-utils.js"></script>
+<body>
+<script>
+// Structure:
+// <div #aboveHost tabindex=0>
+// <div #host>
+// #shadowRoot
+// <div #aboveSlot tabindex=0>
+// <slot #slotAbove tabindex=0>
+// (slotted) <div #slottedAbove tabindex=0>
+// <slot #slotBelow tabindex=0>
+// (slotted) <div #slottedBelow tabindex=0>
+// <div #belowSlot tabindex=0>
+// <div #belowHost tabindex=0>
+
+promise_test(() => {
+ let elementsInFlatTreeOrder;
+ let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
+ elementsInFlatTreeOrder = prepareDOM(document.body, false);
+ setTabIndex(elementsInFlatTreeOrder, 0);
+ removeTabIndex([host]);
+ resetFocus();
+ // Focus should move in flat tree order since every one of them has tabindex ==0,
+ // but doesn't include #slot since it's not rendered and #host since its tabindex is not set
+ // (but #host is considered as 0 in focus scope navigation, keeping the flat tree order for the shadow root's descendants).
+ return assertFocusOrder(elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow && el !== host)));
+}, "Order when all tabindex=0 except host (tabindex not set)");
+</script>
+</body>
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 00000000000..1aa5292997a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0 except host (tabindex=1)</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/shadow-utils.js"></script>
+<body>
+<script>
+// Structure:
+// <div #aboveHost tabindex=0>
+// <div #host tabindex=1>
+// #shadowRoot
+// <div #aboveSlot tabindex=0>
+// <slot #slotAbove tabindex=0>
+// (slotted) <div #slottedAbove tabindex=0>
+// <slot #slotBelow tabindex=0>
+// (slotted) <div #slottedBelow tabindex=0>
+// <div #belowSlot tabindex=0>
+// <div #belowHost tabindex=0>
+
+promise_test(() => {
+ let elementsInFlatTreeOrder;
+ let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
+ elementsInFlatTreeOrder = prepareDOM(document.body, false);
+ setTabIndex(elementsInFlatTreeOrder, 0);
+ host.tabIndex = 1;
+ resetFocus();
+ // Focus should move first to #host because it has tabindex=1, and then to the contents of its scope
+ // (e.g. the contents of its shadow tree) in flat tree order, and then outside to the document scope
+ // again (aboveHost & belowHost).
+ return assertFocusOrder([host, aboveSlot, slottedAbove, slottedBelow, belowSlot, aboveHost, belowHost]);
+}, "Order when all tabindex=0 except for host, which has tabindex=1");
+</script>
+</body>
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 00000000000..d8b12ed8ac6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/shadow-utils.js"></script>
+<body>
+<script>
+// Structure:
+// <div #aboveHost tabindex=0>
+// <div #host tabindex=0>
+// #shadowRoot
+// <div #aboveSlot tabindex=0>
+// <slot #slotAbove tabindex=0>
+// (slotted) <div #slottedAbove tabindex=0>
+// <slot #slotBelow tabindex=0>
+// (slotted) <div #slottedBelow tabindex=0>
+// <div #belowSlot tabindex=0>
+// <div #belowHost tabindex=0>
+
+promise_test(() => {
+ let elementsInFlatTreeOrder;
+ let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] =
+ elementsInFlatTreeOrder = prepareDOM(document.body, false);
+ setTabIndex(elementsInFlatTreeOrder, 0);
+ resetFocus();
+ // Focus should move in flat tree order since every one of them has tabindex==0,
+ // but doesn't include slots.
+ return assertFocusOrder(elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow)));
+}, "Order when all tabindex=0 is and delegatesFocus = false");
+</script>
+</body>
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 00000000000..6ea372afdf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/focus/resources/shadow-utils.js
@@ -0,0 +1,79 @@
+// Structure:
+// <div #aboveHost>
+// <div #host>
+// #shadowRoot
+// <div #aboveSlot>
+// <slot #slotAbove>
+// (slotted) <div #slottedAbove>
+// <slot #slotBelow>
+// (slotted) <div #slottedBelow>
+// <div #belowSlot>
+// <div #belowHost>
+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 00000000000..7cd98964c24
--- /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 500979f5b37..813dd42e68a 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 00000000000..7813494a6a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/accumulate-values-width-animation.html
@@ -0,0 +1,110 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests values animation and accumulate='sum'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width to 100 in 10s with a wobbling animation -->
+<rect width="20" height="100" fill="green">
+ <animate id="an1" attributeName="width" dur="2s" values="0; 30; 20" accumulate="sum" repeatCount="5" fill="freeze"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 0, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 20, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 40, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 70, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample7() {
+ assert_approx_equals(rect.width.animVal.value, 60, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample8() {
+ assert_approx_equals(rect.width.animVal.value, 90, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample9() {
+ assert_approx_equals(rect.width.animVal.value, 80, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample10() {
+ assert_approx_equals(rect.width.animVal.value, 110, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample11() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.0, sample2],
+ ["an1", 1.999, sample3],
+ ["an1", 2.001, sample3],
+ ["an1", 3.0, sample4],
+ ["an1", 3.999, sample5],
+ ["an1", 4.001, sample5],
+ ["an1", 5.0, sample6],
+ ["an1", 5.999, sample7],
+ ["an1", 6.001, sample7],
+ ["an1", 7.0, sample8],
+ ["an1", 7.999, sample9],
+ ["an1", 8.001, sample9],
+ ["an1", 9.0, sample10],
+ ["an1", 9.999, sample11],
+ ["an1", 10.001, sample11],
+ ["an1", 11.0, sample11],
+ ["an1", 60.0, sample11]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..0899f5e0b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/additive-from-to-width-animation.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests multiple additive='sum' animations running at the same time</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 10 to 25 + additive=sum. This results in a change from 20 to 75 -->
+<!-- an3: Change width from 0 to 25 + additve=sum. This results in a final change from 20 to 100 -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" from="10" to="50" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="sum" fill="freeze" from="10" to="25" begin="0s" dur="4s"/>
+ <animate id="an3" attributeType="XML" attributeName="width" additive="sum" fill="freeze" from="0" to="25" begin="0s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 20, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 60, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 60.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..2dc7732dd6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/additive-type-by-animation.html
@@ -0,0 +1,275 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This by animation for all XML property types</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg id="svg" viewBox="0 0 300 300" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- All additive types except AnimatedPath are tested here -->
+<defs>
+ <marker id="marker" viewBox="0 0 10 10" markerWidth="4" markerHeight="3" refX="1" refY="5" orient="-45deg">
+ <polyline id="polyline" points="0,0 10,5 0,10 1,5" fill="green"/>
+ </marker>
+
+ <filter id="filter">
+ <feConvolveMatrix id="feConvolveMatrix" kernelUnitLength="20 30" kernelMatrix="0 1 0 0 1 0 0 1 0" divisor="37.5" order="6 6" targetX="5" preserveAlpha="false"/>
+ </filter>
+</defs>
+
+<!-- Non-additive types AnimatedBoolean, AnimatedEnumeration, AnimatedPreserveAspectRatio, AnimatedString are tested in non-additive-type-by-animation.svg -->
+
+<path id="path" d="M45,50 L55,50" transform="rotate(45)" stroke-width="10" stroke="green" marker-end="url(#marker)"/>
+<rect id="rect" y="0" width="100" height="100" fill="black" filter="url(#filter)"/>
+<text id="text" x="50" y="50" dy="5 -10 10 -10">ABCD</text>
+
+<!-- AnimatedAngle -->
+<animate id="an1" xlink:href="#marker" attributeName="orient" begin="0s" dur="4s" by="45deg" fill="freeze"/>
+
+<!-- AnimatedColor -->
+<animate xlink:href="#rect" attributeName="fill" begin="0s" dur="4s" by="green" fill="freeze"/>
+
+<!-- AnimatedLength -->
+<animate xlink:href="#rect" attributeName="y" begin="0s" dur="4s" by="100" fill="freeze"/>
+
+<!-- AnimatedLengthList -->
+<animate xlink:href="#text" attributeName="dy" begin="0s" dur="4s" by="-10 20 -20 20" fill="freeze"/>
+
+<!-- AnimatedNumberOptionalNumber -->
+<animate xlink:href="#feConvolveMatrix" attributeName="kernelUnitLength" begin="0s" dur="4s" by="-10 -20" fill="freeze"/>
+
+<!-- AnimatedNumber -->
+<animate xlink:href="#feConvolveMatrix" attributeName="divisor" begin="0s" dur="4s" by="-17.5" fill="freeze"/>
+
+<!-- AnimatedNumberList -->
+<animate xlink:href="#feConvolveMatrix" attributeName="kernelMatrix" begin="0s" dur="4s" by="2 1 3 2 1 3 2 1 3" fill="freeze"/>
+
+<!-- AnimatedIntegerOptionalInteger -->
+<animate xlink:href="#feConvolveMatrix" attributeName="order" begin="0s" dur="4s" by="-3 -3" fill="freeze"/>
+
+<!-- AnimatedInteger -->
+<animate xlink:href="#feConvolveMatrix" attributeName="targetX" begin="0s" dur="4s" by="-4" fill="freeze"/>
+
+<!-- AnimatedPoints -->
+<animate xlink:href="#polyline" attributeName="points" begin="0s" dur="4s" by="0,0 10,5 0,10 1,5" fill="freeze"/>
+
+<!-- AnimatedRect -->
+<animate xlink:href="#svg" attributeName="viewBox" begin="0s" dur="4s" by="0 0 -100 -100" fill="freeze"/>
+
+<!-- AnimatedTransformList -->
+<animateTransform xlink:href="#path" attributeName="transform" type="rotate" begin="0s" dur="4s" by="-45" fill="freeze"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function checkBaseVal() {
+ assert_equals(marker.orientAngle.baseVal.value, -45);
+ assert_equals(feConvolveMatrix.divisor.baseVal, 37.5);
+ assert_equals(feConvolveMatrix.orderX.baseVal, 6);
+ assert_equals(feConvolveMatrix.orderY.baseVal, 6);
+ assert_equals(feConvolveMatrix.targetX.baseVal, 5);
+ assert_equals(feConvolveMatrix.kernelUnitLengthX.baseVal, 20);
+ assert_equals(feConvolveMatrix.kernelUnitLengthY.baseVal, 30);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.numberOfItems, 9);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(0).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(1).value, 1);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(2).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(3).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(4).value, 1);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(5).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(6).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(7).value, 1);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(8).value, 0);
+ assert_equals(rect.y.baseVal.value, 0);
+ assert_equals(text.dy.baseVal.numberOfItems, 4);
+ assert_equals(text.dy.baseVal.getItem(0).value, 5);
+ assert_equals(text.dy.baseVal.getItem(1).value, -10);
+ assert_equals(text.dy.baseVal.getItem(2).value, 10);
+ assert_equals(text.dy.baseVal.getItem(3).value, -10);
+ assert_equals(svg.viewBox.baseVal.x, 0);
+ assert_equals(svg.viewBox.baseVal.y, 0);
+ assert_equals(svg.viewBox.baseVal.width, 300);
+ assert_equals(svg.viewBox.baseVal.height, 300);
+ assert_equals(polyline.points.numberOfItems, 4);
+ assert_equals(polyline.points.getItem(0).x, 0);
+ assert_equals(polyline.points.getItem(0).y, 0);
+ assert_equals(polyline.points.getItem(1).x, 10);
+ assert_equals(polyline.points.getItem(1).y, 5);
+ assert_equals(polyline.points.getItem(1).x, 10);
+ assert_equals(polyline.points.getItem(1).y, 5);
+ assert_equals(polyline.points.getItem(2).x, 0);
+ assert_equals(polyline.points.getItem(2).y, 10);
+ assert_equals(path.transform.baseVal.numberOfItems, 1);
+ assert_equals(path.transform.baseVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_equals(path.transform.baseVal.getItem(0).angle, 45);
+}
+
+function sample1() {
+ assert_approx_equals(marker.orientAngle.animVal.value, -45, epsilon);
+ assert_approx_equals(feConvolveMatrix.divisor.animVal, 37.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 6, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 6, epsilon);
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthX.animVal, 20, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthY.animVal, 30, epsilon);
+ assert_equals(feConvolveMatrix.kernelMatrix.animVal.numberOfItems, 9);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(0).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(1).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(2).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(3).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(4).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(5).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(6).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(7).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(8).value, 0, epsilon);
+ assert_approx_equals(rect.y.animVal.value, 0, epsilon);
+ assert_equals(text.dy.animVal.numberOfItems, 4);
+ assert_approx_equals(text.dy.animVal.getItem(0).value, 5, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(1).value, -10, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(2).value, 10, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(3).value, -10, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.x, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.y, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.width, 300, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.height, 300, epsilon);
+ assert_equals(polyline.animatedPoints.numberOfItems, 4);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).y, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 10, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 5, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 10, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 5, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).y, 10, epsilon);
+ assert_equals(path.transform.animVal.numberOfItems, 2);
+ assert_equals(path.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_equals(path.transform.animVal.getItem(0).angle, 45);
+ assert_equals(path.transform.animVal.getItem(1).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_approx_equals(path.transform.animVal.getItem(1).angle, 0, epsilon);
+ expectFillColor(rect, 0, 0, 0);
+ checkBaseVal();
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, -22.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.divisor.animVal, 28.75, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 5, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 5, epsilon);
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthX.animVal, 15, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthY.animVal, 20, epsilon);
+ assert_equals(feConvolveMatrix.kernelMatrix.animVal.numberOfItems, 9);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(0).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(1).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(2).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(3).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(4).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(5).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(6).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(7).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(8).value, 1.5, epsilon);
+ assert_approx_equals(rect.y.animVal.value, 50, epsilon);
+ assert_equals(text.dy.animVal.numberOfItems, 4);
+ assert_approx_equals(text.dy.animVal.getItem(0).value, 0, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(1).value, 0, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(2).value, 0, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(3).value, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.x, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.y, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.width, 250, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.height, 250, epsilon);
+ assert_equals(polyline.animatedPoints.numberOfItems, 4);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).y, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 15, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 7.5, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 15, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 7.5, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).y, 15, epsilon);
+ assert_equals(path.transform.animVal.numberOfItems, 2);
+ assert_equals(path.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_equals(path.transform.animVal.getItem(0).angle, 45);
+ assert_equals(path.transform.animVal.getItem(1).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_approx_equals(path.transform.animVal.getItem(1).angle, -22.5, epsilon);
+ expectFillColor(rect, 0, 63, 0);
+ checkBaseVal();
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.divisor.animVal, 20, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthX.animVal, 10, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthY.animVal, 10, epsilon);
+ assert_equals(feConvolveMatrix.kernelMatrix.animVal.numberOfItems, 9);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(0).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(1).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(2).value, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(3).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(4).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(5).value, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(6).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(7).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(8).value, 3, epsilon);
+ assert_approx_equals(rect.y.animVal.value, 100, epsilon);
+ assert_equals(text.dy.animVal.numberOfItems, 4);
+ assert_approx_equals(text.dy.animVal.getItem(0).value, -5, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(1).value, 10, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(2).value, -10, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(3).value, 10, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.x, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.y, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.width, 200, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.height, 200, epsilon);
+ assert_equals(polyline.animatedPoints.numberOfItems, 4);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).y, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 20, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 10, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 20, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 10, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).y, 20, epsilon);
+ assert_equals(path.transform.animVal.numberOfItems, 2);
+ assert_equals(path.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_equals(path.transform.animVal.getItem(0).angle, 45);
+ assert_equals(path.transform.animVal.getItem(1).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_approx_equals(path.transform.animVal.getItem(1).angle, -45, epsilon);
+ expectFillColor(rect, 0, 128, 0);
+ checkBaseVal();
+}
+
+smil_async_test((t) => {
+ marker = rootSVGElement.ownerDocument.getElementsByTagName("marker")[0];
+ filter = rootSVGElement.ownerDocument.getElementsByTagName("filter")[0];
+ feConvolveMatrix = rootSVGElement.ownerDocument.getElementsByTagName("feConvolveMatrix")[0];
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+ svg = rootSVGElement.ownerDocument.getElementsByTagName("svg")[0];
+ path = rootSVGElement.ownerDocument.getElementsByTagName("path")[0];
+ polyline = rootSVGElement.ownerDocument.getElementsByTagName("polyline")[0];
+ text = rootSVGElement.ownerDocument.getElementsByTagName("text")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..5b874f5a4f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/additive-values-width-animation.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests values animation and additive='sum'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 0 to 50 to 100, all linear interpolated. As additive is set to sum it should add the current baseValue
+ to the new animated value each time a value from the values list is consumed. Expected:
+ At 0s, width=10, at 2s, width=50+10=60, at 4s, width=100+10=110.
+
+ Our testing harness will change the baseValue from 10 to 60 at 5s. The current animated value (before the script change)
+ is: <baseValue>+<animValue>: 10 + (100/6*5) = 93.333 at this point. As we change the baseValue to 60, the equation now looks like:
+ 60 + (100/6*5) = 143.333. Before the script change the last second of the animation would have animated width from 85 to 110.
+ Due the script change its now animating from 93.999 to 143.333 during the last second.
+-->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" additive="sum" values="0; 50; 100" begin="0s" dur="6s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 60, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 93.3, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function changeBaseVal() {
+ // At 5s, only change the baseVal.
+ rect.width.baseVal.value = 60;
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 143.33, epsilon);
+ assert_equals(rect.width.baseVal.value, 60);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 160, epsilon);
+ assert_equals(rect.width.baseVal.value, 60);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 3.0, sample2],
+ ["an1", 4.999, sample3],
+ ["an1", 5.0, changeBaseVal],
+ ["an1", 5.001, sample4],
+ ["an1", 6.001, sample5],
+ ["an1", 60.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..5ce9bcc763e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-by.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with by animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("by", "-100");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ 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 00000000000..1f15760c7d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-by.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with from-by animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("from", "100");
+animate.setAttribute("by", "-100");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ 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 00000000000..4d608008314
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-from-to.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with from-to animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("from", "100");
+animate.setAttribute("to", "0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ 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 00000000000..4a26cd716ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-to.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with to animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("to", "0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ 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 00000000000..46952aa45db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-calcMode-spline-values.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with values animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("values", "100;0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ 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 00000000000..980f39282e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-color-calcMode-discrete.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode discrete with from-to animation on colors. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("color", "rgb(128,255,255)");
+rect.setAttribute("fill", "currentColor");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "color");
+animate.setAttribute("from", "rgb(255,0,0)");
+animate.setAttribute("to", "rgb(0,255,255)");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("calcMode", "discrete");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ expectFillColor(rect, 128, 255, 255);
+}
+
+function sample2() {
+ expectFillColor(rect, 255, 0, 0);
+}
+
+function sample3() {
+ expectFillColor(rect, 0, 255, 255);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..2780ce2ac9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-color-fill-currentColor.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation on 'currentColor'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "currentColor");
+rect.setAttribute("color", "red");
+rect.setAttribute("onclick", "executeTest()");
+
+var animateColor = createSVGElement("animate");
+animateColor.setAttribute("id", "animateColor");
+animateColor.setAttribute("attributeName", "color");
+animateColor.setAttribute("from", "red");
+animateColor.setAttribute("to", "green");
+animateColor.setAttribute("dur", "3s");
+animateColor.setAttribute("begin", "0s");
+animateColor.setAttribute("fill", "freeze");
+rect.appendChild(animateColor);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+
+ expectFillColor(rect, 255, 0, 0);
+}
+
+function sample2() {
+
+ expectFillColor(rect, 128, 64, 0);
+}
+
+function sample3() {
+
+ expectFillColor(rect, 0, 128, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animateColor", 0.0, sample1],
+ ["animateColor", 1.5, sample2],
+ ["animateColor", 3.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..410b27b75a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-color-fill-from-by.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation on 'currentColor'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "currentColor");
+rect.setAttribute("color", "#d00000");
+rect.setAttribute("onclick", "executeTest()");
+
+var animateColor = createSVGElement("animate");
+animateColor.setAttribute("id", "animateColor");
+animateColor.setAttribute("attributeName", "color");
+animateColor.setAttribute("from", "#d00000");
+animateColor.setAttribute("by", "#0000d0");
+animateColor.setAttribute("dur", "3s");
+animateColor.setAttribute("begin", "0s");
+animateColor.setAttribute("fill", "freeze");
+rect.appendChild(animateColor);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+
+ expectFillColor(rect, 208, 0, 0);
+}
+
+function sample2() {
+
+ expectFillColor(rect, 208, 0, 104);
+}
+
+function sample3() {
+
+ expectFillColor(rect, 208, 0, 208);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animateColor", 0.0, sample1],
+ ["animateColor", 1.5, sample2],
+ ["animateColor", 3.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..e2a946cfb0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-color-transparent.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests that 'transparent' is treated as a valid color.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "test");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "#00FF00");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "fill");
+animate.setAttribute("from", "transparent");
+animate.setAttribute("by", "red");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("begin", "0s");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function expectTransparent() {
+ expectFillColor(rect, 0, 255, 0);
+}
+
+function expectOtherColor() {
+ expectFillColor(rect, 127, 0, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, expectTransparent],
+ ["animation", 1.5, expectOtherColor]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..4494eb77369
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-css-xml-attributeType.html
@@ -0,0 +1,88 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests that XML and CSS attributeTypes can be switched between.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var polygon = createSVGElement("polygon");
+polygon.setAttribute("id", "polygon");
+polygon.setAttribute("points", "100 0 200 0 200 100 100 100");
+polygon.setAttribute("fill", "green");
+polygon.setAttribute("onclick", "executeTest()");
+
+var set = createSVGElement("set");
+set.setAttribute("id", "set");
+set.setAttribute("attributeName", "points");
+set.setAttribute("attributeType", "XML");
+set.setAttribute("to", "300 0 400 0 400 100 300 100");
+set.setAttribute("begin", "0s");
+polygon.appendChild(set);
+rootSVGElement.appendChild(polygon);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 100, epsilon);
+ assert_equals(polygon.points.getItem(0).x, 100);
+}
+
+function sample2() {
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 300, epsilon);
+ // change the animationType to CSS which is invalid.
+ set.setAttribute("attributeType", "CSS");
+}
+
+function sample3() {
+ // verify that the animation resets.
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 100, epsilon);
+ // change the animation to a CSS animatable value.
+ set.setAttribute("attributeName", "opacity");
+ set.setAttribute("to", "0.8");
+}
+
+function sample4() {
+ assert_approx_equals(parseFloat(getComputedStyle(polygon).opacity), 0.8, epsilon);
+ // change the animation to a non-CSS animatable value.
+ set.setAttribute("attributeName", "points");
+ set.setAttribute("to", "200 0 300 0 300 100 200 100");
+}
+
+function sample5() {
+ // verify that the animation does not run.
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 100, epsilon);
+ assert_approx_equals(parseFloat(getComputedStyle(polygon).opacity), 1.0, epsilon);
+ // change the animationType to XML which is valid.
+ set.setAttribute("attributeType", "XML");
+}
+
+function sample6() {
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 200, epsilon);
+ assert_equals(polygon.points.getItem(0).x, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["set", 0.0, sample1],
+ ["set", 0.5, sample2],
+ ["set", 1.0, sample3],
+ ["set", 1.5, sample4],
+ ["set", 2.0, sample5],
+ ["set", 2.5, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ 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 00000000000..a8b3c1f16f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-currentColor.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation on 'currentColor'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "red");
+rect.setAttribute("color", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animateCurrentColor = createSVGElement("animate");
+animateCurrentColor.setAttribute("id", "animateCurrentColor");
+animateCurrentColor.setAttribute("attributeName", "fill");
+animateCurrentColor.setAttribute("from", "red");
+animateCurrentColor.setAttribute("to", "currentColor");
+animateCurrentColor.setAttribute("dur", "3s");
+animateCurrentColor.setAttribute("begin", "0s");
+animateCurrentColor.setAttribute("fill", "freeze");
+rect.appendChild(animateCurrentColor);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial conditions
+ expectFillColor(rect, 255, 0, 0);
+}
+
+function sample2() {
+ // Check half-time conditions
+ expectFillColor(rect, 128, 64, 0);
+}
+
+function sample3() {
+ // Check end condition
+ expectFillColor(rect, 0, 128, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animateCurrentColor", 0.0, sample1],
+ ["animateCurrentColor", 1.5, sample2],
+ ["animateCurrentColor", 3.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..47ca52526ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-dynamic-update-attributeName.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test behavior on dynamic-update of attributeName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "red");
+rect.setAttribute("color", "red");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "color");
+animate.setAttribute("from", "green");
+animate.setAttribute("to", "green");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("fill", "freeze");
+animate.setAttribute("calcMode", "discrete");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ expectColor(rect, 255, 0, 0);
+ assert_equals(rect.style.color, "");
+}
+
+function sample2() {
+ expectColor(rect, 0, 128, 0);
+ assert_equals(rect.style.color, "");
+}
+
+function sample3() {
+ // Set 'attributeName' from 'color' to 'fill'
+ animate.setAttribute("attributeName", "fill");
+}
+
+function sample4() {
+ expectFillColor(rect, 0, 128, 0);
+ assert_equals(rect.style.color, "");
+ assert_equals(rect.style.fill, "");
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 1.5, sample3],
+ ["animation", 3.0, sample4],
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..31f34ce56f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-02-t-drt.html
@@ -0,0 +1,183 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-09.svg -->
+<!-- renamed for 1.1 suite to animate-elem-02-t.svg -->
+<!-- -->
+<!-- Test 'additive' and 'accumulate' attributes. -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Rick Graham Feb/05/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg version="1.1" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root"
+ width="100%" height="100%" viewBox="0 0 480 360">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+<!--nav data here-->
+ <OperatorScript version="$Revision: 1.8 $" testname="animate-elem-02-t.svg">
+ <Paragraph>
+ Test 'additive' and 'accumulate' attributes.
+ </Paragraph>
+ <Paragraph>
+ 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.
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-02-t</title>
+ <desc id="test-desc">Test 'additive' and 'accumulate' attributes.</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content" font-family="Arial" font-size="30">
+
+ <g transform="translate(0, 0)">
+ <rect x="60" y="20" width="50" height="200" fill="#dfdfdf" stroke="#dfdfdf" stroke-width="4"/>
+ <line x1="40" x2="100" y1="220" y2="220" fill="none" stroke="#880000" stroke-width="4"/>
+ <line x1="40" x2="100" y1="120" y2="120" fill="none" stroke="#880000" stroke-width="4"/>
+ <rect x="60" y="20" width="50" height="20" fill="#0f5" stroke="#085" stroke-width="4">
+ <animate id="an5" attributeName="height" calcMode="discrete" additive="replace" accumulate="none"
+ repeatCount="2" from="200" to="20" begin="0s" dur="4s" fill="freeze"/>
+ </rect>
+ <text x="30" y="285" fill="navy">anim.5</text>
+ </g>
+ <g transform="translate(110, 0)">
+ <rect x="60" y="20" width="50" height="200" fill="#dfdfdf" stroke="#dfdfdf" stroke-width="4"/>
+ <line x1="40" x2="100" y1="220" y2="220" fill="none" stroke="#880000" stroke-width="4"/>
+ <line x1="40" x2="100" y1="120" y2="120" fill="none" stroke="#880000" stroke-width="4"/>
+ <rect x="60" y="20" width="50" height="20" fill="#0f5" stroke="#085" stroke-width="4">
+ <animate id="an6" attributeName="height" calcMode="discrete" additive="sum" accumulate="none"
+ repeatCount="2" from="200" to="20" begin="0s" dur="4s" fill="freeze"/>
+ </rect>
+ <text x="30" y="285" fill="navy">anim.6</text>
+ </g>
+ <g transform="translate(220, 0)">
+ <rect x="60" y="20" width="50" height="200" fill="#dfdfdf" stroke="#dfdfdf" stroke-width="4"/>
+ <line x1="40" x2="100" y1="220" y2="220" fill="none" stroke="#880000" stroke-width="4"/>
+ <line x1="40" x2="100" y1="120" y2="120" fill="none" stroke="#880000" stroke-width="4"/>
+ <rect x="60" y="20" width="50" height="20" fill="#0f5" stroke="#085" stroke-width="4">
+ <animate id="an7" attributeName="height" calcMode="discrete" additive="replace" accumulate="sum"
+ repeatCount="2" from="200" to="20" begin="0s" dur="4s" fill="freeze"/>
+ </rect>
+ <text x="30" y="285" fill="navy">anim.7</text>
+ </g>
+ <g transform="translate(330, 0)">
+ <rect x="60" y="20" width="50" height="200" fill="#dfdfdf" stroke="#dfdfdf" stroke-width="4"/>
+ <line x1="40" x2="100" y1="220" y2="220" fill="none" stroke="#880000" stroke-width="4"/>
+ <line x1="40" x2="100" y1="120" y2="120" fill="none" stroke="#880000" stroke-width="4"/>
+ <rect x="60" y="20" width="50" height="20" fill="#0f5" stroke="#085" stroke-width="4">
+ <animate id="an8" attributeName="height" calcMode="discrete" additive="sum" accumulate="sum"
+ repeatCount="2" from="200" to="20" begin="0s" dur="4s" fill="freeze"/>
+ </rect>
+ <text x="30" y="285" fill="navy">anim.8</text>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.8 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ </g>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sampleAfterBegin() {
+ assert_equals(rect1.height.animVal.value, 200);
+ assert_equals(rect1.height.baseVal.value, 20);
+
+ assert_equals(rect2.height.animVal.value, 220);
+ assert_equals(rect2.height.baseVal.value, 20);
+
+ assert_equals(rect3.height.animVal.value, 200);
+ assert_equals(rect3.height.baseVal.value, 20);
+}
+
+function sampleAfterMid() {
+ assert_equals(rect1.height.animVal.value, 20);
+ assert_equals(rect1.height.baseVal.value, 20);
+
+ assert_equals(rect2.height.animVal.value, 40);
+ assert_equals(rect2.height.baseVal.value, 20);
+
+ assert_equals(rect3.height.animVal.value, 20);
+ assert_equals(rect3.height.baseVal.value, 20);
+}
+
+function sampleAfterBeginOfFirstRepetition() {
+ assert_equals(rect1.height.animVal.value, 200);
+ assert_equals(rect1.height.baseVal.value, 20);
+
+ assert_equals(rect2.height.animVal.value, 220);
+ assert_equals(rect2.height.baseVal.value, 20);
+
+ assert_equals(rect3.height.animVal.value, 220);
+ assert_equals(rect3.height.baseVal.value, 20);
+}
+
+function sampleAfterMidOfFirstRepetition() {
+ assert_equals(rect1.height.animVal.value, 20);
+ assert_equals(rect1.height.baseVal.value, 20);
+
+ assert_equals(rect2.height.animVal.value, 40);
+ assert_equals(rect2.height.baseVal.value, 20);
+
+ assert_equals(rect3.height.animVal.value, 40);
+ assert_equals(rect3.height.baseVal.value, 20);
+}
+
+smil_async_test((t) => {
+ rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[1];
+ rect2 = rects[3];
+ rect3 = rects[5];
+ rect4 = rects[7];
+
+ // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an5", 0.0, sampleAfterBegin],
+ ["an5", 1.999, sampleAfterBegin],
+ ["an5", 2.0, sampleAfterMid],
+ ["an5", 3.999, sampleAfterMid],
+ ["an5", 4.0, sampleAfterBeginOfFirstRepetition],
+ ["an5", 5.999, sampleAfterBeginOfFirstRepetition],
+ ["an5", 6.001, sampleAfterMidOfFirstRepetition],
+ ["an5", 7.999, sampleAfterMidOfFirstRepetition],
+ ["an5", 8.001, sampleAfterMidOfFirstRepetition],
+ ["an5", 60.0, sampleAfterMidOfFirstRepetition]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..64fc35f596f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-14-t-drt.html
@@ -0,0 +1,140 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-14-t.svg -->
+<!-- renamed and split for svgt/b to animate-elem-07-t-a.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.6 $" testname="animate-elem-14-t.svg">
+ <Paragraph>
+ Test 'calcMode'=discrete
+ </Paragraph>
+ <Paragraph>
+ 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.
+ </Paragraph>
+ <Paragraph>
+ This test shows an animation with calcMode="discrete" (i.e., a jumping animation).
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-14-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="discrete"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.2;.4;.6"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">2</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">4</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">6</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="discrete" values="300;255;180;30" keyTimes="0;.2;.4;.6" begin="0s" dur="10s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.6 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2s to 4s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 4s to 6s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 6s to 10s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.2;.4;.6" begin="0s" dur="10s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample1],
+ ["an1", 2.001, sample2],
+ ["an1", 3.999, sample2],
+ ["an1", 4.001, sample3],
+ ["an1", 5.999, sample3],
+ ["an1", 6.001, sample4],
+ ["an1", 7.001, sample4],
+ ["an1", 8.001, sample4],
+ ["an1", 9.001, sample4],
+ ["an1", 9.999, sample4],
+ ["an1", 10.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..9d5cb1b437b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-15-t-drt.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-15-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.5 $" testname="animate-elem-15-t.svg">
+ <Paragraph>
+ Test 'calcMode'=paced
+ </Paragraph>
+ <Paragraph>
+ 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.
+ </Paragraph>
+ <Paragraph>
+ This test shows calcMode="paced" for an animation that has constant velocity, thus showing how 'values'
+ and 'keyTimes' are ignored.
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-15-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="paced"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.25;.5;1"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="230" y="140">1.5</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">4</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">9</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="paced" values="300;255;180;30" keyTimes="0;.25;.5;1" begin="0s" dur="9s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.5 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2.25s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2.25s to 4.5s
+ assert_approx_equals(rect.width.animVal.value, 232.5, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 4.5s to 9s
+ assert_approx_equals(rect.width.animVal.value, 165, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 9s to 9s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.25;.5;1" begin="0s" dur="9s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.249, sample2],
+ ["an1", 2.251, sample2],
+ ["an1", 4.499, sample3],
+ ["an1", 4.501, sample3],
+ ["an1", 8.999, sample4],
+ ["an1", 9.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..0ac98e2fc80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-16-t-drt.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-16-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.1 $" testname="animate-elem-07-t-c.svg">
+ <Paragraph>
+ Test 'calcMode'=linear
+ </Paragraph>
+ <Paragraph>
+ 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.
+ </Paragraph>
+ <Paragraph>
+ This test shows an animation with calcMode="linear".
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-16-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="linear"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.25;.5;1"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">2</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">4</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">8</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="linear" values="300;255;180;30" keyTimes="0;.25;.5;1" begin="0s" dur="8s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.1 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2s to 4s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 4s to 8s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 8s to 8s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.25;.5;1" begin="0s" dur="8s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample2],
+ ["an1", 2.001, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample3],
+ ["an1", 7.999, sample4],
+ ["an1", 8.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..1b101491953
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-17-t-drt.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-17-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.6 $" testname="animate-elem-17-t.svg">
+ <Paragraph>
+ Test 'calcMode'=spline
+ </Paragraph>
+ <Paragraph>
+ 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.
+ </Paragraph>
+ <Paragraph>
+ 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.
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-17-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="spline"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.25;.5;1"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">2</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">4</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">8</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="spline" values="300;255;180;30" keyTimes="0;.25;.5;1" keySplines="0,0,1,1;0,0,1,1;1,0,0,1" begin="0s" dur="8s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.6 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2s to 4s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 4s to 8s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 8s to 8s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.25;.5;1" keySplines="0,0,1,1;0,0,1,1;1,0,0,1" begin="0s" dur="8s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample2],
+ ["an1", 2.001, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample3],
+ ["an1", 7.999, sample4],
+ ["an1", 8.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..4f9dbb77658
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-18-t-drt.html
@@ -0,0 +1,137 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-18-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.1 $" testname="animate-elem-07-t-e.svg">
+ <Paragraph>
+ Test 'calcMode'=discrete
+ </Paragraph>
+ <Paragraph>
+ 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.
+ </Paragraph>
+ <Paragraph>
+ This test shows an animation with calcMode="discrete" (i.e., a jumping animation).
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-18-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="discrete"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.2;.6;.8"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">2</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">6</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">8</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="discrete" values="300;255;180;30" keyTimes="0;.2;.6;.8" begin="0s" dur="10s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.1 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2s to 6s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 6s to 8s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 8s to 10s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.2;.6;.8" begin="0s" dur="10s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample1],
+ ["an1", 2.001, sample2],
+ ["an1", 5.999, sample2],
+ ["an1", 6.001, sample3],
+ ["an1", 7.999, sample3],
+ ["an1", 8.001, sample4],
+ ["an1", 9.999, sample4],
+ ["an1", 10.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..9b9d61c90bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-elem-19-t-drt.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-19-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.6 $" testname="animate-elem-19-t.svg">
+ <Paragraph>
+ Test 'calcMode'=linear
+ </Paragraph>
+ <Paragraph>
+ 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.
+ </Paragraph>
+ <Paragraph>
+ This test shows an animation with calcMode="linear".
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-19-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="linear"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.5;.75;1"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">4</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">6</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">8</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="linear" values="300;255;180;30" keyTimes="0;.5;.75;1" begin="0s" dur="8s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.6 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 4s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 4s to 6s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 6s to 8s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 8s to 8s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: values="300;255;180;30" keyTimes="0;.5;.75;1" begin="0s" dur="8s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 3.999, sample2],
+ ["an1", 4.001, sample2],
+ ["an1", 5.999, sample3],
+ ["an1", 6.001, sample3],
+ ["an1", 7.999, sample4],
+ ["an1", 8.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..d0515ac850e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-end-attribute-numeric-precision.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests end conditions are respected properly near the limits of float numeric precision</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("values", "0;300");
+animate.setAttribute("begin", "0.333333333333333s");
+animate.setAttribute("dur", "0.4256483205159505s");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.x.animVal.value, 300, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+var animationStartsImmediately = true;
+
+</script> \ 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 00000000000..aab9eacff26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-fill-freeze-with-repeatDur.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for animation freeze when repeatDur is not a multiple of dur</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <rect x='0' y='0' width='50' height='50' fill='green'>
+ <animate id="anim" attributeName='x' from='0' to='100' dur='4s' begin='0s' repeatDur="6s" accumulate="sum" fill='freeze'/>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect1.x.animVal.value, 150, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 6.0, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..7295bcdb630
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-from-to-keyTimes.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests discrete from-to-keyTimes animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("to", "200");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;0.25");
+animate.setAttribute("calcMode", "discrete");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_equals(rect.x.animVal.value, 100);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_equals(rect.x.animVal.value, 200);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.5, sample1],
+ ["animation", 1.5, sample2],
+ ["animation", 2.5, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ 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 00000000000..ddb9946fda6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-gradient-transform.html
@@ -0,0 +1,103 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests if gradientTransform of a gradient is animateable.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var gradient = createSVGElement("linearGradient");
+gradient.setAttribute("id", "gradient");
+gradient.setAttribute("gradientUnits", "userSpaceOnUse");
+gradient.setAttribute("x1", "0");
+gradient.setAttribute("x2", "200");
+gradient.setAttribute("gradientTransform", "translate(0)");
+
+var stop1 = createSVGElement("stop");
+stop1.setAttribute("offset", "0");
+stop1.setAttribute("stop-color", "green");
+
+var stop2 = createSVGElement("stop");
+stop2.setAttribute("offset", "1");
+stop2.setAttribute("stop-color", "red");
+
+var animate = createSVGElement("animateTransform");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "gradientTransform");
+animate.setAttribute("type", "translate");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "200");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("fill", "freeze");
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("fill", "url(#gradient)");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("onclick", "executeTest()");
+
+gradient.appendChild(stop1);
+gradient.appendChild(stop2);
+gradient.appendChild(animate);
+
+rootSVGElement.appendChild(gradient);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial conditions
+ shouldThrow("gradient.gradientTransform.animVal.consolidate()");
+ assert_equals(gradient.gradientTransform.animVal.numberOfItems, 1);
+ assert_approx_equals(gradient.gradientTransform.animVal.getItem(0).matrix.e, 0, epsilon);
+ assert_equals(gradient.gradientTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+
+ assert_equals(gradient.gradientTransform.baseVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).matrix.e, 0);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_equals(gradient.gradientTransform.animVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_approx_equals(gradient.gradientTransform.animVal.getItem(0).matrix.e, 100, epsilon);
+
+ assert_equals(gradient.gradientTransform.baseVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).matrix.e, 0);
+}
+
+function sample3() {
+ // Check end conditions
+ assert_equals(gradient.gradientTransform.animVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_approx_equals(gradient.gradientTransform.animVal.getItem(0).matrix.e, 200, epsilon);
+
+ assert_equals(gradient.gradientTransform.baseVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).matrix.e, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..a8b56bab2bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-inherit-css-property.html
@@ -0,0 +1,69 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation with 'inherit'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var g = createSVGElement("g");
+g.setAttribute("fill", "green");
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "red");
+rect.setAttribute("onclick", "executeTest()");
+g.appendChild(rect);
+
+var animateInherit = createSVGElement("animate");
+animateInherit.setAttribute("id", "animateInherit");
+animateInherit.setAttribute("attributeName", "fill");
+animateInherit.setAttribute("from", "red");
+animateInherit.setAttribute("to", "inherit");
+animateInherit.setAttribute("dur", "3s");
+animateInherit.setAttribute("begin", "0s");
+animateInherit.setAttribute("fill", "freeze");
+rect.appendChild(animateInherit);
+rootSVGElement.appendChild(g);
+
+// Setup animation test
+function sample1() {
+ // Check initial conditions
+ expectFillColor(rect, 255, 0, 0);
+ assert_equals(rect.style.fill, "");
+}
+
+function sample2() {
+ // Check half-time conditions
+ expectFillColor(rect, 128, 64, 0);
+ assert_equals(rect.style.fill, "");
+}
+
+function sample3() {
+ // Check end conditions
+ expectFillColor(rect, 0, 128, 0);
+ assert_equals(rect.style.fill, "");
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animateInherit", 0.0, sample1],
+ ["animateInherit", 1.5, sample2],
+ ["animateInherit", 3.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..5155391a912
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-insert-begin.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test behavior of dynamically inserting animate with begin attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("y", "45");
+rect.setAttribute("width", "10");
+rect.setAttribute("height", "10");
+rect.setAttribute("fill", "green");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("begin", "0");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "90");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect.x.animVal.value, 90, epsilon);
+ assert_equals(rect.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 3.0, sample2],
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..3db406ecd48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-insert-no-begin.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test behavior of dynamically inserting animate without begin attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("y", "45");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "90");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect.x.animVal.value, 90, epsilon);
+ assert_equals(rect.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 3.0, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ 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 00000000000..0b02f71d3fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-keySplines.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Testing correct parsing of keySplines.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("fill", "green");
+rect.setAttribute("x", "0");
+rect.setAttribute("y", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "height");
+animate.setAttribute("calcMode", "spline");
+animate.setAttribute("keyTimes", " 0 ; 0.3333333 ; 0.666666; 1 ");
+animate.setAttribute("keySplines", " 0 ,0 1 , 1 ; 0 0 , 1 , 1 ; .75 , 0 , 0 , .75 ; ");
+animate.setAttribute("values", "200;167;111;0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "9s");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.height.animVal.value, 167, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.height.animVal.value, 111, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.height.animVal.value, 0, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+function sample4() {
+ // Check end conditions
+ assert_approx_equals(rect.height.animVal.value, 100, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 3.0, sample1],
+ ["animation", 6.0, sample2],
+ ["animation", 8.999, sample3],
+ ["animation", 9.001, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..a9c16740e63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/animate-marker-orient-from-angle-to-angle.html
@@ -0,0 +1,104 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Animate SVGMarkerElement orientAttr from an angle to an angle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "2");
+marker.setAttribute("markerHeight", "2");
+marker.setAttribute("refX", "5");
+marker.setAttribute("refY", "5");
+marker.setAttribute("markerUnits", "strokeWidth");
+
+var markerPath = createSVGElement("path");
+markerPath.setAttribute("fill", "blue");
+markerPath.setAttribute("d", "M 5 0 L 10 10 L 0 10 Z");
+marker.appendChild(markerPath);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(marker);
+rootSVGElement.appendChild(defsElement);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("fill", "none");
+path.setAttribute("stroke", "green");
+path.setAttribute("stroke-width", "10");
+path.setAttribute("marker-start", "url(#marker)");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("d", "M 130 135 L 180 135 L 180 185");
+path.setAttribute("transform", "translate(-130, -120)");
+rootSVGElement.appendChild(path);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "orient");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("from", "90deg");
+animate1.setAttribute("to", "180deg");
+animate1.setAttribute("fill", "freeze");
+marker.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 135, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample4() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 2.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ 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 00000000000..bebd5372501
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/animations/syncbase-remove-add-while-running.html
@@ -0,0 +1,44 @@
+<!doctype html>
+
+<meta charset="utf-8">
+<title>Remove/Add syncbase while animation is running</title>
+<link rel="help" href="https://www.w3.org/TR/SMIL3/smil-timing.html#q26">
+<link rel="author" title="Edvard Thörnros" href="mailto:edvardt@opera.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<svg>
+ <animate id="anim" attributeName="visibility" to="visible" begin="10s" dur="2s"/>
+ <rect x="0" y="0" width="0" height="100" fill="#0F0">
+ <set attributeName="width" fill="freeze" to="100" begin="anim.begin"/>
+ </rect>
+</svg>
+
+<script>
+ document.querySelector("body").onload = async_test(function(t) {
+ let svg = document.querySelector("svg");
+ let rect = document.querySelector("rect");
+
+ window.requestAnimationFrame(t.step_func(function() {
+ window.requestAnimationFrame(t.step_func(function() {
+ var anim1 = document.getElementById("anim");
+ anim1.parentNode.removeChild(anim1);
+
+ var anim2 = document.createElementNS("http://www.w3.org/2000/svg", "animate");
+ anim2.setAttribute("id", "anim");
+ anim2.setAttribute("attributeName", "visibility");
+ anim2.setAttribute("to", "visible");
+ anim2.setAttribute("begin", "0s");
+ anim2.setAttribute("dur", "2s");
+ svg.appendChild(anim2);
+
+ window.requestAnimationFrame(t.step_func(function() {
+ window.requestAnimationFrame(t.step_func_done(function() {
+ svg.pauseAnimations();
+ assert_equals(rect.width.animVal.value, 100, "Sync base triggered");
+ }));
+ }));
+ }));
+ }));
+ });
+</script>
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 98e7ce75e51..de17089214e 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 @@ logger = logging.getLogger(__name__)
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 08e46b9a63e..3202a1a2df6 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 9b104c66bb6..eca4a30678c 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 @@ logger = logging.getLogger(__name__)
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 aadfcbd6a21..e99fcb0cc9f 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 fa45388d7b1..bb15c583981 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 99a2fe4d798..95160fea894 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 8783ff7e226..df674d931f4 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 @@ test_method_throw_exception('performance.measure("Exception4", "NonExistMark1",
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());
</script>
</body>
</html>
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 55cbd9246f9..0c4be9a3bcb 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 7b14797d962..3c1750f1f26 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 73bbb4f8ab5..5be4571493a 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 @@
<link rel="help" href="https://w3c.github.io/web-nfc/#dom-ndefmessage">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
+<script src="resources/nfc-helpers.js"></script>
<script>
test(() => {
diff --git a/tests/wpt/web-platform-tests/web-nfc/NDEFRecord_constructor.https.html b/tests/wpt/web-platform-tests/web-nfc/NDEFRecord_constructor.https.html
index 81148856473..e2e2c455072 100644
--- a/tests/wpt/web-platform-tests/web-nfc/NDEFRecord_constructor.https.html
+++ b/tests/wpt/web-platform-tests/web-nfc/NDEFRecord_constructor.https.html
@@ -3,7 +3,7 @@
<link rel="help" href="https://w3c.github.io/web-nfc/#dom-ndefrecord">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
+<script src="resources/nfc-helpers.js"></script>
<script>
test(() => {
diff --git a/tests/wpt/web-platform-tests/web-nfc/NFCReader-manual.https.html b/tests/wpt/web-platform-tests/web-nfc/NFCReader-manual.https.html
deleted file mode 100644
index a3171c3544e..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCReader-manual.https.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC: NFCReader tests</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-promise_test(async t => {
- const reader = new NFCReader();
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("reading");
- assert_true(event instanceof NFCReadingEvent);
-}, 'Test that nfc watch success if NFC HW is enabled.');
-
-promise_test(async t => {
- const reader = new NFCReader({url: "https://a.com"});
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("reading");
- assert_true(event instanceof NFCReadingEvent);
-}, 'Test that NFCReader.start succeeds if NFCReaderOptions.url is valid URL.');
-
-promise_test(async t => {
- const reader = new NFCReader({url: "https://a.com/*"});
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("reading");
- assert_true(event instanceof NFCReadingEvent);
-}, 'Test that NFCReader.start succeeds if NFCReaderOptions.url is valid URL with "*"' +
- ' wildcard character in path.');
-
-promise_test(async t => {
- const reader = new NFCReader({url: "https://a.com/*/bar"});
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("reading");
- assert_true(event instanceof NFCReadingEvent);
-}, 'Test that NFCReader.start succeeds if NFCReaderOptions.url is valid URL with "*"' +
- ' wildcard character in the beginning of path component followed by' +
- ' subpath.');
-
-promise_test(async t => {
- const reader = new NFCReader({url: ""});
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("reading");
- assert_true(event instanceof NFCReadingEvent);
-}, 'Test that NFCReader.start succeeds if NFCReaderOptions.url is empty.');
-
-</script>
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 3032b652edf..4488097d6eb 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 @@
<link rel="help" href="https://w3c.github.io/web-nfc/"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-
-<div id="log"></div>
-
+<script src="resources/nfc-helpers.js"></script>
<script>
"use strict";
@@ -17,24 +15,117 @@ function waitSyntaxErrorPromise(t, reader) {
const promise = readerWatcher.wait_for("error").then(event => {
assert_equals(event.error.name, 'SyntaxError');
});
- // NFCReader#start() synchronously dispatches the syntax error event.
+ // NFCReader#start() asynchronously dispatches the syntax error event.
reader.start();
return promise;
}
-promise_test(t => {
+promise_test(async t => {
const reader = new NFCReader({url: "www.a.com"});
- return waitSyntaxErrorPromise(t, reader);
-}, 'Test that NFCReader.start fails if NFCReaderOptions.url is missing components.');
+ await waitSyntaxErrorPromise(t, reader);
+}, "Test that NFCReader.start fails if NFCReaderOptions.url is missing \
+components.");
-promise_test(t => {
+promise_test(async t => {
const reader = new NFCReader({url: "invalid"});
- return waitSyntaxErrorPromise(t, reader);
-}, 'Test that NFCReader.start fails if NFCReaderOptions.url is invalid.');
+ await waitSyntaxErrorPromise(t, reader);
+}, "Test that NFCReader.start fails if NFCReaderOptions.url is invalid.");
-promise_test(t => {
+promise_test(async t => {
const reader = new NFCReader({url: "http://a.com"});
- return waitSyntaxErrorPromise(t, reader);
-}, 'Test that NFCReader.start fails if NFCReaderOptions.url has wrong protocol.');
+ await waitSyntaxErrorPromise(t, reader);
+}, "Test that NFCReader.start fails if NFCReaderOptions.url has wrong \
+protocol.");
+
+nfc_test(async (t, mockNFC) => {
+ const reader = new NFCReader();
+ const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
+ reader.start();
+ mockNFC.setHWStatus(NFCHWStatus.DISABLED);
+ const event = await readerWatcher.wait_for("error");
+ assert_equals(event.error.name, 'NotReadableError');
+}, "NFCReader.start should fail if NFC HW is disabled.");
+
+nfc_test(async (t, mockNFC) => {
+ const reader = new NFCReader();
+ const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
+ reader.start();
+ mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED);
+ const event = await readerWatcher.wait_for("error");
+ assert_equals(event.error.name, 'NotSupportedError');
+}, "NFCReader.start should fail if NFC HW is not supported.");
+
+nfc_test(async (t, mockNFC) => {
+ const reader = new NFCReader();
+ const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
+
+ mockNFC.setReadingMessage(createMessage([createTextRecord(test_text_data)]));
+ const promise = readerWatcher.wait_for("reading").then(event => {
+ assert_true(event instanceof NFCReadingEvent);
+ reader.stop();
+ });
+ // NFCReader#start() asynchronously dispatches the reading event.
+ reader.start();
+ await promise;
+}, "Test that nfc watch success if NFC HW is enabled.");
+
+nfc_test(async (t, mockNFC) => {
+ const reader = new NFCReader({url: "https://a.com"});
+ const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
+
+ mockNFC.setReadingMessage(createMessage([createTextRecord(test_text_data)]));
+ const promise = readerWatcher.wait_for("reading").then(event => {
+ assert_true(event instanceof NFCReadingEvent);
+ reader.stop();
+ });
+ // NFCReader#start() asynchronously dispatches the reading event.
+ reader.start();
+ await promise;
+}, "Test that NFCReader.start succeeds if NFCReaderOptions.url is valid URL.");
+
+nfc_test(async (t, mockNFC) => {
+ const reader = new NFCReader({url: "https://a.com/*"});
+ const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
+
+ mockNFC.setReadingMessage(createMessage([createTextRecord(test_text_data)]));
+ const promise = readerWatcher.wait_for("reading").then(event => {
+ assert_true(event instanceof NFCReadingEvent);
+ reader.stop();
+ });
+ // NFCReader#start() asynchronously dispatches the reading event.
+ reader.start();
+ await promise;
+}, "Test that NFCReader.start succeeds if NFCReaderOptions.url is valid URL \
+with '*' wildcard character in path.");
+
+nfc_test(async (t, mockNFC) => {
+ const reader = new NFCReader({url: "https://a.com/*/bar"});
+ const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
+
+ mockNFC.setReadingMessage(createMessage([createTextRecord(test_text_data)]));
+ const promise = readerWatcher.wait_for("reading").then(event => {
+ assert_true(event instanceof NFCReadingEvent);
+ reader.stop();
+ });
+ // NFCReader#start() asynchronously dispatches the reading event.
+ reader.start();
+ await promise;
+}, "Test that NFCReader.start succeeds if NFCReaderOptions.url is valid URL \
+with '*' wildcard character in the beginning of path component followed by \
+subpath.");
+
+nfc_test(async (t, mockNFC) => {
+ const reader = new NFCReader({url: ""});
+ const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
+
+ mockNFC.setReadingMessage(createMessage([createTextRecord(test_text_data)]));
+ const promise = readerWatcher.wait_for("reading").then(event => {
+ assert_true(event instanceof NFCReadingEvent);
+ reader.stop();
+ });
+ // NFCReader#start() asynchronously dispatches the reading event.
+ reader.start();
+ await promise;
+}, "Test that NFCReader.start succeeds if NFCReaderOptions.url is empty.");
</script>
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 00000000000..ebda3859834
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-nfc/NFCReader_options.https.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Web NFC: NFCReader option tests</title>
+<link rel="author" title="Intel" href="http://www.intel.com"/>
+<link rel="help" href="https://w3c.github.io/web-nfc/"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/nfc-helpers.js"></script>
+<script>
+
+'use strict';
+
+const NFCReaderOptionTests =
+ [
+ {
+ desc: "Test that reading data succeed when NFCReaderOptions'" +
+ " recordType is set to 'empty'.",
+ readOptions: {recordType: "empty"},
+ unmatchedReadOptions: {recordType: "json"},
+ message: createMessage([createRecord('empty', '')])
+ },
+ {
+ desc: "Test that reading data succeed when NFCReaderOptions'" +
+ " recordType is set to 'json'.",
+ readOptions: {recordType: "json"},
+ unmatchedReadOptions: {recordType: "url"},
+ message: createMessage([createJsonRecord(test_json_data)])
+ },
+ {
+ desc: "Test that reading data succeed when NFCReaderOptions'" +
+ " recordType is set to 'opaque'.",
+ readOptions: {recordType: "opaque"},
+ unmatchedReadOptions: {recordType: "json"},
+ message: createMessage([createOpaqueRecord(test_buffer_data)])
+ },
+ {
+ desc: "Test that reading data succeed when NFCReaderOptions'" +
+ " recordType is set to 'text'.",
+ readOptions: {recordType: "text"},
+ unmatchedReadOptions: {recordType: "json"},
+ message: createMessage([createTextRecord(test_text_data)])
+ },
+ {
+ desc: "Test that reading data succeed when NFCReaderOptions'" +
+ " recordType is set to 'url'.",
+ readOptions: {recordType: "url"},
+ unmatchedReadOptions: {recordType: "json"},
+ message: createMessage([createUrlRecord(test_url_data)])
+ },
+ {
+ desc: "Test that the url of NFCReaderOptions filters relevant data" +
+ " sources correctly.",
+ readOptions: {url: `${location.origin}/custom/path`},
+ unmatchedReadOptions: {url: `${location.origin}/custom/invalid`},
+ message: {url: `${location.origin}/custom/path/update`,
+ records: [createTextRecord(test_text_data)]}
+ },
+ {
+ desc: "Test that the mediaType of NFCReaderOptions filters relevant data" +
+ " sources correctly.",
+ readOptions: {mediaType: "application/octet-stream"},
+ unmatchedReadOptions: {mediaType: "application/json"},
+ message: createMessage([createOpaqueRecord(test_buffer_data)])
+ },
+ {
+ desc: "Test that the compatibility of NFCReaderOptions filters relevant data" +
+ " sources correctly.",
+ readOptions: {compatibility: "vendor"},
+ unmatchedReadOptions: {compatibility: "nfc-forum"},
+ message: createMessage([createTextRecord(test_text_data)]),
+ }
+ ];
+
+const ReadMultiMessagesTests =
+ [
+ {
+ desc: "Test that filtering 'empty' record from different messages" +
+ " correctly with NFCReaderOptions' recordType is set to 'empty'.",
+ readOptions: {recordType: "empty"},
+ message: createMessage([createRecord('empty', '')]),
+ unmatchedMessage: createMessage([createJsonRecord(test_json_data)]),
+ },
+ {
+ desc: "Test that filtering 'json' record from different messages" +
+ " correctly with NFCReaderOptions' recordType is set to 'json'.",
+ readOptions: {recordType: "json"},
+ message: createMessage([createJsonRecord(test_json_data)]),
+ unmatchedMessage: createMessage([createUrlRecord(test_url_data)])
+ },
+ {
+ desc: "Test that filtering 'opaque' record from different messages" +
+ " correctly with NFCReaderOptions' recordType is set to 'opaque'.",
+ readOptions: {recordType: "opaque"},
+ message: createMessage([createOpaqueRecord(test_buffer_data)]),
+ unmatchedMessage: createMessage([createJsonRecord(test_json_data)])
+ },
+ {
+ desc: "Test that filtering 'text' record from different messages" +
+ " correctly with NFCReaderOptions' recordType is set to 'text'.",
+ readOptions: {recordType: "text"},
+ message: createMessage([createTextRecord(test_text_data)]),
+ unmatchedMessage: createMessage([createUrlRecord(test_url_data)])
+ },
+ {
+ desc: "Test that filtering 'url' record from different messages" +
+ " correctly with NFCReaderOptions' recordType is set to 'url'.",
+ readOptions: {recordType: "url"},
+ message: createMessage([createUrlRecord(test_url_data)]),
+ unmatchedMessage: createMessage([createTextRecord(test_text_data)])
+ },
+ {
+ desc: "Test that filtering 'text' record from different messages" +
+ " correctly with NFCReaderOptions' url set.",
+ readOptions: {url: `${location.origin}/custom/path`},
+ message: {url: `${location.origin}/custom/path/update`,
+ records: [createTextRecord(test_text_data)]},
+ unmatchedMessage: {url: `${location.origin}/custom/invalid`,
+ records: [createUrlRecord(test_url_data)]}
+ },
+ {
+ desc: "Test that filtering 'opaque' record from different messages" +
+ " correctly with NFCReaderOptions' mediaType set.",
+ readOptions: {mediaType: "application/octet-stream"},
+ message: createMessage([createOpaqueRecord(test_buffer_data)]),
+ unmatchedMessage: createMessage([createJsonRecord(test_json_data)])
+ },
+ {
+ desc: "Test that filtering 'text' record from different messages" +
+ " correctly with NFCReaderOptions' compatibility set.",
+ readOptions: {compatibility: "nfc-forum"},
+ message: createMessage([createTextRecord(test_text_data)]),
+ unmatchedMessage: createMessage([createJsonRecord(test_json_data)]),
+ unmatchedCompatibility: "vendor"
+ }
+ ];
+
+for (let NFCReaderOptionTest of NFCReaderOptionTests) {
+ testNFCReaderOptions(
+ NFCReaderOptionTest.message,
+ NFCReaderOptionTest.readOptions,
+ NFCReaderOptionTest.unmatchedReadOptions,
+ NFCReaderOptionTest.desc
+ );
+}
+
+for (let readMultiMessagesTest of ReadMultiMessagesTests) {
+ // Sets default message's associated compatibility
+ let unmatchedCompatibility = "nfc-forum";
+ if(readMultiMessagesTest.unmatchedCompatibility)
+ unmatchedCompatibility = readMultiMessagesTest.unmatchedCompatibility;
+
+ testReadingMultiMessages(
+ readMultiMessagesTest.message,
+ readMultiMessagesTest.readOptions,
+ readMultiMessagesTest.unmatchedMessage,
+ unmatchedCompatibility,
+ readMultiMessagesTest.desc
+ );
+}
+</script>
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 faaf8f39a77..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_mediaType-manual.https.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: NFCReader NFCReaderOptions mediaType test</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-const desc = "Test that the mediaType of NFCReaderOptions filters relevant data sources correctly.";
-const readOptions = {mediaType: "application/octet-stream"};
-const unacceptableReadOptions = {mediaType: "application/json"};
-const message = createMessage([createOpaqueRecord(test_buffer_data)]);
-
-testNFCReaderOptions(message, readOptions, unacceptableReadOptions, desc);
-
-</script>
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 995072b260d..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_empty-manual.https.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: write and read empty records</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-const desc = "Test that write and read data succeed when NFCReaderOptions's recordType is set to 'empty'.";
-const readOptions = {recordType: "empty"};
-const unacceptableReadOptions = {recordType: "json"};
-const message = createMessage([createRecord('empty', '')]);
-
-testNFCReaderOptions(message, readOptions, unacceptableReadOptions, desc);
-
-</script>
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 4120bc72f30..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_json-manual.https.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: write and read json records</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-const desc = "Test that write and read data succeed when NFCReaderOptions's recordType is set to 'json'.";
-const readOptions = {recordType: "json"};
-const unacceptableReadOptions = {recordType: "url"};
-const message = createMessage([createJsonRecord(test_json_data)]);
-
-testNFCReaderOptions(message, readOptions, unacceptableReadOptions, desc);
-
-</script>
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 94ded3e8a0f..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_opaque-manual.https.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: write and read opaque records</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-const desc = "Test that write and read data succeed when NFCReaderOptions's recordType is set to 'opaque'.";
-const readOptions = {recordType: "opaque"};
-const unacceptableReadOptions = {recordType: "json"};
-const message = createMessage([createOpaqueRecord(test_buffer_data)]);
-
-testNFCReaderOptions(message, readOptions, unacceptableReadOptions, desc);
-
-</script>
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 72ca3e70d43..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_text-manual.https.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: write and read text records</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-const desc = "Test that write and read data succeed when NFCReaderOptions's recordType is set to 'text'.";
-const readOptions = {recordType: "text"};
-const unacceptableReadOptions = {recordType: "json"};
-const message = createMessage([createTextRecord(test_text_data)]);
-
-testNFCReaderOptions(message, readOptions, unacceptableReadOptions, desc);
-
-</script>
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 af57610c285..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_recordType_url-manual.https.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: write and read url records</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-const desc = "Test that write and read data succeed when NFCReaderOptions's recordType is set to 'url'.";
-const readOptions = {recordType: "url"};
-const unacceptableReadOptions = {recordType: "json"};
-const message = createMessage([createUrlRecord(test_url_data)]);
-
-testNFCReaderOptions(message, readOptions, unacceptableReadOptions, desc);
-
-</script>
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 aa0e72b089a..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCReader_options_url-manual.https.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: NFCReader NFCReaderOptions url test</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-const desc = "Test that the url of NFCReaderOptions filters relevant data sources correctly.";
-const readOptions = {url: `${location.origin}/custom/path`};
-const unacceptableReadOptions = {url: `${location.origin}/custom/invalid`};
-const message = {
- url: "/custom/path/update",
- records: [createTextRecord(test_text_data)]
-}
-
-testNFCReaderOptions(message, readOptions, unacceptableReadOptions, desc);
-
-</script>
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 172b0a619c2..c2f9cef6e50 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 @@
<link rel="help" href="https://w3c.github.io/web-nfc/#dom-nfcreadingevent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
+<script src="resources/nfc-helpers.js"></script>
<script>
test(() => {
@@ -34,7 +34,7 @@
const event = new NFCReadingEvent('type', {serialNumber: '', message: message});
assert_equals(event.type, 'type', 'type');
assert_equals(event.serialNumber, '', 'serialNumber');
- assertWebNDEFMessagesEqual(event.message, new NDEFMessage(message), 'message');
+ assertWebNDEFMessagesEqual(event.message, message);
}, 'NFCReadingEvent constructor with valid parameters');
</script>
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 0b804615930..33471a18d8e 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 @@
<link rel="help" href="https://w3c.github.io/web-nfc/"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-
-<div id="log"></div>
-
+<script src="resources/nfc-helpers.js"></script>
<script>
"use strict";
@@ -84,105 +81,139 @@ const invalid_signals = [
self
];
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
const promises = [];
invalid_type_messages.forEach(message => {
promises.push(
promise_rejects(t, new TypeError(), writer.push(message)));
});
- return Promise.all(promises);
+ await Promise.all(promises);
}, "Test that promise is rejected with TypeError if NDEFMessageSource is invalid.");
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
const promises = [];
invalid_syntax_messages.forEach(message => {
promises.push(
promise_rejects(t, 'SyntaxError', writer.push(message)));
});
- return Promise.all(promises);
-}, "'Test that promise is rejected with SyntaxError if NDEFMessageSource contains invalid records.");
+ await Promise.all(promises);
+}, "Test that promise is rejected with SyntaxError if NDEFMessageSource contains\
+ invalid records.");
-promise_test(async t => {
+nfc_test(async (t, mockNFC) => {
const writer = new NFCWriter();
const controller = new AbortController();
- const p = writer.push(test_text_data, { signal: controller.signal });
+
+ //Make sure push is pending
+ mockNFC.setPendingPushCompleted(false);
+ const p = writer.push(test_text_data,
+ { signal: controller.signal, timeout: 100 });
const rejected = promise_rejects(t, 'AbortError', p);
let callback_called = false;
- t.step_timeout(() => {
- callback_called = true;
- controller.abort();
- }, 10);
+ await new Promise(resolve => {
+ t.step_timeout(() => {
+ callback_called = true;
+ controller.abort();
+ resolve();
+ }, 10);
+ });
await rejected;
assert_true(callback_called, 'timeout should have caused the abort');
}, "NFCWriter.push should fail if abort push request before push happends.");
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
const controller = new AbortController();
assert_false(controller.signal.aborted);
controller.abort();
assert_true(controller.signal.aborted);
- return promise_rejects(t, 'AbortError', writer.push(test_text_data, { signal: controller.signal }));
+ await promise_rejects(t, 'AbortError',
+ writer.push(test_text_data, { signal: controller.signal }));
}, "NFCWriter.push should fail if signal's aborted flag is set.");
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
const promises = [];
invalid_signals.forEach(invalid_signal => {
- promises.push(
- promise_rejects(t, new TypeError(), writer.push(test_text_data, { signal: invalid_signal })));
+ promises.push(promise_rejects(t, new TypeError(),
+ writer.push(test_text_data, { signal: invalid_signal })));
});
- return Promise.all(promises);
+ await Promise.all(promises);
}, "NFCWriter.push should fail if signal is not an AbortSignal.");
-promise_test(t => {
+nfc_test(async (t, mockNFC) => {
const writer = new NFCWriter();
- return promise_rejects(t, new TypeError(), writer.push(test_text_data, { timeout: "invalid"}));
-}, "NFCWriter.push should fail with TypeError when invalid timeout is provided.");
+ mockNFC.setHWStatus(NFCHWStatus.DISABLED);
+ await promise_rejects(t, 'NotReadableError', writer.push(test_text_data));
+}, "NFCWriter.push should fail when NFC HW is disabled.");
-promise_test(t => {
+nfc_test(async (t, mockNFC) => {
const writer = new NFCWriter();
- return promise_rejects(t, new TypeError(), writer.push(test_text_data, { timeout: -1 }));
-}, "NFCWriter.push should fail with TypeError when invalid negative timeout value is provided.");
+ mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED);
+ await promise_rejects(t, 'NotSupportedError', writer.push(test_text_data));
+}, "NFCWriter.push should fail when NFC HW is not supported.");
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
- return promise_rejects(t, 'TimeoutError', writer.push(test_text_data, { timeout: 1 }));
+ await promise_rejects(
+ t, new TypeError(), writer.push(test_text_data, { timeout: "invalid"}));
+}, "NFCWriter.push should fail with TypeError when invalid timeout is \
+provided.");
+
+promise_test(async t => {
+ const writer = new NFCWriter();
+ await promise_rejects(
+ t, new TypeError(), writer.push(test_text_data, { timeout: -1 }));
+}, "NFCWriter.push should fail with TypeError when invalid negative timeout \
+value is provided.");
+
+nfc_test(async (t, mockNFC) => {
+ const writer = new NFCWriter();
+ mockNFC.setPendingPushCompleted(false);
+ const p = writer.push(test_text_data, { timeout: 1 });
+ mockNFC.setPushShouldTimeout(true);
+ await promise_rejects(t, 'TimeoutError', p);
}, "NFCWriter.push should fail with TimeoutError when timer expires.");
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
- return promise_rejects(t, 'NotSupportedError', writer.push(new ArrayBuffer(32 * 1024 + 1)));
+ await promise_rejects(
+ t, 'NotSupportedError', writer.push(new ArrayBuffer(32 * 1024 + 1)));
}, "Reject promise with NotSupportedError if NFC message size exceeds 32KB.");
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
const message = createMessage([createTextRecord(test_text_data)]);
message.url = '%00/invalid/ path';
- return promise_rejects(t, 'SyntaxError', writer.push(message));
-}, "Reject promise with SyntaxError if WebNFC Id cannot be created from provided URL.");
+ await promise_rejects(t, 'SyntaxError', writer.push(message));
+}, "Reject promise with SyntaxError if WebNFC Id cannot be created from \
+provided URL.");
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
const message = createMessage([createRecord('json','application/json',
{ get x(){ return this; } })]);
- return promise_rejects(t, 'SyntaxError', writer.push(message));
+ await promise_rejects(t, 'SyntaxError', writer.push(message));
}, "Reject promise with SyntaxError if 'json' record cannot be serialized.");
-promise_test(t => {
+promise_test(async t => {
const writer = new NFCWriter();
- return promise_rejects(t, new TypeError(), writer.push(test_text_data, {target: "invalid"}));
-}, "NFCWriter.push should fail with TypeError when invalid target value is provided.");
+ await promise_rejects(
+ t, new TypeError(), writer.push(test_text_data, {target: "invalid"}));
+}, "NFCWriter.push should fail with TypeError when invalid target value is \
+provided.");
-promise_test(() => {
- return new Promise((resolve,reject) => {
+promise_test(async () => {
+ await new Promise((resolve,reject) => {
const iframe = document.createElement('iframe');
iframe.srcdoc = `<script>
window.onmessage = message => {
if (message.data === "Ready") {
- const onSuccess = () => { parent.postMessage("Failure", "*"); };
+ const onSuccess = () => {
+ parent.postMessage("Failure", "*");
+ };
const onError = error => {
if (error.name == "NotAllowedError") {
parent.postMessage("Success", "*");
@@ -211,4 +242,70 @@ promise_test(() => {
});
}, 'Test that WebNFC API is not accessible from iframe context.');
+nfc_test(async () => {
+ const writer = new NFCWriter();
+ await writer.push(test_text_data, { timeout: 1 });
+}, 'NFCWriter.push should succeed when NFC HW is enabled');
+
+nfc_test(async (t, mockNFC) => {
+ const writer = new NFCWriter();
+ let message = createMessage([createTextRecord(test_text_data),
+ createJsonRecord(test_json_data),
+ createOpaqueRecord(test_buffer_data),
+ createTextRecord(test_number_data),
+ createUrlRecord(test_url_data)],
+ test_message_origin);
+ await writer.push(message);
+ assertNDEFMessagesEqual(message, mockNFC.pushedMessage());
+}, "NFCWriter.push NDEFMessage containing text, json, opaque and url records \
+with default NFCPushOptions.");
+
+nfc_test(async (t, mockNFC) => {
+ const writer = new NFCWriter();
+ await writer.push(test_text_data);
+ assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage());
+}, "Test that NFCWriter.push succeeds when message is DOMString.");
+
+nfc_test(async (t, mockNFC) => {
+ const writer = new NFCWriter();
+ await writer.push(test_buffer_data);
+ assertNDEFMessagesEqual(test_buffer_data, mockNFC.pushedMessage());
+}, "Test that NFCWriter.push succeeds when message is ArrayBuffer.");
+
+nfc_test(async () => {
+ const writer = new NFCWriter();
+ await writer.push(createMessage([createRecord('empty')]));
+}, "NFCWriter.push with 'empty' record should succeed.");
+
+nfc_test(async (t, mockNFC) => {
+ const writer = new NFCWriter();
+ await writer.push(test_text_data);
+ assertNFCPushOptionsEqual(createNFCPushOptions('any', Infinity, true),
+ mockNFC.pushOptions());
+}, "Check that default NFCPushOptions values are correctly set.");
+
+nfc_test(async (t, mockNFC) => {
+ const writer = new NFCWriter();
+ let nfcPushOptions = createNFCPushOptions('tag', 1, false);
+ await writer.push(test_text_data, nfcPushOptions);
+ assertNFCPushOptionsEqual(nfcPushOptions, mockNFC.pushOptions());
+}, "Check that provided NFCPushOptions values are correctly converted.");
+
+nfc_test(async (t, mockNFC) => {
+ const writer1 = new NFCWriter();
+ const writer2 = new NFCWriter();
+ const controller = new AbortController();
+ mockNFC.setPendingPushCompleted(false);
+ const p1 = writer1.push(test_text_data,
+ { signal: controller.signal, timeout: 100 });
+
+ // Even though push request is grantable,
+ // this abort should be processed synchronously.
+ controller.abort();
+ await promise_rejects(t, 'AbortError', p1);
+
+ await writer2.push(test_text_data);
+ assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage());
+}, "Synchronously signaled abort.");
+
</script>
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 f45d0bbbd49..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/NFCWriter_push_signal-manual.https.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: NFCWriter signal test</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-promise_test(async t => {
- const writer = new NFCWriter();
- const reader = new NFCReader();
- const controller = new AbortController();
-
- const p1 = writer.push(test_text_data, { signal: controller.signal });
- const p2 = writer.push(test_text_data);
-
- // Even though push request is grantable, this abort should be processed synchronously.
- controller.abort();
- await promise_rejects(t, 'AbortError', p1);
- await p2;
-
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("reading");
- for (let record of event.message.records) {
- assert_equals(record.data, test_text_data);
- }
-}, "Synchronously signaled abort.");
-
-</script>
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 00000000000..8ae597e36fd
--- /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 bb2cd42f1e6..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/nfc_hw_disabled-manual.https.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: NFC HW Disabled</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<h2>Precondition</h2>
-<ol>
- <li>
- Disable the NFC module or run test on a device without NFC module.
- </li>
-</ol>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-promise_test(async t => {
- const reader = new NFCReader();
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("error");
- assert_equals(event.error.name, 'NotReadableError');
-}, "NFCReader.start should fail if NFC HW is disabled.");
-
-promise_test(t => {
- const writer = new NFCWriter();
- return promise_rejects(t, 'NotReadableError', writer.push(test_text_data));
-}, "NFCWriter.push should fail when NFC HW is disabled.");
-
-</script>
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 0e5764e6ebc..f883f0473b7 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 @@
<link rel="help" href="https://w3c.github.io/web-nfc/"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
<h2>Note</h2>
<ol>
<li>
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 90a356f9b26..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/nfc_push_ArrayBuffer-manual.https.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: push ArrayBuffer message</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-promise_test(async t => {
- const writer = new NFCWriter();
- const reader = new NFCReader();
- await writer.push(test_buffer_data);
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("reading");
- for (let record of event.message.records) {
- assert_equals(record.recordType, "opaque");
- assert_equals(record.mediaType, "application/octet-stream");
- assert_array_equals(new Uint8Array(record.data), new Uint8Array(test_buffer_data));
- }
-}, "Test that NFCWriter.push succeeds when message is ArrayBuffer.");
-
-</script>
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 15e1da50fb3..00000000000
--- a/tests/wpt/web-platform-tests/web-nfc/nfc_push_DOMString-manual.https.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Web NFC Test: push DOMString message</title>
-<link rel="author" title="Intel" href="http://www.intel.com"/>
-<link rel="help" href="https://w3c.github.io/web-nfc/"/>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/nfc_help.js"></script>
-<meta name="flags" content="interact">
-
-<p>Tap an NFC tag to the test device with NFC support.</p>
-
-<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
-
-<div id="log"></div>
-
-<script>
-
-"use strict";
-
-setup({ explicit_timeout: true });
-
-promise_test(async t => {
- const writer = new NFCWriter();
- const reader = new NFCReader();
- await writer.push(test_text_data);
- const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
- reader.start();
- const event = await readerWatcher.wait_for("reading");
- for (let record of event.message.records) {
- assert_equals(record.data, test_text_data);
- }
-}, "Test that NFCWriter.push succeeds when message is DOMString.");
-
-</script>
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 00000000000..fc72fa2de89
--- /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 67fd5af381c..00000000000
--- 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);
-}