diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-07-26 18:48:20 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-26 18:48:20 -0400 |
commit | eb1f03242abd2a1be4aeead9cb26a86197d708a2 (patch) | |
tree | d601a99d43f942f3adc9c40bf8d7b2cebba57899 | |
parent | 8ec28978cdc3e0fa66652a7a0a57911ca414254c (diff) | |
parent | b6ddc8cdcdb3fc1ed40b826a64d28b0ef3b86522 (diff) | |
download | servo-eb1f03242abd2a1be4aeead9cb26a86197d708a2.tar.gz servo-eb1f03242abd2a1be4aeead9cb26a86197d708a2.zip |
Auto merge of #23864 - servo-wpt-sync:wpt_update_26-07-2019, r=jdm
Sync WPT with upstream (26-07-2019)
Automated downstream sync of changes from upstream as of 26-07-2019.
[no-wpt-sync]
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23864)
<!-- Reviewable:end -->
222 files changed, 7521 insertions, 2099 deletions
diff --git a/tests/wpt/metadata/FileAPI/url/url-with-fetch.any.js.ini b/tests/wpt/metadata/FileAPI/url/url-with-fetch.any.js.ini index 6a3af4e2ece..3b874fc1748 100644 --- a/tests/wpt/metadata/FileAPI/url/url-with-fetch.any.js.ini +++ b/tests/wpt/metadata/FileAPI/url/url-with-fetch.any.js.ini @@ -14,9 +14,6 @@ [Revoke blob URL after creating Request, will fetch] expected: FAIL - [Revoke blob URL after calling fetch, fetch should succeed] - expected: FAIL - [url-with-fetch.any.html] [Untitled] @@ -37,3 +34,6 @@ [Revoke blob URL after creating Request, will fetch] expected: FAIL + [Revoke blob URL after calling fetch, fetch should succeed] + expected: FAIL + diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index c6fc3b65f77..53f7c6ecab5 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -105681,6 +105681,18 @@ {} ] ], + "css/css-backgrounds/background-color-body-propagation-007.html": [ + [ + "css/css-backgrounds/background-color-body-propagation-007.html", + [ + [ + "/css/reference/blank.html", + "==" + ] + ], + {} + ] + ], "css/css-backgrounds/background-color-clip.html": [ [ "css/css-backgrounds/background-color-clip.html", @@ -128611,6 +128623,18 @@ {} ] ], + "css/css-lists/li-insert-child.html": [ + [ + "css/css-lists/li-insert-child.html", + [ + [ + "/css/css-lists/li-insert-child-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-lists/li-list-item-counter.html": [ [ "css/css-lists/li-list-item-counter.html", @@ -133603,6 +133627,54 @@ {} ] ], + "css/css-overflow/overflow-body-propagation-001.tentative.html": [ + [ + "css/css-overflow/overflow-body-propagation-001.tentative.html", + [ + [ + "/css/css-overflow/reference/overflow-body-propagation-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-overflow/overflow-body-propagation-002.tentative.html": [ + [ + "css/css-overflow/overflow-body-propagation-002.tentative.html", + [ + [ + "/css/reference/blank.html", + "==" + ] + ], + {} + ] + ], + "css/css-overflow/overflow-body-propagation-003.tentative.html": [ + [ + "css/css-overflow/overflow-body-propagation-003.tentative.html", + [ + [ + "/css/reference/blank.html", + "==" + ] + ], + {} + ] + ], + "css/css-overflow/overflow-body-propagation-004.tentative.html": [ + [ + "css/css-overflow/overflow-body-propagation-004.tentative.html", + [ + [ + "/css/css-overflow/reference/overflow-body-no-propagation-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-overflow/webkit-line-clamp-001.html": [ [ "css/css-overflow/webkit-line-clamp-001.html", @@ -133980,7 +134052,7 @@ "css/css-overflow/webkit-line-clamp-033.html", [ [ - "about:blank", + "/css/reference/blank.html", "==" ] ], @@ -139667,6 +139739,18 @@ {} ] ], + "css/css-scrollbars/scrollbars-chrome-bug-001.html": [ + [ + "css/css-scrollbars/scrollbars-chrome-bug-001.html", + [ + [ + "/css/css-scrollbars/scrollbars-chrome-bug-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-scrollbars/textarea-scrollbar-width-none.html": [ [ "css/css-scrollbars/textarea-scrollbar-width-none.html", @@ -155463,6 +155547,34 @@ {} ] ], + "css/css-transforms/perspective-transforms-equivalence.html": [ + [ + "css/css-transforms/perspective-transforms-equivalence.html", + [ + [ + "/css/css-transforms/perspective-transforms-equivalence-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 10, + 10 + ], + [ + 10, + 10 + ] + ] + ] + ] + } + ] + ], "css/css-transforms/perspective-translateZ-0.html": [ [ "css/css-transforms/perspective-translateZ-0.html", @@ -177117,6 +177229,42 @@ {} ] ], + "css/css-writing-modes/tcy-white-space-processing-001.html": [ + [ + "css/css-writing-modes/tcy-white-space-processing-001.html", + [ + [ + "/css/css-writing-modes/reference/tcy-white-space-processing-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-writing-modes/tcy-white-space-processing-002.html": [ + [ + "css/css-writing-modes/tcy-white-space-processing-002.html", + [ + [ + "/css/css-writing-modes/reference/tcy-white-space-processing-002-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-writing-modes/tcy-white-space-processing-003.html": [ + [ + "css/css-writing-modes/tcy-white-space-processing-003.html", + [ + [ + "/css/css-writing-modes/reference/tcy-white-space-processing-003-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-writing-modes/text-align-vlr-003.xht": [ [ "css/css-writing-modes/text-align-vlr-003.xht", @@ -203433,12 +203581,48 @@ {} ] ], - "mathml/relations/css-styling/color-1.html": [ + "mathml/relations/css-styling/color-001.html": [ + [ + "mathml/relations/css-styling/color-001.html", + [ + [ + "/mathml/relations/css-styling/color-001-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/relations/css-styling/color-002.html": [ + [ + "mathml/relations/css-styling/color-002.html", + [ + [ + "/mathml/relations/css-styling/color-002-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/relations/css-styling/color-003.html": [ + [ + "mathml/relations/css-styling/color-003.html", + [ + [ + "/mathml/relations/css-styling/color-003-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/relations/css-styling/color-004.html": [ [ - "mathml/relations/css-styling/color-1.html", + "mathml/relations/css-styling/color-004.html", [ [ - "/mathml/relations/css-styling/color-1-ref.html", + "/mathml/relations/css-styling/color-004-ref.html", "==" ] ], @@ -203709,12 +203893,48 @@ {} ] ], - "mathml/relations/css-styling/visibility-1.html": [ + "mathml/relations/css-styling/visibility-001.html": [ [ - "mathml/relations/css-styling/visibility-1.html", + "mathml/relations/css-styling/visibility-001.html", [ [ - "/mathml/relations/css-styling/visibility-1-ref.html", + "/mathml/relations/css-styling/visibility-001-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/relations/css-styling/visibility-002.html": [ + [ + "mathml/relations/css-styling/visibility-002.html", + [ + [ + "/mathml/relations/css-styling/visibility-002-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/relations/css-styling/visibility-003.html": [ + [ + "mathml/relations/css-styling/visibility-003.html", + [ + [ + "/mathml/relations/css-styling/visibility-003-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/relations/css-styling/visibility-004.html": [ + [ + "mathml/relations/css-styling/visibility-004.html", + [ + [ + "/mathml/relations/css-styling/visibility-004-ref.html", "==" ] ], @@ -204129,6 +204349,18 @@ {} ] ], + "svg/coordinate-systems/viewBox-change-repaint-001.html": [ + [ + "svg/coordinate-systems/viewBox-change-repaint-001.html", + [ + [ + "/svg/coordinate-systems/support/viewBox-change-repaint-001-ref.html", + "==" + ] + ], + {} + ] + ], "svg/coordinate-systems/viewBox-scaling-text-001.html": [ [ "svg/coordinate-systems/viewBox-scaling-text-001.html", @@ -205773,6 +206005,18 @@ {} ] ], + "webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size.html": [ + [ + "webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size.html", + [ + [ + "/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size-ref.html", + "==" + ] + ], + {} + ] + ], "webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50.html": [ [ "webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50.html", @@ -213392,9 +213636,15 @@ "common/security-features/subresource/xhr.py": [ [] ], + "common/security-features/tools/format_spec_src_json.py": [ + [] + ], "common/security-features/tools/generate.py": [ [] ], + "common/security-features/tools/spec_validator.py": [ + [] + ], "common/security-features/tools/template/disclaimer.template": [ [] ], @@ -250346,6 +250596,9 @@ "css/css-lists/counter-set-002-ref.html": [ [] ], + "css/css-lists/li-insert-child-ref.html": [ + [] + ], "css/css-lists/li-list-item-counter-ref.html": [ [] ], @@ -251201,6 +251454,12 @@ "css/css-overflow/reference/input-scrollable-region-001-ref.html": [ [] ], + "css/css-overflow/reference/overflow-body-no-propagation-ref.html": [ + [] + ], + "css/css-overflow/reference/overflow-body-propagation-ref.html": [ + [] + ], "css/css-overflow/reference/webkit-line-clamp-001-ref.html": [ [] ], @@ -252464,6 +252723,9 @@ "css/css-scrollbars/META.yml": [ [] ], + "css/css-scrollbars/scrollbars-chrome-bug-001-ref.html": [ + [] + ], "css/css-scrollbars/support/viewport-scrollbar-body-frame.html": [ [] ], @@ -255110,6 +255372,9 @@ "css/css-transforms/patternTransform/reference/svg-patternTransform-relative-ref.html": [ [] ], + "css/css-transforms/perspective-transforms-equivalence-ref.html": [ + [] + ], "css/css-transforms/preserve3d-button-ref.html": [ [] ], @@ -257825,6 +258090,15 @@ "css/css-writing-modes/reference/table-cell-002-ref.html": [ [] ], + "css/css-writing-modes/reference/tcy-white-space-processing-001-ref.html": [ + [] + ], + "css/css-writing-modes/reference/tcy-white-space-processing-002-ref.html": [ + [] + ], + "css/css-writing-modes/reference/tcy-white-space-processing-003-ref.html": [ + [] + ], "css/css-writing-modes/reference/text-combine-upright-decorations-001.html": [ [] ], @@ -263441,6 +263715,9 @@ "element-timing/resources/element-timing-helpers.js": [ [] ], + "element-timing/resources/iframe-stores-entry.html": [ + [] + ], "element-timing/resources/iframe-with-square-sends-entry.html": [ [] ], @@ -272624,6 +272901,9 @@ "interfaces/dom.idl": [ [] ], + "interfaces/element-timing.idl": [ + [] + ], "interfaces/encoding.idl": [ [] ], @@ -272693,6 +272973,9 @@ "interfaces/keyboard-map.idl": [ [] ], + "interfaces/largest-contentful-paint.idl": [ + [] + ], "interfaces/longtasks.idl": [ [] ], @@ -272990,6 +273273,9 @@ "kv-storage/secure-context/resources/test-side-effects.js": [ [] ], + "largest-contentful-paint/resources/iframe-stores-entry.html": [ + [] + ], "layout-instability/resources/slow-image.py": [ [] ], @@ -273158,7 +273444,16 @@ "mathml/presentation-markup/spaces/space-2-ref.html": [ [] ], - "mathml/relations/css-styling/color-1-ref.html": [ + "mathml/relations/css-styling/color-001-ref.html": [ + [] + ], + "mathml/relations/css-styling/color-002-ref.html": [ + [] + ], + "mathml/relations/css-styling/color-003-ref.html": [ + [] + ], + "mathml/relations/css-styling/color-004-ref.html": [ [] ], "mathml/relations/css-styling/display-1-ref.html": [ @@ -273227,7 +273522,19 @@ "mathml/relations/css-styling/mathvariant-tailed-ref.html": [ [] ], - "mathml/relations/css-styling/visibility-1-ref.html": [ + "mathml/relations/css-styling/padding-border-margin/helper.js": [ + [] + ], + "mathml/relations/css-styling/visibility-001-ref.html": [ + [] + ], + "mathml/relations/css-styling/visibility-002-ref.html": [ + [] + ], + "mathml/relations/css-styling/visibility-003-ref.html": [ + [] + ], + "mathml/relations/css-styling/visibility-004-ref.html": [ [] ], "mathml/relations/html5-tree/class-1-ref.html": [ @@ -273272,6 +273579,9 @@ "mathml/relations/text-and-math/use-typo-metrics-1-ref.html": [ [] ], + "mathml/support/feature-detection.js": [ + [] + ], "mathml/tools/axisheight.py": [ [] ], @@ -273758,9 +274068,6 @@ "mixed-content/generic/tools/regenerate": [ [] ], - "mixed-content/generic/tools/spec_validator.py": [ - [] - ], "mixed-content/img-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [ [] ], @@ -274976,9 +275283,6 @@ "referrer-policy/generic/tools/regenerate": [ [] ], - "referrer-policy/generic/tools/spec_validator.py": [ - [] - ], "referrer-policy/no-referrer-when-downgrade/http-rp/cross-origin/http-http/a-tag/no-redirect/insecure-protocol.http.html.headers": [ [] ], @@ -279452,6 +279756,9 @@ "svg/coordinate-systems/support/simple.svg": [ [] ], + "svg/coordinate-systems/support/viewBox-change-repaint-001-ref.html": [ + [] + ], "svg/coordinate-systems/support/viewBox-scaling-text-001-ref.html": [ [] ], @@ -285962,6 +286269,9 @@ "webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50-ref.html": [ [] ], + "webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size-ref.html": [ + [] + ], "webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50-ref.html": [ [] ], @@ -286721,6 +287031,9 @@ "webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50.vtt": [ [] ], + "webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50_size_gt_maximum_size.vtt": [ + [] + ], "webvtt/rendering/cues-with-video/processing-model/support/align_center_position_lt_50.vtt": [ [] ], @@ -295844,6 +296157,48 @@ {} ] ], + "IndexedDB/structured-clone.any.js": [ + [ + "IndexedDB/structured-clone.any.html", + { + "script_metadata": [ + [ + "script", + "support-promises.js" + ], + [ + "title", + "Indexed DB and Structured Serializing/Deserializing" + ], + [ + "timeout", + "long" + ] + ], + "timeout": "long" + } + ], + [ + "IndexedDB/structured-clone.any.worker.html", + { + "script_metadata": [ + [ + "script", + "support-promises.js" + ], + [ + "title", + "Indexed DB and Structured Serializing/Deserializing" + ], + [ + "timeout", + "long" + ] + ], + "timeout": "long" + } + ] + ], "IndexedDB/transaction-abort-generator-revert.html": [ [ "IndexedDB/transaction-abort-generator-revert.html", @@ -308015,6 +308370,12 @@ {} ] ], + "cookie-store/cookieStore_delete_insecure.tentative.https.window.js": [ + [ + "cookie-store/cookieStore_delete_insecure.tentative.https.window.html", + {} + ] + ], "cookie-store/cookieStore_event_arguments.tenative.https.window.js": [ [ "cookie-store/cookieStore_event_arguments.tenative.https.window.html", @@ -310288,9 +310649,9 @@ {} ] ], - "css/css-backgrounds/parsing/border-image-source-computed.html": [ + "css/css-backgrounds/parsing/border-image-source-computed.sub.html": [ [ - "css/css-backgrounds/parsing/border-image-source-computed.html", + "css/css-backgrounds/parsing/border-image-source-computed.sub.html", {} ] ], @@ -314512,9 +314873,9 @@ {} ] ], - "css/css-lists/parsing/list-style-computed.html": [ + "css/css-lists/parsing/list-style-computed.sub.html": [ [ - "css/css-lists/parsing/list-style-computed.html", + "css/css-lists/parsing/list-style-computed.sub.html", {} ] ], @@ -321012,6 +321373,12 @@ {} ] ], + "css/css-typed-om/set-var-reference-crash.html": [ + [ + "css/css-typed-om/set-var-reference-crash.html", + {} + ] + ], "css/css-typed-om/stylevalue-normalization/normalize-ident.tentative.html": [ [ "css/css-typed-om/stylevalue-normalization/normalize-ident.tentative.html", @@ -330105,6 +330472,35 @@ {} ] ], + "element-timing/element-only-when-fully-active.html": [ + [ + "element-timing/element-only-when-fully-active.html", + {} + ] + ], + "element-timing/fixed-id-identifier.html": [ + [ + "element-timing/fixed-id-identifier.html", + {} + ] + ], + "element-timing/idlharness.window.js": [ + [ + "element-timing/idlharness.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/WebIDLParser.js" + ], + [ + "script", + "/resources/idlharness.js" + ] + ] + } + ] + ], "element-timing/image-TAO.sub.html": [ [ "element-timing/image-TAO.sub.html", @@ -359911,6 +360307,12 @@ {} ] ], + "intersection-observer/rtl-clipped-root.html": [ + [ + "intersection-observer/rtl-clipped-root.html", + {} + ] + ], "intersection-observer/same-document-no-root.html": [ [ "intersection-observer/same-document-no-root.html", @@ -360363,12 +360765,24 @@ {} ] ], + "largest-contentful-paint/element-only-when-fully-active.html": [ + [ + "largest-contentful-paint/element-only-when-fully-active.html", + {} + ] + ], "largest-contentful-paint/expanded-image.html": [ [ "largest-contentful-paint/expanded-image.html", {} ] ], + "largest-contentful-paint/idlharness.html": [ + [ + "largest-contentful-paint/idlharness.html", + {} + ] + ], "largest-contentful-paint/image-src-change.html": [ [ "largest-contentful-paint/image-src-change.html", @@ -360381,6 +360795,12 @@ {} ] ], + "largest-contentful-paint/observe-after-untrusted-scroll.html": [ + [ + "largest-contentful-paint/observe-after-untrusted-scroll.html", + {} + ] + ], "largest-contentful-paint/observe-image.html": [ [ "largest-contentful-paint/observe-image.html", @@ -360731,6 +361151,18 @@ {} ] ], + "mathml/presentation-markup/operators/embellished-operator-001.html": [ + [ + "mathml/presentation-markup/operators/embellished-operator-001.html", + {} + ] + ], + "mathml/presentation-markup/operators/embellished-operator-002.html": [ + [ + "mathml/presentation-markup/operators/embellished-operator-002.html", + {} + ] + ], "mathml/presentation-markup/operators/mo-axis-height-1.html": [ [ "mathml/presentation-markup/operators/mo-axis-height-1.html", @@ -360821,6 +361253,30 @@ {} ] ], + "mathml/presentation-markup/spaces/space-like-001.html": [ + [ + "mathml/presentation-markup/spaces/space-like-001.html", + {} + ] + ], + "mathml/presentation-markup/spaces/space-like-002.html": [ + [ + "mathml/presentation-markup/spaces/space-like-002.html", + {} + ] + ], + "mathml/presentation-markup/spaces/space-like-003.html": [ + [ + "mathml/presentation-markup/spaces/space-like-003.html", + {} + ] + ], + "mathml/presentation-markup/spaces/space-like-004.html": [ + [ + "mathml/presentation-markup/spaces/space-like-004.html", + {} + ] + ], "mathml/presentation-markup/tables/table-axis-height.html": [ [ "mathml/presentation-markup/tables/table-axis-height.html", @@ -360839,6 +361295,24 @@ {} ] ], + "mathml/relations/css-styling/padding-border-margin/border-001.html": [ + [ + "mathml/relations/css-styling/padding-border-margin/border-001.html", + {} + ] + ], + "mathml/relations/css-styling/padding-border-margin/margin-001.html": [ + [ + "mathml/relations/css-styling/padding-border-margin/margin-001.html", + {} + ] + ], + "mathml/relations/css-styling/padding-border-margin/padding-001.html": [ + [ + "mathml/relations/css-styling/padding-border-margin/padding-001.html", + {} + ] + ], "mathml/relations/html5-tree/class-2.html": [ [ "mathml/relations/html5-tree/class-2.html", @@ -364755,19 +365229,6 @@ } ] ], - "native-file-system/NativeFileSystemWritableFileStream.tentative.https.window.js": [ - [ - "native-file-system/NativeFileSystemWritableFileStream.tentative.https.window.html", - { - "script_metadata": [ - [ - "script", - "resources/test-helpers.js" - ] - ] - } - ] - ], "navigation-timing/buffered-flag.window.js": [ [ "navigation-timing/buffered-flag.window.html", @@ -398787,7 +399248,9 @@ "upgrade-insecure-requests/worker-subresource-fetch-redirect-upgrade.https.html": [ [ "upgrade-insecure-requests/worker-subresource-fetch-redirect-upgrade.https.html", - {} + { + "timeout": "long" + } ] ], "upgrade-insecure-requests/worker-subresource-fetch-upgrade.https.html": [ @@ -405994,6 +406457,12 @@ {} ] ], + "webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html": [ + [ + "webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html", + {} + ] + ], "webrtc/RTCPeerConnection-restartIce.https.html": [ [ "webrtc/RTCPeerConnection-restartIce.https.html", @@ -410973,6 +411442,12 @@ {} ] ], + "webxr/exclusive_requestFrame_nolayer.https.html": [ + [ + "webxr/exclusive_requestFrame_nolayer.https.html", + {} + ] + ], "webxr/getInputPose_handedness.https.html": [ [ "webxr/getInputPose_handedness.https.html", @@ -411002,6 +411477,18 @@ } ] ], + "webxr/render_state_vertical_fov_immersive.https.html": [ + [ + "webxr/render_state_vertical_fov_immersive.https.html", + {} + ] + ], + "webxr/render_state_vertical_fov_inline.https.html": [ + [ + "webxr/render_state_vertical_fov_inline.https.html", + {} + ] + ], "webxr/webGLCanvasContext_create_xrcompatible.https.html": [ [ "webxr/webGLCanvasContext_create_xrcompatible.https.html", @@ -411218,6 +411705,12 @@ {} ] ], + "webxr/xrSession_requestAnimationFrame_timestamp.https.html": [ + [ + "webxr/xrSession_requestAnimationFrame_timestamp.https.html", + {} + ] + ], "webxr/xrSession_requestReferenceSpace.https.html": [ [ "webxr/xrSession_requestReferenceSpace.https.html", @@ -411248,12 +411741,54 @@ {} ] ], + "webxr/xrView_match.https.html": [ + [ + "webxr/xrView_match.https.html", + {} + ] + ], + "webxr/xrView_oneframeupdate.https.html": [ + [ + "webxr/xrView_oneframeupdate.https.html", + {} + ] + ], + "webxr/xrViewport_valid.https.html": [ + [ + "webxr/xrViewport_valid.https.html", + {} + ] + ], + "webxr/xrWebGLLayer_constructor.https.html": [ + [ + "webxr/xrWebGLLayer_constructor.https.html", + {} + ] + ], "webxr/xrWebGLLayer_framebuffer.https.html": [ [ "webxr/xrWebGLLayer_framebuffer.https.html", {} ] ], + "webxr/xrWebGLLayer_framebuffer_draw.https.html": [ + [ + "webxr/xrWebGLLayer_framebuffer_draw.https.html", + {} + ] + ], + "webxr/xrWebGLLayer_framebuffer_scale.https.html": [ + [ + "webxr/xrWebGLLayer_framebuffer_scale.https.html", + {} + ] + ], + "webxr/xrWebGLLayer_opaque_framebuffer.https.html": [ + [ + "webxr/xrWebGLLayer_opaque_framebuffer.https.html", + {} + ] + ], "webxr/xrWebGLLayer_viewports.https.html": [ [ "webxr/xrWebGLLayer_viewports.https.html", @@ -436840,7 +437375,7 @@ "support" ], ".taskcluster.yml": [ - "a8e297242fe1d9d63ffd23f0403dbb1fa6f079ac", + "1a162ed740285cc0e7c99943f7988686bab89b5b", "support" ], ".well-known/README.md": [ @@ -442955,6 +443490,10 @@ "cc905e56ecf83ea4cd4f1fe2ccfac425cdc5f9d0", "testharness" ], + "IndexedDB/structured-clone.any.js": [ + "8078aaf796b843aaf9f23be5889febbe4c8fb960", + "testharness" + ], "IndexedDB/support-promises.js": [ "8195be341e18860865c072bc78a1efa1f25f2d56", "support" @@ -448571,8 +449110,16 @@ "82a4cb0b657956cb20efcfb0142ad4040875eabe", "support" ], + "common/security-features/tools/format_spec_src_json.py": [ + "1276c78f9fb71f98971476000c082ab3511787e6", + "support" + ], "common/security-features/tools/generate.py": [ - "50c3a2c250c9d992377809cb731441fd6588263d", + "fc10e635dbd0d52469e5a105764fa681c86dc654", + "support" + ], + "common/security-features/tools/spec_validator.py": [ + "2c9664788699676a27e2715344ba581f35c89ad7", "support" ], "common/security-features/tools/template/disclaimer.template": [ @@ -448592,7 +449139,7 @@ "support" ], "common/security-features/tools/util.py": [ - "77b89769ca27f606ae6adb080fbdc5ee9df8966d", + "1f6c86e6efcc3bb5dbde41ba484a026d55a5961e", "support" ], "common/sleep.py": [ @@ -469147,6 +469694,10 @@ "8a3f7ed66da0cc7d6e6d2e07a3d6fa345e28d9b3", "testharness" ], + "cookie-store/cookieStore_delete_insecure.tentative.https.window.js": [ + "bb1907faf58dfd4edfaf523f89ecad17785804bd", + "testharness" + ], "cookie-store/cookieStore_event_arguments.tenative.https.window.js": [ "bcb698eeb0d6ce760033ba628120ebf7772a1084", "testharness" @@ -472548,7 +473099,7 @@ "testharness" ], "credential-management/idlharness.https.window.js": [ - "15508b872ed7f9dc5cd0b6409aaa4de6c15f4b29", + "789643e2369fca0baed12579bc0cfb23f943f61e", "testharness" ], "credential-management/passwordcredential-framed-get.sub.https.html": [ @@ -532992,15 +533543,19 @@ "reftest" ], "css/css-backgrounds/background-color-body-propagation-004.html": [ - "c4b21959626ad4ddfe8edb5065c57369920ea772", + "ede419096ff1faedd91b4f712e238a76101ca081", "reftest" ], "css/css-backgrounds/background-color-body-propagation-005.html": [ - "702b2b29ae3cb20358b3c125f5b0cd69a1477d0b", + "05c5421977e74259189bab32b85e35c94daadddb", "reftest" ], "css/css-backgrounds/background-color-body-propagation-006.html": [ - "b575891382c8b9f21998996a48fc7581a0f9e115", + "4c58cb9dc212f9b02a94b5bc7121cb50bd70cb61", + "reftest" + ], + "css/css-backgrounds/background-color-body-propagation-007.html": [ + "6deda8dcdb581e6f064ed522c036e5f1d72ea474", "reftest" ], "css/css-backgrounds/background-color-body-propagation-ref.html": [ @@ -535619,8 +536174,8 @@ "671120b41b7e55bddd2c286dc7ce4807ce9c3665", "testharness" ], - "css/css-backgrounds/parsing/border-image-source-computed.html": [ - "96e6bdf2f09ee50e8649e7a918debeaf06902e32", + "css/css-backgrounds/parsing/border-image-source-computed.sub.html": [ + "20343882096f2ce3fe1f0dbfb6d2164279e8aade", "testharness" ], "css/css-backgrounds/parsing/border-image-source-invalid.html": [ @@ -556419,6 +556974,14 @@ "0fae6e3f6036c46b8f658304787da5879913296f", "testharness" ], + "css/css-lists/li-insert-child-ref.html": [ + "bbf2e66a0dfddd3f399eea4889fd867444b7eca4", + "support" + ], + "css/css-lists/li-insert-child.html": [ + "d82bf1374aebc47740285a54a7532b6b7242377f", + "reftest" + ], "css/css-lists/li-list-item-counter-ref.html": [ "96ca6c1122188015d6e40e01102bdb4fecfb0567", "support" @@ -556543,8 +557106,8 @@ "9627ce936ae570325b430a1ac673cd66ae7d4252", "reftest" ], - "css/css-lists/parsing/list-style-computed.html": [ - "67bdc46f8c11ae085d5ee8449ee97ddba319a8b4", + "css/css-lists/parsing/list-style-computed.sub.html": [ + "611fae5bf93636cd4d3402e91b1cd47148303617", "testharness" ], "css/css-lists/parsing/list-style-image-computed.sub.html": [ @@ -559835,6 +560398,22 @@ "df1128316f6010f010e6d27c395d7751fa05d7b1", "testharness" ], + "css/css-overflow/overflow-body-propagation-001.tentative.html": [ + "0998fe68e007d5a46ff11d5ff87fdbad12d1dfe2", + "reftest" + ], + "css/css-overflow/overflow-body-propagation-002.tentative.html": [ + "5991dd52e8b6aec74f55780587f15c2b9399c968", + "reftest" + ], + "css/css-overflow/overflow-body-propagation-003.tentative.html": [ + "a329a8dfe3e44c92368bf0496897f74ccec5a63a", + "reftest" + ], + "css/css-overflow/overflow-body-propagation-004.tentative.html": [ + "2ed8d2687a33608e0e70884ad2ea59330d2b09e3", + "reftest" + ], "css/css-overflow/overflow-inline-transform-relative.html": [ "4df7b6389432cc6c65bae3fe3b5b9c2f00ba7bde", "testharness" @@ -559915,6 +560494,14 @@ "d7125ee2ef3285d461b2172208e23d8d4cc27a64", "support" ], + "css/css-overflow/reference/overflow-body-no-propagation-ref.html": [ + "9795d1f5861f0affaeb3a36b3644d17fd60e1f4d", + "support" + ], + "css/css-overflow/reference/overflow-body-propagation-ref.html": [ + "340bda9de92352fe1ef6633610da31e867013299", + "support" + ], "css/css-overflow/reference/webkit-line-clamp-001-ref.html": [ "ef28e01dac0223c9a2768d3fd1415fb9ef2f1c6b", "support" @@ -560152,7 +560739,7 @@ "reftest" ], "css/css-overflow/webkit-line-clamp-033.html": [ - "a25be8b25dbc9ed8e1d84ab040b490a673508a96", + "261cf5b6b2478698cd50c25f6d6a437e6853e5b1", "reftest" ], "css/css-overflow/webkit-line-clamp/webkit-line-clamp-with-line-height-ref.html": [ @@ -561712,7 +562299,7 @@ "testharness" ], "css/css-properties-values-api/registered-property-cssom.html": [ - "59443b3323a89f64e2ae5b07508819b2872ead12", + "d408fa98f9fb23e569a9d20d8fb882331cc7e3f1", "testharness" ], "css/css-properties-values-api/registered-property-initial.html": [ @@ -561748,7 +562335,7 @@ "support" ], "css/css-properties-values-api/typedom.html": [ - "2fc6447f22b0078d57e6e54eed751323c322a090", + "b8e6f4aaf840c017ff7e49c14333c635c8483c50", "testharness" ], "css/css-properties-values-api/unit-cycles.html": [ @@ -564991,6 +565578,14 @@ "94ccd6ef6d550c83c97ba9525135cc309cc35842", "testharness" ], + "css/css-scrollbars/scrollbars-chrome-bug-001-ref.html": [ + "1bf59f90e740ae119b87d96855ea0277a6f8afc9", + "support" + ], + "css/css-scrollbars/scrollbars-chrome-bug-001.html": [ + "643781bac8079267c21c4c51920c56ab5f6a315a", + "reftest" + ], "css/css-scrollbars/support/viewport-scrollbar-body-frame.html": [ "8dacffefb62a8d348963a51c67e73887ca9b977b", "support" @@ -565144,15 +565739,15 @@ "testharness" ], "css/css-shapes/parsing/shape-image-threshold-computed.html": [ - "a90d23a6044af840cc8b4251e8825097f6a43646", + "81bc0ccb8453109ca99fed496ef607ee99e95035", "testharness" ], "css/css-shapes/parsing/shape-image-threshold-invalid.html": [ - "6299e2ecaad8247affa1e54ace4aea276322c114", + "c0cac033fb6d10a00275fcce6bb5e27ed4514984", "testharness" ], "css/css-shapes/parsing/shape-image-threshold-valid.html": [ - "914abd02210d4db881017c9453d3bcb68fd8e9f2", + "4ed1fb9fbaf1bd4aed1cdb89753d4f15c6a72fd9", "testharness" ], "css/css-shapes/parsing/shape-margin-computed.html": [ @@ -576791,6 +577386,14 @@ "c6c4c6aedd6394658966a12665f3bd298f9f80a6", "reftest" ], + "css/css-transforms/perspective-transforms-equivalence-ref.html": [ + "a4fc022382c957fe130905f5935cd33736117b03", + "support" + ], + "css/css-transforms/perspective-transforms-equivalence.html": [ + "2f2ae21f87fdfc392e5ec1373875e65ee58c3c4f", + "reftest" + ], "css/css-transforms/perspective-translateZ-0.html": [ "eca8e4de5adb744ce6b910bcbf7cd7f1fff52317", "reftest" @@ -581579,6 +582182,10 @@ "bb79a7df8d27c708e21a70a7589fbfa0422be3fb", "reftest" ], + "css/css-typed-om/set-var-reference-crash.html": [ + "c6bc3cc2a39703fcaee050c459fa3182b5454cd5", + "testharness" + ], "css/css-typed-om/stylevalue-normalization/normalize-ident.tentative.html": [ "d118dda4a2bbf6e766ab46d60d6717ab383f40d1", "testharness" @@ -590623,6 +591230,18 @@ "e5b895aa956bd26084737a174c31628c9c51db90", "support" ], + "css/css-writing-modes/reference/tcy-white-space-processing-001-ref.html": [ + "9c5acb315d7793026e13daecfe70cecff44a1c84", + "support" + ], + "css/css-writing-modes/reference/tcy-white-space-processing-002-ref.html": [ + "384499111072070543e1e7c1a34ad2fcd71ae0a4", + "support" + ], + "css/css-writing-modes/reference/tcy-white-space-processing-003-ref.html": [ + "449036ff5452b2cde0739226fa67a4d98e78cf2b", + "support" + ], "css/css-writing-modes/reference/text-combine-upright-decorations-001.html": [ "6b35f7f2549b1e58b8a88d82b5a05acea224a650", "support" @@ -592315,6 +592934,18 @@ "bcafef13c9d94876a1d201f344386866a812a68c", "reftest" ], + "css/css-writing-modes/tcy-white-space-processing-001.html": [ + "fd81fe91fa7f872a102e720aa94635f897683878", + "reftest" + ], + "css/css-writing-modes/tcy-white-space-processing-002.html": [ + "58a8a61013270917c196c3b3e1fe3538376e3ba2", + "reftest" + ], + "css/css-writing-modes/tcy-white-space-processing-003.html": [ + "50b0650f8c7948fdcd3544a9b4b56752d9cb44ec", + "reftest" + ], "css/css-writing-modes/test-plan/img/figure-over_and_under-fail.svg": [ "76b484996959008024647a321fb1789b9dfd4774", "support" @@ -608612,7 +609243,7 @@ "support" ], "docs/writing-tests/general-guidelines.md": [ - "02a4545fe40be93b65cbcba698ec72f63be4749a", + "63942b07c6736657183bc1478b45f3147e9a7c98", "support" ], "docs/writing-tests/h2tests.md": [ @@ -608644,7 +609275,7 @@ "support" ], "docs/writing-tests/rendering.md": [ - "feb0a53648a1b092e1abf0518e6a95629fe925c6", + "13cc669bfe1842b1b873bec391c74d6abeb944db", "support" ], "docs/writing-tests/server-features.md": [ @@ -611087,6 +611718,18 @@ "82e7461b0417fb6f667ad266c08789b58f06c457", "testharness" ], + "element-timing/element-only-when-fully-active.html": [ + "5608685a34219d831dd6c57743e829967d3ed247", + "testharness" + ], + "element-timing/fixed-id-identifier.html": [ + "00d6d4dd94c466939dbbabb93bbe5ef9f29b86e1", + "testharness" + ], + "element-timing/idlharness.window.js": [ + "f0e5d06658e773fd5f9ebf85511636e74c92dc80", + "testharness" + ], "element-timing/image-TAO.sub.html": [ "032ae6b12198b76107ab3dfcc2ab3b7f92b13c00", "testharness" @@ -611192,7 +611835,11 @@ "support" ], "element-timing/resources/element-timing-helpers.js": [ - "8933732616c116f1617c64f07182c9cbeb9f59fe", + "6328ee7bb6fc8b29003882b458de90cc282dc591", + "support" + ], + "element-timing/resources/iframe-stores-entry.html": [ + "2fa24769729f705547aa526cf4eca16c483cad78", "support" ], "element-timing/resources/iframe-with-square-sends-entry.html": [ @@ -621388,7 +622035,7 @@ "testharness" ], "html/dom/interfaces.https.html": [ - "6ca7721253200d4511758f5ba15a61f756509370", + "7745e4c68e25f3291e91a5f8b701ed6985923b84", "testharness" ], "html/dom/interfaces.worker.js": [ @@ -625476,7 +626123,7 @@ "testharness" ], "html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html": [ - "d42599661bf595d27de82db892b17a5ec400062d", + "e3e0778c97a2a04ded5a151d31b1dc4f82334187", "testharness" ], "html/infrastructure/common-dom-interfaces/collections/htmlformcontrolscollection.html": [ @@ -637516,7 +638163,7 @@ "support" ], "infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini": [ - "e34c73f1ba984ed27b5ced8ad99a3f673cd109cf", + "ee1217860b88bab3aa41966f4034c99c124cdb46", "support" ], "infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini": [ @@ -637828,7 +638475,7 @@ "support" ], "interfaces/FileAPI.idl": [ - "b5b40296429646cfbe13110153f2e281201ba669", + "0ae43bbe38cf6cfd78d2f8f468d45ee3aea8ee2b", "support" ], "interfaces/IndexedDB.idl": [ @@ -637999,6 +638646,10 @@ "1788faae5207bb7a21b23771bf2b0e978ea49a69", "support" ], + "interfaces/element-timing.idl": [ + "dc3b886cfe5b6da608cc71fbc13c97e3d7695b76", + "support" + ], "interfaces/encoding.idl": [ "b3086b8588cdfec129a4c038c074021cacff83c5", "support" @@ -638076,7 +638727,7 @@ "support" ], "interfaces/input-events.idl": [ - "0086128e562fbdb11e6c07ecd41f99a6e9a84189", + "c10aa32bed093a27df7993d1d384a926b7a65536", "support" ], "interfaces/intersection-observer.idl": [ @@ -638091,6 +638742,10 @@ "70aaaffd3cfb5781b77f92eedf57bd4205e308bc", "support" ], + "interfaces/largest-contentful-paint.idl": [ + "f16a7ff812c96ab28f7d3b8d0f1b92d141e552a0", + "support" + ], "interfaces/longtasks.idl": [ "333b842f86e5d41f6f1aab8827cf086356c5a782", "support" @@ -638172,7 +638827,7 @@ "support" ], "interfaces/performance-timeline.idl": [ - "8ded59d8a269f83037a8845417c1275dd91ec538", + "d9362ea27516ac4e40caa7632d9aa1e2ed9edb11", "support" ], "interfaces/permissions.idl": [ @@ -638288,7 +638943,7 @@ "support" ], "interfaces/user-timing.idl": [ - "4130803ff9c45c15ef670813127657a98bd5631a", + "8b0f813ba8e6efc34b979ac7323afcbcac41e72b", "support" ], "interfaces/vibration.idl": [ @@ -638324,7 +638979,7 @@ "support" ], "interfaces/web-share.idl": [ - "e275aac96fe9b0daad6a35b21db15c725698d6d7", + "ae1f3f8580c0ff038ebe798bd66437ca3eb3fefc", "support" ], "interfaces/webaudio.idl": [ @@ -638523,6 +639178,10 @@ "898454c4f385794d78ef4635612b6754cdd060af", "testharness" ], + "intersection-observer/rtl-clipped-root.html": [ + "a30c6e38c5a02df96215cfea2e40be78a871cb20", + "testharness" + ], "intersection-observer/same-document-no-root.html": [ "63e9f86d9c60533a2b4b193cf4e2860ef712ee4f", "testharness" @@ -638768,7 +639427,7 @@ "support" ], "kv-storage/backingstore.https.html": [ - "44e634d85bbc34621450c4029a63c5e9114075b3", + "c0f49d48f48fdf3db7e724fa4760121c5e1f595a", "testharness" ], "kv-storage/cause-errors-via-idb.https.html": [ @@ -638792,11 +639451,11 @@ "support" ], "kv-storage/helpers/kvs-tests.js": [ - "0cf4c2fd3d5fcaa392e8cbbcf64101155bcbe441", + "9fd9d205ae1996c355647d86e8b12b46369d1053", "support" ], "kv-storage/interface.https.html": [ - "ab1930b25c355e2da15fc4d2a2fea8fa2042ffcc", + "a5eba425b6d22469c37ee50e2845dcaa87ff8967", "testharness" ], "kv-storage/key-types.https.html": [ @@ -638844,7 +639503,7 @@ "testharness" ], "kv-storage/storage-smoke-test.https.html": [ - "31dac972d984f4301f54f2948eb4e2c7d6481c25", + "748b59bb2f2d0364669c55e566e8e84ae285b943", "testharness" ], "kv-storage/undefined-value.https.html": [ @@ -638863,10 +639522,18 @@ "88775b861a6b98b1af0fb5163222a1025a6df02e", "testharness" ], + "largest-contentful-paint/element-only-when-fully-active.html": [ + "41bdc8f8b984e61ab62f39734a1e19342697ef4e", + "testharness" + ], "largest-contentful-paint/expanded-image.html": [ "766b61d013da2cefddb9e35398648d4fa2a2bded", "testharness" ], + "largest-contentful-paint/idlharness.html": [ + "273fef80ce2d855075781512a9a8ab0a736af420", + "testharness" + ], "largest-contentful-paint/image-src-change.html": [ "3e083625bdc1812a2c344b8eefaaa10d3b31e623", "testharness" @@ -638875,6 +639542,10 @@ "fb0eddb220ec660d529a43b112c576bf146a87e8", "testharness" ], + "largest-contentful-paint/observe-after-untrusted-scroll.html": [ + "abe753fc14a33f88a398900632146ae3b8e8ee13", + "testharness" + ], "largest-contentful-paint/observe-image.html": [ "16b3502eb340cbce179bf440c245cafafe4beea4", "testharness" @@ -638887,6 +639558,10 @@ "94406b20d62b417a690ce6a96d909bb29c791081", "testharness" ], + "largest-contentful-paint/resources/iframe-stores-entry.html": [ + "cd600254805570deab8447ea843657d7f268b7c5", + "support" + ], "largest-contentful-paint/supported-lcp-type.html": [ "25d4eaa0367f45440d286c6c1c14de4458465d7b", "testharness" @@ -639180,15 +639855,15 @@ "support" ], "mathml/presentation-markup/direction/direction-overall.html": [ - "5351ca51688d51b2e399a296d52e1b23543a0c96", + "f668c55dbaecf1b89cc3c433ecf8b83f55d6b18f", "reftest" ], "mathml/presentation-markup/direction/direction-token-ref.html": [ - "95f182bc8c716e84e1e76cfce7013a16cf4c5ada", + "f1895b578adeaee2ef1a4c8b8ff35424bc81ea37", "support" ], "mathml/presentation-markup/direction/direction-token.html": [ - "1896f3fe394d6a31f6f6aaff79f6bfc3d647c462", + "25c8d6a13275a56afcbd6f89cc5bc0665a5f4102", "reftest" ], "mathml/presentation-markup/direction/direction.html": [ @@ -639196,7 +639871,7 @@ "testharness" ], "mathml/presentation-markup/fractions/frac-1.html": [ - "6be38d5439da9181ee53464abcf22863a9d176ce", + "5ecb66ecf6aabec264d8452a1277eb7769dde3fd", "testharness" ], "mathml/presentation-markup/fractions/frac-bar-001-ref.html": [ @@ -639204,7 +639879,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-bar-001.html": [ - "887ff174cc40c9b06303d22e08cef59e9b72f382", + "e381ffe77c391d91893789474bdd7530f3c969ac", "reftest" ], "mathml/presentation-markup/fractions/frac-color-001-notref.html": [ @@ -639220,7 +639895,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-color-002.html": [ - "4b45c8e1cfb7b4bb775832c03e5e692c22f19f90", + "ca4c41b46b198f01564ecad1521536f498a8bb45", "reftest" ], "mathml/presentation-markup/fractions/frac-created-dynamically-2-ref.html": [ @@ -639228,7 +639903,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-created-dynamically-2.html": [ - "2aa9675bb1f170640088a1071687890ee715523a", + "f16a367129d7b477fb6135597b79cc0ad9b569cd", "reftest" ], "mathml/presentation-markup/fractions/frac-created-dynamically-3-ref.html": [ @@ -639236,7 +639911,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-created-dynamically-3.html": [ - "c90119d8ef5f5282331c94ae1c57a9a3c8284f9d", + "e11a357fd4251ee11a2f50ae49822dff9208dd1c", "reftest" ], "mathml/presentation-markup/fractions/frac-created-dynamically-ref.html": [ @@ -639244,7 +639919,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-created-dynamically.html": [ - "7a555f20ea370b918bca2c64d5381cbab625732b", + "b74338a8804ed4e71c99675035fa070159185905", "reftest" ], "mathml/presentation-markup/fractions/frac-linethickness-001-ref.html": [ @@ -639252,11 +639927,11 @@ "support" ], "mathml/presentation-markup/fractions/frac-linethickness-001.html": [ - "4d6bda2c1670d9e615c7c3ffbc3891b90a22ecd4", + "a8ab7bd81ab593163e2c10ad1c9fd0dbe123ab25", "reftest" ], "mathml/presentation-markup/fractions/frac-linethickness-002.html": [ - "c3b3d69e59ad20fac86889f6869cc487eda8ec8d", + "85c7c58701042e3fd4494f7f2e04a7b16bccebb4", "testharness" ], "mathml/presentation-markup/fractions/frac-linethickness-003-notref.html": [ @@ -639272,7 +639947,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-linethickness-004.html": [ - "d9689fcdc6813382d92ced5c5941181a47110b2c", + "a8b36c19265f00b6e88c89181a307b577fc6b9da", "reftest" ], "mathml/presentation-markup/fractions/frac-mrow-001-ref.html": [ @@ -639280,7 +639955,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-mrow-001.html": [ - "cb154c65edc38103a6ebc47b5fc9f1466655abb1", + "228d4ec3f0b1e1484bd4078c32b9ebb37add733f", "reftest" ], "mathml/presentation-markup/fractions/frac-numalign-denomalign-001-ref.html": [ @@ -639288,15 +639963,15 @@ "support" ], "mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html": [ - "59d663f6a4e455b2e66a1d22a6a141a7edc9a132", + "78c95c28755bdef6019bf0912b43e5f2e98ccfb4", "reftest" ], "mathml/presentation-markup/fractions/frac-parameters-1.html": [ - "55404fa562c4dd304eb84702bee4578d02ae7925", + "b8bc405107bd643519fef9e0fb0dba1ba0a66762", "testharness" ], "mathml/presentation-markup/fractions/frac-parameters-2.html": [ - "63ab97760fc03161b9b3c63d09819463131864ad", + "ce2d299f281b639c1e4026caa9354a8bc8c5298d", "testharness" ], "mathml/presentation-markup/fractions/frac-parameters-gap-001-ref.html": [ @@ -639304,7 +639979,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-parameters-gap-001.html": [ - "f577682ad92631bb721354e2c3d6fb1f59db94b3", + "e87b357dd2ae7c06549538f5da422ff89f49ad1c", "reftest" ], "mathml/presentation-markup/fractions/frac-parameters-gap-002-ref.html": [ @@ -639312,7 +639987,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-parameters-gap-002.html": [ - "2c0a9a1a668307b2b7e90774fd118d89628dc6c6", + "0b704dc801e85825359c34de3a5d6d081814ab5b", "reftest" ], "mathml/presentation-markup/fractions/frac-parameters-gap-003-ref.html": [ @@ -639320,7 +639995,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-parameters-gap-003.html": [ - "826eecd55c4da13fafdbe08457ecb5cda260b46b", + "9bd79836cc06fe7a05c806aa8c5083c914273472", "reftest" ], "mathml/presentation-markup/fractions/frac-parameters-gap-004-ref.html": [ @@ -639328,7 +640003,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-parameters-gap-004.html": [ - "359176228d7c543d5efa7b448c777e575df184ac", + "43410cba6089c23c7c960bb3c6207100cd341da2", "reftest" ], "mathml/presentation-markup/fractions/frac-parameters-gap-005-ref.html": [ @@ -639336,7 +640011,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-parameters-gap-005.html": [ - "60295f7ddd20c1a9b55d4c3b800c8a78f324c7fe", + "da77012b96dd9ebfb000df6ad22123bafe97ff4c", "reftest" ], "mathml/presentation-markup/fractions/frac-parameters-gap-006-ref.html": [ @@ -639344,7 +640019,7 @@ "support" ], "mathml/presentation-markup/fractions/frac-parameters-gap-006.html": [ - "7895052d4fd5b02e11e03872ab3d6de574781db2", + "25bf644ec61fad2a82c794cd3bf5072ad644cb15", "reftest" ], "mathml/presentation-markup/fractions/frac-visibility-001-ref.html": [ @@ -639352,15 +640027,23 @@ "support" ], "mathml/presentation-markup/fractions/frac-visibility-001.html": [ - "65b95054db46339159fc6e0f8438144b02b19a09", + "140603b47f5af19e35df63ea176b460f4c7b6151", "reftest" ], "mathml/presentation-markup/mrow/inferred-mrow-baseline.html": [ - "672d90de93363331a418f33ecac8f2380bd5fb5f", + "1541b2d6ce17c90a52c15f3ce5461a5c7d42920f", "testharness" ], "mathml/presentation-markup/mrow/inferred-mrow-stretchy.html": [ - "75587d076c2790608133b7a81558a42dc2581cff", + "ee40561a634c00eb9e29dd66d4a28f579a78af59", + "testharness" + ], + "mathml/presentation-markup/operators/embellished-operator-001.html": [ + "78c5069b90cab40ec2703c6c01c5d8643b5f836d", + "testharness" + ], + "mathml/presentation-markup/operators/embellished-operator-002.html": [ + "da343dd0bc35a79e0f309c38bbff34a69aa7df34", "testharness" ], "mathml/presentation-markup/operators/mo-axis-height-1.html": [ @@ -639432,55 +640115,55 @@ "reftest" ], "mathml/presentation-markup/radicals/root-parameters-1.html": [ - "5ad0b7315e02b9d893937a376b0545ff7bb0eada", + "d09d117b8ad5b52ea3c8778dcd6c4dd56a7b9270", "testharness" ], "mathml/presentation-markup/scripts/subsup-1.html": [ - "01a6b0e1ed1fed2d069ac2b8b3e3716ffeee08b7", + "e5321d6c4a3c3dafca68caacdb651fed5c778c9b", "testharness" ], "mathml/presentation-markup/scripts/subsup-2.html": [ - "2fd6963b6a7906aaeabd17a16a53a9ebbe56116f", + "1a5b80d34397962c2e7d3400c782bed8cd6f149b", "testharness" ], "mathml/presentation-markup/scripts/subsup-3.html": [ - "60df24a799027c0704be4622976ea8e2ae2a3d22", + "5494bb0c919cba3c02320d4f59481dc4eebed74f", "testharness" ], "mathml/presentation-markup/scripts/subsup-4.html": [ - "6886766097cecff350ddcf3ce81bb87e70b4ce28", + "00bd45413c85667a028394c3b3f983a3b11fed75", "testharness" ], "mathml/presentation-markup/scripts/subsup-5.html": [ - "2cc4e6d9554a1f6fde6c16e37fec2a39c441a0e8", + "566b0133ec68d12c69e6f70d8a9205e2336f8936", "testharness" ], "mathml/presentation-markup/scripts/subsup-parameters-1.html": [ - "7503ad166af33745701ab379cf51fd5cda8ce7dc", + "a5f21ec5458f0cce4b6517e39572d3e928585e20", "testharness" ], "mathml/presentation-markup/scripts/subsup-parameters-2.html": [ - "62aa7a9dc3be90a343dbcb4810e5cb479707be2e", + "0abf01838c8c8c05f1c6cb4bf72e9fea57bca8d9", "testharness" ], "mathml/presentation-markup/scripts/underover-1.html": [ - "b17835528a0ed8d78d643ef9f24dd7822b62f559", + "5b718707de9ab316c6abb0ae7bf26667af191447", "testharness" ], "mathml/presentation-markup/scripts/underover-parameters-1.html": [ - "d8a564a1159518195e889694aee8d0b167efec91", + "26a1b3964cc10ced8762314390840db94efdb970", "testharness" ], "mathml/presentation-markup/scripts/underover-parameters-2.html": [ - "c10f77ee2c807b8a24566574f6ff6377736ae514", + "aed22235b8c192ee69237c63face745e7e35e1bd", "testharness" ], "mathml/presentation-markup/scripts/underover-parameters-3.html": [ - "86562fd374bdb44983657954f5b554ae62db8984", + "6a1e51cdc4516ae1fdd2784c0e77682222773b2f", "testharness" ], "mathml/presentation-markup/scripts/underover-parameters-4.html": [ - "f7fb389b59feb23276773a91b854fd6ab105fc15", + "e569c15a6993321051b2490f62c5b6ae39666b7a", "testharness" ], "mathml/presentation-markup/spaces/mspace-children-ref.html": [ @@ -639503,16 +640186,56 @@ "d7b38458998c7d4d96adf3f31ccaca9d9886469f", "reftest" ], + "mathml/presentation-markup/spaces/space-like-001.html": [ + "61375bcd8e320be57e471815891c68aa01e76065", + "testharness" + ], + "mathml/presentation-markup/spaces/space-like-002.html": [ + "f5f4e5a84b248184bf33aa46ffacf35241209ce3", + "testharness" + ], + "mathml/presentation-markup/spaces/space-like-003.html": [ + "6d3d007744e7a346cee178187f39928407ac1511", + "testharness" + ], + "mathml/presentation-markup/spaces/space-like-004.html": [ + "091a3ea0a628c9b18b4b262aef737d7a7c9dac0a", + "testharness" + ], "mathml/presentation-markup/tables/table-axis-height.html": [ - "feb29077e8e34bcd3155f0661f4878bb93bdbf19", + "3eaf9c8fff483232eb6794b603f270bb86c47d3d", "testharness" ], - "mathml/relations/css-styling/color-1-ref.html": [ + "mathml/relations/css-styling/color-001-ref.html": [ + "0efca480eec5a3da684fe79a429982b139b202e4", + "support" + ], + "mathml/relations/css-styling/color-001.html": [ + "bc4b17730c9c1c0981562ea0ebe04d4f0d68e4f8", + "reftest" + ], + "mathml/relations/css-styling/color-002-ref.html": [ + "0efca480eec5a3da684fe79a429982b139b202e4", + "support" + ], + "mathml/relations/css-styling/color-002.html": [ + "177333830e5f89a36942f1a11278e2dc90d1e37d", + "reftest" + ], + "mathml/relations/css-styling/color-003-ref.html": [ + "0efca480eec5a3da684fe79a429982b139b202e4", + "support" + ], + "mathml/relations/css-styling/color-003.html": [ + "2422ffdf09f3cfdc73972267542dd82f1a3cd152", + "reftest" + ], + "mathml/relations/css-styling/color-004-ref.html": [ "0efca480eec5a3da684fe79a429982b139b202e4", "support" ], - "mathml/relations/css-styling/color-1.html": [ - "4d9d084a5a6b6414e01d4f4693237b4544e1ad48", + "mathml/relations/css-styling/color-004.html": [ + "65f6c4469ad6ade177b4d2b6b8d32fc5038c430b", "reftest" ], "mathml/relations/css-styling/display-1-ref.html": [ @@ -639520,11 +640243,11 @@ "support" ], "mathml/relations/css-styling/display-1.html": [ - "38dd0bafdf84e5e20cfc904bc9b9f2a219a6b8ff", + "f32a15ec01ac808d2e32ecb8cb232c12a5e0aa19", "reftest" ], "mathml/relations/css-styling/displaystyle-1.html": [ - "c2ccb78dc9f49ed5dceb10a4a1f6eccf19ad3902", + "12108836ce9356ea80e29ae6e095a355a519d49f", "testharness" ], "mathml/relations/css-styling/dynamic-dir-1-ref.html": [ @@ -639532,7 +640255,7 @@ "support" ], "mathml/relations/css-styling/dynamic-dir-1.html": [ - "3667ece8c53ccdb4747794ff48dde79f5c405629", + "d28f66c3d5f628dd6b3150251c818a3c7d11df8f", "reftest" ], "mathml/relations/css-styling/lengths-1-ref.html": [ @@ -639544,7 +640267,7 @@ "reftest" ], "mathml/relations/css-styling/lengths-2.html": [ - "c3b88549cdbb891be326798ead484b461fbfff96", + "22fc40156f177564beb0eb0907637a6bce6e60ca", "testharness" ], "mathml/relations/css-styling/mathsize-attribute-ref.html": [ @@ -639699,12 +640422,52 @@ "fa8bea41f470bbe83441bdea2693cd16b9b01320", "reftest" ], - "mathml/relations/css-styling/visibility-1-ref.html": [ + "mathml/relations/css-styling/padding-border-margin/border-001.html": [ + "38922118edd8f22596f388aceab7af63192577b0", + "testharness" + ], + "mathml/relations/css-styling/padding-border-margin/helper.js": [ + "8d8ac32f442d0593abeb16fa961dee479e22b552", + "support" + ], + "mathml/relations/css-styling/padding-border-margin/margin-001.html": [ + "dc3a2b4a150d7b140cbc2339a04363a2a29e2e25", + "testharness" + ], + "mathml/relations/css-styling/padding-border-margin/padding-001.html": [ + "1f8875f657d0ce30719390fc0f6b7c28aae04c65", + "testharness" + ], + "mathml/relations/css-styling/visibility-001-ref.html": [ "fcaf5fe85b44129db71f82913374859380576369", "support" ], - "mathml/relations/css-styling/visibility-1.html": [ - "7083ef70fb3c8b5e90b7e590364b5c2c3502aefe", + "mathml/relations/css-styling/visibility-001.html": [ + "f47bfad1fee107ab294a84279ccbf98d2ea9a729", + "reftest" + ], + "mathml/relations/css-styling/visibility-002-ref.html": [ + "fcaf5fe85b44129db71f82913374859380576369", + "support" + ], + "mathml/relations/css-styling/visibility-002.html": [ + "f3afb79c157d8d6f60a6a681fac2c2129cdba99b", + "reftest" + ], + "mathml/relations/css-styling/visibility-003-ref.html": [ + "fcaf5fe85b44129db71f82913374859380576369", + "support" + ], + "mathml/relations/css-styling/visibility-003.html": [ + "cfeed644cbea10a031a37c2fef01cabacb6a68a0", + "reftest" + ], + "mathml/relations/css-styling/visibility-004-ref.html": [ + "fcaf5fe85b44129db71f82913374859380576369", + "support" + ], + "mathml/relations/css-styling/visibility-004.html": [ + "8173b9cd2ef9162d6596c412d559abdb409d7267", "reftest" ], "mathml/relations/html5-tree/class-1-ref.html": [ @@ -639728,7 +640491,7 @@ "reftest" ], "mathml/relations/html5-tree/display-1.html": [ - "3a180f5d42bcd3d260019edabc6ecf455b8dcf8f", + "6747413e477a0baeb8dc8ea75a2ddd7b97b6f280", "testharness" ], "mathml/relations/html5-tree/dynamic-1-ref.html": [ @@ -639827,6 +640590,10 @@ "4e92a846461b65d150cef9a9444de27abf40a26d", "reftest" ], + "mathml/support/feature-detection.js": [ + "50ca926d25ea810177068a5f5de29f39749db7e6", + "support" + ], "mathml/tools/axisheight.py": [ "43827e7031665bdd57ee54e208ea0f875a9a60ec", "support" @@ -641384,17 +642151,13 @@ "support" ], "mixed-content/generic/tools/generate.py": [ - "fe4305c4eea53b1e0317e92303078f0b6875c772", + "ed978bcef9cc9322ef600e5217ae1d754588d50b", "support" ], "mixed-content/generic/tools/regenerate": [ "e6bd63519b331b3a921755445f6895e39f7864f5", "support" ], - "mixed-content/generic/tools/spec_validator.py": [ - "686579ece5797abfdb5441e080db85758fe1b220", - "support" - ], "mixed-content/imageset.https.sub.html": [ "1f3d0471fbd2b38649894619494750ef221d72c9", "testharness" @@ -642264,7 +643027,7 @@ "testharness" ], "mixed-content/spec.src.json": [ - "06d381d363eeaeb825629f70c912a132d3551646", + "95dc2d318f54fcff89d5ad4fbd15656f32608288", "support" ], "mixed-content/spec_json.js": [ @@ -643595,10 +644358,6 @@ "f2c2fc82866b83953e2783f8dc56ceaa0803b097", "testharness" ], - "native-file-system/NativeFileSystemWritableFileStream.tentative.https.window.js": [ - "1dbcb2b136220954c777b2cc3b0197039cf730be", - "testharness" - ], "native-file-system/README.md": [ "6905a68e7901ce26bc1a363062304e1536604400", "support" @@ -652920,7 +653679,7 @@ "support" ], "referrer-policy/README.md": [ - "303362df924c81e3c7d2389255af8f625e6898da", + "498f7f26137b71a7776f07868261776c542b27c7", "support" ], "referrer-policy/css-integration/README.md": [ @@ -653120,17 +653879,13 @@ "support" ], "referrer-policy/generic/tools/generate.py": [ - "b3e3340d97b346c3f2aa787dd55635dffa63f929", + "98374982a8d17909e7f192c6d90ae7998e21953b", "support" ], "referrer-policy/generic/tools/regenerate": [ "e6bd63519b331b3a921755445f6895e39f7864f5", "support" ], - "referrer-policy/generic/tools/spec_validator.py": [ - "70656db25d2ce4f09c3fbb8a90294cb7fa20ba97", - "support" - ], "referrer-policy/generic/unsupported-csp-referrer-directive.html": [ "0a29f38c0288c34c23eea14a6053d68d6b19582e", "testharness" @@ -657976,7 +658731,7 @@ "testharness" ], "referrer-policy/spec.src.json": [ - "5f0247b935b78c645f8afc6287d58722b50e3d80", + "f69c289526ab79acdebc872725c00a847685591a", "support" ], "referrer-policy/spec_json.js": [ @@ -662536,7 +663291,7 @@ "support" ], "resources/idlharness.js": [ - "9be554d96b6e29cb43576f5ac8c1f8209e89fd62", + "e7a3abbec44778f8882a763374f25ced0d6cedf0", "support" ], "resources/idlharness.js.headers": [ @@ -667940,7 +668695,7 @@ "testharness" ], "std-toast/options.html": [ - "6d4a462d3a9417a501c6ad434b25896a03e162db", + "9f53bf88601ce914b1acf4054121d9420370fffa", "testharness" ], "std-toast/ref-tests/toast-slotting-expected.html": [ @@ -668535,10 +669290,18 @@ "e0af766e8ff5de780818b9d0712714dd5638e882", "support" ], + "svg/coordinate-systems/support/viewBox-change-repaint-001-ref.html": [ + "e13e368d7b8ab6021d5041d9bd51714b0859f024", + "support" + ], "svg/coordinate-systems/support/viewBox-scaling-text-001-ref.html": [ "effaba5fc4aeceb2249b8a843873ef53860e4ba7", "support" ], + "svg/coordinate-systems/viewBox-change-repaint-001.html": [ + "2a90349754b366b0610626750d2790108ee1346d", + "reftest" + ], "svg/coordinate-systems/viewBox-scaling-text-001.html": [ "3089043078746231cda5331140f56a6b907c70fd", "reftest" @@ -673404,11 +674167,11 @@ "support" ], "tools/requirements_flake8.txt": [ - "480aacd466257f82068f5c133ec90e59a2b1eb4f", + "d73e7c3dbbe2f0cf20637e639c449b0fa4538caf", "support" ], "tools/requirements_mypy.txt": [ - "8f1d67cd21230939a2ff4fe09f7e3960b58ca560", + "c1bf4bc088e7003d7ea2b362a28048e8952d2031", "support" ], "tools/runner/css/bootstrap-theme.min.css": [ @@ -677416,7 +678179,7 @@ "support" ], "tools/tox.ini": [ - "ba6dc038a172895f0bda838c6456a5db95a75952", + "63fb8ed9832ba9d11dae965e3c335e3d26289720", "support" ], "tools/webdriver/.gitignore": [ @@ -677484,7 +678247,7 @@ "support" ], "tools/wpt/run.py": [ - "6acc5b8e7400f5726538657239de5710ecea396d", + "d5d7e7a21f5f3b195ce5b93141d6798bdfeb5e2d", "support" ], "tools/wpt/testfiles.py": [ @@ -677528,7 +678291,7 @@ "support" ], "tools/wpt/wpt.py": [ - "4130e1eecf8ae52dbc0b68f6cd59010dd4e435e4", + "93301dd86b4ffe202902a492204eba6537fb50d5", "support" ], "tools/wptrunner/.gitignore": [ @@ -677544,7 +678307,7 @@ "support" ], "tools/wptrunner/README.rst": [ - "76e496dcdbb697a2d6662a6dffb603b17ace053f", + "d4f976dfca1a18c3b1c8b90c4175bf974f6169e2", "support" ], "tools/wptrunner/docs/Makefile": [ @@ -677564,7 +678327,7 @@ "support" ], "tools/wptrunner/docs/expectation.rst": [ - "7fe89d943ebdd0cf521d201bff40645fb9b663f7", + "9b3e5e05e5cc3c86bb66d739e9737b4ea20b34b9", "support" ], "tools/wptrunner/docs/index.rst": [ @@ -677580,7 +678343,7 @@ "support" ], "tools/wptrunner/requirements.txt": [ - "e25eec38283e0825a7a402912376c3a396d6de70", + "d6c7a4ff3983663d088c64f6608e3fcf7de3bbfe", "support" ], "tools/wptrunner/requirements_chrome.txt": [ @@ -677796,11 +678559,11 @@ "support" ], "tools/wptrunner/wptrunner/browsers/firefox.py": [ - "2f58022d238742ac97e4d898830cfe48801718fe", + "7e6d017d541ac85a4b711f18c037a832c134b9ef", "support" ], "tools/wptrunner/wptrunner/browsers/firefox_android.py": [ - "d8d5c7f728451a97b4f93fb80bfb6c56a3c2a595", + "b6d7bc8851e0fd9b8cb2745e7360a665152b7cba", "support" ], "tools/wptrunner/wptrunner/browsers/ie.py": [ @@ -677844,7 +678607,7 @@ "support" ], "tools/wptrunner/wptrunner/environment.py": [ - "2493f1fa4407a39aad3ac3c2a724322b75b0944a", + "924409216411050b038b61c7402eab687b122429", "support" ], "tools/wptrunner/wptrunner/executors/__init__.py": [ @@ -677964,7 +678727,7 @@ "support" ], "tools/wptrunner/wptrunner/formatters/wptreport.py": [ - "c58422d0de0a594c237b7fa6b2e89bf14eaf44cc", + "d73911f6a94e922dc8dc6f1d7f746abbf1a04362", "support" ], "tools/wptrunner/wptrunner/formatters/wptscreenshot.py": [ @@ -678044,7 +678807,7 @@ "support" ], "tools/wptrunner/wptrunner/tests/test_formatters.py": [ - "ec91cca1c13e7a9ce80a6214b8e3ac2dd73034f8", + "72f3a591ad7f90532671ccb897dfcb161bc8f45d", "support" ], "tools/wptrunner/wptrunner/tests/test_manifestexpected.py": [ @@ -678096,7 +678859,7 @@ "support" ], "tools/wptrunner/wptrunner/update/update.py": [ - "a0f42377734b1963d7df1ce1dcb3472be4b7781c", + "0bcaf823b72c30e346a64f3c0344bc2275df64f5", "support" ], "tools/wptrunner/wptrunner/vcs.py": [ @@ -678176,7 +678939,7 @@ "support" ], "tools/wptrunner/wptrunner/wpttest.py": [ - "5f50fbcef1181929fc12052e09edd85e57400068", + "2ce15a0d9c7f85339caadecc017f178ee0245d27", "support" ], "tools/wptserve/.gitignore": [ @@ -678808,11 +679571,11 @@ "support" ], "trusted-types/trusted-types-reporting.tentative.https.html": [ - "3074895ba13f7f734d00898e723b4b604234a9cb", + "8dda8b23c8f06bfa375b6c6de874c7de0fbfc3c3", "testharness" ], "trusted-types/trusted-types-reporting.tentative.https.html.headers": [ - "8093b8474d686fd665c6e835c6d0ed8f337cf2cd", + "947a151c874ce9d372baa786c1b2964cbd9bc279", "support" ], "uievents/META.yml": [ @@ -679172,7 +679935,7 @@ "testharness" ], "upgrade-insecure-requests/support/generate.py": [ - "4fb7078e7709bd1541df8cc61bbcfa449bc14b37", + "1b0c2897feed76afb338ba11a93f01022a024550", "support" ], "upgrade-insecure-requests/support/redirect-cors.py": [ @@ -679192,7 +679955,7 @@ "testharness" ], "upgrade-insecure-requests/worker-subresource-fetch-redirect-upgrade.https.html": [ - "948dd6566c2a1fae7b015c3bf15a4a43fdb3c06d", + "bcda7ed4432493f93e616915d11a4df76571a21c", "testharness" ], "upgrade-insecure-requests/worker-subresource-fetch-upgrade.https.html": [ @@ -683352,7 +684115,7 @@ "support" ], "webdriver/tests/get_window_rect/get.py": [ - "ee2c9eefd3f4ff81ea1cb8f33be58cc17f332030", + "b5103787e15effe1d03b353a956f5db6b29d7de0", "wdspec" ], "webdriver/tests/get_window_rect/user_prompts.py": [ @@ -684548,7 +685311,7 @@ "testharness" ], "webrtc/RTCPeerConnection-helper.js": [ - "6a4ce854db70573a368ced9889e0623b15311f72", + "25ddd99bb0981db40b4d147580a343e773fc7f1a", "support" ], "webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html": [ @@ -684595,8 +685358,12 @@ "f2add7f0d34bada5c156cafeac399e104b2a414a", "testharness" ], + "webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html": [ + "4dcce451995597ea072c7e491f0cef908014cf0c", + "testharness" + ], "webrtc/RTCPeerConnection-restartIce.https.html": [ - "6b66975fdad2b5b11159baf921bdcae93d6deb23", + "c069736fa0b37be2bff7174e5ea65aaf91fb5b61", "testharness" ], "webrtc/RTCPeerConnection-setDescription-transceiver.html": [ @@ -684756,7 +685523,7 @@ "testharness" ], "webrtc/RTCRtpTransceiver.https.html": [ - "e3cd68809cc1e4ca443d9de13251972fc3bcbe67", + "67571895175f19c008743523f035aa31fced9681", "testharness" ], "webrtc/RTCSctpTransport-constructor.html": [ @@ -687116,27 +687883,35 @@ "reftest" ], "webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50-ref.html": [ - "c37ae7a7dfadd9481102eb542c7d9b10e5baa323", + "4d7553a8b7a0f7713c7b576511bb66eb07e1f97a", "support" ], "webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50.html": [ - "ec0460f1b736b1c803aa5fa22b8ccaf9aecdb0bb", + "0f69e5725110b281f61d0a110de4ec28c14a2b47", + "reftest" + ], + "webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size-ref.html": [ + "73db73ed6aa7ff2a0f3fc8c5b45a97542d4d5c28", + "support" + ], + "webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size.html": [ + "869b5f669e1088ce3d1056ab1588b0c47154ed6d", "reftest" ], "webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50-ref.html": [ - "108495e4b00e52a78a83975f064e6d86ad9a08ba", + "baa6511046330c8114e6805eb13c695bc2b5c4a0", "support" ], "webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50.html": [ - "160435c62e367eb51367893019d6090446ff0f8b", + "953e74183b2b870af0f552b2e22c28eb8786882e", "reftest" ], "webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size-ref.html": [ - "296369332cf8f542e14548a9b7d884ea810b2634", + "aeaf757cc6842674186dee1157de4df9c7c890cc", "support" ], "webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size.html": [ - "04d0be47d9033ab0600f2b024f5e906e2ecf3d96", + "174894bf0c5a7c3f99926d8a64979fea38687288", "reftest" ], "webvtt/rendering/cues-with-video/processing-model/align_center_wrapped-ref.html": [ @@ -689040,11 +689815,15 @@ "support" ], "webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50.vtt": [ - "4d8538a2be773fc7a9277044a6713622b6262bb6", + "69fd3e00d90f6352506e6fe1062fff2453089df9", + "support" + ], + "webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50_size_gt_maximum_size.vtt": [ + "50e80cc3e1435789c2dbea73f9fb71939e463769", "support" ], "webvtt/rendering/cues-with-video/processing-model/support/align_center_position_lt_50.vtt": [ - "4ea1e656077b63830b9032517113d781dadbc95d", + "86f8c37ec5ed5e6cef58aea0fd9a80595bd92df0", "support" ], "webvtt/rendering/cues-with-video/processing-model/support/align_center_position_lt_50_size_gt_maximum_size.vtt": [ @@ -689363,6 +690142,10 @@ "0e2c23424c0893b6a563c2aa2fbd999e50b1cfef", "testharness" ], + "webxr/exclusive_requestFrame_nolayer.https.html": [ + "d31b927631f91128933c1badd56747315c767780", + "testharness" + ], "webxr/getInputPose_handedness.https.html": [ "5a310c6dd77274631d0ef9e751c6f195def9c3d3", "testharness" @@ -689375,6 +690158,14 @@ "3e54e367787cb95dada398790fe23b10174df29f", "testharness" ], + "webxr/render_state_vertical_fov_immersive.https.html": [ + "485438cabf6a633df42a0f94c04922e7274013e1", + "testharness" + ], + "webxr/render_state_vertical_fov_inline.https.html": [ + "8bf384f4f150b0b2e841b33d67e290011694c0f4", + "testharness" + ], "webxr/resources/webxr_check.html": [ "2d8e5b387dc88588921ccfa49dd14db58009900c", "support" @@ -689392,7 +690183,7 @@ "support" ], "webxr/resources/webxr_util.js": [ - "d75e5c7bd2e26cf79794a01b8bed637c165926e6", + "022aca8c93e232f00c2d76de5580231af59ff487", "support" ], "webxr/webGLCanvasContext_create_xrcompatible.https.html": [ @@ -689539,6 +690330,10 @@ "bdb5edda566704c4d1434b328d3adbe46d3501ba", "testharness" ], + "webxr/xrSession_requestAnimationFrame_timestamp.https.html": [ + "daa786b368627dfc60663470e9e339f97eff729c", + "testharness" + ], "webxr/xrSession_requestReferenceSpace.https.html": [ "51aa8885f5e853ca4bf225134dee120b71d28011", "testharness" @@ -689559,10 +690354,38 @@ "956edba98365d90eb180ad3c9697dae098bd25db", "testharness" ], + "webxr/xrView_match.https.html": [ + "142f272d36f812c49455a78bfc62f285f9e64818", + "testharness" + ], + "webxr/xrView_oneframeupdate.https.html": [ + "9404fcb8aaf33876f2918d3796190f16feafe506", + "testharness" + ], + "webxr/xrViewport_valid.https.html": [ + "1b7d982d596187f1381bee73eac2990900a37f8f", + "testharness" + ], + "webxr/xrWebGLLayer_constructor.https.html": [ + "74f0e7611e5e201a275b1a444a6d4b367af3e53d", + "testharness" + ], "webxr/xrWebGLLayer_framebuffer.https.html": [ "ba6b7dc0b922ae45aa714de8d3ca6f4ffbaf414c", "testharness" ], + "webxr/xrWebGLLayer_framebuffer_draw.https.html": [ + "dd40865e445aafce88f5941f4127236c36f01f2d", + "testharness" + ], + "webxr/xrWebGLLayer_framebuffer_scale.https.html": [ + "7b5cedb1c83987daf435f662e5687cf6e1bb0559", + "testharness" + ], + "webxr/xrWebGLLayer_opaque_framebuffer.https.html": [ + "ceff6251d565726ddb56798da7bbbef649d96d2f", + "testharness" + ], "webxr/xrWebGLLayer_viewports.https.html": [ "94a23dcdb427298722a989987a02f35a8d98d055", "testharness" diff --git a/tests/wpt/metadata/css/css-backgrounds/background-color-body-propagation-007.html.ini b/tests/wpt/metadata/css/css-backgrounds/background-color-body-propagation-007.html.ini new file mode 100644 index 00000000000..a8b1ffe5757 --- /dev/null +++ b/tests/wpt/metadata/css/css-backgrounds/background-color-body-propagation-007.html.ini @@ -0,0 +1,2 @@ +[background-color-body-propagation-007.html] + expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/perspective-transforms-equivalence.html.ini b/tests/wpt/metadata/css/css-transforms/perspective-transforms-equivalence.html.ini new file mode 100644 index 00000000000..49b7aea325b --- /dev/null +++ b/tests/wpt/metadata/css/css-transforms/perspective-transforms-equivalence.html.ini @@ -0,0 +1,2 @@ +[perspective-transforms-equivalence.html] + expected: FAIL 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 66a90b0d890..8c3f8f31612 100644 --- a/tests/wpt/metadata/fetch/content-type/response.window.js.ini +++ b/tests/wpt/metadata/fetch/content-type/response.window.js.ini @@ -315,18 +315,21 @@ [<iframe>: combined response Content-Type: text/html */*] expected: FAIL - [<iframe>: combined response Content-Type: text/html;x=" text/plain] - expected: FAIL - [<iframe>: combined response Content-Type: text/html;" text/plain] expected: FAIL [<iframe>: separate response Content-Type: text/html */*] expected: FAIL - [<iframe>: combined response Content-Type: text/html */*;charset=gbk] + [<iframe>: combined response Content-Type: */* text/html] + expected: FAIL + + [<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html] + expected: FAIL + + [<iframe>: separate response Content-Type: text/html;" text/plain] expected: FAIL - [<iframe>: separate response Content-Type: text/html;" \\" text/plain] + [<iframe>: separate response Content-Type: text/html;x=" text/plain] 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 646a46c0cbb..279734168dc 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,6 @@ [separate text/javascript x/x] expected: FAIL - [separate text/javascript;charset=windows-1252 error text/javascript] - expected: FAIL - - [separate text/javascript error] + [separate text/javascript;charset=windows-1252 text/javascript] expected: FAIL diff --git a/tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini b/tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini index d4ba399b762..b2cd43ef76c 100644 --- a/tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini +++ b/tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini @@ -14,3 +14,6 @@ [X-Content-Type-Options%3A%20'NosniFF'] expected: FAIL + [X-Content-Type-Options%3A%0D%0AX-Content-Type-Options%3A%20nosniff] + expected: FAIL + diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini index 75d75b4cda2..385376c7321 100644 --- a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_2.html.ini +++ b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini @@ -1,4 +1,4 @@ -[traverse_the_history_2.html] +[traverse_the_history_4.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 index dec4c579137..16fa2c5cfc1 100644 --- 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 @@ -1,5 +1,4 @@ [creating_browsing_context_test_01.html] - expected: TIMEOUT [first argument: absolute url] - expected: TIMEOUT + 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 a537311d2d1..c1ce887cc10 100644 --- a/tests/wpt/metadata/html/dom/interfaces.https.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.https.html.ini @@ -5824,6 +5824,72 @@ [Window interface: operation queueMicrotask(VoidFunction)] expected: FAIL + [Document interface: documentWithHandlers must inherit property "queryCommandEnabled(DOMString)" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "onsecuritypolicyviolation" with the proper type] + expected: FAIL + + [Document interface: calling queryCommandEnabled(DOMString) on documentWithHandlers with too few arguments must throw TypeError] + expected: FAIL + + [Document interface: calling queryCommandIndeterm(DOMString) on documentWithHandlers with too few arguments must throw TypeError] + expected: FAIL + + [Document interface: calling queryCommandSupported(DOMString) on documentWithHandlers with too few arguments must throw TypeError] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "execCommand(DOMString, boolean, DOMString)" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "vlinkColor" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "queryCommandSupported(DOMString)" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "designMode" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "dir" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "onauxclick" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "onformdata" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "queryCommandValue(DOMString)" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "alinkColor" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "all" with the proper type] + expected: FAIL + + [Document interface: calling queryCommandValue(DOMString) on documentWithHandlers with too few arguments must throw TypeError] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "onloadend" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "linkColor" with the proper type] + expected: FAIL + + [Document interface: calling execCommand(DOMString, boolean, DOMString) on documentWithHandlers with too few arguments must throw TypeError] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "queryCommandState(DOMString)" with the proper type] + expected: FAIL + + [Document interface: documentWithHandlers must inherit property "queryCommandIndeterm(DOMString)" with the proper type] + expected: FAIL + + [Document interface: calling queryCommandState(DOMString) on documentWithHandlers with too few arguments must throw TypeError] + expected: FAIL + [interfaces.https.html?include=HTML.*] [HTML IDL tests] @@ -8085,9 +8151,6 @@ [HTMLInputElement interface: createInput("file") must inherit property "autofocus" with the proper type] expected: FAIL - [HTMLInputElement interface: createInput("file") must inherit property "files" with the proper type] - expected: FAIL - [HTMLInputElement interface: createInput("file") must inherit property "height" with the proper type] 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/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini b/tests/wpt/metadata/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini index 910c88d3e81..69bd952d756 100644 --- a/tests/wpt/metadata/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini +++ b/tests/wpt/metadata/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js.ini @@ -1,5 +1,5 @@ [ignore-opens-during-unload.window.html] - expected: CRASH + expected: TIMEOUT [ignore-opens-during-unload] expected: FAIL diff --git a/tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini b/tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini index 494f0d4a752..aa36a14c6a6 100644 --- a/tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini +++ b/tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini @@ -20,3 +20,6 @@ [domainLookupStart should be 0 in cross-origin request.] expected: FAIL + [responseEnd should be greater than 0 in cross-origin request.] + 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 881cbd9301b..134db732f78 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 @@ -128,3 +128,9 @@ [X SNR (21.440582478520547 dB) is not greater than or equal to 65.737. Got 21.440582478520547.] 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.2820157235101721e+11 at index of 39267.\n\t[39267\]\t-9.2820157235200000e+11\t-9.8276454210281372e-1\t9.2820157235101721e+11\t9.4448011968864026e+11\t3.8985999999999999e-3\n\tMax RelError of 9.4448011968864026e+11 at index of 39267.\n\t[39267\]\t-9.2820157235200000e+11\t-9.8276454210281372e-1\t9.2820157235101721e+11\t9.4448011968864026e+11\t3.8985999999999999e-3\n] + expected: FAIL + + [X SNR (-195.93871551689728 dB) is not greater than or equal to 65.737. Got -195.93871551689728.] + expected: FAIL + diff --git a/tests/wpt/metadata/webxr/exclusive_requestFrame_nolayer.https.html.ini b/tests/wpt/metadata/webxr/exclusive_requestFrame_nolayer.https.html.ini new file mode 100644 index 00000000000..19dcddf4665 --- /dev/null +++ b/tests/wpt/metadata/webxr/exclusive_requestFrame_nolayer.https.html.ini @@ -0,0 +1,7 @@ +[exclusive_requestFrame_nolayer.https.html] + [XRSession requestAnimationFrame must fail if the session has no baseLayer for immersive] + expected: FAIL + + [XRSession requestAnimationFrame must fail if the session has no baseLayer for non immersive] + expected: FAIL + diff --git a/tests/wpt/metadata/webxr/render_state_vertical_fov_immersive.https.html.ini b/tests/wpt/metadata/webxr/render_state_vertical_fov_immersive.https.html.ini new file mode 100644 index 00000000000..2ae6711642c --- /dev/null +++ b/tests/wpt/metadata/webxr/render_state_vertical_fov_immersive.https.html.ini @@ -0,0 +1,4 @@ +[render_state_vertical_fov_immersive.https.html] + [inlineVerticalFieldOfView is set appropriately on immersively sessions] + expected: FAIL + diff --git a/tests/wpt/metadata/webxr/render_state_vertical_fov_inline.https.html.ini b/tests/wpt/metadata/webxr/render_state_vertical_fov_inline.https.html.ini new file mode 100644 index 00000000000..d9762ab91bc --- /dev/null +++ b/tests/wpt/metadata/webxr/render_state_vertical_fov_inline.https.html.ini @@ -0,0 +1,4 @@ +[render_state_vertical_fov_inline.https.html] + [inlineVerticalFieldOfView is set appropriately on inline sessions] + 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 27f6c5ed7a2..6ff00c31bef 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: ERROR + expected: TIMEOUT ['XRBoundedReferenceSpace updates properly when the changes are applied] expected: TIMEOUT diff --git a/tests/wpt/metadata/webxr/xrSession_prevent_multiple_exclusive.https.html.ini b/tests/wpt/metadata/webxr/xrSession_prevent_multiple_exclusive.https.html.ini index 7987d965e4c..d97e34090f9 100644 --- a/tests/wpt/metadata/webxr/xrSession_prevent_multiple_exclusive.https.html.ini +++ b/tests/wpt/metadata/webxr/xrSession_prevent_multiple_exclusive.https.html.ini @@ -1,5 +1,4 @@ [xrSession_prevent_multiple_exclusive.https.html] - expected: TIMEOUT [Test prevention of multiple simultaneous immersive sessions] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/metadata/webxr/xrSession_requestAnimationFrame_timestamp.https.html.ini b/tests/wpt/metadata/webxr/xrSession_requestAnimationFrame_timestamp.https.html.ini new file mode 100644 index 00000000000..85fce01757f --- /dev/null +++ b/tests/wpt/metadata/webxr/xrSession_requestAnimationFrame_timestamp.https.html.ini @@ -0,0 +1,7 @@ +[xrSession_requestAnimationFrame_timestamp.https.html] + [XRFrame getViewerPose updates on the next frame for immersive] + expected: FAIL + + [XRFrame getViewerPose updates on the next frame for non-immersive] + expected: FAIL + diff --git a/tests/wpt/metadata/webxr/xrView_oneframeupdate.https.html.ini b/tests/wpt/metadata/webxr/xrView_oneframeupdate.https.html.ini new file mode 100644 index 00000000000..dfeec8ff525 --- /dev/null +++ b/tests/wpt/metadata/webxr/xrView_oneframeupdate.https.html.ini @@ -0,0 +1,5 @@ +[xrView_oneframeupdate.https.html] + expected: ERROR + [XRView projection matrices update near and far depths on the next frame] + expected: TIMEOUT + diff --git a/tests/wpt/metadata/webxr/xrWebGLLayer_constructor.https.html.ini b/tests/wpt/metadata/webxr/xrWebGLLayer_constructor.https.html.ini new file mode 100644 index 00000000000..08a51f5b1bc --- /dev/null +++ b/tests/wpt/metadata/webxr/xrWebGLLayer_constructor.https.html.ini @@ -0,0 +1,5 @@ +[xrWebGLLayer_constructor.https.html] + expected: ERROR + [Ensure that XRWebGLLayer's constructor throws appropriate errors] + expected: TIMEOUT + diff --git a/tests/wpt/metadata/webxr/xrWebGLLayer_framebuffer_draw.https.html.ini b/tests/wpt/metadata/webxr/xrWebGLLayer_framebuffer_draw.https.html.ini new file mode 100644 index 00000000000..bf7eed9a971 --- /dev/null +++ b/tests/wpt/metadata/webxr/xrWebGLLayer_framebuffer_draw.https.html.ini @@ -0,0 +1,4 @@ +[xrWebGLLayer_framebuffer_draw.https.html] + [Ensure a WebGL layer's framebuffer can only be drawn to inside a XR frame] + expected: FAIL + diff --git a/tests/wpt/metadata/webxr/xrWebGLLayer_framebuffer_scale.https.html.ini b/tests/wpt/metadata/webxr/xrWebGLLayer_framebuffer_scale.https.html.ini new file mode 100644 index 00000000000..0b738710eea --- /dev/null +++ b/tests/wpt/metadata/webxr/xrWebGLLayer_framebuffer_scale.https.html.ini @@ -0,0 +1,4 @@ +[xrWebGLLayer_framebuffer_scale.https.html] + [Ensure framebuffer scaling works as expected.] + expected: FAIL + diff --git a/tests/wpt/metadata/webxr/xrWebGLLayer_opaque_framebuffer.https.html.ini b/tests/wpt/metadata/webxr/xrWebGLLayer_opaque_framebuffer.https.html.ini new file mode 100644 index 00000000000..63c92e14304 --- /dev/null +++ b/tests/wpt/metadata/webxr/xrWebGLLayer_opaque_framebuffer.https.html.ini @@ -0,0 +1,7 @@ +[xrWebGLLayer_opaque_framebuffer.https.html] + [Ensure that the framebuffer given by the WebGL layer is opaque for immersive] + expected: FAIL + + [Ensure that the framebuffer given by the WebGL layer is opaque for non-immersive] + expected: FAIL + diff --git a/tests/wpt/mozilla/meta/css/transition_calc_implicit.html.ini b/tests/wpt/mozilla/meta/css/transition_calc_implicit.html.ini deleted file mode 100644 index dbea4f293ad..00000000000 --- a/tests/wpt/mozilla/meta/css/transition_calc_implicit.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transition_calc_implicit.html] - expected: TIMEOUT diff --git a/tests/wpt/web-platform-tests/.taskcluster.yml b/tests/wpt/web-platform-tests/.taskcluster.yml index a8e297242fe..1a162ed7402 100644 --- a/tests/wpt/web-platform-tests/.taskcluster.yml +++ b/tests/wpt/web-platform-tests/.taskcluster.yml @@ -222,6 +222,7 @@ tasks: script: >- export TOXENV=py27; export HYPOTHESIS_PROFILE=ci; + export PY_COLORS=0; ./tools/ci/run_tc.py \ tools_unittest \ tools/ci/ci_tools_unittest.sh @@ -234,6 +235,7 @@ tasks: script: >- export TOXENV=py36; export HYPOTHESIS_PROFILE=ci; + export PY_COLORS=0; sudo apt update -qqy; sudo apt install -qqy python3-pip; ./tools/ci/run_tc.py \ diff --git a/tests/wpt/web-platform-tests/IndexedDB/structured-clone.any.js b/tests/wpt/web-platform-tests/IndexedDB/structured-clone.any.js new file mode 100644 index 00000000000..8078aaf796b --- /dev/null +++ b/tests/wpt/web-platform-tests/IndexedDB/structured-clone.any.js @@ -0,0 +1,320 @@ +// META: script=support-promises.js +// META: title=Indexed DB and Structured Serializing/Deserializing +// META: timeout=long + +// Tests Indexed DB coverage of HTML's Safe "passing of structured data" +// https://html.spec.whatwg.org/multipage/structured-data.html + +function describe(value) { + let type, str; + if (typeof value === 'object' && value) { + type = value.__proto__.constructor.name; + // Handle Number(-0), etc. + str = Object.is(value.valueOf(), -0) ? '-0' : String(value); + } else { + type = typeof value; + // Handle primitive -0. + str = Object.is(value, -0) ? '-0' : String(value); + } + return `${type}: ${str}`; +} + +function cloneTest(value, verifyFunc) { + promise_test(async t => { + const db = await createDatabase(t, db => { + const store = db.createObjectStore('store'); + // This index is not used, but evaluating key path on each put() + // call will exercise (de)serialization. + store.createIndex('index', 'dummyKeyPath'); + }); + t.add_cleanup(() => { + if (db) { + db.close(); + indexedDB.deleteDatabase(db.name); + } + }); + const tx = db.transaction('store', 'readwrite'); + const store = tx.objectStore('store'); + await promiseForRequest(t, store.put(value, 'key')); + const result = await promiseForRequest(t, store.get('key')); + await verifyFunc(value, result); + await promiseForTransaction(t, tx); + }, describe(value)); +} + +// Specialization of cloneTest() for objects, with common asserts. +function cloneObjectTest(value, verifyFunc) { + cloneTest(value, async (orig, clone) => { + assert_not_equals(orig, clone); + assert_equals(typeof clone, 'object'); + assert_equals(orig.__proto__, clone.__proto__); + await verifyFunc(orig, clone); + }); +} + +function cloneFailureTest(value) { + promise_test(async t => { + const db = await createDatabase(t, db => { + db.createObjectStore('store'); + }); + t.add_cleanup(() => { + if (db) { + db.close(); + indexedDB.deleteDatabase(db.name); + } + }); + const tx = db.transaction('store', 'readwrite'); + const store = tx.objectStore('store'); + assert_throws('DataCloneError', () => store.put(value, 'key')); + }, 'Not serializable: ' + describe(value)); +} + +// +// ECMAScript types +// + +// Primitive values: Undefined, Null, Boolean, Number, BigInt, String +const booleans = [false, true]; +const numbers = [ + NaN, + -Infinity, + -Number.MAX_VALUE, + -0xffffffff, + -0x80000000, + -0x7fffffff, + -1, + -Number.MIN_VALUE, + -0, + 0, + 1, + Number.MIN_VALUE, + 0x7fffffff, + 0x80000000, + 0xffffffff, + Number.MAX_VALUE, + Infinity, +]; +const bigints = [ + -12345678901234567890n, + -1n, + 0n, + 1n, + 12345678901234567890n, +]; +const strings = [ + '', + 'this is a sample string', + 'null(\0)', +]; + +[undefined, null].concat(booleans, numbers, bigints, strings) + .forEach(value => cloneTest(value, (orig, clone) => { + assert_equals(orig, clone); + })); + +// "Primitive" Objects (Boolean, Number, BigInt, String) +[].concat(booleans, numbers, strings) + .forEach(value => cloneObjectTest(Object(value), (orig, clone) => { + assert_equals(orig.valueOf(), clone.valueOf()); + })); + +// Dates +[ + new Date(-1e13), + new Date(-1e12), + new Date(-1e9), + new Date(-1e6), + new Date(-1e3), + new Date(0), + new Date(1e3), + new Date(1e6), + new Date(1e9), + new Date(1e12), + new Date(1e13) +].forEach(value => cloneTest(value, (orig, clone) => { + assert_not_equals(orig, clone); + assert_equals(typeof clone, 'object'); + assert_equals(orig.__proto__, clone.__proto__); + assert_equals(orig.valueOf(), clone.valueOf()); + })); + +// Regular Expressions +[ + new RegExp(), + /abc/, + /abc/g, + /abc/i, + /abc/gi, + /abc/m, + /abc/mg, + /abc/mi, + /abc/mgi, + /abc/gimsuy, +].forEach(value => cloneObjectTest(value, (orig, clone) => { + assert_equals(orig.toString(), clone.toString()); +})); + +// ArrayBuffer +cloneObjectTest(new Uint8Array([0, 1, 254, 255]).buffer, (orig, clone) => { + assert_array_equals(new Uint8Array(orig), new Uint8Array(clone)); +}); + +// TODO SharedArrayBuffer + +// Array Buffer Views +[ + new Uint8Array([]), + new Uint8Array([0, 1, 254, 255]), + new Uint16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF]), + new Uint32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF]), + new Int8Array([0, 1, 254, 255]), + new Int16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF]), + new Int32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF]), + new Uint8ClampedArray([0, 1, 254, 255]), + new Float32Array([-Infinity, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, Infinity, NaN]), + new Float64Array([-Infinity, -Number.MAX_VALUE, -Number.MIN_VALUE, 0, + Number.MIN_VALUE, Number.MAX_VALUE, Infinity, NaN]) +].forEach(value => cloneObjectTest(value, (orig, clone) => { + assert_array_equals(orig, clone); +})); + +// Map +cloneObjectTest(new Map([[1,2],[3,4]]), (orig, clone) => { + assert_array_equals([...orig.keys()], [...clone.keys()]); + assert_array_equals([...orig.values()], [...clone.values()]); +}); + +// Set +cloneObjectTest(new Set([1,2,3,4]), (orig, clone) => { + assert_array_equals([...orig.values()], [...clone.values()]); +}); + +// Error +[ + new Error(), + new Error('abc', 'def'), + new EvalError(), + new EvalError('ghi', 'jkl'), + new RangeError(), + new RangeError('ghi', 'jkl'), + new ReferenceError(), + new ReferenceError('ghi', 'jkl'), + new SyntaxError(), + new SyntaxError('ghi', 'jkl'), + new TypeError(), + new TypeError('ghi', 'jkl'), + new URIError(), + new URIError('ghi', 'jkl'), +].forEach(value => cloneObjectTest(value, (orig, clone) => { + assert_equals(orig.name, clone.name); + assert_equals(orig.message, clone.message); +})); + +// Arrays +[ + [], + [1,2,3], + Object.assign( + ['foo', 'bar'], + {10: true, 11: false, 20: 123, 21: 456, 30: null}), + Object.assign( + ['foo', 'bar'], + {a: true, b: false, foo: 123, bar: 456, '': null}), +].forEach(value => cloneObjectTest(value, (orig, clone) => { + assert_array_equals(orig, clone); + assert_array_equals(Object.keys(orig), Object.keys(clone)); + Object.keys(orig).forEach(key => { + assert_equals(orig[key], clone[key], `Property ${key}`); + }); +})); + +// Objects +cloneObjectTest({foo: true, bar: false}, (orig, clone) => { + assert_array_equals(Object.keys(orig), Object.keys(clone)); + Object.keys(orig).forEach(key => { + assert_equals(orig[key], clone[key], `Property ${key}`); + }); +}); + +// +// [Serializable] Platform objects +// + +// TODO: Test these additional interfaces: +// * DOMQuad +// * DOMException +// * DetectedText, DetectedFace, DetectedBarcode +// * RTCCertificate + +// Geometry types +[ + new DOMMatrix(), + new DOMMatrixReadOnly(), + new DOMPoint(), + new DOMPointReadOnly(), + new DOMRect, + new DOMRectReadOnly(), +].forEach(value => cloneObjectTest(value, (orig, clone) => { + Object.keys(orig.__proto__).forEach(key => { + assert_equals(orig[key], clone[key], `Property ${key}`); + }); +})); + +// ImageData +const image_data = new ImageData(8, 8); +for (let i = 0; i < 256; ++i) { + image_data.data[i] = i; +} +cloneObjectTest(image_data, (orig, clone) => { + assert_equals(orig.width, clone.width); + assert_equals(orig.height, clone.height); + assert_array_equals(orig.data, clone.data); +}); + +// Blob +cloneObjectTest( + new Blob(['This is a test.'], {type: 'a/b'}), + async (orig, clone) => { + assert_equals(orig.size, clone.size); + assert_equals(orig.type, clone.type); + assert_equals(await orig.text(), await clone.text()); + }); + +// File +cloneObjectTest( + new File(['This is a test.'], 'foo.txt', {type: 'c/d'}), + async (orig, clone) => { + assert_equals(orig.size, clone.size); + assert_equals(orig.type, clone.type); + assert_equals(orig.name, clone.name); + assert_equals(orig.lastModified, clone.lastModified); + assert_equals(String(orig.lastModifiedDate), + String(clone.lastModifiedDate)); + assert_equals(await orig.text(), await clone.text()); + }); + + +// FileList - exposed in Workers, but not constructable. +if ('document' in self) { + // TODO: Test with populated list. + cloneObjectTest( + Object.assign(document.createElement('input'), + {type: 'file', multiple: true}).files, + async (orig, clone) => { + assert_equals(orig.length, clone.length); + }); +} + +// +// Non-serializable types +// +[ + // ECMAScript types + function() {}, + Symbol('desc'), + + // Non-[Serializable] platform objects + self, + new Event(''), + new MessageChannel() +].forEach(cloneFailureTest); diff --git a/tests/wpt/web-platform-tests/common/security-features/tools/format_spec_src_json.py b/tests/wpt/web-platform-tests/common/security-features/tools/format_spec_src_json.py new file mode 100644 index 00000000000..1276c78f9fb --- /dev/null +++ b/tests/wpt/web-platform-tests/common/security-features/tools/format_spec_src_json.py @@ -0,0 +1,20 @@ +import collections +import json +import os + + +def main(): + '''Formats spec.src.json.''' + script_directory = os.path.dirname(os.path.abspath(__file__)) + for dir in ['mixed-content', 'referrer-policy']: + filename = os.path.join(script_directory, '..', '..', '..', dir, + 'spec.src.json') + spec = json.load( + open(filename, 'r'), object_pairs_hook=collections.OrderedDict) + with open(filename, 'w') as f: + f.write(json.dumps(spec, indent=2, separators=(',', ': '))) + f.write('\n') + + +if __name__ == '__main__': + main() diff --git a/tests/wpt/web-platform-tests/common/security-features/tools/generate.py b/tests/wpt/web-platform-tests/common/security-features/tools/generate.py index 50c3a2c250c..fc10e635dbd 100644 --- a/tests/wpt/web-platform-tests/common/security-features/tools/generate.py +++ b/tests/wpt/web-platform-tests/common/security-features/tools/generate.py @@ -28,7 +28,10 @@ def expand_pattern(expansion_pattern, test_expansion_schema): return expansion -def permute_expansion(expansion, artifact_order, selection = {}, artifact_index = 0): +def permute_expansion(expansion, + artifact_order, + selection={}, + artifact_index=0): assert isinstance(artifact_order, list), "artifact_order should be a list" if artifact_index >= len(artifact_order): @@ -39,20 +42,23 @@ def permute_expansion(expansion, artifact_order, selection = {}, artifact_index for artifact_value in expansion[artifact_key]: selection[artifact_key] = artifact_value - for next_selection in permute_expansion(expansion, - artifact_order, - selection, - artifact_index + 1): + for next_selection in permute_expansion(expansion, artifact_order, + selection, artifact_index + 1): yield next_selection -def generate_selection(config, selection, spec, test_html_template_basename): - # TODO: Refactor out this referrer-policy-specific part. - if 'referrer_policy' in spec: - # Oddball: it can be None, so in JS it's null. - selection['referrer_policy'] = spec['referrer_policy'] +# Dumps the test config `selection` into a serialized JSON string. +# We omit `name` parameter because it is not used by tests. +def dump_test_parameters(selection): + selection = dict(selection) + del selection['name'] + + return json.dumps( + selection, indent=2, separators=(',', ': '), sort_keys=True) - test_parameters = json.dumps(selection, indent=2, separators=(',', ':')) + +def generate_selection(config, selection, spec, test_html_template_basename): + test_parameters = dump_test_parameters(selection) # Adjust the template for the test invoking JS. Indent it to look nice. indent = "\n" + " " * 8 test_parameters = test_parameters.replace("\n", indent) @@ -66,14 +72,16 @@ def generate_selection(config, selection, spec, test_html_template_basename): ''' % (config.test_case_name, test_parameters) selection['spec_name'] = spec['name'] - selection['test_page_title'] = config.test_page_title_template % spec['title'] + selection[ + 'test_page_title'] = config.test_page_title_template % spec['title'] selection['spec_description'] = spec['description'] selection['spec_specification_url'] = spec['specification_url'] selection['helper_js'] = config.helper_js selection['sanity_checker_js'] = config.sanity_checker_js selection['spec_json_js'] = config.spec_json_js - test_filename = os.path.join(config.spec_directory, config.test_file_path_pattern % selection) + test_filename = os.path.join(config.spec_directory, + config.test_file_path_pattern % selection) test_headers_filename = test_filename + ".headers" test_directory = os.path.dirname(test_filename) @@ -83,14 +91,15 @@ def generate_selection(config, selection, spec, test_html_template_basename): html_template_filename = os.path.join(util.template_directory, test_html_template_basename) generated_disclaimer = disclaimer_template \ - % {'generating_script_filename': os.path.relpath(__file__, + % {'generating_script_filename': os.path.relpath(sys.argv[0], util.test_root_directory), 'html_template_filename': os.path.relpath(html_template_filename, util.test_root_directory)} # Adjust the template for the test invoking JS. Indent it to look nice. selection['generated_disclaimer'] = generated_disclaimer.rstrip() - selection['test_description'] = config.test_description_template % selection + selection[ + 'test_description'] = config.test_description_template % selection selection['test_description'] = \ selection['test_description'].rstrip().replace("\n", "\n" + " " * 33) @@ -123,9 +132,11 @@ def generate_test_source_files(config, spec_json, target): specification = spec_json['specification'] spec_json_js_template = util.get_template('spec_json.js.template') - generated_spec_json_filename = os.path.join(config.spec_directory, "spec_json.js") - util.write_file(generated_spec_json_filename, - spec_json_js_template % {'spec_json': json.dumps(spec_json)}) + generated_spec_json_filename = os.path.join(config.spec_directory, + "spec_json.js") + util.write_file( + generated_spec_json_filename, + spec_json_js_template % {'spec_json': json.dumps(spec_json)}) # Choose a debug/release template depending on the target. html_template = "test.%s.html.template" % target @@ -149,13 +160,18 @@ def generate_test_source_files(config, spec_json, target): output_dict = {} for expansion_pattern in spec['test_expansion']: - expansion = expand_pattern(expansion_pattern, test_expansion_schema) + expansion = expand_pattern(expansion_pattern, + test_expansion_schema) for selection in permute_expansion(expansion, artifact_order): + selection['delivery_key'] = spec_json['delivery_key'] selection_path = config.selection_pattern % selection if not selection_path in exclusion_dict: if selection_path in output_dict: if expansion_pattern['expansion'] != 'override': - print("Error: %s's expansion is default but overrides %s" % (selection['name'], output_dict[selection_path]['name'])) + print( + "Error: %s's expansion is default but overrides %s" + % (selection['name'], + output_dict[selection_path]['name'])) sys.exit(1) output_dict[selection_path] = copy.deepcopy(selection) else: @@ -163,24 +179,30 @@ def generate_test_source_files(config, spec_json, target): for selection_path in output_dict: selection = output_dict[selection_path] - generate_selection(config, - selection, - spec, - html_template) + generate_selection(config, selection, spec, html_template) def main(config): - parser = argparse.ArgumentParser(description='Test suite generator utility') - parser.add_argument('-t', '--target', type = str, - choices = ("release", "debug"), default = "release", - help = 'Sets the appropriate template for generating tests') - parser.add_argument('-s', '--spec', type = str, default = None, - help = 'Specify a file used for describing and generating the tests') + parser = argparse.ArgumentParser( + description='Test suite generator utility') + parser.add_argument( + '-t', + '--target', + type=str, + choices=("release", "debug"), + default="release", + help='Sets the appropriate template for generating tests') + parser.add_argument( + '-s', + '--spec', + type=str, + default=None, + help='Specify a file used for describing and generating the tests') # TODO(kristijanburnik): Add option for the spec_json file. args = parser.parse_args() if args.spec: - config.spec_directory = args.spec + config.spec_directory = args.spec spec_filename = os.path.join(config.spec_directory, "spec.src.json") spec_json = util.load_spec_json(spec_filename) diff --git a/tests/wpt/web-platform-tests/mixed-content/generic/tools/spec_validator.py b/tests/wpt/web-platform-tests/common/security-features/tools/spec_validator.py index 686579ece57..2c966478869 100755 --- a/tests/wpt/web-platform-tests/mixed-content/generic/tools/spec_validator.py +++ b/tests/wpt/web-platform-tests/common/security-features/tools/spec_validator.py @@ -3,7 +3,7 @@ from __future__ import print_function import json, sys -from common_paths import * + def assert_non_empty_string(obj, field): assert field in obj, 'Missing field "%s"' % field @@ -31,12 +31,13 @@ def assert_contains(obj, field): def assert_value_from(obj, field, items): - assert obj[field] in items, \ - 'Field "%s" must be from: %s' % (field, str(items)) + assert obj[field] in items, \ + 'Field "%s" must be from: %s' % (field, str(items)) def assert_atom_or_list_items_from(obj, field, items): - if isinstance(obj[field], basestring) or isinstance(obj[field], int): + if isinstance(obj[field], basestring) or isinstance( + obj[field], int) or obj[field] is None: assert_value_from(obj, field, items) return @@ -71,13 +72,15 @@ def assert_valid_artifact(exp_pattern, artifact_key, schema): assert_valid_artifact(exp_pattern[artifact_key], sub_artifact_key, sub_schema) + def validate(spec_json, details): """ Validates the json specification for generating tests. """ details['object'] = spec_json - assert_contains_only_fields(spec_json, ["specification", - "test_expansion_schema", - "excluded_tests"]) + assert_contains_only_fields(spec_json, [ + "specification", "delivery_key", "test_expansion_schema", + "excluded_tests" + ]) assert_non_empty_list(spec_json, "specification") assert_non_empty_dict(spec_json, "test_expansion_schema") assert_non_empty_list(spec_json, "excluded_tests") @@ -93,11 +96,10 @@ def validate(spec_json, details): details['object'] = spec # Validate required fields for a single spec. - assert_contains_only_fields(spec, ['name', - 'title', - 'description', - 'specification_url', - 'test_expansion']) + assert_contains_only_fields(spec, [ + 'name', 'title', 'description', 'specification_url', + 'test_expansion' + ]) assert_non_empty_string(spec, 'name') assert_non_empty_string(spec, 'title') assert_non_empty_string(spec, 'description') @@ -123,14 +125,10 @@ def validate(spec_json, details): # Validate the test_expansion schema members. details['object'] = test_expansion_schema - assert_contains_only_fields(test_expansion_schema, ['expansion', - 'source_scheme', - 'opt_in_method', - 'context_nesting', - 'redirection', - 'subresource', - 'origin', - 'expectation']) + assert_contains_only_fields(test_expansion_schema, [ + 'expansion', 'source_scheme', 'delivery_type', 'delivery_value', + 'redirection', 'subresource', 'origin', 'expectation' + ]) # Validate excluded tests. details['object'] = excluded_tests for excluded_test_expansion in excluded_tests: @@ -139,10 +137,8 @@ def validate(spec_json, details): details['object'] = excluded_test_expansion for artifact in test_expansion_schema: details['test_expansion_field'] = artifact - assert_valid_artifact( - excluded_test_expansion, - artifact, - test_expansion_schema[artifact]) + assert_valid_artifact(excluded_test_expansion, artifact, + test_expansion_schema[artifact]) del details['test_expansion_field'] del details['object'] @@ -159,7 +155,7 @@ def assert_valid_spec_json(spec_json): def main(): - spec_json = load_spec_json(); + spec_json = load_spec_json() assert_valid_spec_json(spec_json) print("Spec JSON is valid.") diff --git a/tests/wpt/web-platform-tests/common/security-features/tools/util.py b/tests/wpt/web-platform-tests/common/security-features/tools/util.py index 77b89769ca2..1f6c86e6efc 100644 --- a/tests/wpt/web-platform-tests/common/security-features/tools/util.py +++ b/tests/wpt/web-platform-tests/common/security-features/tools/util.py @@ -3,10 +3,10 @@ from __future__ import print_function import os, sys, json, re script_directory = os.path.dirname(os.path.abspath(__file__)) -template_directory = os.path.abspath(os.path.join(script_directory, - 'template')) -test_root_directory = os.path.abspath(os.path.join(script_directory, - '..', '..', '..')) +template_directory = os.path.abspath( + os.path.join(script_directory, 'template')) +test_root_directory = os.path.abspath( + os.path.join(script_directory, '..', '..', '..')) def get_template(basename): @@ -20,22 +20,22 @@ def write_file(filename, contents): def read_nth_line(fp, line_number): - fp.seek(0) - for i, line in enumerate(fp): - if (i + 1) == line_number: - return line + fp.seek(0) + for i, line in enumerate(fp): + if (i + 1) == line_number: + return line def load_spec_json(path_to_spec): re_error_location = re.compile('line ([0-9]+) column ([0-9]+)') with open(path_to_spec, "r") as f: try: - return json.load(f) + return json.load(f) except ValueError as ex: - print(ex.message) - match = re_error_location.search(ex.message) - if match: - line_number, column = int(match.group(1)), int(match.group(2)) - print(read_nth_line(f, line_number).rstrip()) - print(" " * (column - 1) + "^") - sys.exit(1) + print(ex.message) + match = re_error_location.search(ex.message) + if match: + line_number, column = int(match.group(1)), int(match.group(2)) + print(read_nth_line(f, line_number).rstrip()) + print(" " * (column - 1) + "^") + sys.exit(1) diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_delete_insecure.tentative.https.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_delete_insecure.tentative.https.window.js new file mode 100644 index 00000000000..bb1907faf58 --- /dev/null +++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_delete_insecure.tentative.https.window.js @@ -0,0 +1,19 @@ +'use strict'; + +promise_test(async t => { + await cookieStore.set('cookie-name', 'cookie-value', { secure: false }); + t.add_cleanup(async () => { await cookieStore.delete('cookie-name'); }); + + await cookieStore.delete('cookie-name'); + const cookie = await cookieStore.get('cookie-name'); + assert_equals(cookie, null); +}, 'cookieStore.delete(name) can delete an insecure cookie'); + +promise_test(async t => { + await cookieStore.set('cookie-name', 'cookie-value', { secure: false }); + t.add_cleanup(async () => { await cookieStore.delete('cookie-name'); }); + + await cookieStore.delete({ name: 'cookie-name' }); + const cookie = await cookieStore.get('cookie-name'); + assert_equals(cookie, null); +}, 'cookieStore.delete(options) can delete an insecure cookie');
\ No newline at end of file diff --git a/tests/wpt/web-platform-tests/credential-management/idlharness.https.window.js b/tests/wpt/web-platform-tests/credential-management/idlharness.https.window.js index 15508b872ed..789643e2369 100644 --- a/tests/wpt/web-platform-tests/credential-management/idlharness.https.window.js +++ b/tests/wpt/web-platform-tests/credential-management/idlharness.https.window.js @@ -5,31 +5,32 @@ 'use strict'; -promise_test(async () => { - const idl = await fetch('/interfaces/credential-management.idl').then(r => r.text()); - const html = await fetch('/interfaces/html.idl').then(r => r.text()); +idl_test( + ['credential-management'], + ['html', 'dom'], + idl_array => { + idl_array.add_objects({ + CredentialsContainer: ['navigator.credentials'], + PasswordCredential: ['passwordCredential'], + FederatedCredential: ['federatedCredential'], + }); - var idl_array = new IdlArray(); - idl_array.add_idls(idl); - idl_array.add_dependency_idls(html); - idl_array.add_objects({ - CredentialsContainer: ['navigator.credentials'], - PasswordCredential: [ - `new PasswordCredential({ + try { + self.passwordCredential = new PasswordCredential({ id: "id", password: "pencil", iconURL: "https://example.com/", name: "name" - })` - ], - FederatedCredential: [ - `new FederatedCredential({ + }); + } catch (e) {} + + try { + self.federatedCredential = new FederatedCredential({ id: "id", provider: "https://example.com", iconURL: "https://example.com/", name: "name" - })` - ] - }); - idl_array.test(); -}) + }); + } catch (e) {} + } +) diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-004.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-004.html index c4b21959626..ede419096ff 100644 --- a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-004.html +++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-004.html @@ -8,3 +8,4 @@ display: none } </style> +<body></body> diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-005.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-005.html index 702b2b29ae3..05c5421977e 100644 --- a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-005.html +++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-005.html @@ -6,3 +6,4 @@ html { display: none; } body { background: red; } </style> +<body></body> diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-006.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-006.html index b575891382c..4c58cb9dc21 100644 --- a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-006.html +++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-006.html @@ -14,3 +14,4 @@ })); }; </script> +<body></body> diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-007.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-007.html new file mode 100644 index 00000000000..6deda8dcdb5 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-007.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>CSS Backgrounds and Borders Test: don't propagate body background when display:contents</title> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#special-backgrounds"> +<link rel="match" href="../reference/blank.html"> +<style> + body { + background: red; + display: contents + } +</style> +<body></body> diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/parsing/border-image-source-computed.html b/tests/wpt/web-platform-tests/css/css-backgrounds/parsing/border-image-source-computed.sub.html index 96e6bdf2f09..20343882096 100644 --- a/tests/wpt/web-platform-tests/css/css-backgrounds/parsing/border-image-source-computed.html +++ b/tests/wpt/web-platform-tests/css/css-backgrounds/parsing/border-image-source-computed.sub.html @@ -13,7 +13,7 @@ <div id="target"></div> <script> test_computed_value("border-image-source", "none"); -test_computed_value("border-image-source", 'url("http://www.example.com/")'); +test_computed_value("border-image-source", 'url("http://{{host}}/")'); test(() => { const target = document.getElementById('target'); diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-insert-child-ref.html b/tests/wpt/web-platform-tests/css/css-lists/li-insert-child-ref.html new file mode 100644 index 00000000000..bbf2e66a0df --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-lists/li-insert-child-ref.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>Reference: Insert text node as first child in LI</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.org"> + <style> + ul.inside { list-style-position: inside; } + .before::before { content: "before"; } + .after::after { content: "after"; } + </style> +</head> +<body> + +<ul class="inside"> + <li>AB</li> +</ul> + +<ul class="inside"> + <li class="before">AB</li> +</ul> + +<ul class="inside"> + <li class="after">AB</li> +</ul> + +<ul class="inside"> + <li class="before after">AB</li> +</ul> + +<ul> + <li>AB</li> +</ul> + +<ul> + <li class="before">AB</li> +</ul> + +<ul> + <li class="after">AB</li> +</ul> + +<ul> + <li class="before after">AB</li> +</ul> + +</body> +</html> diff --git a/tests/wpt/web-platform-tests/css/css-lists/li-insert-child.html b/tests/wpt/web-platform-tests/css/css-lists/li-insert-child.html new file mode 100644 index 00000000000..d82bf1374ae --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-lists/li-insert-child.html @@ -0,0 +1,60 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html class="reftest-wait"><head> + <meta charset="utf-8"> + <title>Test: Insert text node as first child in LI</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.org"> + <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1567773"> + <link rel="match" href="li-insert-child-ref.html"> + <style> + ul.inside { list-style-position: inside; } + .before::before { content: "before"; } + .after::after { content: "after"; } + </style> +</head> +<body> + +<ul class="inside"> + <li>B</li> +</ul> + +<ul class="inside"> + <li class="before">B</li> +</ul> + +<ul class="inside"> + <li class="after">B</li> +</ul> + +<ul class="inside"> + <li class="before after">B</li> +</ul> + +<ul> + <li>B</li> +</ul> + +<ul> + <li class="before">B</li> +</ul> + +<ul> + <li class="after">B</li> +</ul> + +<ul> + <li class="before after">B</li> +</ul> + +<script> +document.body.offsetHeight; +let items = Array.prototype.slice.call(document.querySelectorAll('li')); +items.map(li => li.insertBefore(document.createTextNode('A'), li.firstChild)); +document.documentElement.className = ''; +</script> + +</body> +</html> diff --git a/tests/wpt/web-platform-tests/css/css-lists/parsing/list-style-computed.html b/tests/wpt/web-platform-tests/css/css-lists/parsing/list-style-computed.sub.html index 67bdc46f8c1..611fae5bf93 100644 --- a/tests/wpt/web-platform-tests/css/css-lists/parsing/list-style-computed.html +++ b/tests/wpt/web-platform-tests/css/css-lists/parsing/list-style-computed.sub.html @@ -15,10 +15,10 @@ test_computed_value('list-style', 'none', 'outside none none'); test_computed_value('list-style', 'inside', 'inside none disc'); -test_computed_value('list-style', 'url("https://example.com/")', 'outside url("https://example.com/") disc'); +test_computed_value('list-style', 'url("https://{{host}}/")', 'outside url("https://{{host}}/") disc'); test_computed_value('list-style', 'square', 'outside none square'); -test_computed_value('list-style', 'inside url("https://example.com/") square'); +test_computed_value('list-style', 'inside url("https://{{host}}/") square'); </script> </body> </html> diff --git a/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-001.tentative.html b/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-001.tentative.html new file mode 100644 index 00000000000..0998fe68e00 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-001.tentative.html @@ -0,0 +1,12 @@ +<!doctype html> +<title>CSS Overflow Test: Propagation of body overflow to viewport</title> +<link rel="help" href="https://drafts.csswg.org/css-overflow/#overflow-propagation"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/4148"> +<link rel="match" href="reference/overflow-body-propagation-ref.html"> +<style> + body { + overflow: scroll; + margin-top: 100px; + } +</style> +<body>The viewport should have scrollbars, not the body.</body> diff --git a/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-002.tentative.html b/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-002.tentative.html new file mode 100644 index 00000000000..5991dd52e8b --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-002.tentative.html @@ -0,0 +1,6 @@ +<!doctype html> +<title>CSS Overflow Test: Do not propagate overflow of display:none body to viewport</title> +<link rel="help" href="https://drafts.csswg.org/css-overflow-3/#overflow-propagation"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/4148"> +<link rel="match" href="/css/reference/blank.html"> +<body style="display:none; overflow:scroll"></body> diff --git a/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-003.tentative.html b/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-003.tentative.html new file mode 100644 index 00000000000..a329a8dfe3e --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-003.tentative.html @@ -0,0 +1,6 @@ +<!doctype html> +<title>CSS Overflow Test: Do not propagate overflow of display:contents body to viewport</title> +<link rel="help" href="https://drafts.csswg.org/css-overflow-3/#overflow-propagation"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/4148"> +<link rel="match" href="/css/reference/blank.html"> +<body style="display:contents; overflow:scroll"></body> diff --git a/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-004.tentative.html b/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-004.tentative.html new file mode 100644 index 00000000000..2ed8d2687a3 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-overflow/overflow-body-propagation-004.tentative.html @@ -0,0 +1,14 @@ +<!doctype html> +<link rel="help" href="https://drafts.csswg.org/css-overflow/#overflow-propagation"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/4148"> +<link rel="match" href="reference/overflow-body-no-propagation-ref.html"> +<style> + html { + overflow: hidden; + } + body { + overflow: scroll; + margin-top: 100px; + } +</style> +<body>The body should have scrollbars, not the viewport.</body> diff --git a/tests/wpt/web-platform-tests/css/css-overflow/reference/overflow-body-no-propagation-ref.html b/tests/wpt/web-platform-tests/css/css-overflow/reference/overflow-body-no-propagation-ref.html new file mode 100644 index 00000000000..9795d1f5861 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-overflow/reference/overflow-body-no-propagation-ref.html @@ -0,0 +1,5 @@ +<!doctype html> +<html style="overflow:auto"> +<title>CSS Overflow Test Reference</title> +<body style="margin-top:100px;overflow:scroll">The body should have scrollbars, not the viewport.</body> +</html> diff --git a/tests/wpt/web-platform-tests/css/css-overflow/reference/overflow-body-propagation-ref.html b/tests/wpt/web-platform-tests/css/css-overflow/reference/overflow-body-propagation-ref.html new file mode 100644 index 00000000000..340bda9de92 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-overflow/reference/overflow-body-propagation-ref.html @@ -0,0 +1,5 @@ +<!doctype html> +<html style="overflow:scroll"> +<title>CSS Overflow Test Reference</title> +<body style="margin-top:100px">The viewport should have scrollbars, not the body.</body> +</html> diff --git a/tests/wpt/web-platform-tests/css/css-overflow/webkit-line-clamp-033.html b/tests/wpt/web-platform-tests/css/css-overflow/webkit-line-clamp-033.html index a25be8b25db..261cf5b6b24 100644 --- a/tests/wpt/web-platform-tests/css/css-overflow/webkit-line-clamp-033.html +++ b/tests/wpt/web-platform-tests/css/css-overflow/webkit-line-clamp-033.html @@ -3,7 +3,7 @@ <title>CSS Overflow: -webkit-line-clamp with an empty line</title> <link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> <link rel="help" href="https://drafts.csswg.org/css-overflow-3/#webkit-line-clamp"> -<link rel="match" href="about:blank"> +<link rel="match" href="/css/reference/blank.html"> <style> .clamp { display: -webkit-box; diff --git a/tests/wpt/web-platform-tests/css/css-properties-values-api/registered-property-cssom.html b/tests/wpt/web-platform-tests/css/css-properties-values-api/registered-property-cssom.html index 59443b3323a..d408fa98f9f 100644 --- a/tests/wpt/web-platform-tests/css/css-properties-values-api/registered-property-cssom.html +++ b/tests/wpt/web-platform-tests/css/css-properties-values-api/registered-property-cssom.html @@ -52,9 +52,9 @@ test(function() { test(function() { inlineStyle.setProperty('--length', 'hi'); inlineStyle.setProperty('--color', '20'); - assert_equals(inlineStyle.getPropertyValue('--length'), '5'); - assert_equals(inlineStyle.getPropertyValue('--color'), 'hello'); -}, "Values not matching the registered type can't be set"); + assert_equals(inlineStyle.getPropertyValue('--length'), 'hi'); + assert_equals(inlineStyle.getPropertyValue('--color'), '20'); +}, "Values not matching the registered type can still be set"); test(function() { inlineStyle.removeProperty('--length'); @@ -66,8 +66,9 @@ test(function() { }, "Values can be removed from inline styles"); test(function() { - sheetStyle.setProperty('--length', 'banana'); // Invalid, no change - assert_equals(computedStyle.getPropertyValue('--length'), '10px'); + // 'banana' is not a valid <length>, but still accepted. + sheetStyle.setProperty('--length', 'banana'); + assert_equals(computedStyle.getPropertyValue('--length'), '0px'); sheetStyle.setProperty('--length', '20px'); assert_equals(computedStyle.getPropertyValue('--length'), '20px'); sheetStyle.setProperty('--length', 'initial'); diff --git a/tests/wpt/web-platform-tests/css/css-properties-values-api/typedom.html b/tests/wpt/web-platform-tests/css/css-properties-values-api/typedom.html index 2fc6447f22b..b8e6f4aaf84 100644 --- a/tests/wpt/web-platform-tests/css/css-properties-values-api/typedom.html +++ b/tests/wpt/web-platform-tests/css/css-properties-values-api/typedom.html @@ -3,6 +3,7 @@ <meta name="assert" content="Verifies that registered custom properties interact correctly with CSS Typed OM" /> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="./resources/utils.js"></script> <style id=style> div {} </style> @@ -10,28 +11,6 @@ <script> -// Properties are generated on demand, as `--prop-${g_counter}`. -let g_counter = 1; - -// Generate a new property name. -function gen_name() { - let name = `--prop-${g_counter}`; - g_counter++; - return name; -} - -// Generate a property and return its name. -function gen_prop(syntax, initialValue) { - let name = gen_name(); - CSS.registerProperty({ - name: name, - syntax: syntax, - initialValue: initialValue, - inherits: false - }); - return name; -} - // Cleans style rules used for testing between every test. add_result_callback(function(){ target.attributeStyleMap.clear(); @@ -39,54 +18,123 @@ add_result_callback(function(){ style.sheet.rules[0].styleMap.clear(); }); +// In the following utility functions, the 'map' parameter (if present) +// can be any StylePropertyMap. (Not StylePropertyMapReadOnly). + +// Verifies that get()/getAll() reifies the specified property to a +// CSSUnparsedValue, with a string serialization equal to 'value'. +function verify_map_get_unparsed(map, name, value) { + map.set(name, value); + + let specifiedValue = map.get(name); + assert_true(specifiedValue instanceof CSSUnparsedValue); + assert_equals(specifiedValue.toString(), value); + + let allSpecifiedValues = map.getAll(name); + assert_equals(allSpecifiedValues.length, 1); + assert_true(allSpecifiedValues[0] instanceof CSSUnparsedValue); + assert_equals(allSpecifiedValues[0].toString(), value); +} + +// Verifies that the specified value is accepted by set(). +function verify_map_set(map, name, value) { + map.set(name, value); + assert_equals(map.get(name).toString(), value.toString()); +} + +// Verifies that the specified value is NOT accepted by set(). +function verify_map_not_set(map, name, value) { + assert_throws(new TypeError(), () => { + map.set(name, value); + }); +} + +// Verifies that the specified value is NOT accepted by append(). +function verify_map_no_append(map, name, value) { + assert_throws(new TypeError(), () => { + map.append(name, value); + }); +} + +// Verifies that the property 'name' shows up on iteration, that it's reified +// as a CSSUnparsedValue, and that the string representation is equal to +// 'value'. +function verify_map_iteration_unparsed(map, name, value) { + map.set(name, value); + let result = Array.from(map).filter(e => e[0] == name)[0]; + assert_equals(result.length, 2); + let iter_value = result[1]; + assert_equals(iter_value.length, 1); + assert_true(iter_value[0] instanceof CSSUnparsedValue); + assert_equals(iter_value[0].toString(), value); +} + +// Verifies that CSSStyleValue.parse/parseAll results in a CSSStyleValue with +// the 'expected' type. +function verify_parsed_type(prop, value, expected) { + let parse_value = CSSStyleValue.parse(prop, value); + let parse_all_value = CSSStyleValue.parseAll(prop, value); + + assert_true(parse_value instanceof expected); + assert_true(parse_all_value.every(x => x instanceof expected)) +} + // On the target element, verify that computed value of 'name' is an instance // of 'expected' and not an instance of CSSUnparsedValue. // -// If 'value' is non-null, that value is first set on the attributeStyleMap -// of the target. -function assert_computed_type(name, value, expected) { +// If 'value' is non-null, that value is first set using the style attribute +// of the target element. +function verify_computed_type(name, value, expected) { if (expected == CSSUnparsedValue) { throw 'CSSUnparsedValue may not be used as expected type'; } - if (value != null) { - target.style = `${name}: ${value}`; - } - - let computedValue = target.computedStyleMap().get(name); + try { + if (value != null) { + target.style = `${name}: ${value}`; + } - assert_false(computedValue instanceof CSSUnparsedValue); - assert_true(computedValue instanceof expected); + let computedValue = target.computedStyleMap().get(name); - if (value != null) { - target.style = ''; + assert_false(computedValue instanceof CSSUnparsedValue); + assert_true(computedValue instanceof expected); + } finally { + if (value != null) { + target.style = ''; + } } } -function assert_attribute_get_type(styleDecl, propertyMap, syntax, value, expected) { - let name = gen_name(); - styleDecl.setProperty(name, value); - - assert_true(propertyMap.get(name) instanceof CSSUnparsedValue); - - CSS.registerProperty({ - name: name, - syntax: syntax, - initialValue: value, - inherits: false - }); +// Verifies that the property 'name' shows up on iteration, that it's reified +// to the specified type, and that the string representation is equal to 'value'. +function verify_computed_iteration_type(name, value, type) { + target.attributeStyleMap.set(name, value); + let result = Array.from(target.computedStyleMap()).filter(e => e[0] == name)[0]; + assert_equals(result.length, 2); + let iter_value = result[1]; + assert_equals(iter_value.length, 1); + assert_true(iter_value[0] instanceof type); + assert_equals(iter_value[0].toString(), value); +} - if (expected == CSSStyleValue) { - assert_false(propertyMap.get(name) instanceof CSSUnparsedValue); - } +// Run the same test twice: once for each StylePropertyMap. +// +// https://drafts.css-houdini.org/css-typed-om-1/#stylepropertymap +function test_specified_maps(func, description) { + test(function(){ + func(target.attributeStyleMap) + }, description + ' [attributeStyleMap]'); - assert_true(propertyMap.get(name) instanceof expected); + test(function(){ + let rule = style.sheet.rules[0]; + func(rule.styleMap) + }, description + ' [styleMap]'); } -// computedStyleMap +// StylePropertyMapReadOnly.get test(function(){ - let name = gen_prop('*', 'if(){}'); + let name = generate_property('*', 'if(){}'); assert_true(target.computedStyleMap().get(name) instanceof CSSUnparsedValue); target.attributeStyleMap.set(name, 'as{}df'); @@ -95,92 +143,94 @@ test(function(){ }, 'Computed * is reified as CSSUnparsedValue'); test(function(){ - assert_computed_type(gen_prop('<angle>', '42deg'), null, CSSUnitValue); - assert_computed_type(gen_prop('<angle> | fail', 'fail'), '42deg', CSSUnitValue); + verify_computed_type(generate_property('<angle>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <angle> '), '42deg', CSSUnitValue); }, 'Computed <angle> is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<color>', '#fefefe'), null, CSSStyleValue); - assert_computed_type(gen_prop('<color> | fail', 'fail'), null, CSSStyleValue); + verify_computed_type(generate_property('<color>'), null, CSSStyleValue); + verify_computed_type(generate_property('fail | <color> '), null, CSSStyleValue); }, 'Computed <color> is reified as CSSStyleValue'); test(function(){ - assert_computed_type(gen_prop('<custom-ident>', 'none'), null, CSSKeywordValue); - assert_computed_type(gen_prop('<custom-ident> | <length>', '10px'), 'none', CSSKeywordValue); + verify_computed_type(generate_property('<custom-ident>'), null, CSSKeywordValue); + verify_computed_type(generate_property('<custom-ident> | <length>'), 'none', CSSKeywordValue); }, 'Computed <custom-ident> is reified as CSSKeywordValue'); test(function(){ - assert_computed_type(gen_prop('<image>', 'url(thing.png)'), null, CSSImageValue); - assert_computed_type(gen_prop('<image> | fail', 'fail'), 'url(thing.png)', CSSImageValue); + verify_computed_type(generate_property('<image>'), null, CSSImageValue); + verify_computed_type(generate_property('fail | <image> '), 'url(thing.png)', CSSImageValue); }, 'Computed <image> [url] is reified as CSSImageValue'); test(function(){ - assert_computed_type(gen_prop('<integer>', '100'), null, CSSUnitValue); - assert_computed_type(gen_prop('<integer> | fail', 'fail'), '100', CSSUnitValue); + verify_computed_type(generate_property('<integer>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <integer> '), '100', CSSUnitValue); }, 'Computed <integer> is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<length-percentage>', '10%'), null, CSSUnitValue); - assert_computed_type(gen_prop('<length-percentage> | fail', 'fail'), '10%', CSSUnitValue); + verify_computed_type(generate_property('<length-percentage>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <length-percentage> '), '10%', CSSUnitValue); }, 'Computed <length-percentage> [%] is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<length-percentage>', '10px'), null, CSSUnitValue); - assert_computed_type(gen_prop('<length-percentage> | fail', 'fail'), '10px', CSSUnitValue); + verify_computed_type(generate_property('<length-percentage>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <length-percentage> '), '10px', CSSUnitValue); }, 'Computed <length-percentage> [px] is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<length-percentage>', 'calc(10px + 10%)'), null, CSSMathSum); - assert_computed_type(gen_prop('<length-percentage> | fail', 'fail'), 'calc(10px + 10%)', CSSMathSum); + verify_computed_type(generate_property({syntax: '<length-percentage>', initialValue: 'calc(10% + 10px)'}), null, CSSMathSum); + verify_computed_type(generate_property('fail | <length-percentage> '), 'calc(10px + 10%)', CSSMathSum); }, 'Computed <length-percentage> [px + %] is reified as CSSMathSum'); test(function(){ - assert_computed_type(gen_prop('<length>', '10px'), null, CSSUnitValue); - assert_computed_type(gen_prop('<length> | fail', 'fail'), '10px', CSSUnitValue); + verify_computed_type(generate_property('<length>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <length> '), '10px', CSSUnitValue); }, 'Computed <length> is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<number>', '42'), null, CSSUnitValue); - assert_computed_type(gen_prop('<number> | fail', 'fail'), '42', CSSUnitValue); + verify_computed_type(generate_property('<number>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <number> '), '42', CSSUnitValue); }, 'Computed <number> is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<percentage>', '10%'), null, CSSUnitValue); - assert_computed_type(gen_prop('<percentage> | fail', 'fail'), '10%', CSSUnitValue); + verify_computed_type(generate_property('<percentage>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <percentage> '), '10%', CSSUnitValue); }, 'Computed <percentage> is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<resolution>', '300dpi'), null, CSSUnitValue); - assert_computed_type(gen_prop('<resolution> | fail', 'fail'), '300dpi', CSSUnitValue); + verify_computed_type(generate_property('<resolution>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <resolution> '), '300dpi', CSSUnitValue); }, 'Computed <resolution> is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<time>', '42s'), null, CSSUnitValue); - assert_computed_type(gen_prop('<time> | fail', 'fail'), '42s', CSSUnitValue); + verify_computed_type(generate_property('<time>'), null, CSSUnitValue); + verify_computed_type(generate_property('fail | <time> '), '42s', CSSUnitValue); }, 'Computed <time> is reified as CSSUnitValue'); test(function(){ - assert_computed_type(gen_prop('<url>', 'url(a)'), null, CSSStyleValue); - assert_computed_type(gen_prop('<url> | fail', 'fail'), 'url(a)', CSSStyleValue); + verify_computed_type(generate_property('<url>'), null, CSSStyleValue); + verify_computed_type(generate_property('fail | <url> '), 'url(a)', CSSStyleValue); }, 'Computed <url> is reified as CSSStyleValue'); test(function(){ - assert_computed_type(gen_prop('thing1 | THING2', 'thing1'), null, CSSKeywordValue); - assert_computed_type(gen_prop('thing1 | THING2 | <url>', 'url(fail)'), 'THING2', CSSKeywordValue); + verify_computed_type(generate_property('thing1 | THING2'), null, CSSKeywordValue); + verify_computed_type(generate_property('thing1 | THING2 | <url>'), 'THING2', CSSKeywordValue); }, 'Computed ident is reified as CSSKeywordValue'); test(function(){ - assert_computed_type(gen_prop('<length>+', '10px 20px'), null, CSSUnitValue); - assert_computed_type(gen_prop('<length>+', '0px 0px'), '10px 20px', CSSUnitValue); + verify_computed_type(generate_property('<length>+'), null, CSSUnitValue); + verify_computed_type(generate_property('<length>+'), '10px 20px', CSSUnitValue); }, 'First computed value correctly reified in space-separated list'); test(function(){ - assert_computed_type(gen_prop('<length>#', '10px, 20px'), null, CSSUnitValue); - assert_computed_type(gen_prop('<length>#', '0px, 0px'), '10px, 20px', CSSUnitValue); + verify_computed_type(generate_property('<length>#'), null, CSSUnitValue); + verify_computed_type(generate_property('<length>#'), '10px, 20px', CSSUnitValue); }, 'First computed value correctly reified in comma-separated list'); +// StylePropertyMapReadOnly.getAll + test(function(){ - let name = gen_prop('<length>+', '10px 20px'); + let name = generate_property({syntax: '<length>+', initialValue: '10px 20px'}); assert_equals(target.computedStyleMap().getAll(name).length, 2); assert_true(target.computedStyleMap().getAll(name).every(x => x instanceof CSSUnitValue)); @@ -190,7 +240,7 @@ test(function(){ }, 'All computed values correctly reified in space-separated list'); test(function(){ - let name = gen_prop('<length>#', '10px, 20px'); + let name = generate_property({syntax: '<length>#', initialValue: '10px, 20px'}); assert_equals(target.computedStyleMap().getAll(name).length, 2); assert_true(target.computedStyleMap().getAll(name).every(x => x instanceof CSSUnitValue)); @@ -199,680 +249,601 @@ test(function(){ assert_true(target.computedStyleMap().getAll(name).every(x => x instanceof CSSUnitValue)); }, 'All computed values correctly reified in comma-separated list'); -// attributeStyleMap.get / styleMap.get +// StylePropertyMap.get/All -function test_style_property_map_get(test_fn, name_fn) { - let rule = style.sheet.rules[0]; +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('*'), 'foo'); +}, 'Specified * is reified as CSSUnparsedValue from get/getAll'); - test(function(){ - target.attributeStyleMap.clear(); - test_fn(target.style, target.attributeStyleMap); - }, name_fn('attributeStyleMap')); +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('foo'), 'foo'); +}, 'Specified foo is reified as CSSUnparsedValue from get/getAll'); - test(function(){ - rule.styleMap.clear(); - test_fn(rule.style, rule.styleMap); - }, name_fn('styleMap')); -} +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<angle>'), '10deg'); +}, 'Specified <angle> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<color>'), 'green'); +}, 'Specified <color> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<custom-ident>'), 'foo'); +}, 'Specified <custom-ident> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<image>'), 'url("a")'); +}, 'Specified <image> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<integer>'), '1'); +}, 'Specified <integer> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<length-percentage>'), 'calc(10% + 10px)'); +}, 'Specified <length-percentage> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<length>'), '10px'); +}, 'Specified <length> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<number>'), '1'); +}, 'Specified <number> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<percentage>'), '10%'); +}, 'Specified <percentage> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<resolution>'), '10dpi'); +}, 'Specified <resolution> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<time>'), '1s'); +}, 'Specified <time> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<transform-function>'), 'matrix(0, 0, 0, 0, 0, 0)'); +}, 'Specified <transform-function> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<transform-list>'), 'matrix(0, 0, 0, 0, 0, 0)'); +}, 'Specified <transform-list> is reified as CSSUnparsedValue from get/getAll'); -test_style_property_map_get(function(styleDecl, propertyMap){ - let name1 = gen_prop('<length>', '100px'); - let name2 = gen_prop('<length>', '0px'); - styleDecl.setProperty(name2, `var(${name1})`); - assert_true(propertyMap.get(name2) instanceof CSSUnparsedValue); -}, name => `StylePropertyMap.get returns CSSUnparsedValue for value with var references (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - let name1 = gen_prop('<length>', '100px'); - let name2 = gen_prop('<length>#', '0px'); - styleDecl.setProperty(name2, `1px, var(${name1}), 3px`); - assert_true(propertyMap.get(name2) instanceof CSSUnparsedValue); -}, name => `StylePropertyMap.get returns CSSUnparsedValue for value with var references in list (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '*', 'if(){}', CSSUnparsedValue); -}, name => `StylePropertyMap.get returns CSSUnparsedValue for * (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<angle>', '42deg', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <angle> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<color>', '#fefefe', CSSStyleValue); -}, name => `StylePropertyMap.get returns CSSStyleValue for <color> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<custom-ident>', 'none', CSSKeywordValue); -}, name => `StylePropertyMap.get returns CSSKeywordValue for <custom-ident> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<image>', 'url(thing.png)', CSSImageValue); -}, name => `StylePropertyMap.get returns CSSImageValue for <image> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<integer>', '100', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <integer> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<length-percentage>', '10%', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <length-percentage> [10%] (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<length-percentage>', '10px', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <length-percentage> [10px] (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<length-percentage>', 'calc(10px + 10%)', CSSMathSum); -}, name => `StylePropertyMap.get returns CSSMathSum for <length-percentage> [calc(10px + 10%)] (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<length>', '10px', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <length> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<number>', '42', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <number> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<percentage>', '10%', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <percentage> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<resolution>', '300dpi', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <resolution> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<time>', '42s', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <time> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<url>', 'url(a)', CSSStyleValue); -}, name => `StylePropertyMap.get returns CSSStyleValue for <url> (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, 'thing1 | THING2', 'thing1', CSSKeywordValue); -}, name => `StylePropertyMap.get returns CSSKeywordValue for thing1 | THING2 (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<length>+', '10px 20px', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <length>+ (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - assert_attribute_get_type(styleDecl, propertyMap, '<length>#', '10px 20px', CSSUnitValue); -}, name => `StylePropertyMap.get returns CSSUnitValue for <length># (${name})`); - -// attributeStyleMap.getAll - -test_style_property_map_get(function(styleDecl, propertyMap){ - let name = gen_prop('<length>+', '0px'); - styleDecl.setProperty(name, '10px 20px 30px'); - assert_equals(propertyMap.getAll(name).length, 3); - assert_true(propertyMap.getAll(name).every(x => x instanceof CSSUnitValue)); -}, name => `StylePropertyMap.getAll returns a list of CSSUnitValues for <length>+ (${name})`); - -test_style_property_map_get(function(styleDecl, propertyMap){ - let name = gen_prop('<length>#', '0px'); - styleDecl.setProperty(name, '10px, 20px, 30px'); - assert_equals(propertyMap.getAll(name).length, 3); - assert_true(propertyMap.getAll(name).every(x => x instanceof CSSUnitValue)); -}, name => `StylePropertyMap.getAll returns a list of CSSUnitValues for <length># (${name})`); +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<url>'), 'url("a")'); +}, 'Specified <url> is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<length>+'), '10px 11px'); +}, 'Specified <length>+ is reified as CSSUnparsedValue from get/getAll'); + +test_specified_maps(function(map){ + verify_map_get_unparsed(map, generate_property('<length>#'), '10px, 11px'); +}, 'Specified <length># is reified as CSSUnparsedValue from get/getAll'); // StylePropertyMap.set -function test_style_property_map_set_using_property_map(propertyMapName, propertyMap, options) { - test(function(){ - let name = gen_prop(options.syntax, options.initialValue); - propertyMap.clear(); +// The following strings are valid for the specified syntax, and should be +// accepted by set(). - let ensureArray = v => v.constructor === Array ? v : [v]; +test_specified_maps(function(map){ + verify_map_set(map, generate_property('*'), 'foo'); +}, 'Specified string "foo" accepted by set() for syntax *'); - for (let value of options.shouldAccept) - propertyMap.set(name, ...ensureArray(value)); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('foo'), 'foo'); +}, 'Specified string "foo" accepted by set() for syntax foo'); - for (let value of options.shouldReject) { - assert_throws(new TypeError(), () => propertyMap.set(name, ...ensureArray(value))); - } - }, `StylePropertyMap.set accepts correct CSSStyleValues for ${options.syntax} (${propertyMapName})`); -} +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<angle>'), '10deg'); +}, 'Specified string "10deg" accepted by set() for syntax <angle>'); -// Verify that the correct CSSStyleValues are accepted/rejected for a registered -// property with the specified syntax. -// -// The same test is performed twice: once for attributeStyleMap, and once -// for styleMap. -function test_style_property_map_set(options) { - test_style_property_map_set_using_property_map('attributeStyleMap', target.attributeStyleMap, options); - test_style_property_map_set_using_property_map('styleMap', style.sheet.rules[0].styleMap, options); -} +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<color>'), 'green'); +}, 'Specified string "green" accepted by set() for syntax <color>'); -let unparsed = x => new CSSUnparsedValue([x]); -let keyword = x => new CSSKeywordValue(x); -let sum = (a, b) => new CSSMathSum(a, b); -let url_image = x => CSSStyleValue.parse('background-image', x); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<custom-ident>'), 'foo'); +}, 'Specified string "foo" accepted by set() for syntax <custom-ident>'); -test_style_property_map_set({ - syntax: '*', - initialValue: 'none', - shouldAccept: [unparsed('thing')], - shouldReject: [CSS.px(15), keyword('none')], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<image>'), 'url("a")'); +}, 'Specified string "url("a")" accepted by set() for syntax <image>'); -test_style_property_map_set({ - syntax: '<angle>', - initialValue: '0deg', - shouldAccept: [CSS.deg(42), CSS.turn(2), '42deg'], - shouldReject: [unparsed('42deg'), CSS.px(15), '50px', [CSS.deg(15), '10deg']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<integer>'), '1'); +}, 'Specified string "1" accepted by set() for syntax <integer>'); -test_style_property_map_set({ - syntax: '<custom-ident>', - initialValue: 'none', - shouldAccept: [keyword('foo'), 'foo'], - shouldReject: [unparsed('foo'), CSS.px(15), '15px', [keyword('foo'), 'foo']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length-percentage>'), 'calc(10% + 10px)'); +}, 'Specified string "calc(10% + 10px)" accepted by set() for syntax <length-percentage>'); -test_style_property_map_set({ - syntax: '<image>', - initialValue: 'url(a)', - shouldAccept: [url_image('url(b)'), 'url(b)'], - shouldReject: [unparsed('url(b)'), CSS.px(100), '50px', [url_image('url(1)'), 'url(2)']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>'), '10px'); +}, 'Specified string "10px" accepted by set() for syntax <length>'); -test_style_property_map_set({ - syntax: '<integer>', - initialValue: '0', - shouldAccept: [CSS.number(1), CSS.number(-42), '1', '-42', 'calc(2.4)'], - shouldReject: [unparsed('42'), CSS.px(100), '50px', [CSS.number(42), '42'], 'calc(2px + 1px)'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<number>'), '1'); +}, 'Specified string "1" accepted by set() for syntax <number>'); -test_style_property_map_set({ - syntax: '<length-percentage>', - initialValue: '0px', - shouldAccept: [CSS.percent(10), CSS.px(1), CSS.em(1), '10px', '10%'], - shouldReject: [unparsed('10%'), unparsed('10px'), CSS.dpi(1), 'url(b)', [CSS.percent(10), '10%']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<percentage>'), '10%'); +}, 'Specified string "10%" accepted by set() for syntax <percentage>'); -test_style_property_map_set({ - syntax: '<length>', - initialValue: '0px', - shouldAccept: [CSS.px(10), CSS.em(10), CSS.vh(200), sum(CSS.px(10), CSS.em(20)), '10em', 'calc(10px + 10em)'], - shouldReject: [unparsed('10px'), CSS.percent(1), 'url(b)', [CSS.em(10), '10px']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<resolution>'), '10dpi'); +}, 'Specified string "10dpi" accepted by set() for syntax <resolution>'); -test_style_property_map_set({ - syntax: '<number>', - initialValue: '0', - shouldAccept: [CSS.number(1337), CSS.number(-42.5), '1337', '-42.5'], - shouldReject: [unparsed('42'), CSS.px(15), '#fef', [CSS.number(-42.5), '42.5']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<time>'), '1s'); +}, 'Specified string "1s" accepted by set() for syntax <time>'); -test_style_property_map_set({ - syntax: '<percentage>', - initialValue: '0%', - shouldAccept: [CSS.percent(10), '10%'], - shouldReject: [unparsed('10%'), CSS.px(1), '#fef', [CSS.percent(10), '1%']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<transform-function>'), 'matrix(0, 0, 0, 0, 0, 0)'); +}, 'Specified string "matrix(0, 0, 0, 0, 0, 0)" accepted by set() for syntax <transform-function>'); -test_style_property_map_set({ - syntax: '<resolution>', - initialValue: '0dpi', - shouldAccept: [CSS.dpi(100), CSS.dpcm(10), CSS.dppx(50), '100dpi'], - shouldReject: [unparsed('42'), CSS.px(15), '#fef', [CSS.dpi(1), '2dpi']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<transform-list>'), 'matrix(0, 0, 0, 0, 0, 0)'); +}, 'Specified string "matrix(0, 0, 0, 0, 0, 0)" accepted by set() for syntax <transform-list>'); -test_style_property_map_set({ - syntax: '<time>', - initialValue: '0s', - shouldAccept: [CSS.s(42), CSS.ms(16), '16ms'], - shouldReject: [unparsed('42s'), CSS.px(15), '#fef', [CSS.s(5), '6s']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<url>'), 'url("a")'); +}, 'Specified string "url("a")" accepted by set() for syntax <url>'); -test_style_property_map_set({ - syntax: '<url>', - initialValue: 'url(a)', - shouldAccept: [url_image('url(b)')], - shouldReject: [unparsed('url(b)'), CSS.px(100), '#fef', [url_image('url(1)'), 'url(2)']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>+'), '10px 11px'); +}, 'Specified string "10px 11px" accepted by set() for syntax <length>+'); -test_style_property_map_set({ - syntax: '<transform-list>', - initialValue: 'translateX(0px)', - shouldAccept: [CSSStyleValue.parse('transform', 'translateX(10px)')], - shouldReject: [unparsed('transformX(10px'), CSS.px(100), '#fef'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>#'), '10px, 11px'); +}, 'Specified string "10px, 11px" accepted by set() for syntax <length>#'); -test_style_property_map_set({ - syntax: 'none | thing | THING', - initialValue: 'none', - shouldAccept: [keyword('thing'), keyword('THING'), 'thing'], - shouldReject: [unparsed('thing'), CSS.px(15), keyword('notathing'), 'notathing', [keyword('thing'), keyword('thing')]], -}); +// The following strings are invalid for the specified syntax, but should +// should be accepted by set(). -test_style_property_map_set({ - syntax: '<angle> | <length>', - initialValue: '0deg', - shouldAccept: [CSS.deg(42), CSS.turn(2), CSS.px(10), CSS.em(10), '10deg', '10px'], - shouldReject: [unparsed('42deg'), unparsed('20px'), CSS.s(1), '#fef', [CSS.deg(42), '21deg']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('foo'), 'bar'); +}, 'Specified string "bar" accepted by set() for syntax foo'); -// StylePropertyMap.set for list-valued properties: +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<angle>'), '10px'); +}, 'Specified string "10px" accepted by set() for syntax <angle>'); -test_style_property_map_set({ - syntax: '<angle>+', - initialValue: '0deg', - shouldAccept: [CSS.deg(15), [CSS.deg(15), '10deg'], '15deg 10deg'], - shouldReject: [[CSS.deg(15), CSS.px(10)], '15deg 10px'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<color>'), '10px'); +}, 'Specified string "10px" accepted by set() for syntax <color>'); -test_style_property_map_set({ - syntax: '<custom-ident>+', - initialValue: 'none', - shouldAccept: [keyword('foo'), [keyword('foo'), 'bar'], 'foo bar'], - shouldReject: [[keyword('foo'), CSS.px(10)], 'foo 10px'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<custom-ident>'), '10px'); +}, 'Specified string "10px" accepted by set() for syntax <custom-ident>'); -test_style_property_map_set({ - syntax: '<image>+', - initialValue: 'url(a)', - shouldAccept: [url_image('url(1)'), [url_image('url(1)'), 'url(2)'], 'url(1) url(2)'], - shouldReject: [[url_image('url(1)'), CSS.px(10)], 'url(1) 10px'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<image>'), 'a'); +}, 'Specified string "a" accepted by set() for syntax <image>'); -test_style_property_map_set({ - syntax: '<integer>+', - initialValue: '0', - shouldAccept: [CSS.number(42), [CSS.number(42), '42'], '42 42', 'calc(2.4) calc(2.6)'], - shouldReject: [[CSS.number(42), keyword('noint')], '42 noint', 'calc(2px + 2px)'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<integer>'), 'float'); +}, 'Specified string "float" accepted by set() for syntax <integer>'); -test_style_property_map_set({ - syntax: '<length-percentage>+', - initialValue: '0px', - shouldAccept: [CSS.percent(10), [CSS.percent(10), '10%']], - shouldReject: [[CSS.percent(10), keyword('nolength')], '10% nolength'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length-percentage>'), 'red'); +}, 'Specified string "red" accepted by set() for syntax <length-percentage>'); -test_style_property_map_set({ - syntax: '<length>+', - initialValue: '0px', - shouldAccept: [CSS.em(10), [CSS.em(10), '10px']], - shouldReject: [[CSS.em(10), keyword('nolength'), '10em nolength']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>'), 'red'); +}, 'Specified string "red" accepted by set() for syntax <length>'); -test_style_property_map_set({ - syntax: '<number>+', - initialValue: '0', - shouldAccept: [CSS.number(-42.5), [CSS.number(-42.5), '42.5'], '-42.5 42.5'], - shouldReject: [[CSS.number(-42.5), CSS.px(10)], '-42.5 10px'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<number>'), 'red'); +}, 'Specified string "red" accepted by set() for syntax <number>'); -test_style_property_map_set({ - syntax: '<percentage>+', - initialValue: '0%', - shouldAccept: [CSS.percent(10), [CSS.percent(10), '1%'], '10% 1%'], - shouldReject: [[CSS.percent(10), keyword('foo')], '10% foo'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<percentage>'), 'var(--x)'); +}, 'Specified string "var(--x)" accepted by set() for syntax <percentage>'); -test_style_property_map_set({ - syntax: '<resolution>+', - initialValue: '0dpi', - shouldAccept: [CSS.dpi(1), [CSS.dpi(1), '2dpi'], '1dpi 2dpi'], - shouldReject: [[CSS.dpi(1), keyword('foo')], '1dpi foo'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<resolution>'), 'blue'); +}, 'Specified string "blue" accepted by set() for syntax <resolution>'); -test_style_property_map_set({ - syntax: '<time>+', - initialValue: '0s', - shouldAccept: [CSS.s(5), [CSS.s(5), '6s'], '5s 6s'], - shouldReject: [[CSS.s(5), keyword('foo')], '5s foo'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<time>'), '1meter'); +}, 'Specified string "1meter" accepted by set() for syntax <time>'); -test_style_property_map_set({ - syntax: '<url>+', - initialValue: 'url(a)', - shouldAccept: [url_image('url(1)'), [url_image('url(1)'), 'url(2)'], 'url(1) url(2)'], - shouldReject: [[url_image('url(1)'), CSS.px(10)], 'url(1) 10px'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<transform-function>'), 'foo(0)'); +}, 'Specified string "foo(0)" accepted by set() for syntax <transform-function>'); -test_style_property_map_set({ - syntax: 'thing+', - initialValue: 'thing', - shouldAccept: [keyword('thing'), [keyword('thing'), 'thing'], 'thing thing'], - shouldReject: [[keyword('thing'), CSS.px(10)], 'thing 10px'], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<transform-list>'), 'bar(1)'); +}, 'Specified string "bar(1)" accepted by set() for syntax <transform-list>'); -test_style_property_map_set({ - syntax: '<length>#', - initialValue: '0px', - shouldAccept: [CSS.em(10), [CSS.em(10), '10px']], - shouldReject: [[CSS.em(10), keyword('nolength'), '10em nolength']], -}); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<url>'), 'a'); +}, 'Specified string "a" accepted by set() for syntax <url>'); -function test_append_for_property_map(propertyMapName, propertyMap, options) { - test(function(){ - let name = gen_prop(options.syntax, options.initialValue); +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>+'), 'a b'); +}, 'Specified string "a b" accepted by set() for syntax <length>+'); - let ensureArray = v => v.constructor === Array ? v : [v]; +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>#'), 'a, b'); +}, 'Specified string "a, b" accepted by set() for syntax <length>#'); - for (let value of options.values) { - propertyMap.clear(); +// CSSUnparsedValue should always be accepted by any custom property, +// regardless of registation status. - if (value.base !== null) - propertyMap.set(name, ...ensureArray(value.base)); +const unparsed = CSSStyleValue.parse('--x', 'foo bar thing'); - // If 'null' is expected, it means we expect the append to fail. - if (value.expect !== null) { - propertyMap.append(name, ...ensureArray(value.append)); - let actual = Array.from(propertyMap.getAll(name)).join(' '); - assert_equals(actual, value.expect); - } else { - assert_throws(new TypeError(), () => propertyMap.append(name, ...ensureArray(value.append))); - } - } - }, `StylePropertyMap.append accepts correct CSSStyleValues for ${options.syntax} (${propertyMapName})`); -} +test_specified_maps(function(map){ + verify_map_set(map, generate_property('*'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax *'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('foo'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax foo'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<angle>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <angle>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<color>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <color>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<custom-ident>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <custom-ident>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<image>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <image>'); -// Verify that the correct CSSStyleValues are accepted/rejected when -// appending values to list-valued properties. +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<integer>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <integer>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length-percentage>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <length-percentage>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <length>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<number>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <number>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<percentage>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <percentage>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<resolution>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <resolution>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<time>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <time>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<transform-function>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <transform-function>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<transform-list>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <transform-list>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<url>'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <url>'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>+'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <length>+'); + +test_specified_maps(function(map){ + verify_map_set(map, generate_property('<length>#'), unparsed); +}, 'CSSUnparsedValue is accepted via set() for syntax <length>#'); + +// CSSStyleValues which aren't CSSUnparsedValues aren't accepted by set(), +// even if they're a value which is compatible with the syntax. // -// The same test is performed twice: once for attributeStyleMap, and once -// for styleMap. -function test_append(options) { - test_append_for_property_map('attributeStyleMap', target.attributeStyleMap, options); - test_append_for_property_map('styleMap', style.sheet.rules[0].styleMap, options); -} +// https://drafts.css-houdini.org/css-properties-values-api-1/#cssom +const zero_matrix = CSSStyleValue.parse('transform', 'matrix(0, 0, 0, 0, 0, 0)'); +const image_value = CSSStyleValue.parse('background-image', 'url(a)'); -test_append({ - syntax: '<angle>+', - initialValue: '0deg', - values: [ - { base: [CSS.deg(1)], append: [CSS.px(1)], expect: null }, - { base: [CSS.deg(1)], append: [CSS.deg(2), CSS.px(1)], expect: null }, - { base: [CSS.deg(1)], append: [CSS.deg(2), '1px'], expect: null }, - { base: [CSS.deg(1)], append: [CSS.turn(2), CSS.deg(3)], expect: '1deg 2turn 3deg' }, - { base: [CSS.deg(1), CSS.deg(2)], append: [CSS.deg(3)], expect: '1deg 2deg 3deg' }, - { base: [CSS.deg(1)], append: [CSS.deg(2), '3deg'], expect: '1deg 2deg 3deg' }, - { base: [CSS.deg(1)], append: [CSS.deg(2), '3turn 4deg'], expect: '1deg 2deg 3turn 4deg' }, - { base: null, append: [CSS.deg(1), '2deg'], expect: '1deg 2deg' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('*'), new CSSKeywordValue('foo')); +}, 'CSSKeywordValue rejected by set() for syntax *'); -test_append({ - syntax: '<custom-ident>+', - initialValue: 'none', - values: [ - { base: [keyword('foo')], append: [CSS.px(1)], expect: null }, - { base: [keyword('foo')], append: [keyword('bar'), CSS.px(1)], expect: null }, - { base: [keyword('foo')], append: [keyword('bar'), '1px'], expect: null }, - { base: [keyword('foo')], append: [keyword('bar'), keyword('baz')], expect: 'foo bar baz' }, - { base: [keyword('foo'), keyword('bar')], append: [keyword('baz')], expect: 'foo bar baz' }, - { base: [keyword('foo')], append: [keyword('bar'), 'baz'], expect: 'foo bar baz' }, - { base: [keyword('foo')], append: [keyword('bar'), 'baz zim'], expect: 'foo bar baz zim' }, - { base: null, append: [keyword('foo'), 'bar'], expect: 'foo bar' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('foo'), new CSSKeywordValue('foo')); +}, 'CSSKeywordValue rejected by set() for syntax foo'); -['<image>+', '<url>+'].forEach((syntax) => { - test_append({ - syntax: syntax, - initialValue: 'url(0)', - values: [ - { base: [url_image('url("1")')], append: [CSS.px(1)], expect: null }, - { base: [url_image('url("1")')], append: [url_image('url("2")'), CSS.px(1)], expect: null }, - { base: [url_image('url("1")')], append: [url_image('url("2")'), '1px'], expect: null }, - { base: [url_image('url("1")')], append: [url_image('url("2")'), url_image('url("3")')], expect: 'url("1") url("2") url("3")' }, - { base: [url_image('url("1")'), url_image('url("2")')], append: [url_image('url("3")')], expect: 'url("1") url("2") url("3")' }, - { base: [url_image('url("1")')], append: [url_image('url("2")'), 'url("3")'], expect: 'url("1") url("2") url("3")' }, - { base: [url_image('url("1")')], append: [url_image('url("2")'), 'url("3") url("4")'], expect: 'url("1") url("2") url("3") url("4")' }, - { base: null, append: [url_image('url("1")'), 'url("2")'], expect: 'url("1") url("2")' }, - ], - }); -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<angle>'), CSS.deg(10)); +}, 'CSSUnitValue rejected by set() for syntax <angle>'); -test_append({ - syntax: '<integer>+', - initialValue: '0', - values: [ - { base: [CSS.number(1)], append: [CSS.px(1)], expect: null }, - { base: [CSS.number(1)], append: [CSS.number(2), CSS.px(1)], expect: null }, - { base: [CSS.number(1)], append: [CSS.number(2), 'noint'], expect: null }, - { base: [CSS.number(1)], append: [CSS.number(2), CSS.number(3)], expect: '1 2 3' }, - { base: [CSS.number(1), CSS.number(2)], append: [CSS.number(3)], expect: '1 2 3' }, - { base: [CSS.number(1)], append: [CSS.number(2), '3'], expect: '1 2 3' }, - { base: [CSS.number(1)], append: [CSS.number(2), '3 4'], expect: '1 2 3 4' }, - { base: null, append: [CSS.number(1), '2'], expect: '1 2' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<custom-ident>'), new CSSKeywordValue('foo')); +}, 'CSSKeywordValue rejected by set() for syntax <custom-ident>'); -test_append({ - syntax: '<length-percentage>+', - initialValue: '0px', - values: [ - { base: [CSS.px(1)], append: [keyword('nolength')], expect: null }, - { base: [CSS.px(1)], append: [CSS.px(2), keyword('nolength')], expect: null }, - { base: [CSS.px(1)], append: [CSS.px(2), 'nolength'], expect: null }, - { base: [CSS.px(1)], append: [CSS.px(2), CSS.percent(3)], expect: '1px 2px 3%' }, - { base: [CSS.px(1), CSS.px(2)], append: [CSS.percent(3)], expect: '1px 2px 3%' }, - { base: [CSS.px(1)], append: [CSS.percent(2), '3px'], expect: '1px 2% 3px' }, - { base: [CSS.px(1)], append: [CSS.px(2), '3% 4px'], expect: '1px 2px 3% 4px' }, - { base: null, append: [CSS.px(1), '2%'], expect: '1px 2%' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<image>'), image_value); +}, 'CSSImageValue rejected by set() for syntax <image>'); -test_append({ - syntax: '<length>+', - initialValue: '0', - values: [ - { base: [CSS.px(1)], append: [keyword('nolength')], expect: null }, - { base: [CSS.px(1)], append: [CSS.px(2), keyword('nolength')], expect: null }, - { base: [CSS.px(1)], append: [CSS.px(2), 'nolength'], expect: null }, - { base: [CSS.px(1)], append: [CSS.em(2), CSS.px(3)], expect: '1px 2em 3px' }, - { base: [CSS.px(1), CSS.em(2)], append: [CSS.vh(3)], expect: '1px 2em 3vh' }, - { base: [CSS.px(1)], append: [CSS.em(2), '3px'], expect: '1px 2em 3px' }, - { base: [CSS.px(1)], append: [CSS.px(2), '3em 4cm'], expect: '1px 2px 3em 4cm' }, - { base: null, append: [CSS.vh(1), '2px'], expect: '1vh 2px' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<integer>'), CSS.number(1)); +}, 'CSSUnitValue rejected by set() for syntax <integer>'); -test_append({ - syntax: '<number>+', - initialValue: '0', - values: [ - { base: [CSS.number(-1)], append: [keyword('NaN')], expect: null }, - { base: [CSS.number(-1)], append: [CSS.number(2.5), keyword('NaN')], expect: null }, - { base: [CSS.number(-1)], append: [CSS.number(2.5), '1px'], expect: null }, - { base: [CSS.number(-1)], append: [CSS.number(2.5), CSS.number(3.2)], expect: '-1 2.5 3.2' }, - { base: [CSS.number(-1), CSS.number(2.5)], append: [CSS.number(3.2)], expect: '-1 2.5 3.2' }, - { base: [CSS.number(-1)], append: [CSS.number(2.5), '3.2'], expect: '-1 2.5 3.2' }, - { base: [CSS.number(-1)], append: [CSS.number(2.5), '3.2 4'], expect: '-1 2.5 3.2 4' }, - { base: null, append: [CSS.number(-1), '2.5'], expect: '-1 2.5' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<length-percentage>'), CSS.px(10)); +}, 'CSSUnitValue rejected by set() for syntax <length-percentage>'); -test_append({ - syntax: '<percentage>+', - initialValue: '0%', - values: [ - { base: [CSS.percent(1)], append: [CSS.px(1)], expect: null }, - { base: [CSS.percent(1)], append: [CSS.percent(2), CSS.px(1)], expect: null }, - { base: [CSS.percent(1)], append: [CSS.percent(2), '1px'], expect: null }, - { base: [CSS.percent(1)], append: [CSS.percent(2), CSS.percent(3)], expect: '1% 2% 3%' }, - { base: [CSS.percent(1), CSS.percent(2)], append: [CSS.percent(3)], expect: '1% 2% 3%' }, - { base: [CSS.percent(1)], append: [CSS.percent(2), '3%'], expect: '1% 2% 3%' }, - { base: [CSS.percent(1)], append: [CSS.percent(2), '3% 4%'], expect: '1% 2% 3% 4%' }, - { base: null, append: [CSS.percent(1), '2%'], expect: '1% 2%' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<length>'), CSS.px(10)); +}, 'CSSUnitValue rejected by set() for syntax <length>'); -test_append({ - syntax: '<resolution>+', - initialValue: '0dpi', - values: [ - { base: [CSS.dpi(1)], append: [CSS.px(1)], expect: null }, - { base: [CSS.dpi(1)], append: [CSS.dpi(2), CSS.px(1)], expect: null }, - { base: [CSS.dpi(1)], append: [CSS.dpi(2), '1px'], expect: null }, - { base: [CSS.dpi(1)], append: [CSS.dpi(2), CSS.dpi(3)], expect: '1dpi 2dpi 3dpi' }, - { base: [CSS.dpi(1), CSS.dpi(2)], append: [CSS.dpi(3)], expect: '1dpi 2dpi 3dpi' }, - { base: [CSS.dpi(1)], append: [CSS.dpi(2), '3dpi'], expect: '1dpi 2dpi 3dpi' }, - { base: [CSS.dpi(1)], append: [CSS.dpi(2), '3dpi 4dpi'], expect: '1dpi 2dpi 3dpi 4dpi' }, - { base: null, append: [CSS.dpi(1), '2dpi'], expect: '1dpi 2dpi' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<number>'), CSS.number(10)); +}, 'CSSUnitValue rejected by set() for syntax <number>'); -test_append({ - syntax: '<time>+', - initialValue: '0s', - values: [ - { base: [CSS.s(1)], append: [CSS.px(1)], expect: null }, - { base: [CSS.s(1)], append: [CSS.s(2), CSS.px(1)], expect: null }, - { base: [CSS.s(1)], append: [CSS.ms(2), '1px'], expect: null }, - { base: [CSS.s(1)], append: [CSS.ms(2), CSS.s(3)], expect: '1s 2ms 3s' }, - { base: [CSS.s(1), CSS.s(2)], append: [CSS.s(3)], expect: '1s 2s 3s' }, - { base: [CSS.s(1)], append: [CSS.s(2), '3s'], expect: '1s 2s 3s' }, - { base: [CSS.s(1)], append: [CSS.s(2), '3ms 4s'], expect: '1s 2s 3ms 4s' }, - { base: null, append: [CSS.s(1), '2s'], expect: '1s 2s' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<percentage>'), CSS.percent(10)); +}, 'CSSUnitValue rejected by set() for syntax <percentage>'); -test_append({ - syntax: 'foo+', - initialValue: 'foo', - values: [ - { base: [keyword('foo')], append: [CSS.px(1)], expect: null }, - { base: [keyword('foo')], append: [keyword('foo'), CSS.px(1)], expect: null }, - { base: [keyword('foo')], append: [keyword('foo'), '1px'], expect: null }, - { base: [keyword('foo')], append: [keyword('foo'), keyword('foo')], expect: 'foo foo foo' }, - { base: [keyword('foo'), keyword('foo')], append: [keyword('foo')], expect: 'foo foo foo' }, - { base: [keyword('foo')], append: [keyword('foo'), 'foo'], expect: 'foo foo foo' }, - { base: [keyword('foo')], append: [keyword('foo'), 'foo foo'], expect: 'foo foo foo foo' }, - { base: null, append: [keyword('foo'), keyword('foo')], expect: 'foo foo' }, - ], -}); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<resolution>'), CSS.dpi(10)); +}, 'CSSUnitValue rejected by set() for syntax <resolution>'); -// CSSStyleValue.parse/parseAll +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<time>'), CSS.s(10)); +}, 'CSSUnitValue rejected by set() for syntax <time>'); -function assert_parsed_type(prop, value, expected) { - let parse_value = CSSStyleValue.parse(prop, value); - let parse_all_value = CSSStyleValue.parseAll(prop, value); +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<transform-list>'), zero_matrix); +}, 'CSSTransformValue rejected by set() for syntax <transform-list>'); - assert_true(parse_value instanceof expected); - assert_true(parse_all_value.every(x => x instanceof expected)) +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<length>+'), CSS.px(10), CSS.px(10)); +}, 'CSSUnitValue rejected by set() for syntax <length>+'); - // If CSSStyleValue is expected, the values must be exactly CSSStyleValue. - // This is because CSSUnparsedValues are also CSSStyleValues, which would be - // wrong in this case. - if (expected == CSSStyleValue) { - assert_equals(parse_value.constructor, CSSStyleValue); - assert_true(parse_all_value.every(x => x.constructor == CSSStyleValue)); - } -} +test_specified_maps(function(map){ + verify_map_not_set(map, generate_property('<length>#'), CSS.px(10), CSS.px(10)); +}, 'CSSUnitValue rejected by set() for syntax <length>#'); -test(function(){ - assert_parsed_type(gen_prop('*', 'if(){}'), 'while(){}', CSSUnparsedValue); -}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for *'); +// <color> has no CSSStyleValue subclass yet. +// <url> has no CSSStyleValue subclass yet. +// <transform-function> has no CSSStyleValue subclass yet. + +// StylePropertyMap.append + +// It is not allowed to append CSSStyleValues to custom properties, even +// when the string matches the syntax of the custom property. + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('*'), 'a'); +}, 'Appending a string to * is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('foo+'), 'foo'); +}, 'Appending a string to foo+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<angle>+'), '10deg'); +}, 'Appending a string to <angle>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<color>+'), 'red'); +}, 'Appending a string to <color>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<custom-ident>+'), 'foo'); +}, 'Appending a string to <custom-ident>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<image>+'), 'url(a)'); +}, 'Appending a string to <image>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<integer>+'), 'a'); +}, 'Appending a string to <integer>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<length-percentage>+'), 'calc(10*% + 10px)'); +}, 'Appending a string to <length-percentage>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<length>+'), '10px'); +}, 'Appending a string to <length>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<number>+'), '1.3'); +}, 'Appending a string to <number>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<percentage>+'), '10%'); +}, 'Appending a string to <percentage>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<resolution>+'), '10dpi'); +}, 'Appending a string to <resolution>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<time>+'), '1s'); +}, 'Appending a string to <time>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<transform-function>+'), 'matrix(0, 0, 0, 0, 0, 0)'); +}, 'Appending a string to <transform-function>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<transform-list>'), 'matrix(0, 0, 0, 0, 0, 0)'); +}, 'Appending a string to <transform-list> is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<url>+'), 'url(a)'); +}, 'Appending a string to <url>+ is not allowed'); + +test_specified_maps(function(map){ + verify_map_no_append(map, generate_property('<length>#'), '10px'); +}, 'Appending a string to <length># is not allowed'); + +// It is not allowed to append CSSStyleValues to custom properties, even +// when the CSSStyleValue matches the syntax of the custom property. + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('*'), new CSSKeywordValue('foo')); +}, 'Appending a CSSKeywordValue to * is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('foo+'), new CSSKeywordValue('foo')); +}, 'Appending a CSSKeywordValue to foo+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<angle>+'), CSS.deg(10)); +}, 'Appending a CSSUnitValue to <angle>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<custom-ident>+'), new CSSKeywordValue('foo')); +}, 'Appending a CSSKeywordValue to <custom-ident>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<image>+'), image_value); +}, 'Appending a CSSImageValue to <image>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<integer>+'), CSS.number(1)); +}, 'Appending a CSSUnitValue to <integer>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<length-percentage>+'), CSS.px(10)); +}, 'Appending a CSSUnitValue to <length-percentage>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<length>+'), CSS.px(10)); +}, 'Appending a CSSUnitValue to <length>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<number>+'), CSS.number(10)); +}, 'Appending a CSSUnitValue to <number>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<percentage>+'), CSS.percent(10)); +}, 'Appending a CSSUnitValue to <percentage>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<resolution>+'), CSS.dpi(10)); +}, 'Appending a CSSUnitValue to <resolution>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<time>+'), CSS.s(10)); +}, 'Appending a CSSUnitValue to <time>+ is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<transform-list>'), zero_matrix); +}, 'Appending a CSSKeywordValue to <transform-list> is not allowed'); + +test_specified_maps(function(map) { + verify_map_no_append(map, generate_property('<length>#'), CSS.px(10)); +}, 'Appending a CSSUnitValue to <length># is not allowed'); + +// <color> has no CSSStyleValue subclass yet. +// <url> has no CSSStyleValue subclass yet. +// <transform-function> has no CSSStyleValue subclass yet. + +// CSSStyleValue.parse/parseAll test(function(){ - assert_parsed_type(gen_prop('<angle> | fail', 'fail'), '42deg', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <angle>'); + verify_parsed_type(generate_property('*'), 'while(){}', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax *', CSSUnparsedValue); test(function(){ - assert_parsed_type(gen_prop('<color> | fail', 'fail'), '#fefefe', CSSStyleValue); -}, 'CSSStyleValue.parse[All] returns CSSStyleValue for <color>'); + verify_parsed_type(generate_property('<angle>'), '42deg', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <angle>'); test(function(){ - assert_parsed_type(gen_prop('<custom-ident> | <length>', '10px'), 'none', CSSKeywordValue); -}, 'CSSStyleValue.parse[All] returns CSSKeywordValue for <custom-ident>'); + verify_parsed_type(generate_property('<color>'), '#fefefe', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <color>'); test(function(){ - assert_parsed_type(gen_prop('<image> | fail', 'fail'), 'url(thing.png)', CSSImageValue); -}, 'CSSStyleValue.parse[All] returns CSSImageValue for <image> [url]'); + verify_parsed_type(generate_property('<custom-ident> | <length>'), 'none', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <custom-ident> | <length>'); test(function(){ - assert_parsed_type(gen_prop('<integer> | fail', 'fail'), '100', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <integer>'); + verify_parsed_type(generate_property('<image>'), 'url(thing.png)', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <image>'); test(function(){ - assert_parsed_type(gen_prop('<length-percentage> | fail', 'fail'), '10%', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <length-percentage> [%]'); + verify_parsed_type(generate_property('<integer>'), '100', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <integer>'); test(function(){ - assert_parsed_type(gen_prop('<length-percentage> | fail', 'fail'), '10px', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <length-percentage> [px]'); + verify_parsed_type(generate_property('<length-percentage>'), '10%', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <length-percentage> (10%)'); test(function(){ - assert_parsed_type(gen_prop('<length-percentage> | fail', 'fail'), 'calc(10px + 10%)', CSSMathSum); -}, 'CSSStyleValue.parse[All] returns CSSMathSum for <length-percentage> [px + %]'); + verify_parsed_type(generate_property('<length-percentage>'), '10px', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <length-percentage> (10px)'); test(function(){ - assert_parsed_type(gen_prop('<length> | fail', 'fail'), '10px', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <length>'); + verify_parsed_type(generate_property('<length-percentage>'), 'calc(10px + 10%)', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <length-percentage> (calc(10px + 10%))'); test(function(){ - assert_parsed_type(gen_prop('<number> | fail', 'fail'), '42', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <number>'); + verify_parsed_type(generate_property('<length>'), '10px', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <length>'); test(function(){ - assert_parsed_type(gen_prop('<percentage> | fail', 'fail'), '10%', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <percentage>'); + verify_parsed_type(generate_property('<number>'), '42', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <number>'); test(function(){ - assert_parsed_type(gen_prop('<resolution> | fail', 'fail'), '300dpi', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <resolution>'); + verify_parsed_type(generate_property('<percentage>'), '10%', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <percentage>'); test(function(){ - assert_parsed_type(gen_prop('<time> | fail', 'fail'), '42s', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns CSSUnitValue for <time>'); + verify_parsed_type(generate_property('<resolution>'), '300dpi', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <resolution>'); test(function(){ - assert_parsed_type(gen_prop('<url> | fail', 'fail'), 'url(a)', CSSStyleValue); -}, 'CSSStyleValue.parse[All] returns CSSStyleValue for <url>'); + verify_parsed_type(generate_property('<time>'), '42s', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <time>'); test(function(){ - assert_parsed_type(gen_prop('thing1 | THING2 | <url>', 'url(fail)'), 'THING2', CSSKeywordValue); -}, 'CSSStyleValue.parse[All] returns CSSKeywordValue for ident'); + verify_parsed_type(generate_property('<transform-function>'), 'matrix(0, 0, 0, 0, 0, 0)', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <transform-function>'); test(function(){ - assert_parsed_type(gen_prop('<length>+ | fail', 'fail'), '10px 20px', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns list of CSSUnitValues for <length>+'); + verify_parsed_type(generate_property('<transform-list>'), 'matrix(0, 0, 0, 0, 0, 0)', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <transform-list>'); test(function(){ - assert_parsed_type(gen_prop('<length># | fail', 'fail'), '10px, 20px', CSSUnitValue); -}, 'CSSStyleValue.parse[All] returns list of CSSUnitValues for <length>#'); + verify_parsed_type(generate_property('<url>'), 'url(a)', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <url>'); -// Direct CSSStyleValue objects: +test(function(){ + verify_parsed_type(generate_property('thing1 | THING2 | <url>'), 'THING2', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax thing1 | THING2 | <url>'); -function gen_all_props() { - return [ - gen_prop('*', 'foo'), - gen_prop('foo', 'foo'), - gen_prop('<angle>', '0deg'), - gen_prop('<color>', 'rgb(1, 2, 3)'), - gen_prop('<custom-ident>', 'thing'), - gen_prop('<image>', 'url(a)'), - gen_prop('<integer>', '0'), - gen_prop('<length-percentage>', 'calc(10px + 10%)'), - gen_prop('<length>', '0px'), - gen_prop('<number>', '0.5'), - gen_prop('<percentage>', '0%'), - gen_prop('<resolution>', '0dpi'), - gen_prop('<time>', '0s'), - gen_prop('<transform-function>', 'rotateX(0deg)'), - gen_prop('<transform-list>', 'rotateX(0deg)'), - gen_prop('<url>', 'url(a)') - ]; -} +test(function(){ + verify_parsed_type(generate_property('<length>+'), '10px 20px', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <length>+'); test(function(){ - let props0 = gen_all_props(); - let props1 = gen_all_props(); + verify_parsed_type(generate_property('<length>#'), '10px, 20px', CSSUnparsedValue); +}, 'CSSStyleValue.parse[All] returns CSSUnparsedValue for syntax <length>#'); - for (let i = 0; i < props0.length; i++) { - let prop0 = props0[i]; - let prop1 = props1[i]; +// Direct CSSStyleValue objects: - // Abuse computedStyleMap to get the initialValue (just to get some - // value that will parse for prop0/1's syntax). - let initialValue = target.computedStyleMap().get(prop0); +test_specified_maps(function(map){ + for (let syntax of all_syntaxes()) { + let name = generate_property(syntax); + + let initialValue = target.computedStyleMap().get(name); // We only care about direct CSSStyleValue instances in this test. // Ultimately, in some future version of CSS TypedOM, we may have no @@ -881,139 +852,142 @@ test(function(){ continue; } - let value = CSSStyleValue.parse(prop0, initialValue.toString()); + // Verify that direct CSSStyleValues are rejected by set(). Two things + // should prevent this: 1) direct CSSStyleValues are not + // CSSUnparsedValues, and 2) direct CSSStyleValues are only valid for + // the property they were reified from. + verify_map_not_set(map, generate_property(syntax), initialValue); + } +}, 'Direct CSSStyleValue may not be set'); - // A value parsed for prop0 must be assignable to prop0. - target.attributeStyleMap.clear(); - target.attributeStyleMap.set(prop0, value); // Don't throw. +// StylePropertyMap iteration - // A value parsed for prop0 must not be assignable to prop1, even if - // the properties have compatible syntaxes. - assert_throws(new TypeError(), () => { - target.attributeStyleMap.clear(); - target.attributeStyleMap.set(prop1, value); - }); - } -}, 'Direct CSSStyleValue instances are tied to their associated property'); +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('*'), 'foo'); +}, 'Specified * is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('foo'), 'foo'); +}, 'Specified foo is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<angle>'), '10deg'); +}, 'Specified <angle> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<color>'), 'green'); +}, 'Specified <color> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<custom-ident>'), 'foo'); +}, 'Specified <custom-ident> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<image>'), 'url("a")'); +}, 'Specified <image> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<integer>'), '1'); +}, 'Specified <integer> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<length-percentage>'), 'calc(10% + 10px)'); +}, 'Specified <length-percentage> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<length>'), '10px'); +}, 'Specified <length> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<number>'), '1'); +}, 'Specified <number> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<percentage>'), '10%'); +}, 'Specified <percentage> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<resolution>'), '10dpi'); +}, 'Specified <resolution> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<time>'), '1s'); +}, 'Specified <time> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<transform-function>'), 'matrix(0, 0, 0, 0, 0, 0)'); +}, 'Specified <transform-function> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<transform-list>'), 'matrix(0, 0, 0, 0, 0, 0)'); +}, 'Specified <transform-list> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<url>'), 'url("a")'); +}, 'Specified <url> is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<length>+'), '10px 11px'); +}, 'Specified <length>+ is reified CSSUnparsedValue by iterator'); + +test_specified_maps(function(map){ + verify_map_iteration_unparsed(map, generate_property('<length>#'), '10px, 11px'); +}, 'Specified <length># is reified CSSUnparsedValue by iterator'); // StylePropertyMapReadOnly iteration test(function(){ - let name = gen_prop('<length>', '10px'); + let name = generate_property({syntax: '<length>', initialValue: '10px'}); let result = Array.from(target.computedStyleMap()).filter(e => e[0] == name)[0]; assert_true(typeof(result) !== 'undefined'); }, 'Registered property with initial value show up on iteration of computedStyleMap'); -// Verifies that iterating a StylePropertyMap[ReadOnly] yields correctly -// typed objects for a given syntax/value. -function test_iteration_type_for_property_map(propertyMapName, propertyMap, options) { - test(function(){ - let name = gen_prop(options.syntax, options.initialValue); - if (propertyMap instanceof StylePropertyMap) { - // Only set the value if the propertyMap is mutable. - propertyMap.set(name, options.value); - } - let result = Array.from(propertyMap).filter(e => e[0] == name)[0]; - let value = result[1]; - assert_true(options.expect(value)); - }, `Iteration on ${propertyMapName} produces correct type for ${options.syntax}`); -} - -function test_iteration_type(options) { - test_iteration_type_for_property_map('computedStyleMap', target.computedStyleMap(), options); - test_iteration_type_for_property_map('attributeStyleMap', target.attributeStyleMap, options); - test_iteration_type_for_property_map('styleMap', style.sheet.rules[0].styleMap, options); -} - -test_iteration_type({ - syntax: '*', - initialValue: 'none', - value: 'thing', - expect: v => v.length == 1 && v[0] instanceof CSSUnparsedValue, -}); - -test_iteration_type({ - syntax: '<angle>', - initialValue: '0deg', - value: '42deg', - expect: v => v.length == 1 && v[0] instanceof CSSUnitValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('*'), 'thing', CSSUnparsedValue); +}, 'Computed * is reified as CSSUnparsedValue by iterator'); -test_iteration_type({ - syntax: '<custom-ident>', - initialValue: 'none', - value: 'thing', - expect: v => v.length == 1 && v[0] instanceof CSSKeywordValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<angle>'), '42deg', CSSUnitValue); +}, 'Computed <angle> is reified as CSSUnitValue by iterator'); -test_iteration_type({ - syntax: '<image>', - initialValue: 'url(a)', - value: 'url(b)', - expect: v => v.length == 1 && v[0] instanceof CSSImageValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<custom-ident>'), 'thing', CSSKeywordValue); +}, 'Computed <custom-ident> is reified as CSSKeywordValue by iterator'); -test_iteration_type({ - syntax: '<integer>', - initialValue: '0', - value: '100', - expect: v => v.length == 1 && v[0] instanceof CSSUnitValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<image>'), 'url(\"a\")', CSSImageValue); +}, 'Computed <image> is reified as CSSImageValue by iterator'); -test_iteration_type({ - syntax: '<length>', - initialValue: '0px', - value: '10px', - expect: v => v.length == 1 && v[0] instanceof CSSUnitValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<integer>'), '100', CSSUnitValue); +}, 'Computed <integer> is reified as CSSUnitValue by iterator'); -test_iteration_type({ - syntax: '<number>', - initialValue: '0', - value: '42', - expect: v => v.length == 1 && v[0] instanceof CSSUnitValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<length>'), '10px', CSSUnitValue); +}, 'Computed <length> is reified as CSSUnitValue by iterator'); -test_iteration_type({ - syntax: '<percentage>', - initialValue: '0%', - value: '10%', - expect: v => v.length == 1 && v[0] instanceof CSSUnitValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<number>'), '42', CSSUnitValue); +}, 'Computed <number> is reified as CSSUnitValue by iterator'); -test_iteration_type({ - syntax: '<resolution>', - initialValue: '0dpi', - value: '300dpi', - expect: v => v.length == 1 && v[0] instanceof CSSUnitValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<percentage>'), '10%', CSSUnitValue); +}, 'Computed <percentage> is reified as CSSUnitValue by iterator'); -test_iteration_type({ - syntax: '<time>', - initialValue: '0s', - value: '10s', - expect: v => v.length == 1 && v[0] instanceof CSSUnitValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<resolution>'), '300dppx', CSSUnitValue); +}, 'Computed <resolution> is reified as CSSUnitValue by iterator'); -test_iteration_type({ - syntax: '<url>', - initialValue: 'url(a)', - value: 'url(b)', - expect: v => v.length == 1 && v[0].constructor === CSSStyleValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<time>'), '10s', CSSUnitValue); +}, 'Computed <time> is reified as CSSUnitValue by iterator'); -test_iteration_type({ - syntax: 'none | thing | THING', - initialValue: 'none', - value: 'THING', - expect: v => v.length == 1 && v[0] instanceof CSSKeywordValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('none | thing | THING'), 'THING', CSSKeywordValue); +}, 'Computed none | thing | THING is reified as CSSKeywordValue by iterator'); -test_iteration_type({ - syntax: '<angle> | <length>', - initialValue: '0deg', - value: '10px', - expect: v => v.length == 1 && v[0] instanceof CSSUnitValue, -}); +test(function(){ + verify_computed_iteration_type(generate_property('<angle> | <length>'), '10px', CSSUnitValue); +}, 'Computed <angle> | <length> is reified as CSSUnitValue by iterator'); </script> diff --git a/tests/wpt/web-platform-tests/css/css-scrollbars/scrollbars-chrome-bug-001-ref.html b/tests/wpt/web-platform-tests/css/css-scrollbars/scrollbars-chrome-bug-001-ref.html new file mode 100644 index 00000000000..1bf59f90e74 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-scrollbars/scrollbars-chrome-bug-001-ref.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<link rel="help" href="https://crbug.com/926167"> +<style> + +#container { + width: 200px; + height: 150px; + border: 1px solid black; + overflow: scroll; +} +#target { + width: 100px; + height: 50px; + background: green; + transform: scale(4); +} +</style> +<!-- --> +<div id="container"> + <div id="target"></div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-scrollbars/scrollbars-chrome-bug-001.html b/tests/wpt/web-platform-tests/css/css-scrollbars/scrollbars-chrome-bug-001.html new file mode 100644 index 00000000000..643781bac80 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-scrollbars/scrollbars-chrome-bug-001.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>CSS Overflow: css-overflow-3</title> +<link rel="author" href="mailto:atotic@google.com"> +<link rel="help" href="https://crbug.com/926167"> +<link rel="match" href="scrollbars-chrome-bug-001-ref.html"> +<meta name="assert" content="scrollbars keep up to date with a changing transform"> +<style> + +#container { + width: 200px; + height: 150px; + border: 1px solid black; + overflow: scroll; +} +#target { + width: 100px; + height: 50px; + background: green; + transform: scale(1); +} +</style> +<!-- --> +<div id="container"> + <div id="target"></div> +</div> +<script> + // 1st transform triggers layer creation, and full layout. + // 2nd transform just updates overflow, which does not update scrollbars. + // This triggers the bug. + document.body.offsetTop; + document.querySelector("#target").style.transform = "scale(1.5)"; + document.body.offsetTop; + document.querySelector("#target").style.transform = "scale(4.0)"; +</script> diff --git a/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-computed.html b/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-computed.html index a90d23a6044..81bc0ccb845 100644 --- a/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-computed.html +++ b/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-computed.html @@ -15,6 +15,11 @@ test_computed_value("shape-image-threshold", "-7", "0"); test_computed_value("shape-image-threshold", "0.5"); test_computed_value("shape-image-threshold", "12.5", "1"); + +// https://github.com/w3c/csswg-drafts/issues/4102 +test_computed_value("shape-image-threshold", "-100%", "0"); +test_computed_value("shape-image-threshold", "50%", "0.5"); +test_computed_value("shape-image-threshold", "300%", "1"); </script> </body> </html> diff --git a/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-invalid.html b/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-invalid.html index 6299e2ecaad..c0cac033fb6 100644 --- a/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-invalid.html +++ b/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-invalid.html @@ -14,7 +14,6 @@ <script> test_invalid_value("shape-image-threshold", "auto"); test_invalid_value("shape-image-threshold", "10px"); -test_invalid_value("shape-image-threshold", "100%"); </script> </body> </html> diff --git a/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-valid.html b/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-valid.html index 914abd02210..4ed1fb9fbaf 100644 --- a/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-valid.html +++ b/tests/wpt/web-platform-tests/css/css-shapes/parsing/shape-image-threshold-valid.html @@ -14,6 +14,11 @@ <script> test_valid_value("shape-image-threshold", "12.5"); test_valid_value("shape-image-threshold", "-7"); + +// https://github.com/w3c/csswg-drafts/issues/4102 +test_valid_value("shape-image-threshold", "-100%", "-1"); +test_valid_value("shape-image-threshold", "50%", "0.5"); +test_valid_value("shape-image-threshold", "300%", "3"); </script> </body> </html> diff --git a/tests/wpt/web-platform-tests/css/css-transforms/perspective-transforms-equivalence-ref.html b/tests/wpt/web-platform-tests/css/css-transforms/perspective-transforms-equivalence-ref.html new file mode 100644 index 00000000000..a4fc022382c --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-transforms/perspective-transforms-equivalence-ref.html @@ -0,0 +1,40 @@ +<!doctype HTML> +<meta charset="utf8"> +<title>Perspective with transforms equivalencies.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<style> + +#container { + transform: translate(-200px, -200px); + width: 500px; + height: 500px; + perspective: 500px; +} + +#container > div { + width: 100%; + height: 100%; + transform-style: preserve-3d; + transform: translateZ(-250px) rotateZ(45deg); +} + +#container > div > div { + width: 100%; + height: 100%; + position: absolute; + background-color: rgba(3, 121, 255, 0.3); + box-sizing: border-box; + border: 3px solid black; +} + +#one { transform: rotateY(90deg) translateZ(250px); } +</style> + +<div id="container"> + <div> + <div id="one"></div> + <div id="one"></div> + <div id="one"></div> + <div id="one"></div> + </div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-transforms/perspective-transforms-equivalence.html b/tests/wpt/web-platform-tests/css/css-transforms/perspective-transforms-equivalence.html new file mode 100644 index 00000000000..2f2ae21f87f --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-transforms/perspective-transforms-equivalence.html @@ -0,0 +1,52 @@ +<!doctype HTML> +<meta charset="utf8"> +<title>Perspective with transforms equivalencies.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="http://www.w3.org/TR/css-transforms-2/#perspective-property"> +<link rel="help" href="http://www.w3.org/TR/css-transforms-1/#transform-property"> +<link rel="match" href="perspective-transforms-equivalence-ref.html"> +<!-- +Perspective with different transforms can have small anti-aliasing +pixel differences, so the test should fuzzy patch to the ref. +--> +<meta name="fuzzy" content="maxDifference=10;totalPixels=10"> +<style> + +#container { + transform: translate(-200px, -200px); + width: 500px; + height: 500px; + perspective: 500px; +} + +#container > div { + width: 100%; + height: 100%; + transform-style: preserve-3d; + transform: translateZ(-250px) rotateZ(45deg); +} + +#container > div > div { + width: 100%; + height: 100%; + position: absolute; + background-color: rgba(3, 121, 255, 0.3); + box-sizing: border-box; + border: 3px solid black; +} + +/* The following four should be equivalent. */ +#one { transform: rotateY(90deg) translateZ(250px); } +#two { transform: rotateZ(90deg) rotateX(90deg) translateZ(250px); } +#three { transform: rotateY(-90deg) translateZ(-250px); } +#four { transform: rotateZ(-90deg) rotateX(90deg) translateZ(-250px); } +</style> + +<div id="container"> + <div> + <div id="one"></div> + <div id="two"></div> + <div id="three"></div> + <div id="four"></div> + </div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-typed-om/set-var-reference-crash.html b/tests/wpt/web-platform-tests/css/css-typed-om/set-var-reference-crash.html new file mode 100644 index 00000000000..c6bc3cc2a39 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-typed-om/set-var-reference-crash.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>Don't crash when setting a CSSVariableReferenceValue</title> +<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#cssvariablereferencevalue"> +<link rel="help" href="https://crbug.com/986710<"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + :root { --x: green; } +</style> +<div id="target"></div> +<script> + test(function(){ + let ref = new CSSVariableReferenceValue('--x') + let unparsed = new CSSUnparsedValue([' ', ref]); + target.attributeStyleMap.set('color', unparsed); + assert_equals('rgb(0, 128, 0)', target.computedStyleMap().get('color').toString()); + }, 'Do not crash when referencing a variable with CSSVariableReferenceValue'); +</script> diff --git a/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-001-ref.html b/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-001-ref.html new file mode 100644 index 00000000000..9c5acb315d7 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-001-ref.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test reference</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> +<style> +.v-rl { + writing-mode: vertical-rl; + width: 200px; +} +span { + -webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/ + text-combine-upright: all; + white-space: normal; +} +#test { color: blue; } +#ref { color: orange; } +</style> +<p>Test passes if the blue and orange lines of text are identical. + +<div class=v-rl> + <div id=test>あ<span>12</span>い<span>34</span>う<span>5 6</span>えお</div> + <div id=ref>あ<span>12</span>い<span>34</span>う<span>5 6</span>えお</div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-002-ref.html b/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-002-ref.html new file mode 100644 index 00000000000..38449911107 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-002-ref.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test Reference</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> +<style> +.v-rl { + writing-mode: vertical-rl; + width: 200px; +} +span { + -webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/ + text-combine-upright: all; + white-space: pre; +} +#test { color: blue; } +#ref { color: orange; } +</style> +<p>Test passes if the blue and orange lines of text are identical. + +<div class=v-rl> + <div id=test>あ<span> 12</span>い<span>34 </span>う<span>5 6</span>えお</div> + <div id=ref>あ<span> 12</span>い<span>34 </span>う<span>5 6</span>えお</div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-003-ref.html b/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-003-ref.html new file mode 100644 index 00000000000..449036ff545 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-writing-modes/reference/tcy-white-space-processing-003-ref.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test Reference</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> +<style> +.v-rl { + writing-mode: vertical-rl; + width: 200px; +} +span { + display: inline-block; + height: 1em; +} +#test { color: blue; } +#test2 { color: brown; } +#ref { color: orange; } +.v-rl > div { + display: inline-block; + border: solid; + margin: 0 5px; +} +</style> +<p>Test passes if the blue, orange, brown boxes are identical. + +<div class=v-rl> + <div id=test>あいう<span></span>えお<span></span></div> + <br> + <div id=test2>あいう<span></span>えお<span></span></div> + <br> + <div id=ref>あいう<span></span>えお<span></span></div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-001.html b/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-001.html new file mode 100644 index 00000000000..fd81fe91fa7 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-001.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Writing Modes Test: white-space:normal space processing in text-combine-horizontal</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> +<link rel="help" href="https://www.w3.org/TR/css-writing-modes-4/#text-combine-layout"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-rules"> +<link rel="match" href="reference/tcy-white-space-processing-001-ref.html"> +<meta name="assert" content="Spaces with white-space:normal in a text-combine horizontal is trimmed at the start and end, and collapsed in the middle."> +<style> +.v-rl { + writing-mode: vertical-rl; + width: 200px; +} +span { + -webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/ + text-combine-upright: all; + white-space: normal; +} +#test { color: blue; } +#ref { color: orange; } +</style> +<p>Test passes if the blue and orange lines of text are identical. + +<div class=v-rl> + <div id=test>あ<span> 12</span>い<span>34 </span>う<span>5 6</span>えお</div> + <div id=ref>あ<span>12</span>い<span>34</span>う<span>5 6</span>えお</div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-002.html b/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-002.html new file mode 100644 index 00000000000..58a8a610132 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-002.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Writing Modes Test: white-space:pre space processing in text-combine-horizontal</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> +<link rel="help" href="https://www.w3.org/TR/css-writing-modes-4/#text-combine-layout"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-rules"> +<link rel="match" href="reference/tcy-white-space-processing-002-ref.html"> +<meta name="assert" content="Spaces with white-space:pre in a text-combine-upright are preserved"> +<style> +.v-rl { + writing-mode: vertical-rl; + width: 200px; +} +span { + -webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/ + text-combine-upright: all; + white-space: pre; +} +#test { color: blue; } +#ref { color: orange; } +</style> +<p>Test passes if the blue and orange lines of text are identical. + +<div class=v-rl> + <div id=test>あ<span> 12</span>い<span>34 </span>う<span>5 6</span>えお</div> + <div id=ref>あ<span> 12</span>い<span>34 </span>う<span>5 6</span>えお</div> +</div> diff --git a/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-003.html b/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-003.html new file mode 100644 index 00000000000..50b0650f8c7 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-writing-modes/tcy-white-space-processing-003.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Writing Modes Test: white space only text-combine-horizontal</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> +<link rel="help" href="https://www.w3.org/TR/css-writing-modes-4/#text-combine-layout"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-rules"> +<link rel="match" href="reference/tcy-white-space-processing-003-ref.html"> +<meta name="assert" content="a text-combine-upright with only white-space is preserved as a 1em square, including at the end of the containing line, regardless of the value of the white-space property"> +<style> +.v-rl { + writing-mode: vertical-rl; + width: 200px; +} +#test span { + -webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/ + text-combine-upright: all; +} +#test2 span { + -webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/ + text-combine-upright: all; + white-space: pre; +} +#ref span { + display: inline-block; + height: 1em; +} +#test { color: blue; } +#test2 { color: brown; } +#ref { color: orange; } +.v-rl > div { + display: inline-block; + border: solid; + margin: 0 5px; +} +</style> +<p>Test passes if the blue, orange, brown boxes are identical. + +<div class=v-rl> + <div id=test>あいう<span> </span>えお<span> </span></div> + <br> + <div id=test2>あいう<span> </span>えお<span> </span></div> + <br> + <div id=ref>あいう<span></span>えお<span></span></div> +</div> diff --git a/tests/wpt/web-platform-tests/docs/writing-tests/general-guidelines.md b/tests/wpt/web-platform-tests/docs/writing-tests/general-guidelines.md index 02a4545fe40..63942b07c67 100644 --- a/tests/wpt/web-platform-tests/docs/writing-tests/general-guidelines.md +++ b/tests/wpt/web-platform-tests/docs/writing-tests/general-guidelines.md @@ -37,11 +37,10 @@ on [file names][file-name-flags]. #### Support Files -Various support files are available in in the `/common/` and `/media/` -directories (web-platform-tests) and `/support/` (in css/). Reusing -existing resources is encouraged where possible, as is adding -generally useful files to these common areas rather than to specific -test suites. +Various support files are available in in the directories named `/common/`, +`/media/`, and `/css/support/`. Reusing existing resources is encouraged where +possible, as is adding generally-useful files to these common areas rather than +to specific test suites. #### Tools @@ -61,9 +60,17 @@ subdirectory and put your script there. ### File Formats -Tests must be HTML or XML (inc. XHTML and SVG) files; some -testharness.js tests -are [auto-generated from JS files][server features]. +Tests are generally formatted as HTML (including XHTML) or XML (including SVG). +Some test types support other formats: + +- [testharness.js tests](testharness) may be expressed as JavaScript files + ([the WPT server automatically generates the HTML documents for these][server + features]) +- [WebDriver specification tests](wdspec) are expressed as Python files + +The best way to determine how to format a new test is to look at how similar +tests have been formatted. You can also ask for advice in [the project's IRC +room][IRC]. ### Character Encoding @@ -179,6 +186,7 @@ for CSS have some additional requirements for: [server features]: server-features [assumptions]: assumptions [ahem]: ahem +[IRC]: irc://irc.w3.org:6667/testing [lint-tool]: lint-tool [css-metadata]: css-metadata [css-user-styles]: css-user-styles diff --git a/tests/wpt/web-platform-tests/docs/writing-tests/rendering.md b/tests/wpt/web-platform-tests/docs/writing-tests/rendering.md index feb0a53648a..13cc669bfe1 100644 --- a/tests/wpt/web-platform-tests/docs/writing-tests/rendering.md +++ b/tests/wpt/web-platform-tests/docs/writing-tests/rendering.md @@ -5,10 +5,6 @@ these are especially using for [visual](visual) tests which need to be manually judged and following common patterns makes it easier to correctly tell if a given test passed or not. -## Make tests self-describing - -Tests should make it obvious when they pass and when they fail. It shouldn't be necessary to consult the specification to figure out whether a test has passed of failed. - ## Indicating success Success is largely indicated by the color green; typically in one of @@ -80,7 +76,7 @@ ways: * Silver or light gray is often used for irrelevant content, such as filler text. -Obviously, none of this can be taken as absolute rules, as testing of +None of these rules are absolute because testing color-related functionality will necessitate using some of these colors! diff --git a/tests/wpt/web-platform-tests/element-timing/element-only-when-fully-active.html b/tests/wpt/web-platform-tests/element-timing/element-only-when-fully-active.html new file mode 100644 index 00000000000..5608685a342 --- /dev/null +++ b/tests/wpt/web-platform-tests/element-timing/element-only-when-fully-active.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>ElementTiming: element is only exposed for fully active documents.</title> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe src="resources/iframe-stores-entry.html" id="ifr"></iframe> +<script> + let t = async_test('Only expose element attribute for fully active documents'); + window.triggerTest = t.step_func_done(elementEntry => { + assert_not_equals(elementEntry.element, null); + const iframe = document.getElementById('ifr'); + iframe.remove(); + assert_equals(elementEntry.element, null); + }); +</script> +</body> diff --git a/tests/wpt/web-platform-tests/element-timing/fixed-id-identifier.html b/tests/wpt/web-platform-tests/element-timing/fixed-id-identifier.html new file mode 100644 index 00000000000..00d6d4dd94c --- /dev/null +++ b/tests/wpt/web-platform-tests/element-timing/fixed-id-identifier.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Element Timing: entry does not change its id or identifier value</title> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/element-timing-helpers.js"></script> +<p elementtiming='my_identifier' id='my_id'>Text</p> +<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(entry.id, 'my_id'); + assert_equals(entry.identifier, 'my_identifier'); + const element = document.getElementById('my_id'); + element.id = 'other_id'; + element.setAttribute('elementtiming', 'other_identifier'); + assert_equals(entry.id, 'my_id'); + assert_equals(entry.identifier, 'my_identifier'); + }) + ); + observer.observe({type: 'element', buffered: true}); + }, 'PerformanceElementTiming id and identifier do not change when Element changes.'); +</script> +</body> diff --git a/tests/wpt/web-platform-tests/element-timing/idlharness.window.js b/tests/wpt/web-platform-tests/element-timing/idlharness.window.js new file mode 100644 index 00000000000..f0e5d06658e --- /dev/null +++ b/tests/wpt/web-platform-tests/element-timing/idlharness.window.js @@ -0,0 +1,16 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://wicg.github.io/element-timing/ + +'use strict'; + +idl_test( + ['element-timing'], + ['performance-timeline', 'dom'], + idl_array => { + idl_array.add_objects({ + // PerformanceElementTiming: [ TODO ] + }); + } +); diff --git a/tests/wpt/web-platform-tests/element-timing/resources/element-timing-helpers.js b/tests/wpt/web-platform-tests/element-timing/resources/element-timing-helpers.js index 8933732616c..6328ee7bb6f 100644 --- a/tests/wpt/web-platform-tests/element-timing/resources/element-timing-helpers.js +++ b/tests/wpt/web-platform-tests/element-timing/resources/element-timing-helpers.js @@ -4,13 +4,22 @@ function checkElementInternal(entry, expectedUrl, expectedIdentifier, expectedID assert_equals(entry.entryType, 'element'); assert_equals(entry.url, expectedUrl); assert_equals(entry.identifier, expectedIdentifier); - assert_equals(entry.startTime, 0); + if (beforeRender != 0) { + // In this case, renderTime is not 0. + assert_equals(entry.startTime, entry.renderTime); + } else { + // In this case, renderTime is 0, so compare to loadTime. + assert_equals(entry.startTime, entry.loadTime); + } assert_equals(entry.duration, 0); assert_equals(entry.id, expectedID); assert_greater_than_equal(entry.renderTime, beforeRender); assert_greater_than_equal(performance.now(), entry.renderTime); - if (expectedElement !== null) + if (expectedElement !== null) { assert_equals(entry.element, expectedElement); + assert_equals(entry.identifier, expectedElement.elementTiming); + assert_equals(entry.id, expectedElement.id); + } } // Checks that this is an ElementTiming entry with url |expectedUrl|. It also diff --git a/tests/wpt/web-platform-tests/element-timing/resources/iframe-stores-entry.html b/tests/wpt/web-platform-tests/element-timing/resources/iframe-stores-entry.html new file mode 100644 index 00000000000..2fa24769729 --- /dev/null +++ b/tests/wpt/web-platform-tests/element-timing/resources/iframe-stores-entry.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<body> +<p elementtiming='text'>Text</p> +<script> + const observer = new PerformanceObserver(entryList => { + window.parent.triggerTest(entryList.getEntries()[0]); + }); + observer.observe({type: 'element', buffered: true}); +</script> +</body> +</html> 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 6ca77212532..7745e4c68e2 100644 --- a/tests/wpt/web-platform-tests/html/dom/interfaces.https.html +++ b/tests/wpt/web-platform-tests/html/dom/interfaces.https.html @@ -38,8 +38,16 @@ const waitForLoad = new Promise(resolve => { addEventListener('load', resolve); idl_test( ['html'], - ['SVG', 'cssom', 'touch-events', 'uievents', 'dom', 'xhr'], + ['SVG', 'cssom', 'touch-events', 'uievents', 'dom', 'xhr', 'FileAPI'], async idlArray => { + self.documentWithHandlers = new Document(); + const handler = function(e) {}; + for (const callback of idlArray.members['GlobalEventHandlers'].members) { + if (callback.idlType && callback.idlType.idlType === 'EventHandler') { + documentWithHandlers[callback.name] = handler; + } + } + idlArray.add_objects({ NodeList: ['document.getElementsByName("name")'], HTMLAllCollection: ['document.all'], @@ -48,7 +56,7 @@ idl_test( HTMLOptionsCollection: ['document.createElement("select").options'], DOMStringMap: ['document.head.dataset'], Transferable: [], - Document: ['iframe.contentDocument', 'new Document()'], + Document: ['iframe.contentDocument', 'new Document()', 'documentWithHandlers'], XMLDocument: ['document.implementation.createDocument(null, "", null)'], HTMLElement: ['document.createElement("noscript")'], // more tests in html/semantics/interfaces.js HTMLUnknownElement: ['document.createElement("bgsound")'], // more tests in html/semantics/interfaces.js diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html index d42599661bf..e3e0778c97a 100644 --- a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html +++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html @@ -23,6 +23,7 @@ <div id="null"></div> <div name="divwithname"></div> <div id="-0"></div> +<div id="log"></div> <script> var anchors = document.querySelectorAll("a"); var divs = document.querySelectorAll("div"); @@ -34,7 +35,7 @@ test(function() { }, "document.all is an HTMLAllCollection"); test(function() { - assert_equals(document.all.length, 24); + assert_equals(document.all.length, 25); }, "length attribute"); // indexed property getter @@ -42,12 +43,12 @@ test(function() { test(function() { assert_equals(document.all[0], document.documentElement); assert_equals(document.all[-0], document.documentElement); - assert_equals(document.all[23], scripts[2]); + assert_equals(document.all[24], scripts[2]); }, "indexed property getter"); test(function() { assert_equals(document.all[-1], undefined); - assert_equals(document.all[24], undefined); + assert_equals(document.all[25], undefined); assert_equals(document.all[42], undefined); assert_equals(document.all[43], undefined); assert_equals(document.all[4294967294], undefined); @@ -86,8 +87,8 @@ test(function() { test(function() { assert_equals(document.all["0"], document.documentElement); - assert_equals(document.all["23"], document.scripts[2]); - assert_equals(document.all["24"], undefined); + assert_equals(document.all["24"], document.scripts[2]); + assert_equals(document.all["25"], undefined); assert_equals(document.all["42"], undefined); assert_equals(document.all["43"], undefined); }, "named property getter with \"array index property name\""); @@ -187,16 +188,16 @@ test(function() { test(function() { assert_equals(document.all("0"), document.documentElement); - assert_equals(document.all("23"), document.scripts[2]); - assert_equals(document.all("24"), null); + assert_equals(document.all("24"), document.scripts[2]); + assert_equals(document.all("25"), null); assert_equals(document.all("42"), null); assert_equals(document.all("43"), null); }, "legacy caller with \"array index property name\""); test(function() { assert_equals(document.all(0), document.documentElement); - assert_equals(document.all(23), document.scripts[2]); - assert_equals(document.all(24), null); + assert_equals(document.all(24), document.scripts[2]); + assert_equals(document.all(25), null); assert_equals(document.all(42), null); assert_equals(document.all(43), null); }, "legacy caller with \"array index property name\" as number"); @@ -267,16 +268,16 @@ test(function() { test(function() { assert_equals(document.all.item("0"), document.documentElement); - assert_equals(document.all.item("23"), document.scripts[2]); - assert_equals(document.all.item("24"), null); + assert_equals(document.all.item("24"), document.scripts[2]); + assert_equals(document.all.item("25"), null); assert_equals(document.all.item("42"), null); assert_equals(document.all.item("43"), null); }, "item method with \"array index property name\""); test(function() { assert_equals(document.all.item(0), document.documentElement); - assert_equals(document.all.item(23), document.scripts[2]); - assert_equals(document.all.item(24), null); + assert_equals(document.all.item(24), document.scripts[2]); + assert_equals(document.all.item(25), null); assert_equals(document.all.item(42), null); assert_equals(document.all.item(43), null); }, "item method with \"array index property name\" as number"); @@ -329,6 +330,5 @@ test(function() { } }, "collections are new live HTMLCollection instances"); </script> -<div id="log"></div> </body> </html> diff --git a/tests/wpt/web-platform-tests/infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini b/tests/wpt/web-platform-tests/infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini index e34c73f1ba9..ee1217860b8 100644 --- a/tests/wpt/web-platform-tests/infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini +++ b/tests/wpt/web-platform-tests/infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini @@ -4,4 +4,4 @@ [TestDriver actions: actions with key pressed] expected: - if os == "mac" and product == "chrome": FAIL + if os == "mac" and (product == "chrome" or product=="firefox"): FAIL diff --git a/tests/wpt/web-platform-tests/interfaces/FileAPI.idl b/tests/wpt/web-platform-tests/interfaces/FileAPI.idl index b5b40296429..0ae43bbe38c 100644 --- a/tests/wpt/web-platform-tests/interfaces/FileAPI.idl +++ b/tests/wpt/web-platform-tests/interfaces/FileAPI.idl @@ -4,7 +4,7 @@ // Source: File API (https://w3c.github.io/FileAPI/) [Constructor(optional sequence<BlobPart> blobParts, - optional BlobPropertyBag options), + optional BlobPropertyBag options = {}), Exposed=(Window,Worker), Serializable] interface Blob { @@ -33,7 +33,7 @@ typedef (BufferSource or Blob or USVString) BlobPart; [Constructor(sequence<BlobPart> fileBits, USVString fileName, - optional FilePropertyBag options), + optional FilePropertyBag options = {}), Exposed=(Window,Worker), Serializable] interface File : Blob { readonly attribute DOMString name; diff --git a/tests/wpt/web-platform-tests/interfaces/element-timing.idl b/tests/wpt/web-platform-tests/interfaces/element-timing.idl new file mode 100644 index 00000000000..dc3b886cfe5 --- /dev/null +++ b/tests/wpt/web-platform-tests/interfaces/element-timing.idl @@ -0,0 +1,20 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into reffy-reports +// (https://github.com/tidoust/reffy-reports) +// Source: Element Timing API (https://wicg.github.io/element-timing/) + +interface PerformanceElementTiming : PerformanceEntry { + readonly attribute DOMHighResTimeStamp renderTime; + readonly attribute DOMHighResTimeStamp loadTime; + readonly attribute DOMRectReadOnly intersectionRect; + readonly attribute DOMString identifier; + readonly attribute unsigned long naturalWidth; + readonly attribute unsigned long naturalHeight; + readonly attribute DOMString id; + readonly attribute Element? element; + readonly attribute DOMString url; +}; + +partial interface Element { + [CEReactions] attribute DOMString elementTiming; +}; diff --git a/tests/wpt/web-platform-tests/interfaces/input-events.idl b/tests/wpt/web-platform-tests/interfaces/input-events.idl index 0086128e562..c10aa32bed0 100644 --- a/tests/wpt/web-platform-tests/interfaces/input-events.idl +++ b/tests/wpt/web-platform-tests/interfaces/input-events.idl @@ -4,11 +4,11 @@ // Source: Input Events Level 1 (https://cdn.staticaly.com/gh/w3c/input-events/v1/index.html) partial interface InputEvent { - readonly attribute DataTransfer? dataTransfer; - sequence<StaticRange> getTargetRanges(); + readonly attribute DataTransfer? dataTransfer; + sequence<StaticRange> getTargetRanges(); }; partial dictionary InputEventInit { - DataTransfer? dataTransfer = null; - sequence<StaticRange> targetRanges = []; + DataTransfer? dataTransfer = null; + sequence<StaticRange> targetRanges = []; }; diff --git a/tests/wpt/web-platform-tests/interfaces/largest-contentful-paint.idl b/tests/wpt/web-platform-tests/interfaces/largest-contentful-paint.idl new file mode 100644 index 00000000000..f16a7ff812c --- /dev/null +++ b/tests/wpt/web-platform-tests/interfaces/largest-contentful-paint.idl @@ -0,0 +1,13 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into reffy-reports +// (https://github.com/tidoust/reffy-reports) +// Source: Largest Contentful Paint (https://wicg.github.io/largest-contentful-paint/) + +interface LargestContentfulPaint : PerformanceEntry { + readonly attribute DOMHighResTimeStamp renderTime; + readonly attribute DOMHighResTimeStamp loadTime; + readonly attribute unsigned long size; + readonly attribute DOMString id; + readonly attribute DOMString url; + readonly attribute Element? element; +}; diff --git a/tests/wpt/web-platform-tests/interfaces/performance-timeline.idl b/tests/wpt/web-platform-tests/interfaces/performance-timeline.idl index 8ded59d8a26..d9362ea2751 100644 --- a/tests/wpt/web-platform-tests/interfaces/performance-timeline.idl +++ b/tests/wpt/web-platform-tests/interfaces/performance-timeline.idl @@ -23,8 +23,8 @@ callback PerformanceObserverCallback = void (PerformanceObserverEntryList entrie PerformanceObserver observer); [Constructor(PerformanceObserverCallback callback), Exposed=(Window,Worker)] interface PerformanceObserver { - void observe(optional PerformanceObserverInit options); - void disconnect(); + void observe (optional PerformanceObserverInit options = {}); + void disconnect (); PerformanceEntryList takeRecords(); [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes; }; diff --git a/tests/wpt/web-platform-tests/interfaces/user-timing.idl b/tests/wpt/web-platform-tests/interfaces/user-timing.idl index 4130803ff9c..8b0f813ba8e 100644 --- a/tests/wpt/web-platform-tests/interfaces/user-timing.idl +++ b/tests/wpt/web-platform-tests/interfaces/user-timing.idl @@ -4,23 +4,23 @@ // Source: User Timing Level 3 (https://w3c.github.io/user-timing/) dictionary PerformanceMarkOptions { - any detail; - DOMHighResTimeStamp startTime; - }; + any detail; + DOMHighResTimeStamp startTime; +}; - dictionary PerformanceMeasureOptions { - any detail; - (DOMString or DOMHighResTimeStamp) start; - DOMHighResTimeStamp duration; - (DOMString or DOMHighResTimeStamp) end; - }; +dictionary PerformanceMeasureOptions { + any detail; + (DOMString or DOMHighResTimeStamp) start; + DOMHighResTimeStamp duration; + (DOMString or DOMHighResTimeStamp) end; +}; - partial interface Performance { - PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions = {}); - void clearMarks(optional DOMString markName); - PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions = {}, optional DOMString endMark); - void clearMeasures(optional DOMString measureName); - }; +partial interface Performance { + PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions = {}); + void clearMarks(optional DOMString markName); + PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions = {}, optional DOMString endMark); + void clearMeasures(optional DOMString measureName); +}; [Exposed=(Window,Worker), Constructor(DOMString markName, optional PerformanceMarkOptions markOptions)] diff --git a/tests/wpt/web-platform-tests/interfaces/web-share.idl b/tests/wpt/web-platform-tests/interfaces/web-share.idl index e275aac96fe..ae1f3f8580c 100644 --- a/tests/wpt/web-platform-tests/interfaces/web-share.idl +++ b/tests/wpt/web-platform-tests/interfaces/web-share.idl @@ -3,6 +3,10 @@ // (https://github.com/tidoust/reffy-reports) // Source: Web Share API - Level 1 (https://wicg.github.io/web-share/) +partial interface Navigator { + [SecureContext] Promise<void> share(optional ShareData data = {}); +}; + dictionary ShareData { USVString title; USVString text; diff --git a/tests/wpt/web-platform-tests/intersection-observer/rtl-clipped-root.html b/tests/wpt/web-platform-tests/intersection-observer/rtl-clipped-root.html new file mode 100644 index 00000000000..a30c6e38c5a --- /dev/null +++ b/tests/wpt/web-platform-tests/intersection-observer/rtl-clipped-root.html @@ -0,0 +1,66 @@ +<!DOCTYPE html> +<html dir="rtl"> +<head> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="./resources/intersection-observer-test-utils.js"></script> + + <style> + pre, #log { + position: absolute; + top: 120px; + left: 0; + } + #root { + width: 350px; + height: 100px; + border: 1px solid black; + display: flex; + flex-direction: row; + overflow-x: auto; + } + #target-start, #target-end { + width: 100px; + height: 100px; + flex-shrink: 0; + background-color: green; + text-align: center; + } + #target-end { + margin-inline-start: 500px; + } + </style> +</head> + +<div id="root"> + <div id="target-start">start</div> + <div id="target-end">end</div> +</div> + +<script> +runTestCycle(function() { + let io = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.classList.add("intersecting"); + } else { + entry.target.classList.remove("intersecting"); + } + }); + }, { root: document.getElementById("root") }); + document.querySelectorAll("#root > div").forEach(element => { + io.observe(element); + }); + runTestCycle(step0, "First rAF"); +}, "Explicit rtl root with overflow clipping"); + +function step0() { + assert_true( + document.getElementById("target-start").classList.contains("intersecting"), + "Target at scroll start is intersecting"); + assert_false( + document.getElementById("target-end").classList.contains("intersecting"), + "Target at scroll end is not intersecting"); +} +</script> diff --git a/tests/wpt/web-platform-tests/kv-storage/backingstore.https.html b/tests/wpt/web-platform-tests/kv-storage/backingstore.https.html index 44e634d85bb..c0f49d48f48 100644 --- a/tests/wpt/web-platform-tests/kv-storage/backingstore.https.html +++ b/tests/wpt/web-platform-tests/kv-storage/backingstore.https.html @@ -7,7 +7,7 @@ <script src="/resources/testharnessreport.js"></script> <script type="module"> -import { storage } from "std:kv-storage"; +import storage from "std:kv-storage"; test(() => { assert_equals(storage.backingStore, storage.backingStore); diff --git a/tests/wpt/web-platform-tests/kv-storage/helpers/kvs-tests.js b/tests/wpt/web-platform-tests/kv-storage/helpers/kvs-tests.js index 0cf4c2fd3d5..9fd9d205ae1 100644 --- a/tests/wpt/web-platform-tests/kv-storage/helpers/kvs-tests.js +++ b/tests/wpt/web-platform-tests/kv-storage/helpers/kvs-tests.js @@ -1,4 +1,4 @@ -import { StorageArea, storage as defaultArea } from "std:kv-storage"; +import defaultArea, { StorageArea } from "std:kv-storage"; import { assertAsyncIteratorEquals, assertAsyncIteratorCustomEquals } from "./equality-asserters.js"; // Used when we're manually creating the database, and so the IDB helpers also want to clean it up. diff --git a/tests/wpt/web-platform-tests/kv-storage/interface.https.html b/tests/wpt/web-platform-tests/kv-storage/interface.https.html index ab1930b25c3..a5eba425b6d 100644 --- a/tests/wpt/web-platform-tests/kv-storage/interface.https.html +++ b/tests/wpt/web-platform-tests/kv-storage/interface.https.html @@ -8,7 +8,7 @@ <script src="/resources/idlharness.js"></script> <script type="module"> -import { storage, StorageArea } from "std:kv-storage"; +import storage, { StorageArea } from "std:kv-storage"; // Web IDL/idlharness.js do not yet have support for the spec's IDL, which uses module {}, // async_iterator, and some new extended attributes. This IDL is a mutated version to work with the @@ -172,4 +172,4 @@ function frameLoadPromise(frame) { frame.onerror = () => reject(new Error(`${frame.src} failed to load`)); }); } -</script>
\ No newline at end of file +</script> diff --git a/tests/wpt/web-platform-tests/kv-storage/storage-smoke-test.https.html b/tests/wpt/web-platform-tests/kv-storage/storage-smoke-test.https.html index 31dac972d98..748b59bb2f2 100644 --- a/tests/wpt/web-platform-tests/kv-storage/storage-smoke-test.https.html +++ b/tests/wpt/web-platform-tests/kv-storage/storage-smoke-test.https.html @@ -8,7 +8,6 @@ <script type="module"> import { testVariousMethodsWithDefaultArea } from "./helpers/kvs-tests.js"; -import { storage } from "std:kv-storage"; testVariousMethodsWithDefaultArea( "Storage methods smoke test with string key and value", "key", "value", assert_equals diff --git a/tests/wpt/web-platform-tests/largest-contentful-paint/element-only-when-fully-active.html b/tests/wpt/web-platform-tests/largest-contentful-paint/element-only-when-fully-active.html new file mode 100644 index 00000000000..41bdc8f8b98 --- /dev/null +++ b/tests/wpt/web-platform-tests/largest-contentful-paint/element-only-when-fully-active.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Largest Contentful Paint: element is only exposed for fully active documents.</title> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe src="resources/iframe-stores-entry.html" id="ifr"></iframe> +<script> + let t = async_test('Only expose element attribute for fully active documents'); + window.triggerTest = t.step_func_done(entry => { + assert_not_equals(entry.element, null); + const iframe = document.getElementById('ifr'); + iframe.remove(); + assert_equals(entry.element, null); + }); +</script> +</body> diff --git a/tests/wpt/web-platform-tests/largest-contentful-paint/idlharness.html b/tests/wpt/web-platform-tests/largest-contentful-paint/idlharness.html new file mode 100644 index 00000000000..273fef80ce2 --- /dev/null +++ b/tests/wpt/web-platform-tests/largest-contentful-paint/idlharness.html @@ -0,0 +1,30 @@ +<!doctype html> +<title>Largest Contentful Paint IDL tests</title> +<link rel="help" href="https://wicg.github.io/largest-contentful-paint/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/WebIDLParser.js"></script> +<script src="/resources/idlharness.js"></script> +<script> +'use strict'; + +idl_test( + ['largest-contentful-paint'], + ['performance-timeline', 'dom'], + async (idl_array, t) => { + idl_array.add_objects({ + LargestContentfulPaint: ['lcp'] + }); + + window.lcp = await new Promise((resolve, reject) => { + const observer = new PerformanceObserver(entryList => { + resolve(entryList.getEntries()[0]); + }); + observer.observe({type: 'largest-contentful-paint', buffered: true}); + t.step_timeout(() => reject('Timed out waiting for LargestContentfulPaint entry'), 3000); + }); + } +); +</script> +<!-- a contentful element to observe --> +<img src=/images/green-100x50.png> 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 new file mode 100644 index 00000000000..abe753fc14a --- /dev/null +++ b/tests/wpt/web-platform-tests/largest-contentful-paint/observe-after-untrusted-scroll.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Largest Contentful Paint: observe image.</title> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + async_test(function (t) { + if (!window.LargestContentfulPaint) { + assert_unreached("LargestContentfulPaint is not implemented"); + } + const beforeRender = performance.now(); + const observer = new PerformanceObserver( + t.step_func_done(function(entryList) { + assert_equals(entryList.getEntries().length, 1); + const entry = entryList.getEntries()[0]; + 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, 0); + assert_equals(entry.duration, 0); + // blue.png is 133 x 106. + assert_equals(entry.size, 14098); + assert_equals(entry.id, 'image_id'); + // 25 is the length of "largest-contentful-paint/". + const index = window.location.href.lastIndexOf('/') - 25; + const pathname = window.location.href.substring(0, index) + '/images/blue.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('image_id')); + }) + ); + observer.observe({type: 'largest-contentful-paint', buffered: true}); + }, 'Same-origin image after a JS initiated scroll event is observable.'); + document.body.dispatchEvent(new Event('scroll')); + const image = new Image(); + image.id = 'image_id'; + image.src = '/images/blue.png'; + document.body.appendChild(image); +</script> + +</body> diff --git a/tests/wpt/web-platform-tests/largest-contentful-paint/resources/iframe-stores-entry.html b/tests/wpt/web-platform-tests/largest-contentful-paint/resources/iframe-stores-entry.html new file mode 100644 index 00000000000..cd600254805 --- /dev/null +++ b/tests/wpt/web-platform-tests/largest-contentful-paint/resources/iframe-stores-entry.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<body> +<p>Text</p> +<script> + const observer = new PerformanceObserver(entryList => { + window.parent.triggerTest(entryList.getEntries()[0]); + }); + observer.observe({type: 'largest-contentful-paint', buffered: true}); +</script> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-overall.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-overall.html index 5351ca51688..f668c55dbae 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-overall.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-overall.html @@ -62,5 +62,7 @@ </math> </p> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mspace");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-token-ref.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-token-ref.html index 95f182bc8c7..f1895b578ad 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-token-ref.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-token-ref.html @@ -6,15 +6,11 @@ </head> <body> - <!-- Test dir="rtl" on MathML token elements. The text contains RTL and - LTR characters, so the attribute is needed to specify the actual - direction. --> - - <p><math><mtext dir="rtl">חוק \left חסר או חוק \right מיותר</mtext></math></p> - <p><math><ms dir="rtl">חוק \left חסר או חוק \right מיותר</ms></math></p> - <p><math><mo dir="rtl">חוק \left חסר או חוק \right מיותר</mo></math></p> - <p><math><mi dir="rtl">חוק \left חסר או חוק \right מיותר</mi></math></p> - <p><math><mn dir="rtl">חוק \left חסר או חוק \right מיותר</mn></math></p> + <p><math><mtext style="direction: rtl;">חוק \left חסר או חוק \right מיותר</mtext></math></p> + <p><math><ms style="direction: rtl;">חוק \left חסר או חוק \right מיותר</ms></math></p> + <p><math><mo style="direction: rtl;">חוק \left חסר או חוק \right מיותר</mo></math></p> + <p><math><mi style="direction: rtl;">חוק \left חסר או חוק \right מיותר</mi></math></p> + <p><math><mn style="direction: rtl;">חוק \left חסר או חוק \right מיותר</mn></math></p> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-token.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-token.html index 1896f3fe394..25c8d6a1327 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-token.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/direction/direction-token.html @@ -21,5 +21,8 @@ <p><math><mi dir="rtl">חוק \left חסר או חוק \right מיותר</mi></math></p> <p><math><mn dir="rtl">חוק \left חסר או חוק \right מיותר</mn></math></p> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_dir");</script> + </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-1.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-1.html index 6be38d5439d..5ecb66ecf6a 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-1.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-1.html @@ -7,6 +7,7 @@ <meta name="assert" content="Verify fraction metrics for different sizes of numerator and denominator."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -33,6 +34,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 3; var mathAxis = getBox("axis").middle; // For stacks, nothing in the OpenType MATH specification seems to ensure @@ -51,6 +54,8 @@ }, "Fraction axis is aligned on the math axis"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + for (var i = 0; i < 10; i++) { assert_less_than(getBox("frac" + i + "num").bottom, getBox("frac" + i + "den").top, "numerator is above denominator"); assert_less_than(getBox("frac" + i + "den").top - getBox("frac" + i + "num").bottom, 5, "The gap between numerator and denominator is not too large"); @@ -58,12 +63,16 @@ }, "Vertical positions of numerator and denominator"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 3; for (var i = 0; i < 10; i++) assert_approx_equals(getBox("frac" + i + "num").center, getBox("frac" + i + "den").center, e, "numerator and denominator are horizontally centered"); }, "Horizontal alignments of numerator and denominator"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 5; for (var i = 0; i < 10; i++) { var frac = getBox("frac" + i); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-bar-001.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-bar-001.html index 887ff174cc4..e381ffe77c3 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-bar-001.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-bar-001.html @@ -51,5 +51,7 @@ </mfrac> </math> </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-color-002.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-color-002.html index 4b45c8e1cfb..ca4c41b46b1 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-color-002.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-color-002.html @@ -28,5 +28,7 @@ </mfrac> </math> </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically-2.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically-2.html index 2aa9675bb1f..f16a367129d 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically-2.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically-2.html @@ -37,6 +37,8 @@ </head> <body> <p>This test passes if it renders the same as an invalid fraction with 3 children.</p> - <math> + <math></math> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically-3.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically-3.html index c90119d8ef5..e11a357fd42 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically-3.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically-3.html @@ -30,5 +30,7 @@ <mn id="mn2">2</mn> </mfrac> </math> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically.html index 7a555f20ea3..b74338a8804 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-created-dynamically.html @@ -32,6 +32,8 @@ </head> <body> <p>This test passes if you see a fraction.</p> - <math> + <math></math> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-001.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-001.html index 4d6bda2c167..a8ab7bd81ab 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-001.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-001.html @@ -41,5 +41,7 @@ <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> </math> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-002.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-002.html index c3b3d69e59a..85c7c587010 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-002.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-002.html @@ -7,6 +7,7 @@ <meta name="assert" content="Verifies fraction with positive, negative, percent and named space linethickness values."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/mathml/support/feature-detection.js"></script> <style type="text/css"> @font-face { font-family: TestFont; @@ -37,19 +38,23 @@ var epsilon = 2; test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_approx_equals(LineThickness("positive"), 5.67 * 10, epsilon); }, "Positive"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); /* Negative values are treated as 0 */ assert_approx_equals(LineThickness("negative"), 0, epsilon); }, "Negative"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_approx_equals(LineThickness("percent"), defaultRuleThickness * 234 / 100, epsilon); }, "Percentage"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); /* Namedspace values are invalid in MathML Core. */ assert_approx_equals(LineThickness("namedspace"), defaultRuleThickness, epsilon); }, "Named space"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-004.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-004.html index d9689fcdc68..a8b36c19265 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-004.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-linethickness-004.html @@ -26,5 +26,7 @@ <mspace width="20px" height="10px" style="background: cyan"></mspace> </mfrac> </math> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-mrow-001.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-mrow-001.html index cb154c65edc..228d4ec3f0b 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-mrow-001.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-mrow-001.html @@ -22,5 +22,7 @@ </mrow> </mfrac> </math> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html index 59d663f6a4e..78c95c28755 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html @@ -52,5 +52,7 @@ </mfrac> </math> </p> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-1.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-1.html index 55404fa562c..b8bc405107b 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-1.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-1.html @@ -7,6 +7,7 @@ <meta name="assert" content="Element mfrac correctly uses the fraction parameters from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -68,6 +69,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 7000 * emToPx; var v2 = 1000 * emToPx; assert_approx_equals(getBox("ref0001").top - getBox("num0001").bottom, @@ -75,54 +78,72 @@ }, "AxisHeight"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 5000 * emToPx; assert_approx_equals(getBox("den0002").top - getBox("ref0002").bottom, v1, epsilon, "mfrac: denominator gap"); }, "DenominatorDisplayStyleGapMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 6000 * emToPx; assert_approx_equals(getBox("den0003").top - getBox("ref0003").bottom, v1, epsilon, "mfrac: denominator shift"); }, "DenominatorDisplayStyleShiftDown"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 4000 * emToPx; assert_approx_equals(getBox("den0004").top - getBox("ref0004").bottom, v1, epsilon, "mfrac: denominator gap"); }, "DenominatorGapMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 3000 * emToPx; assert_approx_equals(getBox("den0005").top - getBox("ref0005").bottom, v1, epsilon, "mfrac: denominator shift"); }, "DenominatorShiftDown"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 8000 * emToPx; assert_approx_equals(getBox("ref0006").top - getBox("num0006").bottom, v1, epsilon, "mfrac: numerator gap"); }, "NumeratorDisplayStyleGapMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 2000 * emToPx; assert_approx_equals(getBox("ref0007").top - getBox("num0007").bottom, v1, epsilon, "mfrac: numerator shift"); }, "NumeratorDisplayStyleShiftDown"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 9000 * emToPx; assert_approx_equals(getBox("ref0008").top - getBox("num0008").bottom, v1, epsilon, "mfrac: numerator gap"); }, "NumeratorGapMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 11000 * emToPx; assert_approx_equals(getBox("ref0009").top - getBox("num0009").bottom, v1, epsilon, "mfrac: numerator shift"); }, "NumeratorShiftDown"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 10000 * emToPx; assert_approx_equals(getBox("den0010").top - getBox("num0010").bottom, v1, epsilon, "mfrac: rule thickness"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-2.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-2.html index 63ab97760fc..ce2d299f281 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-2.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-2.html @@ -7,6 +7,7 @@ <meta name="assert" content="Element mfrac correctly uses the stack parameters from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -56,42 +57,56 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 7000 * emToPx; assert_approx_equals(getBox("ref0001").top - getBox("num0001").bottom, v, epsilon, "mfrac: axis height"); }, "AxisHeight"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 5000 * emToPx; assert_approx_equals(getBox("den0002").top - getBox("ref0002").bottom, v, epsilon, "mfrac: denominator shift"); }, "BottomDisplayStyleShiftDown"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 6000 * emToPx; assert_approx_equals(getBox("den0003").top - getBox("ref0003").bottom, v, epsilon, "mfrac: denominator shift"); }, "BottomShiftDown"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 4000 * emToPx; assert_approx_equals(getBox("den0004").top - getBox("num0004").bottom, v, epsilon, "mfrac: gap"); }, "DisplayStyleGapMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 8000 * emToPx; assert_approx_equals(getBox("den0005").top - getBox("num0005").bottom, v, epsilon, "mfrac: gap"); }, "GapMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 3000 * emToPx; assert_approx_equals(getBox("ref0006").top - getBox("num0006").bottom, v, epsilon, "mfrac: numerator shift"); }, "TopDisplayStyleShiftUp"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 9000 * emToPx; assert_approx_equals(getBox("ref0007").top - getBox("num0007").bottom, v, epsilon, "mfrac: numerator shift"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-001.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-001.html index f577682ad92..e87b357dd2a 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-001.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-001.html @@ -86,5 +86,7 @@ </math> </p> <div id="frame"></div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-002.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-002.html index 2c0a9a1a668..0b704dc801e 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-002.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-002.html @@ -86,5 +86,7 @@ </math> </p> <div id="frame"></div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-003.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-003.html index 826eecd55c4..9bd79836cc0 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-003.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-003.html @@ -86,5 +86,7 @@ </math> </p> <div id="frame"></div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-004.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-004.html index 359176228d7..43410cba608 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-004.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-004.html @@ -86,5 +86,7 @@ </math> </p> <div id="frame"></div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-005.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-005.html index 60295f7ddd2..da77012b96d 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-005.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-005.html @@ -86,5 +86,7 @@ </math> </p> <div id="frame"></div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-006.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-006.html index 7895052d4fd..25bf644ec61 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-006.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-gap-006.html @@ -86,5 +86,7 @@ </math> </p> <div id="frame"></div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-visibility-001.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-visibility-001.html index 65b95054db4..140603b47f5 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-visibility-001.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/fractions/frac-visibility-001.html @@ -18,5 +18,7 @@ </mfrac> </math> </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/inferred-mrow-baseline.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/inferred-mrow-baseline.html index 672d90de933..1541b2d6ce1 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/inferred-mrow-baseline.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/inferred-mrow-baseline.html @@ -12,6 +12,7 @@ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#enclose-expression-inside-notation-menclose"> <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#adjust-space-around-content-mpadded"> <meta name="assert" content="Baseline for mrow-like elements is correct."> +<script src="/mathml/support/feature-detection.js"></script> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script type="text/javascript"> @@ -23,6 +24,7 @@ var x = document.getElementById("above" + tag).getBoundingClientRect(); var y = document.getElementById("below" + tag).getBoundingClientRect(); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_equals(x.bottom, y.top); }, "baseline alignment inside " + tag); }); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/inferred-mrow-stretchy.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/inferred-mrow-stretchy.html index 75587d076c2..ee40561a634 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/inferred-mrow-stretchy.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/inferred-mrow-stretchy.html @@ -13,6 +13,7 @@ <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#adjust-space-around-content-mpadded"> <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-fence-separator-or-accent-mo"> <meta name="assert" content="Operators can stretch inside mrow-like elements."> +<script src="/mathml/support/feature-detection.js"></script> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <style> @@ -36,6 +37,7 @@ ["Mrow", "Sqrt", "Style", "Error", "Phantom", "Math", "Menclose", "Mpadded"].forEach((tag) => { var mo = document.getElementById("mo" + tag); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_greater_than_equal(mo.getBoundingClientRect().height, 100); }, "operator stretching inside " + tag); }); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/operators/embellished-operator-001.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/operators/embellished-operator-001.html new file mode 100644 index 00000000000..78c5069b90c --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/operators/embellished-operator-001.html @@ -0,0 +1,155 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Embellished operators</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#embellished-operators"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#definition-of-space-like-elements"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-of-mrow"> +<meta name="assert" content="Verify definition of embellished operators"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> +<style> + /* Default spacing of operator 'X' is 0.2777777777777778em so quite different + from the measured/specified 0em and 1em. */ + math, math * { + font: 25px/1 Ahem; + } + mn { + color: black; + } + .testedElement mo { + color: yellow !important; + } + .testedElement, .testedElement * { + color: blue !important; + background: blue !important; + } +</style> +<script> + function spaceBeforeElement(id) { + var element = document.getElementById(id); + var mnBefore = element.previousElementSibling; + return element.getBoundingClientRect().left - mnBefore.getBoundingClientRect().right; + } + + function spaceBeforeCoreOperator(id) { + var element = document.getElementById(id); + var coreMo = element.getElementsByTagName("mo")[0]; + return coreMo.getBoundingClientRect().left - element.getBoundingClientRect().left; + } + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + var epsilon = 1; + var emToPx = 25; + + ["mrow", "mstyle", "mphantom", "mpadded"].forEach(tag => { + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBeforeElement(`${tag}-op`), 2 * emToPx, epsilon); + assert_approx_equals(spaceBeforeCoreOperator(`${tag}-op`), 0, epsilon); + }, `${tag} (embellished operator)`); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBeforeElement(`${tag}-nonop`), 0, epsilon); + assert_approx_equals(spaceBeforeCoreOperator(`${tag}-nonop`), 2 * emToPx, epsilon); + }, `${tag} (not embellished operator)`); + }); + + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mn>X</mn> + <mrow id="mrow-op" class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mtext class="space-like">X</mtext> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow id="mrow-nonop" class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> <!-- "mn" is not space-like --> + </mrow> + <mn>X</mn> + </math> + </p> + <!-- mstyle is an embellished operator if its children consist + of one embellished operator and zero or more space-like elements. --> + <p> + <math> + <mn>X</mn> + <mstyle id="mstyle-op" class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + </mstyle> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mstyle id="mstyle-nonop" class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> <!-- "mn" is not space-like --> + </mstyle> + <mn>X</mn> + </math> + </p> + <!-- mphantom is an embellished operator if its children consist + of one embellished operator and zero or more space-like elements. --> + <p> + <math> + <mn>X</mn> + <mphantom id="mphantom-op" class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + </mphantom> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mphantom id="mphantom-nonop" class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> <!-- "mn" is not space-like --> + </mphantom> + <mn>X</mn> + </math> + </p> + <!-- mpadded is an embellished operator if its children consist + of one embellished operator and zero or more space-like elements. --> + <p> + <math> + <mn>X</mn> + <mpadded id="mpadded-op" class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + </mpadded> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mpadded id="mpadded-nonop" class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> <!-- "mn" is not space-like --> + </mpadded> + <mn>X</mn> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/operators/embellished-operator-002.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/operators/embellished-operator-002.html new file mode 100644 index 00000000000..da343dd0bc3 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/operators/embellished-operator-002.html @@ -0,0 +1,286 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Embellished operators</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#embellished-operators"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#definition-of-space-like-elements"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-of-mrow"> +<meta name="assert" content="Verify definition of embellished operators"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> +<style> + /* Default spacing of operator 'X' is 0.2777777777777778em so quite different + from the measured/specified 0em and 1em. */ + math, math * { + font: 25px/1 Ahem; + } + mn { + color: black; + } + mtext.space-like { + color: lightblue !important; + } + .testedElement mo { + color: yellow !important; + } + .testedElement, .testedElement * { + color: blue !important; + background: blue !important; + } +</style> +<script> + function spaceBeforeElement(element) { + var mnBefore = element.previousElementSibling; + return element.getBoundingClientRect().left - mnBefore.getBoundingClientRect().right; + } + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + var epsilon = 1; + var emToPx = 25; + + ["msub", "msup", "msubsup", "munder", "mover", "munderover", + "mmultiscripts", "mfrac", "maction", "semantics"].forEach(tag => { + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + var element = document.getElementsByTagName(tag)[0]; + assert_approx_equals(spaceBeforeElement(element), 2 * emToPx, epsilon); + }, `${tag} (embellished operator)`); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + var element = document.getElementsByTagName(tag)[1]; + assert_approx_equals(spaceBeforeElement(element), 0, epsilon); + }, `${tag} (not embellished operator)`); + }); + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <!-- <msub>, <msup>, <msubsup>, <munder>, <mover>, <munderover>, + <mmultiscripts>, <mfrac>, <semantics> or <maction> are embellished + operators if their first child exists and is an embellished operator --> + <p> + <math> + <mn>X</mn> + <msub class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + </msub> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <msup class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + </msup> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <msubsup class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + <mn>X</mn> + </msubsup> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <munder class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + </munder> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mover class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + </mover> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <munderover class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + </munderover> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mmultiscripts class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + <mn>X</mn> + <mn>X</mn> + <mn>X</mn> + </mmultiscripts> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mfrac class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + </mfrac> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <maction class="testedElement" actiontype="statusline"> + <mo lspace="2em" rspace="0em">X</mo> + <mn>STATUS MESSAGE</mn> + </maction> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <semantics class="testedElement"> + <mo lspace="2em" rspace="0em">X</mo> + <annotation>TEXT ANNOTATION</annotation> + <mn>X</mn> + </semantics> + <mn>X</mn> + </math> + </p> + <!-- <msub>, <msup>, <msubsup>, <munder>, <mover>, <munderover>, + <mmultiscripts>, <mfrac>, <semantics> or <maction> are not embellished + operators if their first child is not an embellished operator --> + <p> + <math> + <mn>X</mn> + <msub class="testedElement"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + </msub> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <msup class="testedElement"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + </msup> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <msubsup class="testedElement"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + </msubsup> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <munder class="testedElement"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + </munder> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mover class="testedElement"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + </mover> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <munderover class="testedElement"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + </munderover> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mmultiscripts class="testedElement"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + <mn>X</mn> + <mn>X</mn> + <mn>X</mn> + </mmultiscripts> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mfrac class="testedElement"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + </mfrac> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <maction class="testedElement" actiontype="statusline"> + <mn>X</mn> + <mo lspace="2em" rspace="0em">STATUS MESSAGE</mo> + </maction> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <semantics class="testedElement"> + <mrow> + <mn>X</mn> + <mo lspace="2em" rspace="0em">X</mo> + </mrow> + <annotation>TEXT ANNOTATION</annotation> + </semantics> + <mn>X</mn> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/radicals/root-parameters-1.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/radicals/root-parameters-1.html index 5ad0b7315e0..d09d117b8ad 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/radicals/root-parameters-1.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/radicals/root-parameters-1.html @@ -7,6 +7,7 @@ <meta name="assert" content="Elements msqrt and mroot correctly use the radical parameters from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -56,6 +57,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 25; var v2 = 1000 * emToPx; var radicalHeight = getBox("base001").height + v2; @@ -65,6 +68,8 @@ }, "RadicalDegreeBottomRaisePercent"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 7000 * emToPx; var v2 = 1000 * emToPx; assert_approx_equals(getBox("base0021").top - getBox("radical0021").top, @@ -76,6 +81,8 @@ }, "RadicalDisplayStyleVerticalGap"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 3000 * emToPx; var v2 = 1000 * emToPx; assert_approx_equals(getBox("base0031").top - getBox("radical0031").top, @@ -86,7 +93,9 @@ "mroot: vertical gap"); }, "RadicalExtraAscender"); - test(function() { + test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + // Note: the size variants of U+221A in this font have width 1000. var v1 = 5000 * emToPx; var radicalSymbolWidth = 1000 * emToPx; @@ -97,6 +106,8 @@ }, "RadicalKernAfterDegree"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 4000 * emToPx; assert_approx_equals(getBox("index005").left - getBox("radical005").left, v1, epsilon, @@ -104,6 +115,8 @@ }, "RadicalKernBeforeDegree"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 8000 * emToPx; assert_approx_equals(getBox("base0061").top - getBox("radical0061").top, v, epsilon, @@ -114,6 +127,8 @@ }, "RadicalRuleThickness"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 6000 * emToPx; var v2 = 1000 * emToPx; assert_approx_equals(getBox("base0071").top - getBox("radical0071").top, diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-1.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-1.html index 01a6b0e1ed1..e5321d6c4a3 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-1.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-1.html @@ -7,6 +7,7 @@ <meta name="assert" content="Basic metrics for elements msub, msup and msubsup."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -28,6 +29,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; assert_less_than_equal(getBox("msubBase").right, getBox("msubSub").left, e, "msub: subscript is after base"); assert_less_than_equal(getBox("msupBase").right, getBox("msupSup").left, e, "msup: superscript is after base"); @@ -43,6 +46,8 @@ }, "Respective horizontal positions"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; assert_approx_equals(getBox("msubBase").middle, getBox("baseline").bottom, e, "msub: base is placed on the baseline"); assert_approx_equals(getBox("msupBase").middle, getBox("baseline").bottom, e, "msup: base is placed on the baseline"); @@ -50,6 +55,8 @@ }, "Alignment of the base on the baseline"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 3; assert_approx_equals(getBox("msubSub").middle, getBox("msubBase").bottom, e, "msub: script is placed at the bottom of the base"); assert_approx_equals(getBox("msupSup").middle, getBox("msupBase").top, e, "msup: script is placed at the top of the base"); @@ -58,6 +65,8 @@ }, "Vertical position of scripts"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 3; assert_approx_equals(getBox("msub").width, getBox("msubSub").right - getBox("msubBase").left, e, "msub: width is determined by the left/right sides of base/script (+ some space after script)"); assert_approx_equals(getBox("msup").width, getBox("msupSup").right - getBox("msupBase").left, e, "msup: width is determined by the left/right sides of base/script (+ some space after script)"); @@ -65,6 +74,8 @@ }, "Width of scripted elements"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; assert_greater_than_equal(getBox("msub").height, getBox("msubBase").height, e, "msub: height is at least the one of the base"); assert_greater_than_equal(getBox("msup").height, getBox("msupBase").height, e, "msup: height is at least the one of the base"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-2.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-2.html index 2fd6963b6a7..1a5b80d3439 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-2.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-2.html @@ -7,6 +7,7 @@ <meta name="assert" content="Basic metrics for the mmultiscript element."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -28,6 +29,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; assert_less_than_equal(getBox("msubBase").right, getBox("msubSub").left, e, "subscript is after base"); assert_less_than_equal(getBox("msupBase").right, getBox("msupSup").left, e, "superscript is after base"); @@ -54,6 +57,8 @@ }, "Respective horizontal positions"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; assert_approx_equals(getBox("msubBase").middle, getBox("baseline").bottom, e, "base is placed on the baseline"); assert_approx_equals(getBox("msupBase").middle, getBox("baseline").bottom, e, "base is placed on the baseline"); @@ -64,6 +69,8 @@ }, "Alignment of the base on the baseline"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 3; assert_approx_equals(getBox("msubSub").middle, getBox("msubBase").bottom, e, "script is placed at the bottom of the base"); assert_approx_equals(getBox("msupSup").middle, getBox("msupBase").top, e, "script is placed at the top of the base"); @@ -77,6 +84,8 @@ }, "Vertical position of scripts"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 3; assert_approx_equals(getBox("msub").width, getBox("msubSub").right - getBox("msubBase").left, e, "width is determined by the left/right sides of base/script (+ some space after script)"); assert_approx_equals(getBox("msup").width, getBox("msupSup").right - getBox("msupBase").left, e, "width is determined by the left/right sides of base/script (+ some space after script)"); @@ -88,6 +97,8 @@ }, "Width of scripted elements"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; assert_greater_than_equal(getBox("msub").height, getBox("msubBase").height, e, "height is at least the one of the base"); assert_greater_than_equal(getBox("msup").height, getBox("msupBase").height, e, "height is at least the one of the base"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-3.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-3.html index 60df24a7990..5494bb0c919 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-3.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-3.html @@ -7,6 +7,7 @@ <meta name="assert" content="Basic metrics for the mmultiscript element with many scripts."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -28,12 +29,16 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; for (var i = 0; i < 5; i++) assert_approx_equals(getBox("multi" + i + "base").middle, getBox("baseline").bottom, e, "base " + i + "is placed on the baseline"); }, "Alignment of the base on the baseline"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 5; assert_approx_equals(getBox("multi0").width, 30, e, "width of multi0"); assert_approx_equals(getBox("multi0").height, 30, e, "height of multi0"); @@ -49,6 +54,8 @@ }, "Dimensions of the scripted elements"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 3; for (var i = 2; i <= 4; i++) { var base = getBox("multi" + i + "base"); @@ -66,6 +73,8 @@ }, "Vertical positions of scripts"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; for (var i = 2; i <= 4; i++) { var base = getBox("multi" + i + "base"); @@ -81,6 +90,8 @@ }, "Horizontal alignment of scripts"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + for (var i = 2; i <= 4; i++) { var base = getBox("multi" + i + "base"); var firstPostScript = getBox("multi" + i + "postsub1"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-4.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-4.html index 6886766097c..00bd45413c8 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-4.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-4.html @@ -7,6 +7,7 @@ <meta name="assert" content="Verify metrics of scripted elements for bases of different heights."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -30,6 +31,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; sizeArray.forEach(function(size) { assert_approx_equals(getBox("msub" + size + "base").middle, getBox("baseline").bottom, e, "msub base " + size + "is placed on the baseline"); @@ -40,6 +43,8 @@ }, "Alignment on the baseline for bases of different heights"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 5; sizeArray.forEach(function(size) { assert_approx_equals(getBox("msub" + size + "sub").middle, getBox("msub" + size + "base").bottom, e, "msub script " + size + "is placed at the top of of the base"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-5.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-5.html index 2cc4e6d9554..566b0133ec6 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-5.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-5.html @@ -7,6 +7,7 @@ <meta name="assert" content="Verify metrics of scripted elements with tall scripts."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -30,6 +31,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; assert_approx_equals(getBox("msubbase").middle, getBox("baseline").bottom, e, "msub base is placed on the baseline"); assert_approx_equals(getBox("msupbase").middle, getBox("baseline").bottom, e, "msup base is placed on the baseline"); @@ -38,6 +41,8 @@ }, "Alignment on the baseline with different and large script heights"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + assert_greater_than(getBox("msubsub").top, getBox("msubbase").top, "msub: subscript is below the top of the base"); assert_less_than(getBox("msupsup").bottom, getBox("msupbase").bottom, "msup: supscript is above the bottom of the base"); assert_greater_than(getBox("msubsupsub").top, getBox("msubsupbase").top, "msubsup: subscript is below the top of the base"); @@ -49,6 +54,8 @@ }, "Tall subscripts/superscripts are not placed too high/low"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + assert_greater_than(getBox("msubsupsub").top, getBox("msubsupsup").bottom, "msubsup: subscript is below the superscript"); assert_greater_than(getBox("multipresub").top, getBox("multipresup").bottom, "mmultiscripts: presubscript is below the presuperscript"); assert_greater_than(getBox("multipostsub").top, getBox("multipostsup").bottom, "mmultiscripts: postsubscript is below the postsuperscript"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-parameters-1.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-parameters-1.html index 7503ad166af..a5f21ec5458 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-parameters-1.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-parameters-1.html @@ -7,6 +7,7 @@ <meta name="assert" content="Elements msub, msup, subsup and msubsup correctly use the subscript and superscript parameters from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -68,6 +69,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 3000 * emToPx; assert_approx_equals(getBox("ref001").left - getBox("sub001").right, v, epsilon, "msub: Space after subscript"); assert_approx_equals(getBox("ref002").left - getBox("sup002").right, v, epsilon, "msup: Space after superscript"); @@ -78,6 +81,8 @@ }, "SpaceAfterScript"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 7000 * emToPx; assert_approx_equals(getBox("ref101").bottom - getBox("sup102").bottom, v, epsilon, "msup: Superscript shift"); assert_approx_equals(getBox("ref101").bottom - getBox("sup103").bottom, v, epsilon, "msubsup: Superscript shift"); @@ -87,6 +92,8 @@ }, "SuperscriptShiftUp"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 5000 * emToPx; assert_approx_equals(getBox("ref201").bottom - getBox("sup202").bottom, v, epsilon, "msup: Superscript shift"); assert_approx_equals(getBox("ref201").bottom - getBox("sup203").bottom, v, epsilon, "msubsup: Superscript shift"); @@ -96,6 +103,8 @@ }, "SuperscriptShiftUpCramped"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 6000 * emToPx; assert_approx_equals(getBox("sub301").bottom - getBox("ref300").bottom, v, epsilon, "msup: Subscript shift"); assert_approx_equals(getBox("sub302").bottom - getBox("ref300").bottom, v, epsilon, "msubsup: Subscript shift"); @@ -104,12 +113,16 @@ }, "SubscriptShiftDown"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 11000 * emToPx; assert_approx_equals(getBox("sub4011").top - getBox("sup4012").bottom, v, epsilon, "msubsup: SubSuperscript gap"); assert_approx_equals(getBox("sub4021").top - getBox("sup4022").bottom, v, epsilon, "mmultiscripts: SubSuperscript gap"); }, "SubSuperscriptGapMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 11000 * emToPx; var v2 = 3000 * emToPx; assert_approx_equals(getBox("sub501").top - getBox("sup501").bottom, v1, epsilon, "msubsup: SubSuperscript gap"); @@ -119,21 +132,29 @@ }, "SuperscriptBottomMaxWithSubscript"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 4000 * emToPx; assert_approx_equals(getBox("ref600").bottom - getBox("sub601").top, v, epsilon, "msub: Subscript top"); }, "SubscriptTopMax"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 8000 * emToPx; assert_approx_equals(getBox("ref700").bottom - getBox("sub701").bottom, v, epsilon, "msub: Superscript bottom"); }, "SuperscriptBottomMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 9000 * emToPx; assert_approx_equals(getBox("sub801").bottom - getBox("base801").bottom, v, epsilon, "msub: Superscript drop"); }, "SubscriptBaselineDrop"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 10000 * emToPx; assert_approx_equals(getBox("sup901").bottom - getBox("base901").top, v, epsilon, "msup: Superscript drop"); }, "SuperscriptBaselineDrop"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-parameters-2.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-parameters-2.html index 62aa7a9dc3b..0abf01838c8 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-parameters-2.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/subsup-parameters-2.html @@ -7,6 +7,7 @@ <meta name="assert" content="Elements msub, msup, subsup and msubsup correctly use the italic correction from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -42,6 +43,8 @@ var epsilon = 1; function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 0; assert_approx_equals(getBox("base001").right - getBox("sub001").left, v, epsilon, "msub"); assert_approx_equals(getBox("sup002").left, getBox("base002").right, epsilon, "msup"); @@ -50,6 +53,8 @@ assert_approx_equals(getBox("sup005").left - getBox("sub005").left, 0, epsilon, "mmultiscripts prescripts"); }, "Null Italic Correction"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var emToPx = 10 / 1000; // font-size: 10px, font.em = 1000 var v = 3000 * emToPx; assert_approx_equals(getBox("base011").right - getBox("sub011").left, v, epsilon, "msub"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-1.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-1.html index b17835528a0..5b718707de9 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-1.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-1.html @@ -7,6 +7,7 @@ <meta name="assert" content="Elements munder, mover, munderover correctly ."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace, mo { font-size: 10px; @@ -29,6 +30,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; for (var i = 0; i <= 3; i++) { assert_approx_equals(getBox("under" + i + "base").middle, getBox("baseline").bottom, e, "munder " + i + ": base is placed on the baseline"); @@ -40,6 +43,8 @@ }, "Alignment of the base on the baseline"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; for (var i = 0; i <= 3; i++) { assert_approx_equals(getBox("under" + i + "under").center, getBox("under" + i + "base").center, e, "munder " + i + ": base and script are horizontally centered"); @@ -52,6 +57,8 @@ }, "Horizontal alignments of base and scripts"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + for (var i = 0; i <= 3; i++) { assert_greater_than_equal(getBox("under" + i + "under").top, getBox("under" + i + "base").bottom, "munder " + i + ": script is under base"); assert_less_than_equal(getBox("over" + i + "over").bottom, getBox("over" + i + "base").top, "mover " + i + ": script is over base"); @@ -63,6 +70,8 @@ }, "Relative vertical positions of base and scripts"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 1; for (var i = 0; i <= 3; i++) { assert_approx_equals(getBox("under" + i).width, Math.max(getBox("under" + i + "base").width, getBox("under" + i + "under").width), e, "munder " + i + ": width is determined by the maximum of width of base and script"); @@ -74,6 +83,8 @@ }, "Width of scripted elements"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var e = 3.2; for (var i = 0; i <= 3; i++) { assert_approx_equals(getBox("under" + i).height, getBox("under" + i + "base").height + getBox("under" + i + "under").height + e, e, "munder " + i + ": height is determined by the sum of heights of base and script plus some spacing."); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-1.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-1.html index d8a564a1159..26a1b3964cc 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-1.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-1.html @@ -7,6 +7,7 @@ <meta name="assert" content="Elements munder, mover, munderover correctly use the limit parameters from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace, mo { font-size: 10px; @@ -44,6 +45,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 3000 * emToPx; assert_approx_equals(getBox("under00011").top - getBox("ref0001").bottom, v, epsilon, "munder: under shift"); @@ -52,6 +55,8 @@ }, "LowerLimitBaselineDropMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 11000 * emToPx; assert_approx_equals(getBox("under00021").top - getBox("ref0002").bottom, v, epsilon, "munder: under gap"); @@ -60,6 +65,8 @@ }, "LowerLimitGapMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 5000 * emToPx; assert_approx_equals(getBox("ref0003").top - getBox("over00031").bottom, v, epsilon, "mover: over shift"); @@ -68,6 +75,8 @@ }, "UpperLimitBaselineRiseMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 7000 * emToPx; assert_approx_equals(getBox("ref0004").top - getBox("over00041").bottom, v, epsilon, "mover: over shift"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-2.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-2.html index c10f77ee2c8..aed22235b8c 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-2.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-2.html @@ -7,6 +7,7 @@ <meta name="assert" content="Elements munder, mover, munderover correctly use the stretch stack parameters from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace, mo { font-size: 10px; @@ -44,6 +45,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 3000 * emToPx; assert_approx_equals(getBox("under00011").top - getBox("ref0001").bottom, v, epsilon, "munder: under shift"); @@ -52,6 +55,8 @@ }, "StretchStackBottomShiftDown"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 11000 * emToPx; assert_approx_equals(getBox("under00021").top - getBox("ref0002").bottom, v, epsilon, "munder: under gap"); @@ -60,6 +65,8 @@ }, "StretchStackGapBelowMin"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 5000 * emToPx; assert_approx_equals(getBox("ref0003").top - getBox("over00031").bottom, v, epsilon, "mover: over shift"); @@ -68,6 +75,8 @@ }, "StretchStackTopShiftUp"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 7000 * emToPx; assert_approx_equals(getBox("ref0004").top - getBox("over00041").bottom, v, epsilon, "mover: over shift"); diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-3.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-3.html index 86562fd374b..6a1e51cdc45 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-3.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-3.html @@ -7,6 +7,7 @@ <meta name="assert" content="Elements munder, mover, munderover correctly use underbar/overbar and AccentBaseHeight parameters from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace, mo { font-size: 10px; @@ -47,6 +48,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + for (var i = 1; i <= 4; i++) { for (var j = 1; j <= 6; j++) { var baseId = ("base00" + i) + j; @@ -59,6 +62,8 @@ }, "Baseline alignment"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + for (var i = 1; i <= 4; i++) { for (var j = 1; j <= 6; j++) { var baseId = ("base00" + i) + j; @@ -72,6 +77,8 @@ }, "Heights of bases"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 5000 * emToPx; assert_approx_equals(getBox("ref001").bottom - getBox("over0014").bottom, shortBaseHeight, epsilon, @@ -96,6 +103,8 @@ }, "AccentBaseHeight, UnderbarExtraDescender"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 7000 * emToPx; assert_approx_equals(getBox("ref002").bottom - getBox("over0024").bottom, shortBaseHeight, epsilon, @@ -118,6 +127,8 @@ }, "AccentBaseHeight, UnderbarVerticalGap"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 3000 * emToPx; assert_approx_equals(getBox("ref003").bottom - getBox("over0031").bottom, shortBaseHeight, epsilon, @@ -154,6 +165,8 @@ }, "AccentBaseHeight, OverbarExtraAscender"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + v = 11000 * emToPx; assert_approx_equals(getBox("ref004").bottom - getBox("over0041").bottom, shortBaseHeight + v, epsilon, diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-4.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-4.html index f7fb389b59f..e569c15a699 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-4.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/scripts/underover-parameters-4.html @@ -7,6 +7,7 @@ <meta name="assert" content="Elements munder, mover, munderover correctly use underbar/overbar and AccentBaseHeight parameters from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace, mo { font-size: 10px; @@ -47,6 +48,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + for (var i = 1; i <= 4; i++) { for (var j = 1; j <= 6; j++) { var baseId = ("base00" + i) + j; @@ -59,6 +62,8 @@ }, "Baseline alignment"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + for (var i = 1; i <= 4; i++) { for (var j = 1; j <= 6; j++) { var baseId = ("base00" + i) + j; @@ -72,6 +77,8 @@ }, "Heights of bases"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 5000 * emToPx; assert_approx_equals(getBox("ref001").bottom - getBox("over0014").bottom, shortBaseHeight, epsilon, @@ -96,6 +103,8 @@ }, "AccentBaseHeight, UnderbarExtraDescender"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 7000 * emToPx; assert_approx_equals(getBox("ref002").bottom - getBox("over0024").bottom, shortBaseHeight, epsilon, @@ -118,6 +127,8 @@ }, "AccentBaseHeight, UnderbarVerticalGap"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v = 3000 * emToPx; assert_approx_equals(getBox("ref003").bottom - getBox("over0031").bottom, shortBaseHeight, epsilon, @@ -154,6 +165,8 @@ }, "AccentBaseHeight, OverbarExtraAscender"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + v = 11000 * emToPx; assert_approx_equals(getBox("ref004").bottom - getBox("over0041").bottom, shortBaseHeight + v, epsilon, diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-001.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-001.html new file mode 100644 index 00000000000..61375bcd8e3 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-001.html @@ -0,0 +1,257 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Space-like elements</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#definition-of-space-like-elements"> +<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/#layout-of-mrow"> +<meta name="assert" content="Verify definition of space-like elements"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> +<style> + /* Default spacing of operator 'X' is 0.2777777777777778em so quite different + from the measured/specified 0em and 1em. */ + math, math * { + font: 25px/1 Ahem; + } + mn { + color: black; + } + mo { + color: yellow; + } + .testedElement, .testedElement * { + color: blue !important; + background: blue !important; + } +</style> +<script> + function spaceBefore(id) { + var element = document.getElementById(id); + var mnBeforeParent = element.parentNode.previousElementSibling; + return element.getBoundingClientRect().left - mnBeforeParent.getBoundingClientRect().right; + } + + function spaceAfter(id) { + var element = document.getElementById(id); + var mnAfterParent = element.parentNode.nextElementSibling; + return mnAfterParent.getBoundingClientRect().left - element.getBoundingClientRect().right; + } + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + var epsilon = 1; + var emToPx = 25; + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mtext"), emToPx, epsilon); + assert_approx_equals(spaceAfter("mtext"), emToPx, epsilon); + }, "mtext is space-like"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mspace"), emToPx, epsilon); + assert_approx_equals(spaceAfter("mspace"), emToPx, epsilon); + }, "mspace is space-like"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mrow1"), emToPx, epsilon); + assert_approx_equals(spaceAfter("mrow1"), emToPx, epsilon); + }, "space-like mrow"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mrow2"), 0, epsilon); + assert_approx_equals(spaceAfter("mrow2"), 2 * emToPx, epsilon); + }, "non-space-like mrow"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mstyle1"), emToPx, epsilon); + assert_approx_equals(spaceAfter("mstyle1"), emToPx, epsilon); + }, "space-like mstyle"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mstyle2"), 0, epsilon); + assert_approx_equals(spaceAfter("mstyle2"), 2 * emToPx, epsilon); + }, "non-space-like mstyle"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mphantom1"), emToPx, epsilon); + assert_approx_equals(spaceAfter("mphantom1"), emToPx, epsilon); + }, "space-like mphantom"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mphantom2"), 0, epsilon); + assert_approx_equals(spaceAfter("mphantom2"), 2 * emToPx, epsilon); + }, "non-space-like mphantom"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mpadded1"), emToPx, epsilon); + assert_approx_equals(spaceAfter("mpadded1"), emToPx, epsilon); + }, "space-like mpadded"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("mpadded2"), 0, epsilon); + assert_approx_equals(spaceAfter("mpadded2"), 2 * emToPx, epsilon); + }, "non-space-like mpadded"); + + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mtext is space-like. --> + <mtext class="testedElement" id="mtext">X</mtext> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mspace is space-like. --> + <mspace class="testedElement" id="mspace" width="25px" height="10px"></mspace> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mrow is space-like when it contains only space-like elements. --> + <mrow id="mrow1" class="testedElement"> + <mtext>X</mtext> + <mspace width="25px" height="10px"></mspace> + </mrow> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mrow is not space-like when it contains a non space-like element + such as "mn". --> + <mrow id="mrow2" class="testedElement"> + <mn>X</mn> + <mspace width="25px" height="10px"></mspace> + </mrow> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mstyle is space-like when it contains only space-like elements. --> + <mstyle id="mstyle1" class="testedElement"> + <mtext>X</mtext> + <mspace width="25px" height="10px"></mspace> + </mstyle> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mstyle is not space-like when it contains a non space-like element + such as "mn". --> + <mstyle id="mstyle2" class="testedElement"> + <mn>X</mn> + <mspace width="25px" height="10px"></mspace> + </mstyle> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mphantom is space-like when it contains only space-like elements. + --> + <mphantom id="mphantom1" class="testedElement"> + <mtext>X</mtext> + <mspace width="25px" height="10px"></mspace> + </mphantom> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mphantom is not space-like when it contains a non space-like + element such as "mn". --> + <mphantom id="mphantom2" class="testedElement"> + <mn>X</mn> + <mspace width="25px" height="10px"></mspace> + </mphantom> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mpadded is space-like when it contains only space-like elements. --> + <mpadded id="mpadded1" class="testedElement"> + <mtext>X</mtext> + <mspace width="25px" height="10px"></mspace> + </mpadded> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- mpadded is not space-like when it contains a non space-like element + such as "mn". --> + <mpadded id="mpadded2" class="testedElement"> + <mn>X</mn> + <mspace width="25px" height="10px"></mspace> + </mpadded> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-002.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-002.html new file mode 100644 index 00000000000..f5f4e5a84b2 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-002.html @@ -0,0 +1,174 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Space-like elements</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#definition-of-space-like-elements"> +<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/#layout-of-mrow"> +<meta name="assert" content="Verify definition of space-like elements"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> +<style> + /* Default spacing of operator 'X' is 0.2777777777777778em so quite different + from the measured/specified 0em and 1em. */ + math, math * { + font: 25px/1 Ahem; + } + mn { + color: black; + } + mo { + color: yellow; + } + .testedElement, .testedElement * { + color: blue !important; + background: blue !important; + } +</style> +<script> + function spaceBefore(id) { + var element = document.getElementById(id); + var mnBeforeParent = element.parentNode.previousElementSibling; + return element.getBoundingClientRect().left - mnBeforeParent.getBoundingClientRect().right; + } + + function spaceAfter(id) { + var element = document.getElementById(id); + var mnAfterParent = element.parentNode.nextElementSibling; + return mnAfterParent.getBoundingClientRect().left - element.getBoundingClientRect().right; + } + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + var epsilon = 1; + var emToPx = 25; + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("maction1"), emToPx, epsilon); + assert_approx_equals(spaceAfter("maction1"), emToPx, epsilon); + }, "space-like maction"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("maction2"), 0, epsilon); + assert_approx_equals(spaceAfter("maction2"), 2 * emToPx, epsilon); + }, "non-space like maction (no first child)"); + + test(function() { + assert_approx_equals(spaceBefore("maction3"), 0, epsilon); + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceAfter("maction3"), 2 * emToPx, epsilon); + }, "non-space like maction (first child not space-like)"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("semantics1"), emToPx, epsilon); + assert_approx_equals(spaceAfter("semantics1"), emToPx, epsilon); + }, "space-like semantics"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("semantics2"), 0, epsilon); + assert_approx_equals(spaceAfter("semantics2"), 2 * emToPx, epsilon); + }, "non-space like semantics (no first child)"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("semantics3"), 0, epsilon); + assert_approx_equals(spaceAfter("semantics3"), 2 * emToPx, epsilon); + }, "non-space like semantics (first child not space-like)"); + + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- maction is space-like when its first child exists and is space-like --> + <maction id="maction1" class="testedElement" actiontype="statusline"> + <mtext>X</mtext> + <mtext>STATUS MESSAGE</mtext> + </maction> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- maction is not space-like when its first does not exist-like --> + <maction id="maction2" class="testedElement" actiontype="statusline"> + </maction> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- maction is not space-like when its first is not space-like --> + <maction id="maction3" class="testedElement" actiontype="statusline"> + <mn>1</mn> + <mtext>STATUS MESSAGE</mtext> + </maction> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- semantics is space-like when its first child exists and is space-like --> + <semantics id="semantics1" class="testedElement" actiontype="statusline"> + <mtext>X</mtext> + <annotation>TEXT ANNOTATION</annotation> + </semantics> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- semantics is not space-like when its first does not exist-like --> + <semantics id="semantics2" class="testedElement" actiontype="statusline"> + </semantics> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- semantics is not space-like when its first is not space-like --> + <semantics id="semantics3" class="testedElement" actiontype="statusline"> + <mn>1</mn> + <annotation>TEXT ANNOTATION</annotation> + </semantics> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-003.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-003.html new file mode 100644 index 00000000000..6d3d007744e --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-003.html @@ -0,0 +1,276 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Non space-like elements</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#definition-of-space-like-elements"> +<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/#layout-of-mrow"> +<meta name="assert" content="Verify definition of space-like elements"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> +<style> + /* Default spacing of operator 'X' is 0.2777777777777778em so quite different + from the measured/specified 0em and 1em. */ + math, math * { + font: 25px/1 Ahem; + } + mn { + color: black; + } + mo { + color: yellow; + } + .testedElement, .testedElement * { + color: blue !important; + background: blue !important; + } +</style> +<script> + function spaceBefore(element) { + var mnBeforeParent = element.parentNode.previousElementSibling; + return element.getBoundingClientRect().left - mnBeforeParent.getBoundingClientRect().right; + } + + function spaceAfter(element) { + var mnAfterParent = element.parentNode.nextElementSibling; + return mnAfterParent.getBoundingClientRect().left - element.getBoundingClientRect().right; + } + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + var epsilon = 1; + var emToPx = 25; + + Array.from(document.querySelectorAll(".testedElement")).forEach(el => { + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore(el), 0, epsilon); + assert_approx_equals(spaceAfter(el), 2 * emToPx, epsilon); + }, `${el.tagName} is not space-like`); + }); + + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mn>X</mn> + <mrow> + <merror class="testedElement"> + <mtext>X</mtext> + </merror> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <mroot class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + </mroot> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <menclose class="testedElement"> + <mtext>X</mtext> + </menclose> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <mfrac class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + </mfrac> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <mi class="testedElement">X</mi> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <mmultiscripts class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + <mtext>X</mtext> + </mmultiscripts> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <mn class="testedElement">X</mn> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <mo class="testedElement" lspace="0" rspace="0">X</mo> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <mover class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + </mover> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <munder class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + </munder> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <ms class="testedElement">X</ms> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <munderover class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + <mtext>X</mtext> + </munderover> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <msup class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + </msup> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <msub class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + </msub> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <msubsup class="testedElement"> + <mtext>X</mtext> + <mtext>X</mtext> + <mtext>X</mtext> + </msubsup> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <msqrt class="testedElement"> + <mtext>X</mtext> + </msqrt> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <mtable class="testedElement"> + <mtr> + <mtd> + <mtext>X</mtext> + </mtd> + </mtr> + </mtable> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-004.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-004.html new file mode 100644 index 00000000000..091a3ea0a62 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/spaces/space-like-004.html @@ -0,0 +1,193 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Space-like elements</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#definition-of-space-like-elements"> +<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/#layout-of-mrow"> +<meta name="assert" content="Verify definition of space-like elements"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> +<style> + /* Default spacing of operator 'X' is 0.2777777777777778em so quite different + from the measured/specified 0em and 1em. */ + math, math * { + font: 25px/1 Ahem; + } + mn { + color: black; + } + mo { + color: yellow; + } + .testedElement, .testedElement * { + color: blue !important; + background: blue !important; + } +</style> +<script> + function spaceBefore(id) { + var element = document.getElementById(id); + var mnBeforeParent = element.parentNode.previousElementSibling; + return element.getBoundingClientRect().left - mnBeforeParent.getBoundingClientRect().right; + } + + function spaceAfter(id) { + var element = document.getElementById(id); + var mnAfterParent = element.parentNode.nextElementSibling; + return mnAfterParent.getBoundingClientRect().left - element.getBoundingClientRect().right; + } + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + var epsilon = 1; + var emToPx = 25; + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("complex1"), emToPx, epsilon); + assert_approx_equals(spaceAfter("complex1"), emToPx, epsilon); + }, "complex space-like subtree"); + + test(function() { + assert_true(MathMLFeatureDetection.has_operator_spacing()); + assert_approx_equals(spaceBefore("complex2"), 0, epsilon); + assert_approx_equals(spaceAfter("complex2"), 2 * emToPx, epsilon); + }, "complex non-space-like subtree"); + + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- This element is space-like because it is made of nested + mrow, mstyle, mpadded, mphantom, mtext, mspace + --> + <mrow class="testedElement" id="complex1"> + <mtext>X</mtext> + <mstyle> + <mstyle> + <mtext>X</mtext> + <mtext>X</mtext> + </mstyle> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mpadded> + <mtext>X</mtext> + <mrow></mrow> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mphantom> + <mtext>X</mtext> + <mspace width="25px"></mspace> + </mphantom> + <mrow> + <mtext>X</mtext> + <mtext>X</mtext> + </mrow> + <mspace width="25px"></mspace> + </mpadded> + <mspace width="25px"></mspace> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mpadded> + <mphantom> + <mtext>X</mtext> + <mspace width="25px"></mspace> + </mphantom> + <mtext>X</mtext> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mtext>X</mtext> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mphantom> + <mtext>X</mtext> + <mspace width="25px"></mspace> + </mphantom> + <mtext>X</mtext> + <mtext>X</mtext> + <mspace width="25px"></mspace> + </mpadded> + </mstyle> + <mspace width="25px"></mspace> + </mrow> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> + <p> + <math> + <mn>X</mn> + <mrow> + <!-- This element is not space-like. It is made of nested + mrow, mstyle, mpadded, mphantom, mtext, mspace but contains + one non-space like descendant (an mn element). + --> + <mrow class="testedElement" id="complex2"> + <mtext>X</mtext> + <mstyle> + <mstyle> + <mtext>X</mtext> + <mtext>X</mtext> + </mstyle> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mpadded> + <mtext>X</mtext> + <mrow></mrow> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mphantom> + <mtext>X</mtext> + <mspace width="25px"></mspace> + </mphantom> + <mrow> + <mtext>X</mtext> + <mtext>X</mtext> + </mrow> + <mspace width="25px"></mspace> + </mpadded> + <mspace width="25px"></mspace> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mpadded> + <mphantom> + <mn>X</mn> <!-- mn is not space-like --> + <mspace width="25px"></mspace> + </mphantom> + <mtext>X</mtext> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mtext>X</mtext> + <mtext>X</mtext> + <mspace width="25px"></mspace> + <mphantom> + <mtext>X</mtext> + <mspace width="25px"></mspace> + </mphantom> + <mtext>X</mtext> + <mtext>X</mtext> + <mspace width="25px"></mspace> + </mpadded> + </mstyle> + <mspace width="25px"></mspace> + </mrow> + <mo lspace="1em" rspace="0em">X</mo> + </mrow> + <mn>X</mn> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/tables/table-axis-height.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/tables/table-axis-height.html index feb29077e8e..3eaf9c8fff4 100644 --- a/tests/wpt/web-platform-tests/mathml/presentation-markup/tables/table-axis-height.html +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/tables/table-axis-height.html @@ -7,6 +7,7 @@ <meta name="assert" content="Element mtable correctly uses the axis height parameter from the MATH table."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> math, mspace { font-size: 10px; @@ -32,6 +33,8 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); + var v1 = 5000 * emToPx; var tableMiddle = (getBox("table").bottom + getBox("table").top) / 2; assert_approx_equals(getBox("baseline").bottom - tableMiddle, diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-1-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-001-ref.html index 0efca480eec..0efca480eec 100644 --- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-1-ref.html +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-001-ref.html diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-001.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-001.html new file mode 100644 index 00000000000..bc4b17730c9 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-001.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>color</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/#text-mtext"> +<link rel="match" href="color-001-ref.html"/> +<meta name="assert" content="Verify that the color is used for the text of token elements."> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; color: red; width: 200px; height: 200px; padding: 1px;"> + <math><mi style="color: green">1</mi></math> + <math><mn style="color: green">2</mn></math> + <math><mo style="color: green">3</mo></math> + <math><mtext style="color: green">4</mtext></math> + <math><ms style="color: green">5</ms></math> + </div> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-002-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-002-ref.html new file mode 100644 index 00000000000..0efca480eec --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-002-ref.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>color (reference)</title> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; width: 200px; height: 200px; padding: 1px;"> + </div> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-002.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-002.html new file mode 100644 index 00000000000..177333830e5 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-002.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>color</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/#text-mtext"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#fraction-with-nonzero-line-thickness"> +<link rel="match" href="color-002-ref.html"/> +<meta name="assert" content="Verify that the color is used for text and fraction bar of the mfrac element."> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; color: red; width: 200px; height: 200px; padding: 1px;"> + <math><mfrac style="color: green"><mn>1</mn><mn>2</mn></mfrac></math> + </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-003-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-003-ref.html new file mode 100644 index 00000000000..0efca480eec --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-003-ref.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>color (reference)</title> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; width: 200px; height: 200px; padding: 1px;"> + </div> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-003.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-003.html new file mode 100644 index 00000000000..2422ffdf09f --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-003.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>color</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/#text-mtext"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#radical-symbol"> +<link rel="match" href="color-003-ref.html"/> +<meta name="assert" content="Verify that the color is used for text and radical symbol of the msqrt and mroot elements."> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; color: red; width: 200px; height: 200px; padding: 1px;"> + <math><msqrt style="color: green"><mn>1</mn></msqrt></math> + <math><mroot style="color: green"><mn>2</mn><mn>2</mn></mroot></math> + </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_msqrt");</script> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-004-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-004-ref.html new file mode 100644 index 00000000000..0efca480eec --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-004-ref.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>color (reference)</title> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; width: 200px; height: 200px; padding: 1px;"> + </div> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-004.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-004.html new file mode 100644 index 00000000000..65f6c4469ad --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-004.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>color</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/#text-mtext"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#enclose-expression-inside-notation-menclose"> +<link rel="match" href="color-004-ref.html"/> +<meta name="assert" content="Verify that the color is used for text and graphical elements of the menclose element."> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; color: red; width: 200px; height: 200px; padding: 1px;"> + <math><menclose notation="left" style="color: green"><mn>1</mn></menclose></math> + <math><menclose notation="right" style="color: green"><mn>2</mn></menclose></math> + <math><menclose notation="top" style="color: green"><mn>3</mn></menclose></math> + <math><menclose notation="bottom" style="color: green"><mn>4</mn></menclose></math> + <math><menclose notation="box" style="color: green"><mn>5</mn></menclose></math> + <math><menclose notation="roundedbox" style="color: green"><mn>6</mn></menclose></math> + <math><menclose notation="actuarial" style="color: green"><mn>7</mn></menclose></math> + <math><menclose notation="madruwb" style="color: green"><mn>8</mn></menclose></math> + <math><menclose notation="horizontalstrike" style="color: green"><mn>9</mn></menclose></math> + <math><menclose notation="verticalstrike" style="color: green"><mn>10</mn></menclose></math> + <math><menclose notation="updiagonalstrike" style="color: green"><mn>11</mn></menclose></math> + <math><menclose notation="downdiagonalstrike" style="color: green"><mn>12</mn></menclose></math> + <math><menclose notation="longdiv" style="color: green"><mn>13</mn></menclose></math> + <math><menclose notation="circle" style="color: green"><mn>14</mn></menclose></math> + </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_menclose");</script> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-1.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-1.html deleted file mode 100644 index 4d9d084a5a6..00000000000 --- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/color-1.html +++ /dev/null @@ -1,41 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"> -<title>color</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/#text-mtext"> -<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#fraction-with-nonzero-line-thickness"> -<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#radical-symbol"> -<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#enclose-expression-inside-notation-menclose"> -<link rel="match" href="color-1-ref.html"/> -<meta name="assert" content="Verify that the color is used for text and graphical elements."> -</head> -<body> - <p>Test passes if you see a green square.</p> - <div style="background: green; color: red; width: 200px; height: 200px; padding: 1px;"> - <math><mfrac style="color: green"><mn>1</mn><mn>2</mn></mfrac></math> - <math><msqrt style="color: green"><mn>3</mn></msqrt></math> - <math><mroot style="color: green"><mn>4</mn><mn>5</mn></mroot></math> - <math><menclose notation="left" style="color: green"><mn>6</mn></menclose></math> - <math><menclose notation="right" style="color: green"><mn>7</mn></menclose></math> - <math><menclose notation="top" style="color: green"><mn>8</mn></menclose></math> - <math><menclose notation="bottom" style="color: green"><mn>9</mn></menclose></math> - <math><menclose notation="box" style="color: green"><mn>10</mn></menclose></math> - <math><menclose notation="roundedbox" style="color: green"><mn>11</mn></menclose></math> - <math><menclose notation="actuarial" style="color: green"><mn>12</mn></menclose></math> - <math><menclose notation="madruwb" style="color: green"><mn>13</mn></menclose></math> - <math><menclose notation="horizontalstrike" style="color: green"><mn>14</mn></menclose></math> - <math><menclose notation="verticalstrike" style="color: green"><mn>15</mn></menclose></math> - <math><menclose notation="updiagonalstrike" style="color: green"><mn>16</mn></menclose></math> - <math><menclose notation="downdiagonalstrike" style="color: green"><mn>17</mn></menclose></math> - <math><menclose notation="longdiv" style="color: green"><mn>18</mn></menclose></math> - <math><menclose notation="circle" style="color: green"><mn>19</mn></menclose></math> - <math><mi style="color: green">20</mi></math> - <math><mn style="color: green">21</mn></math> - <math><mo style="color: green">22</mo></math> - <math><mtext style="color: green">23</mtext></math> - <math><ms style="color: green">24</ms></math> - </div> -</body> -</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/display-1.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/display-1.html index 38dd0bafdf8..f32a15ec01a 100644 --- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/display-1.html +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/display-1.html @@ -12,5 +12,7 @@ <div style="background: green; color: red; width: 200px; height: 200px;"> <math style="display: none;"><mspace width="200px" height="200px" style="background: red"/></math> </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mspace");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/displaystyle-1.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/displaystyle-1.html index c2ccb78dc9f..12108836ce9 100644 --- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/displaystyle-1.html +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/displaystyle-1.html @@ -56,6 +56,7 @@ verify_displaystyle("mtable_true", true, "explicit displaystyle true"); }, "mtable element"); test(function() { + verify_displaystyle("mfrac_sibling", true, "sibling"); verify_displaystyle("mfrac_numerator", false, "numerator"); verify_displaystyle("mfrac_denominator", false, "denominator"); }, "mfrac element"); @@ -105,7 +106,7 @@ <math displaystyle="true"><mtable><mtr><mtd><mo id="mtable_default">⫿</mo></mtd></mtr></mtable></math> <math><mtable displaystyle="true"><mtr><mtd><mo id="mtable_true">⫿</mo></mtd></mtr></mtable></math> <math displaystyle="true"><mtable displaystyle="false"><mtr><mtd><mo id="mtable_false">⫿</mo></mtd></mtr></mtable></math> - <math displaystyle="true"><mfrac><mo id="mfrac_numerator">⫿</mo><mo id="mfrac_denominator">⫿</mo></mfrac></math> + <math displaystyle="true"><mo id="mfrac_sibling">⫿</mo><mfrac><mo id="mfrac_numerator">⫿</mo><mo id="mfrac_denominator">⫿</mo></mfrac></math> <math displaystyle="true"><mroot><mo id="mroot_base">⫿</mo><mo id="mroot_index">⫿</mo></mroot></math> <math displaystyle="true"><msub><mo id="msub_base">⫿</mo><mo id="msub_subscript">⫿</mo></msub></math> <math displaystyle="true"><msup><mo id="msup_base">⫿</mo><mo id="msup_supscript">⫿</mo></msup></math> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/dynamic-dir-1.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/dynamic-dir-1.html index 3667ece8c53..d28f66c3d5f 100644 --- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/dynamic-dir-1.html +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/dynamic-dir-1.html @@ -99,5 +99,7 @@ </mrow> </math> </p> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_dir");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/lengths-2.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/lengths-2.html index c3b88549cdb..22fc40156f1 100644 --- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/lengths-2.html +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/lengths-2.html @@ -10,6 +10,7 @@ <meta name="assert" content="Verify various cases of the MathML length syntax."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <style> @font-face { font-family: TestFont; @@ -35,6 +36,7 @@ function runTests() { test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_equals(getBox("unitCm").width, 96, "cm"); assert_equals(getBox("unitEm").width, 120, "em"); assert_equals(getBox("unitEx").width, 500, "ex"); @@ -47,6 +49,7 @@ }, "Units"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_equals(getBox("spaceCm").width, 96, "cm"); assert_equals(getBox("spaceEm").width, 120, "em"); assert_equals(getBox("spaceEx").width, 500, "ex"); @@ -59,6 +62,7 @@ }, "Trimming of space"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_approx_equals(getBox("n0").width, 0, epsilon, "n0"); assert_approx_equals(getBox("n1").width, 90, epsilon, "n1"); assert_approx_equals(getBox("n2").width, 8, epsilon, "n2"); @@ -72,6 +76,7 @@ }, "Non-negative numbers"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); var topRef = getBox("ref").top; assert_approx_equals(getBox("N0").top - topRef, -0, epsilon, "N0"); assert_approx_equals(topRef - getBox("N1").top, -90, epsilon, "N1"); @@ -86,6 +91,7 @@ }, "Non-positive numbers"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); // Namedspace values are invalid in MathML Core. ["veryverythinmathspace", "verythinmathspace", @@ -110,6 +116,7 @@ }, "Legacy namedspaces"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); // These values are invalid in MathML Core. assert_equals(getBox("unitNone").width, 30, "Unitless"); assert_approx_equals(getBox("n3").width, 0, epsilon, "n3"); diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/border-001.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/border-001.html new file mode 100644 index 00000000000..38922118edd --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/border-001.html @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>border</title> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-algorithms"> +<meta name="assert" content="Verify that border is taken into account."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="helper.js"></script> +<script> + var epsilon = 1; + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + test(function() { + var s = measureSpaceAround("mrow-border") + assert_approx_equals(s.left, 20, epsilon, "left border"); + assert_approx_equals(s.right, 30, epsilon, "right border"); + assert_approx_equals(s.top, 40, epsilon, "top border"); + assert_approx_equals(s.bottom, 50, epsilon, "bottom border"); + }, "Border properties on mrow"); + + test(function() { + var s = measureSpaceAround("mrow-border-shorthand") + assert_approx_equals(s.left, 20, epsilon, "left border"); + assert_approx_equals(s.right, 20, epsilon, "right border"); + assert_approx_equals(s.top, 20, epsilon, "top border"); + assert_approx_equals(s.bottom, 20, epsilon, "bottom border"); + }, "Border properties on mrow (shorthand)"); + + test(function() { + var s = measureSpaceAround("mrow-border-logical") + assert_approx_equals(s.left, 20, epsilon, "left border"); + assert_approx_equals(s.right, 30, epsilon, "right border"); + assert_approx_equals(s.top, 40, epsilon, "top border"); + assert_approx_equals(s.bottom, 50, epsilon, "bottom border"); + }, "Border properties on mrow (logical)"); + + test(function() { + var s = measureSpaceAround("mrow-border-logical-shorthand") + assert_approx_equals(s.left, 20, epsilon, "left border"); + assert_approx_equals(s.right, 20, epsilon, "right border"); + assert_approx_equals(s.top, 30, epsilon, "top border"); + assert_approx_equals(s.bottom, 30, epsilon, "bottom border"); + }, "Border properties on mrow (logical, shorthand)"); + + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mrow> + <mrow id="mrow-border" + style="border-left: 20px; + border-right: 30px; + border-top: 40px; + border-bottom: 50px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-border-shorthand" + style="border: 20px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-border-logical" + style="border-inline-start: 20px; + border-inline-end: 30px; + border-block-start: 40px; + border-block-end: 50px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-border-logical-shorthand" + style="border-inline: 20px; + border-block: 30px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/helper.js b/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/helper.js new file mode 100644 index 00000000000..8d8ac32f442 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/helper.js @@ -0,0 +1,12 @@ +function measureSpaceAround(id) { + var mrow = document.getElementById(id); + var mrowBox = mrow.getBoundingClientRect(); + var parentBox = mrow.parentNode.getBoundingClientRect(); + var childBox = mrow.firstElementChild.getBoundingClientRect(); + return { + left: childBox.left - parentBox.left, + right: parentBox.right - childBox.right, + top: childBox.top - parentBox.top, + bottom: parentBox.bottom - childBox.bottom + }; +} diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/margin-001.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/margin-001.html new file mode 100644 index 00000000000..dc3a2b4a150 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/margin-001.html @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>margin</title> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-algorithms"> +<meta name="assert" content="Verify that margin is taken into account."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="helper.js"></script> +<script> + var epsilon = 1; + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + test(function() { + var s = measureSpaceAround("mrow-margin") + assert_approx_equals(s.left, 20, epsilon, "left margin"); + assert_approx_equals(s.right, 30, epsilon, "right margin"); + assert_approx_equals(s.top, 40, epsilon, "top margin"); + assert_approx_equals(s.bottom, 50, epsilon, "bottom margin"); + }, "Margin properties on mrow"); + + test(function() { + var s = measureSpaceAround("mrow-margin-shorthand") + assert_approx_equals(s.left, 20, epsilon, "left margin"); + assert_approx_equals(s.right, 20, epsilon, "right margin"); + assert_approx_equals(s.top, 20, epsilon, "top margin"); + assert_approx_equals(s.bottom, 20, epsilon, "bottom margin"); + }, "Margin properties on mrow (shorthand)"); + + test(function() { + var s = measureSpaceAround("mrow-margin-logical") + assert_approx_equals(s.left, 20, epsilon, "left margin"); + assert_approx_equals(s.right, 30, epsilon, "right margin"); + assert_approx_equals(s.top, 40, epsilon, "top margin"); + assert_approx_equals(s.bottom, 50, epsilon, "bottom margin"); + }, "Margin properties on mrow (logical)"); + + test(function() { + var s = measureSpaceAround("mrow-margin-logical-shorthand") + assert_approx_equals(s.left, 20, epsilon, "left margin"); + assert_approx_equals(s.right, 20, epsilon, "right margin"); + assert_approx_equals(s.top, 30, epsilon, "top margin"); + assert_approx_equals(s.bottom, 30, epsilon, "bottom margin"); + }, "Margin properties on mrow (logical, shorthand)"); + + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mrow> + <mrow id="mrow-margin" + style="margin-left: 20px; + margin-right: 30px; + margin-top: 40px; + margin-bottom: 50px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-margin-shorthand" + style="margin: 20px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-margin-logical" + style="margin-inline-start: 20px; + margin-inline-end: 30px; + margin-block-start: 40px; + margin-block-end: 50px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-margin-logical-shorthand" + style="margin-inline: 20px; + margin-block: 30px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/padding-001.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/padding-001.html new file mode 100644 index 00000000000..1f8875f657d --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/padding-border-margin/padding-001.html @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>padding</title> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-algorithms"> +<meta name="assert" content="Verify that padding is taken into account."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="helper.js"></script> +<script> + var epsilon = 1; + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + test(function() { + var s = measureSpaceAround("mrow-padding") + assert_approx_equals(s.left, 20, epsilon, "left padding"); + assert_approx_equals(s.right, 30, epsilon, "right padding"); + assert_approx_equals(s.top, 40, epsilon, "top padding"); + assert_approx_equals(s.bottom, 50, epsilon, "bottom padding"); + }, "Padding properties on mrow"); + + test(function() { + var s = measureSpaceAround("mrow-padding-shorthand") + assert_approx_equals(s.left, 20, epsilon, "left padding"); + assert_approx_equals(s.right, 20, epsilon, "right padding"); + assert_approx_equals(s.top, 20, epsilon, "top padding"); + assert_approx_equals(s.bottom, 20, epsilon, "bottom padding"); + }, "Padding properties on mrow (shorthand)"); + + test(function() { + var s = measureSpaceAround("mrow-padding-logical") + assert_approx_equals(s.left, 20, epsilon, "left padding"); + assert_approx_equals(s.right, 30, epsilon, "right padding"); + assert_approx_equals(s.top, 40, epsilon, "top padding"); + assert_approx_equals(s.bottom, 50, epsilon, "bottom padding"); + }, "Padding properties on mrow (logical)"); + + test(function() { + var s = measureSpaceAround("mrow-padding-logical-shorthand") + assert_approx_equals(s.left, 20, epsilon, "left padding"); + assert_approx_equals(s.right, 20, epsilon, "right padding"); + assert_approx_equals(s.top, 30, epsilon, "top padding"); + assert_approx_equals(s.bottom, 30, epsilon, "bottom padding"); + }, "Padding properties on mrow (logical, shorthand)"); + + done(); + } +</script> +</head> +<body> + <div id="log"></div> + <p> + <math> + <mrow> + <mrow id="mrow-padding" + style="padding-left: 20px; + padding-right: 30px; + padding-top: 40px; + padding-bottom: 50px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-padding-shorthand" + style="padding: 20px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-padding-logical" + style="padding-inline-start: 20px; + padding-inline-end: 30px; + padding-block-start: 40px; + padding-block-end: 50px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> + <p> + <math> + <mrow> + <mrow id="mrow-padding-logical-shorthand" + style="padding-inline: 20px; + padding-block: 30px;"> + <mspace width="50px" height="50px"></mspace> + </mrow> + </mrow> + </math> + </p> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-1-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-001-ref.html index fcaf5fe85b4..fcaf5fe85b4 100644 --- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-1-ref.html +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-001-ref.html diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-001.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-001.html new file mode 100644 index 00000000000..f47bfad1fee --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-001.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>visibility</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/#text-mtext"> +<link rel="match" href="visibility-001-ref.html"/> +<meta name="assert" content="Verify that visibility=hidden is used for the text of token elements."> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; color: red; width: 200px; height: 200px;"> + <math><mi style="visibility: hidden">1</mi></math> + <math><mn style="visibility: hidden">2</mn></math> + <math><mo style="visibility: hidden">3</mo></math> + <math><mtext style="visibility: hidden">4</mtext></math> + <math><ms style="visibility: hidden">5</ms></math> + </div> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-002-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-002-ref.html new file mode 100644 index 00000000000..fcaf5fe85b4 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-002-ref.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>visibility (reference)</title> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; width: 200px; height: 200px;"> + </div> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-002.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-002.html new file mode 100644 index 00000000000..f3afb79c157 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-002.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>visibility</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/#text-mtext"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#fraction-with-nonzero-line-thickness"> +<link rel="match" href="visibility-002-ref.html"/> +<meta name="assert" content="Verify that visibility=hidden is used for the text and fraction bar of the mfrac element."> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; color: red; width: 200px; height: 200px;"> + <math><mfrac style="visibility: hidden"><mn>1</mn><mn>2</mn></mfrac></math> + </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-003-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-003-ref.html new file mode 100644 index 00000000000..fcaf5fe85b4 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-003-ref.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>visibility (reference)</title> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; width: 200px; height: 200px;"> + </div> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-003.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-003.html new file mode 100644 index 00000000000..cfeed644cbe --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-003.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>visibility</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/#text-mtext"> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#radical-symbol"> +<link rel="match" href="visibility-003-ref.html"/> +<meta name="assert" content="Verify that visibility=hidden is used for the text and radical symbol of the msqrt and mroot elements."> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; color: red; width: 200px; height: 200px;"> + <math><msqrt style="visibility: hidden"><mn>1</mn></msqrt></math> + <math><mroot style="visibility: hidden"><mn>2</mn><mn>3</mn></mroot></math> + </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_msqrt");</script> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-004-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-004-ref.html new file mode 100644 index 00000000000..fcaf5fe85b4 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-004-ref.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>visibility (reference)</title> +</head> +<body> + <p>Test passes if you see a green square.</p> + <div style="background: green; width: 200px; height: 200px;"> + </div> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-1.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-004.html index 7083ef70fb3..8173b9cd2ef 100644 --- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-1.html +++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/visibility-004.html @@ -5,37 +5,29 @@ <title>visibility</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/#text-mtext"> -<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#fraction-with-nonzero-line-thickness"> -<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#radical-symbol"> <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#enclose-expression-inside-notation-menclose"> -<link rel="match" href="visibility-1-ref.html"/> -<meta name="assert" content="Verify that visibility=hidden is used for text and graphical elements."> +<link rel="match" href="visibility-004-ref.html"/> +<meta name="assert" content="Verify that visibility=hidden is used for the text and graphical elements of the menclose element."> </head> <body> <p>Test passes if you see a green square.</p> <div style="background: green; color: red; width: 200px; height: 200px;"> - <math><mfrac style="visibility: hidden"><mn>1</mn><mn>2</mn></mfrac></math> - <math><msqrt style="visibility: hidden"><mn>3</mn></msqrt></math> - <math><mroot style="visibility: hidden"><mn>4</mn><mn>5</mn></mroot></math> - <math><menclose notation="left" style="visibility: hidden"><mn>6</mn></menclose></math> - <math><menclose notation="right" style="visibility: hidden"><mn>7</mn></menclose></math> - <math><menclose notation="top" style="visibility: hidden"><mn>8</mn></menclose></math> - <math><menclose notation="bottom" style="visibility: hidden"><mn>9</mn></menclose></math> - <math><menclose notation="box" style="visibility: hidden"><mn>10</mn></menclose></math> - <math><menclose notation="roundedbox" style="visibility: hidden"><mn>11</mn></menclose></math> - <math><menclose notation="actuarial" style="visibility: hidden"><mn>12</mn></menclose></math> - <math><menclose notation="madruwb" style="visibility: hidden"><mn>13</mn></menclose></math> - <math><menclose notation="horizontalstrike" style="visibility: hidden"><mn>14</mn></menclose></math> - <math><menclose notation="verticalstrike" style="visibility: hidden"><mn>15</mn></menclose></math> - <math><menclose notation="updiagonalstrike" style="visibility: hidden"><mn>16</mn></menclose></math> - <math><menclose notation="downdiagonalstrike" style="visibility: hidden"><mn>17</mn></menclose></math> - <math><menclose notation="longdiv" style="visibility: hidden"><mn>18</mn></menclose></math> - <math><menclose notation="circle" style="visibility: hidden"><mn>19</mn></menclose></math> - <math><mi style="visibility: hidden">20</mi></math> - <math><mn style="visibility: hidden">21</mn></math> - <math><mo style="visibility: hidden">22</mo></math> - <math><mtext style="visibility: hidden">23</mtext></math> - <math><ms style="visibility: hidden">24</ms></math> + <math><menclose notation="left" style="visibility: hidden"><mn>1</mn></menclose></math> + <math><menclose notation="right" style="visibility: hidden"><mn>2</mn></menclose></math> + <math><menclose notation="top" style="visibility: hidden"><mn>3</mn></menclose></math> + <math><menclose notation="bottom" style="visibility: hidden"><mn>4</mn></menclose></math> + <math><menclose notation="box" style="visibility: hidden"><mn>5</mn></menclose></math> + <math><menclose notation="roundedbox" style="visibility: hidden"><mn>6</mn></menclose></math> + <math><menclose notation="actuarial" style="visibility: hidden"><mn>7</mn></menclose></math> + <math><menclose notation="madruwb" style="visibility: hidden"><mn>8</mn></menclose></math> + <math><menclose notation="horizontalstrike" style="visibility: hidden"><mn>9</mn></menclose></math> + <math><menclose notation="verticalstrike" style="visibility: hidden"><mn>10</mn></menclose></math> + <math><menclose notation="updiagonalstrike" style="visibility: hidden"><mn>11</mn></menclose></math> + <math><menclose notation="downdiagonalstrike" style="visibility: hidden"><mn>12</mn></menclose></math> + <math><menclose notation="longdiv" style="visibility: hidden"><mn>13</mn></menclose></math> + <math><menclose notation="circle" style="visibility: hidden"><mn>14</mn></menclose></math> </div> + <script src="/mathml/support/feature-detection.js"></script> + <script>MathMLFeatureDetection.ensure_for_match_reftest("has_menclose");</script> </body> </html> diff --git a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/display-1.html b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/display-1.html index 3a180f5d42b..6747413e477 100644 --- a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/display-1.html +++ b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/display-1.html @@ -8,6 +8,7 @@ <meta name="assert" content="Verify that the display attribute on the math element is supported and impacts centering and line breaking with surrounding content."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> <script> function getBox(aId) { return document.getElementById(aId).getBoundingClientRect(); @@ -19,6 +20,7 @@ var mspace_block = getBox("mspace_block"); var after_block = getBox("after_block"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_approx_equals(before_block.left, content.left, 1, "content before must be left aligned"); assert_approx_equals((mspace_block.left + mspace_block.right) / 2, @@ -37,6 +39,7 @@ var mspace_inline = getBox("mspace_inline"); var after_inline = getBox("after_inline"); test(function() { + assert_true(MathMLFeatureDetection.has_mspace()); assert_approx_equals((before_inline.top + before_inline.bottom) / 2, (mspace_inline.top + mspace_inline.bottom) / 2, 1, diff --git a/tests/wpt/web-platform-tests/mathml/support/feature-detection.js b/tests/wpt/web-platform-tests/mathml/support/feature-detection.js new file mode 100644 index 00000000000..50ca926d25e --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/support/feature-detection.js @@ -0,0 +1,148 @@ +// This is a helper for MathML feature detection. +// It is indented to be used to prevent false negative test results. + +var MathMLFeatureDetection = { + + has_mspace: function() { + // https://mathml-refresh.github.io/mathml-core/#space-mspace + if (!this.hasOwnProperty("_has_mspace")) { + document.body.insertAdjacentHTML("beforeend", "<math>\ +<mspace></mspace>\ +<mspace width='20px'></mspace>\ +</math>"); + var math = document.body.lastElementChild; + // The width attribute will add 20px per MathML and none if not supported. + this._has_mspace = + math.lastChild.getBoundingClientRect().width - + math.firstChild.getBoundingClientRect().width > 10; + document.body.removeChild(math); + } + return this._has_mspace; + }, + + has_operator_spacing: function() { + // https://mathml-refresh.github.io/mathml-core/#dfn-lspace + // https://mathml-refresh.github.io/mathml-core/#layout-of-mrow + if (!this.hasOwnProperty("_has_operator_spacing")) { + document.body.insertAdjacentHTML("beforeend", "<math>\ +<mrow>\ + <mn>1</mn><mo lspace='0px' rspace='0px'>+</mo><mn>2</mn>\ +</mrow>\ +<mrow>\ + <mn>1</mn><mo lspace='8px' rspace='8px'>+</mo><mn>2</mn>\ +</mrow>\ +</math>"); + var math = document.body.lastElementChild; + var mrow = math.getElementsByTagName("mrow"); + // lspace/rspace will add 16px per MathML and none if not supported. + this._has_operator_spacing = + mrow[1].getBoundingClientRect().width - + mrow[0].getBoundingClientRect().width > 10; + document.body.removeChild(math); + } + return this._has_operator_spacing; + }, + + has_mfrac: function() { + if (!this.hasOwnProperty("_has_mfrac")) { + // Use tall enough fraction to avoid side effect of min num/denum shifts. + document.body.insertAdjacentHTML("beforeend", "<math>\ +<mfrac>\ + <mspace height='50px' depth='50px'></mspace>\ + <mspace height='50px' depth='50px'></mspace>\ +</mfrac>\ +<mfrac>\ + <mspace height='60px' depth='60px'></mspace>\ + <mspace height='60px' depth='60px'></mspace>\ +</mfrac>\ +</math>"); + var math = document.body.lastElementChild; + var mfrac = math.getElementsByTagName("mfrac"); + // height/depth will add 40px per MathML, 20px if mfrac does not stack its children and none if mspace is not supported. + this._has_mfrac = + mfrac[1].getBoundingClientRect().height - + mfrac[0].getBoundingClientRect().height > 30; + document.body.removeChild(math); + } + return this._has_mfrac; + }, + + has_msqrt: function() { + if (!this.hasOwnProperty("_has_msqrt")) { + document.body.insertAdjacentHTML("beforeend", "<math>\ +<mrow style='font-size: 20px !important'>\ + <mtext>A</mtext>\ +</mrow>\ +<msqrt style='font-size: 20px !important'>\ + <mtext>A</mtext>\ +</msqrt>\ +</math>"); + var math = document.body.lastElementChild; + // The radical symbol will make msqrt wider than mrow, if the former is supported. + this._has_msqrt = + math.lastElementChild.getBoundingClientRect().width - + math.firstElementChild.getBoundingClientRect().width > 5; + document.body.removeChild(math); + } + return this._has_msqrt; + }, + + has_menclose: function() { + if (!this.hasOwnProperty("_has_menclose")) { + document.body.insertAdjacentHTML("beforeend", "<math>\ +<mrow style='font-size: 20px !important'>\ + <mrow>\ + <mrow>\ + <mrow>\ + <mtext>A</mtext>\ + </mrow>\ + </mrow>\ + </mrow>\ +</mrow>\ +<menclose notation='box' style='font-size: 20px !important'>\ + <menclose notation='box'>\ + <menclose notation='box'>\ + <menclose notation='box'>\ + <mtext>A</mtext>\ + </menclose>\ + </menclose>\ + </menclose>\ +</menclose>\ +</math>"); + var math = document.body.lastElementChild; + // The boxes will make menclose wider than mrow, if the former is supported. + this._has_menclose = + math.lastElementChild.getBoundingClientRect().width - + math.firstElementChild.getBoundingClientRect().width > 5; + document.body.removeChild(math); + } + return this._has_menclose; + }, + + has_dir: function() { + if (!this.hasOwnProperty("_has_dir")) { + document.body.insertAdjacentHTML("beforeend", "<math style='direction: ltr !important;'>\ +<mtext dir='rtl'></mtext>\ +</math>"); + var math = document.body.lastElementChild; + this._has_dir = + window.getComputedStyle(math.firstElementChild). + getPropertyValue('direction') === 'rtl'; + document.body.removeChild(math); + } + return this._has_dir; + }, + + ensure_for_match_reftest: function(has_function) { + if (!document.querySelector("link[rel='match']")) + throw "This function must only be used for match reftest"; + // Add a little red square at the top left corner if the feature is not supported in order to make match reftest fail. + if (!this[has_function]()) { + document.body.insertAdjacentHTML("beforeend", "\ +<div style='width: 10px !important; height: 10px !important;\ + position: absolute !important;\ + left: 0 !important; top: 0 !important;\ + background: red !important; z-index: 1000 !important;'></div>"); + } + } +}; diff --git a/tests/wpt/web-platform-tests/mixed-content/generic/tools/generate.py b/tests/wpt/web-platform-tests/mixed-content/generic/tools/generate.py index fe4305c4eea..ed978bcef9c 100755 --- a/tests/wpt/web-platform-tests/mixed-content/generic/tools/generate.py +++ b/tests/wpt/web-platform-tests/mixed-content/generic/tools/generate.py @@ -3,62 +3,69 @@ import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', '..', 'common', 'security-features', 'tools')) +sys.path.insert( + 0, + os.path.join( + os.path.dirname(os.path.abspath(__file__)), '..', '..', '..', 'common', + 'security-features', 'tools')) import generate class MixedContentConfig(object): - def __init__(self): - self.selection_pattern = '%(subresource)s/' + \ - '%(opt_in_method)s/' + \ - '%(origin)s/' + \ - '%(context_nesting)s/' + \ - '%(redirection)s/' - - self.test_file_path_pattern = self.selection_pattern + \ - '%(spec_name)s/' + \ - '%(name)s.%(source_scheme)s.html' - - self.test_description_template = '''opt_in_method: %(opt_in_method)s + def __init__(self): + self.selection_pattern = '%(subresource)s/' + \ + '%(delivery_type)s/' + \ + '%(delivery_value)s/' + \ + '%(origin)s/' + \ + 'top-level/' + \ + '%(redirection)s/' + + self.test_file_path_pattern = self.selection_pattern + \ + '%(spec_name)s/' + \ + '%(name)s.%(source_scheme)s.html' + + self.test_description_template = '''delivery_type: %(delivery_type)s +delivery_value: %(delivery_value)s origin: %(origin)s source_scheme: %(source_scheme)s -context_nesting: %(context_nesting)s +context_nesting: top-level redirection: %(redirection)s subresource: %(subresource)s expectation: %(expectation)s ''' - self.test_page_title_template = 'Mixed-Content: %s' + self.test_page_title_template = 'Mixed-Content: %s' - self.helper_js = '/mixed-content/generic/mixed-content-test-case.js?pipe=sub' + self.helper_js = '/mixed-content/generic/mixed-content-test-case.js?pipe=sub' - # For debug target only. - self.sanity_checker_js = '/mixed-content/generic/sanity-checker.js' - self.spec_json_js = '/mixed-content/spec_json.js' + # For debug target only. + self.sanity_checker_js = '/mixed-content/generic/sanity-checker.js' + self.spec_json_js = '/mixed-content/spec_json.js' - self.test_case_name = 'MixedContentTestCase' + self.test_case_name = 'MixedContentTestCase' - script_directory = os.path.dirname(os.path.abspath(__file__)) - self.spec_directory = os.path.abspath(os.path.join(script_directory, '..', '..')) + script_directory = os.path.dirname(os.path.abspath(__file__)) + self.spec_directory = os.path.abspath( + os.path.join(script_directory, '..', '..')) - def handleDelivery(self, selection, spec): - opt_in_method = selection['opt_in_method'] + def handleDelivery(self, selection, spec): + delivery_type = selection['delivery_type'] + delivery_value = selection['delivery_value'] - meta = '' - headers = [] + meta = '' + headers = [] - # TODO(kristijanburnik): Implement the opt-in-method here. - if opt_in_method == 'meta-csp': - meta = '<meta http-equiv="Content-Security-Policy" ' + \ - 'content="block-all-mixed-content">' - elif opt_in_method == 'http-csp': - headers.append("Content-Security-Policy: block-all-mixed-content") - elif opt_in_method == 'no-opt-in': - pass - else: - raise ValueError("Invalid opt_in_method %s" % opt_in_method) + if delivery_value is not None: + if delivery_type == 'meta': + meta = '<meta http-equiv="Content-Security-Policy" ' + \ + 'content="block-all-mixed-content">' + elif delivery_type == 'http-rp': + headers.append( + "Content-Security-Policy: block-all-mixed-content") + else: + raise ValueError("Invalid delivery_type %s" % delivery_type) - return {"meta": meta, "headers": headers} + return {"meta": meta, "headers": headers} if __name__ == '__main__': diff --git a/tests/wpt/web-platform-tests/mixed-content/spec.src.json b/tests/wpt/web-platform-tests/mixed-content/spec.src.json index 06d381d363e..95dc2d318f5 100644 --- a/tests/wpt/web-platform-tests/mixed-content/spec.src.json +++ b/tests/wpt/web-platform-tests/mixed-content/spec.src.json @@ -10,28 +10,34 @@ "name": "opt-in-blocks", "expansion": "default", "source_scheme": "https", - "opt_in_method": ["http-csp", "meta-csp"], - "context_nesting": "top-level", + "delivery_type": "*", + "delivery_value": "opt-in", "redirection": "*", "subresource": { "blockable": [], "optionally-blockable": "*" }, - "origin": ["cross-origin-http", "same-host-http"], + "origin": [ + "cross-http", + "same-http" + ], "expectation": "blocked" }, { "name": "no-opt-in-allows", "expansion": "default", "source_scheme": "https", - "opt_in_method": "no-opt-in", - "context_nesting": "top-level", + "delivery_type": "*", + "delivery_value": null, "redirection": "*", "subresource": { "blockable": [], "optionally-blockable": "*" }, - "origin": ["cross-origin-http", "same-host-http"], + "origin": [ + "cross-http", + "same-http" + ], "expectation": "allowed" } ] @@ -46,42 +52,51 @@ "name": "opt-in-blocks", "expansion": "default", "source_scheme": "https", - "opt_in_method": ["http-csp", "meta-csp"], - "context_nesting": "top-level", + "delivery_type": "*", + "delivery_value": "opt-in", "redirection": "*", "subresource": { "blockable": "*", "optionally-blockable": [] }, - "origin": ["cross-origin-http", "same-host-http"], + "origin": [ + "cross-http", + "same-http" + ], "expectation": "blocked" }, { "name": "no-opt-in-blocks", "expansion": "default", "source_scheme": "https", - "opt_in_method": "no-opt-in", - "context_nesting": "top-level", + "delivery_type": "*", + "delivery_value": null, "redirection": "*", "subresource": { "blockable": "*", "optionally-blockable": [] }, - "origin": ["cross-origin-http", "same-host-http"], + "origin": [ + "cross-http", + "same-http" + ], "expectation": "blocked" }, { "name": "ws-downgrade-blocks", "expansion": "default", "source_scheme": "https", - "opt_in_method": ["no-opt-in", "http-csp", "meta-csp"], - "context_nesting": "top-level", + "delivery_type": "*", + "delivery_value": "*", "redirection": "*", "subresource": { "blockable": "websocket-request", "optionally-blockable": [] }, - "origin": ["cross-origin-ws", "same-host-ws"], + "origin": [ + "cross-ws", + "same-ws" + ], "expectation": "blocked" } ] @@ -96,41 +111,65 @@ "name": "allowed", "expansion": "default", "source_scheme": "https", - "opt_in_method": "*", - "context_nesting": "top-level", - "redirection": ["no-redirect", "keep-scheme-redirect"], + "delivery_type": "*", + "delivery_value": "*", + "redirection": [ + "no-redirect", + "keep-scheme" + ], "subresource": { "blockable": "*", "optionally-blockable": "*" }, - "origin": ["same-host-https"], + "origin": [ + "same-https" + ], "expectation": "allowed" }, { "name": "websocket-allowed", "expansion": "default", "source_scheme": "https", - "opt_in_method": "*", - "context_nesting": "top-level", - "redirection": ["no-redirect", "keep-scheme-redirect"], + "delivery_type": "*", + "delivery_value": "*", + "redirection": [ + "no-redirect", + "keep-scheme" + ], "subresource": { "blockable": "websocket-request", "optionally-blockable": [] }, - "origin": ["same-host-wss"], + "origin": [ + "same-wss" + ], "expectation": "allowed" } ] } ], - + "delivery_key": "mixedContent", "excluded_tests": [ { + "name": "Skip-redundant-no-opt-in", + "expansion": "*", + "source_scheme": "*", + "delivery_type": "http-rp", + "delivery_value": null, + "redirection": "*", + "subresource": { + "blockable": "*", + "optionally-blockable": "*" + }, + "origin": "*", + "expectation": "*" + }, + { "name": "Redundant-subresources", "expansion": "*", "source_scheme": "*", - "opt_in_method": "*", - "context_nesting": "*", + "delivery_type": "*", + "delivery_value": "*", "redirection": "*", "subresource": { "blockable": [ @@ -145,8 +184,8 @@ "name": "Skip-origins-not-applicable-to-websockets", "expansion": "*", "source_scheme": "*", - "opt_in_method": "*", - "context_nesting": "*", + "delivery_type": "*", + "delivery_value": "*", "redirection": "*", "subresource": { "blockable": [ @@ -155,37 +194,23 @@ "optionally-blockable": [] }, "origin": [ - "same-host-https", - "same-host-http", - "cross-origin-https", - "cross-origin-http" + "same-https", + "same-http", + "cross-https", + "cross-http" ], "expectation": "*" }, { - "name": "TODO-opt-in-method-img-cross-origin", - "expansion": "*", - "source_scheme": "*", - "opt_in_method": "img-crossorigin", - "context_nesting": "*", - "redirection": "*", - "subresource": { - "blockable": "*", - "optionally-blockable": "*" - }, - "origin": "*", - "expectation": "*" - }, - { "name": "Skip-redundant-for-opt-in-method", "expansion": "*", "source_scheme": "*", - "opt_in_method": [ - "meta-csp", - "img-crossorigin" + "delivery_type": "meta", + "delivery_value": "opt-in", + "redirection": [ + "keep-scheme", + "swap-scheme" ], - "context_nesting": "*", - "redirection": ["keep-scheme-redirect", "swap-scheme-redirect"], "subresource": { "blockable": "*", "optionally-blockable": "*" @@ -194,7 +219,6 @@ "expectation": "*" } ], - "test_expansion_schema": { "expansion": [ "default", @@ -204,30 +228,28 @@ "http", "https" ], - "opt_in_method": [ - "no-opt-in", - "http-csp", - "meta-csp", - "img-crossorigin" + "delivery_type": [ + "http-rp", + "meta" + ], + "delivery_value": [ + null, + "opt-in" ], "redirection": [ "no-redirect", - "keep-scheme-redirect", - "swap-scheme-redirect" - ], - "context_nesting": [ - "top-level", - "sub-level" + "keep-scheme", + "swap-scheme" ], "origin": [ - "same-host-https", - "same-host-http", - "cross-origin-https", - "cross-origin-http", - "same-host-wss", - "same-host-ws", - "cross-origin-wss", - "cross-origin-ws" + "same-https", + "same-http", + "cross-https", + "cross-http", + "same-wss", + "same-ws", + "cross-wss", + "cross-ws" ], "subresource": { "blockable": [ diff --git a/tests/wpt/web-platform-tests/native-file-system/NativeFileSystemWritableFileStream.tentative.https.window.js b/tests/wpt/web-platform-tests/native-file-system/NativeFileSystemWritableFileStream.tentative.https.window.js deleted file mode 100644 index 1dbcb2b1362..00000000000 --- a/tests/wpt/web-platform-tests/native-file-system/NativeFileSystemWritableFileStream.tentative.https.window.js +++ /dev/null @@ -1,126 +0,0 @@ -// META: script=resources/test-helpers.js -promise_test(async t => cleanupSandboxedFileSystem(), - 'Cleanup to setup test environment'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'empty_blob'); - const stream = await handle.createWritable(); - - await stream.write(0, new Blob([])); - - assert_equals(await getFileContents(handle), ''); - assert_equals(await getFileSize(handle), 0); -}, 'write() with an empty blob to an empty file'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'valid_blob'); - const stream = await handle.createWritable(); - - await stream.write(0, new Blob(['1234567890'])); - - assert_equals(await getFileContents(handle), '1234567890'); - assert_equals(await getFileSize(handle), 10); -}, 'write() a blob to an empty file'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'blob_with_offset'); - const stream = await handle.createWritable(); - - await stream.write(0, new Blob(['1234567890'])); - await stream.write(4, new Blob(['abc'])); - - assert_equals(await getFileContents(handle), '1234abc890'); - assert_equals(await getFileSize(handle), 10); -}, 'write() called with a blob and a valid offset'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'bad_offset'); - const stream = await handle.createWritable(); - - await promise_rejects(t, 'InvalidStateError', stream.write(4, new Blob(['abc']))); - - assert_equals(await getFileContents(handle), ''); - assert_equals(await getFileSize(handle), 0); -}, 'write() called with an invalid offset'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'empty_string'); - const stream = await handle.createWritable(); - - await stream.write(0, ''); - assert_equals(await getFileContents(handle), ''); - assert_equals(await getFileSize(handle), 0); -}, 'write() with an empty string to an empty file'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'valid_utf8_string'); - const stream = await handle.createWritable(); - - await stream.write(0, 'foo🤘'); - assert_equals(await getFileContents(handle), 'foo🤘'); - assert_equals(await getFileSize(handle), 7); -}, 'write() with a valid utf-8 string'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'string_with_unix_line_ending'); - const stream = await handle.createWritable(); - - await stream.write(0, 'foo\n'); - assert_equals(await getFileContents(handle), 'foo\n'); - assert_equals(await getFileSize(handle), 4); -}, 'write() with a string with unix line ending preserved'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'string_with_windows_line_ending'); - const stream = await handle.createWritable(); - - await stream.write(0, 'foo\r\n'); - assert_equals(await getFileContents(handle), 'foo\r\n'); - assert_equals(await getFileSize(handle), 5); -}, 'write() with a string with windows line ending preserved'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'empty_array_buffer'); - const stream = await handle.createWritable(); - - let buf = new ArrayBuffer(0); - await stream.write(0, buf); - assert_equals(await getFileContents(handle), ''); - assert_equals(await getFileSize(handle), 0); -}, 'write() with an empty array buffer to an empty file'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'valid_string_typed_byte_array'); - const stream = await handle.createWritable(); - - let buf = new ArrayBuffer(3); - let intView = new Uint8Array(buf); - intView[0] = 0x66; - intView[1] = 0x6f; - intView[2] = 0x6f; - await stream.write(0, buf); - assert_equals(await getFileContents(handle), 'foo'); - assert_equals(await getFileSize(handle), 3); -}, 'write() with a valid typed array buffer'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'trunc_shrink'); - const stream = await handle.createWritable(); - - await stream.write(0, new Blob(['1234567890'])); - await stream.truncate(5); - - assert_equals(await getFileContents(handle), '12345'); - assert_equals(await getFileSize(handle), 5); -}, 'truncate() to shrink a file'); - -promise_test(async t => { - const handle = await createEmptyFile(t, 'trunc_grow'); - const stream = await handle.createWritable(); - - await stream.write(0, new Blob(['abc'])); - await stream.truncate(5); - - assert_equals(await getFileContents(handle), 'abc\0\0'); - assert_equals(await getFileSize(handle), 5); -}, 'truncate() to grow a file'); diff --git a/tests/wpt/web-platform-tests/referrer-policy/README.md b/tests/wpt/web-platform-tests/referrer-policy/README.md index 303362df924..498f7f26137 100644 --- a/tests/wpt/web-platform-tests/referrer-policy/README.md +++ b/tests/wpt/web-platform-tests/referrer-policy/README.md @@ -30,6 +30,8 @@ Invoking ```./generic/tools/generate.py``` will parse the spec JSON and determin The spec can be validated by running ```./generic/tools/spec_validator.py```. This is specially important when you're making changes to ```spec.src.json```. Make sure it's a valid JSON (no comments or trailing commas). The validator should be informative and very specific on any issues. +The ```spec.src.json``` file can be formatted by running ```../common/security-features/tools/format_spec_src_json.py```. + For details about the spec JSON, see **Overview of the spec JSON** below. diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/generate.py b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/generate.py index b3e3340d97b..98374982a8d 100755 --- a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/generate.py +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/generate.py @@ -3,65 +3,71 @@ import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', '..', 'common', 'security-features', 'tools')) +sys.path.insert( + 0, + os.path.join( + os.path.dirname(os.path.abspath(__file__)), '..', '..', '..', 'common', + 'security-features', 'tools')) import generate + class ReferrerPolicyConfig(object): - def __init__(self): - self.selection_pattern = '%(delivery_method)s/' + \ - '%(origin)s/' + \ - '%(source_protocol)s-%(target_protocol)s/' + \ - '%(subresource)s/' + \ - '%(redirection)s/' + def __init__(self): + self.selection_pattern = '%(delivery_type)s/' + \ + '%(origin)s/' + \ + '%(source_scheme)s/' + \ + '%(subresource)s/' + \ + '%(redirection)s/' - self.test_file_path_pattern = '%(spec_name)s/' + self.selection_pattern + \ - '%(name)s.%(source_protocol)s.html' + self.test_file_path_pattern = '%(spec_name)s/' + self.selection_pattern + \ + '%(name)s.%(source_scheme)s.html' - self.test_description_template = '''The referrer URL is %(referrer_url)s when a -document served over %(source_protocol)s requires an %(target_protocol)s -sub-resource via %(subresource)s using the %(delivery_method)s + self.test_description_template = '''The referrer URL is %(expectation)s when a +document served over %(source_scheme)s requires a +sub-resource via %(subresource)s using the %(delivery_type)s delivery method with %(redirection)s and when the target request is %(origin)s.''' - self.test_page_title_template = 'Referrer-Policy: %s' + self.test_page_title_template = 'Referrer-Policy: %s' - self.helper_js = '/referrer-policy/generic/referrer-policy-test-case.sub.js' + self.helper_js = '/referrer-policy/generic/referrer-policy-test-case.sub.js' - # For debug target only. - self.sanity_checker_js = '/referrer-policy/generic/sanity-checker.js' - self.spec_json_js = '/referrer-policy/spec_json.js' + # For debug target only. + self.sanity_checker_js = '/referrer-policy/generic/sanity-checker.js' + self.spec_json_js = '/referrer-policy/spec_json.js' - self.test_case_name = 'ReferrerPolicyTestCase' + self.test_case_name = 'ReferrerPolicyTestCase' - script_directory = os.path.dirname(os.path.abspath(__file__)) - self.spec_directory = os.path.abspath(os.path.join(script_directory, '..', '..')) + script_directory = os.path.dirname(os.path.abspath(__file__)) + self.spec_directory = os.path.abspath( + os.path.join(script_directory, '..', '..')) - def handleDelivery(self, selection, spec): - delivery_method = selection['delivery_method'] - delivery_value = spec['referrer_policy'] + def handleDelivery(self, selection, spec): + delivery_type = selection['delivery_type'] + delivery_value = selection['delivery_value'] - meta = '' - headers = [] - if delivery_value != None: - if delivery_method == 'meta-referrer': - meta = \ - '<meta name="referrer" content="%s">' % delivery_value - elif delivery_method == 'http-rp': - meta = \ - "<!-- No meta: Referrer policy delivered via HTTP headers. -->" - headers.append('Referrer-Policy: ' + '%s' % delivery_value) - # TODO(kristijanburnik): Limit to WPT origins. - headers.append('Access-Control-Allow-Origin: *') - elif delivery_method == 'attr-referrer': - # attr-referrer is supported by the JS test wrapper. - pass - elif delivery_method == 'rel-noreferrer': - # rel=noreferrer is supported by the JS test wrapper. - pass - else: - raise ValueError('Not implemented delivery_method: ' \ - + delivery_method) - return {"meta": meta, "headers": headers} + meta = '' + headers = [] + if delivery_value != None: + if delivery_type == 'meta': + meta = \ + '<meta name="referrer" content="%s">' % delivery_value + elif delivery_type == 'http-rp': + meta = \ + "<!-- No meta: Referrer policy delivered via HTTP headers. -->" + headers.append('Referrer-Policy: ' + '%s' % delivery_value) + # TODO(kristijanburnik): Limit to WPT origins. + headers.append('Access-Control-Allow-Origin: *') + elif delivery_type == 'attr': + # attr-referrer is supported by the JS test wrapper. + pass + elif delivery_type == 'rel-noref': + # rel=noreferrer is supported by the JS test wrapper. + pass + else: + raise ValueError('Not implemented delivery_type: ' \ + + delivery_type) + return {"meta": meta, "headers": headers} if __name__ == '__main__': diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/spec_validator.py b/tests/wpt/web-platform-tests/referrer-policy/generic/tools/spec_validator.py deleted file mode 100755 index 70656db25d2..00000000000 --- a/tests/wpt/web-platform-tests/referrer-policy/generic/tools/spec_validator.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python - -from __future__ import print_function - -import json, sys -from common_paths import * - -def assert_non_empty_string(obj, field): - assert field in obj, 'Missing field "%s"' % field - assert isinstance(obj[field], basestring), \ - 'Field "%s" must be a string' % field - assert len(obj[field]) > 0, 'Field "%s" must not be empty' % field - - -def assert_non_empty_list(obj, field): - assert isinstance(obj[field], list), \ - '%s must be a list' % field - assert len(obj[field]) > 0, \ - '%s list must not be empty' % field - - -def assert_non_empty_dict(obj, field): - assert isinstance(obj[field], dict), \ - '%s must be a dict' % field - assert len(obj[field]) > 0, \ - '%s dict must not be empty' % field - - -def assert_contains(obj, field): - assert field in obj, 'Must contain field "%s"' % field - - -def assert_value_from(obj, field, items): - assert obj[field] in items, \ - 'Field "%s" must be from: %s' % (field, str(items)) - - -def assert_atom_or_list_items_from(obj, field, items): - if isinstance(obj[field], basestring) or isinstance(obj[field], int): - assert_value_from(obj, field, items) - return - - assert isinstance(obj[field], list), '%s must be a list' % field - for allowed_value in obj[field]: - assert allowed_value != '*', "Wildcard is not supported for lists!" - assert allowed_value in items, \ - 'Field "%s" must be from: %s' % (field, str(items)) - - -def assert_contains_only_fields(obj, expected_fields): - for expected_field in expected_fields: - assert_contains(obj, expected_field) - - for actual_field in obj: - assert actual_field in expected_fields, \ - 'Unexpected field "%s".' % actual_field - - -def assert_value_unique_in(value, used_values): - assert value not in used_values, 'Duplicate value "%s"!' % str(value) - used_values[value] = True - - -def assert_valid_artifact(exp_pattern, artifact_key, schema): - if isinstance(schema, list): - assert_atom_or_list_items_from(exp_pattern, artifact_key, - ["*"] + schema) - return - - for sub_artifact_key, sub_schema in schema.iteritems(): - assert_valid_artifact(exp_pattern[artifact_key], sub_artifact_key, - sub_schema) - -def validate(spec_json, details): - """ Validates the json specification for generating tests. """ - - details['object'] = spec_json - assert_contains_only_fields(spec_json, ["specification", - "referrer_policy_schema", - "test_expansion_schema", - "excluded_tests"]) - assert_non_empty_list(spec_json, "specification") - assert_non_empty_list(spec_json, "referrer_policy_schema") - assert_non_empty_dict(spec_json, "test_expansion_schema") - assert_non_empty_list(spec_json, "excluded_tests") - - specification = spec_json['specification'] - referrer_policy_schema = spec_json['referrer_policy_schema'] - test_expansion_schema = spec_json['test_expansion_schema'] - excluded_tests = spec_json['excluded_tests'] - - valid_test_expansion_fields = ['name'] + test_expansion_schema.keys() - - # Validate each single spec. - for spec in specification: - details['object'] = spec - - # Validate required fields for a single spec. - assert_contains_only_fields(spec, ['name', - 'title', - 'description', - 'referrer_policy', - 'specification_url', - 'test_expansion']) - assert_non_empty_string(spec, 'name') - assert_non_empty_string(spec, 'title') - assert_non_empty_string(spec, 'description') - assert_non_empty_string(spec, 'specification_url') - assert_value_from(spec, 'referrer_policy', referrer_policy_schema) - assert_non_empty_list(spec, 'test_expansion') - - # Validate spec's test expansion. - used_spec_names = {} - - for spec_exp in spec['test_expansion']: - details['object'] = spec_exp - assert_non_empty_string(spec_exp, 'name') - # The name is unique in same expansion group. - assert_value_unique_in((spec_exp['expansion'], spec_exp['name']), - used_spec_names) - assert_contains_only_fields(spec_exp, valid_test_expansion_fields) - - for artifact in test_expansion_schema: - details['test_expansion_field'] = artifact - assert_valid_artifact(spec_exp, artifact, - test_expansion_schema[artifact]) - del details['test_expansion_field'] - - # Validate the test_expansion schema members. - details['object'] = test_expansion_schema - assert_contains_only_fields(test_expansion_schema, ['expansion', - 'delivery_method', - 'redirection', - 'origin', - 'source_protocol', - 'target_protocol', - 'subresource', - 'referrer_url']) - # Validate excluded tests. - details['object'] = excluded_tests - for excluded_test_expansion in excluded_tests: - assert_contains_only_fields(excluded_test_expansion, - valid_test_expansion_fields) - details['object'] = excluded_test_expansion - for artifact in test_expansion_schema: - details['test_expansion_field'] = artifact - assert_valid_artifact( - excluded_test_expansion, - artifact, - test_expansion_schema[artifact]) - del details['test_expansion_field'] - - del details['object'] - - -def assert_valid_spec_json(spec_json): - error_details = {} - try: - validate(spec_json, error_details) - except AssertionError as err: - print('ERROR:', err.message) - print(json.dumps(error_details, indent=4)) - sys.exit(1) - - -def main(): - spec_json = load_spec_json(); - assert_valid_spec_json(spec_json) - print("Spec JSON is valid.") - - -if __name__ == '__main__': - main() diff --git a/tests/wpt/web-platform-tests/referrer-policy/spec.src.json b/tests/wpt/web-platform-tests/referrer-policy/spec.src.json index 5f0247b935b..f69c289526a 100644 --- a/tests/wpt/web-platform-tests/referrer-policy/spec.src.json +++ b/tests/wpt/web-platform-tests/referrer-policy/spec.src.json @@ -5,51 +5,62 @@ "title": "Referrer Policy is not explicitly defined", "description": "Check that referrer URL follows no-referrer-when-downgrade policy when no explicit Referrer Policy is set.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policies", - "referrer_policy": null, "test_expansion": [ { "name": "insecure-protocol", "expansion": "default", - "source_protocol": "http", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": null, "redirection": "*", - "origin": "*", + "origin": [ + "same-http", + "cross-http" + ], "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "upgrade-protocol", "expansion": "default", - "source_protocol": "http", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": null, "redirection": "*", - "origin": "*", + "origin": [ + "same-https", + "cross-https" + ], "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "downgrade-protocol", "expansion": "default", - "source_protocol": "https", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": null, "redirection": "*", - "origin": "*", + "origin": [ + "same-http", + "cross-http" + ], "subresource": "*", - "referrer_url": "omitted" + "expectation": "omitted" }, { "name": "secure-protocol", "expansion": "default", - "source_protocol": "https", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": null, "redirection": "*", - "origin": "*", + "origin": [ + "same-https", + "cross-https" + ], "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" } ] }, @@ -58,18 +69,17 @@ "title": "Referrer Policy is set to 'no-referrer'", "description": "Check that sub-resource never gets the referrer URL.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-no-referrer", - "referrer_policy": "no-referrer", "test_expansion": [ { "name": "generic", "expansion": "default", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "no-referrer", "redirection": "*", "origin": "*", "subresource": "*", - "referrer_url": "omitted" + "expectation": "omitted" } ] }, @@ -78,51 +88,62 @@ "title": "Referrer Policy is set to 'no-referrer-when-downgrade'", "description": "Check that non a priori insecure subresource gets the full Referrer URL. A priori insecure subresource gets no referrer information.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-no-referrer-when-downgrade", - "referrer_policy": "no-referrer-when-downgrade", "test_expansion": [ { "name": "insecure-protocol", "expansion": "default", - "source_protocol": "http", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "no-referrer-when-downgrade", "redirection": "*", - "origin": "*", + "origin": [ + "same-http", + "cross-http" + ], "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "upgrade-protocol", "expansion": "default", - "source_protocol": "http", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "no-referrer-when-downgrade", "redirection": "*", - "origin": "*", + "origin": [ + "same-https", + "cross-https" + ], "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "downgrade-protocol", "expansion": "default", - "source_protocol": "https", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "no-referrer-when-downgrade", "redirection": "*", - "origin": "*", + "origin": [ + "same-http", + "cross-http" + ], "subresource": "*", - "referrer_url": "omitted" + "expectation": "omitted" }, { "name": "secure-protocol", "expansion": "default", - "source_protocol": "https", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "no-referrer-when-downgrade", "redirection": "*", - "origin": "*", + "origin": [ + "same-https", + "cross-https" + ], "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" } ] }, @@ -131,18 +152,17 @@ "title": "Referrer Policy is set to 'origin'", "description": "Check that all subresources in all casses get only the origin portion of the referrer URL.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-origin", - "referrer_policy": "origin", "test_expansion": [ { "name": "generic", "expansion": "default", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "origin", "redirection": "*", "origin": "*", "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" } ] }, @@ -151,51 +171,56 @@ "title": "Referrer Policy is set to 'same-origin'", "description": "Check that cross-origin subresources get no referrer information and same-origin get the stripped referrer URL.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-same-origin", - "referrer_policy": "same-origin", "test_expansion": [ { "name": "same-origin-insecure", "expansion": "default", - "source_protocol": "http", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "same-origin", "redirection": "*", - "origin": "same-origin", + "origin": "same-http", "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "same-origin-secure-default", "expansion": "default", - "source_protocol": "https", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "same-origin", "redirection": "*", - "origin": "same-origin", + "origin": "same-https", "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "same-origin-insecure", "expansion": "override", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], - "redirection": "swap-origin-redirect", - "origin": "same-origin", - "subresource": "*", - "referrer_url": "omitted" + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "same-origin", + "redirection": "swap-origin", + "origin": [ + "same-http", + "same-https" + ], + "subresource": "*", + "expectation": "omitted" }, { "name": "cross-origin", "expansion": "default", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "same-origin", "redirection": "*", - "origin": "cross-origin", + "origin": [ + "cross-http", + "cross-https" + ], "subresource": "*", - "referrer_url": "omitted" + "expectation": "omitted" } ] }, @@ -204,73 +229,78 @@ "title": "Referrer Policy is set to 'origin-when-cross-origin'", "description": "Check that cross-origin subresources get the origin portion of the referrer URL and same-origin get the stripped referrer URL.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-origin-when-cross-origin", - "referrer_policy": "origin-when-cross-origin", "test_expansion": [ { "name": "same-origin-insecure", "expansion": "default", - "source_protocol": "http", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "origin-when-cross-origin", "redirection": "*", - "origin": "same-origin", + "origin": "same-http", "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "same-origin-secure-default", "expansion": "default", - "source_protocol": "https", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "origin-when-cross-origin", "redirection": "*", - "origin": "same-origin", + "origin": "same-https", "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "same-origin-upgrade", "expansion": "default", - "source_protocol": "http", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "origin-when-cross-origin", "redirection": "*", - "origin": "same-origin", + "origin": "same-https", "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" }, { "name": "same-origin-downgrade", "expansion": "default", - "source_protocol": "https", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "origin-when-cross-origin", "redirection": "*", - "origin": "same-origin", + "origin": "same-http", "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" }, { "name": "same-origin-insecure", "expansion": "override", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], - "redirection": "swap-origin-redirect", - "origin": "same-origin", - "subresource": "*", - "referrer_url": "origin" + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "origin-when-cross-origin", + "redirection": "swap-origin", + "origin": [ + "same-http", + "same-https" + ], + "subresource": "*", + "expectation": "origin" }, { "name": "cross-origin", "expansion": "default", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "origin-when-cross-origin", "redirection": "*", - "origin": "cross-origin", + "origin": [ + "cross-http", + "cross-https" + ], "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" } ] }, @@ -279,51 +309,62 @@ "title": "Referrer Policy is set to 'strict-origin'", "description": "Check that non a priori insecure subresource gets only the origin portion of the referrer URL. A priori insecure subresource gets no referrer information.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-strict-origin", - "referrer_policy": "strict-origin", "test_expansion": [ { "name": "insecure-protocol", "expansion": "default", - "source_protocol": "http", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "strict-origin", "redirection": "*", - "origin": "*", + "origin": [ + "same-http", + "cross-http" + ], "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" }, { "name": "upgrade-protocol", "expansion": "default", - "source_protocol": "http", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "strict-origin", "redirection": "*", - "origin": "*", + "origin": [ + "same-https", + "cross-https" + ], "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" }, { "name": "downgrade-protocol", "expansion": "default", - "source_protocol": "https", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "strict-origin", "redirection": "*", - "origin": "*", + "origin": [ + "same-http", + "cross-http" + ], "subresource": "*", - "referrer_url": "omitted" + "expectation": "omitted" }, { "name": "secure-protocol", "expansion": "default", - "source_protocol": "https", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "strict-origin", "redirection": "*", - "origin": "*", + "origin": [ + "same-https", + "cross-https" + ], "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" } ] }, @@ -332,95 +373,100 @@ "title": "Referrer Policy is set to 'strict-origin-when-cross-origin'", "description": "Check that a priori insecure subresource gets no referrer information. Otherwise, cross-origin subresources get the origin portion of the referrer URL and same-origin get the stripped referrer URL.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-strict-origin-when-cross-origin", - "referrer_policy": "strict-origin-when-cross-origin", "test_expansion": [ { "name": "same-insecure", "expansion": "default", - "source_protocol": "http", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "strict-origin-when-cross-origin", "redirection": "*", - "origin": "same-origin", + "origin": "same-http", "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "same-insecure", "expansion": "override", - "source_protocol": "http", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], - "redirection": "swap-origin-redirect", - "origin": "same-origin", + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "strict-origin-when-cross-origin", + "redirection": "swap-origin", + "origin": "same-http", "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" }, { "name": "cross-insecure", "expansion": "default", - "source_protocol": "http", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "strict-origin-when-cross-origin", "redirection": "*", - "origin": "cross-origin", + "origin": "cross-http", "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" }, { "name": "upgrade-protocol", "expansion": "default", - "source_protocol": "http", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "strict-origin-when-cross-origin", "redirection": "*", - "origin": "*", + "origin": [ + "same-https", + "cross-https" + ], "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" }, { "name": "downgrade-protocol", "expansion": "default", - "source_protocol": "https", - "target_protocol": "http", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "strict-origin-when-cross-origin", "redirection": "*", - "origin": "*", + "origin": [ + "same-http", + "cross-http" + ], "subresource": "*", - "referrer_url": "omitted" + "expectation": "omitted" }, { "name": "same-secure", "expansion": "default", - "source_protocol": "https", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "strict-origin-when-cross-origin", "redirection": "*", - "origin": "same-origin", + "origin": "same-https", "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" }, { "name": "same-secure", "expansion": "override", - "source_protocol": "https", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], - "redirection": "swap-origin-redirect", - "origin": "same-origin", + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "strict-origin-when-cross-origin", + "redirection": "swap-origin", + "origin": "same-https", "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" }, { "name": "cross-secure", "expansion": "default", - "source_protocol": "https", - "target_protocol": "https", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "strict-origin-when-cross-origin", "redirection": "*", - "origin": "cross-origin", + "origin": "cross-https", "subresource": "*", - "referrer_url": "origin" + "expectation": "origin" } ] }, @@ -429,199 +475,185 @@ "title": "Referrer Policy is set to 'unsafe-url'", "description": "Check that all sub-resources get the stripped referrer URL.", "specification_url": "https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-unsafe-url", - "referrer_policy": "unsafe-url", "test_expansion": [ { "name": "generic", "expansion": "default", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["http-rp", "meta-referrer", "attr-referrer"], + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "unsafe-url", "redirection": "*", "origin": "*", "subresource": "*", - "referrer_url": "stripped-referrer" + "expectation": "stripped-referrer" } ] } ], - - "excluded_tests":[ + "delivery_key": "referrerPolicy", + "excluded_tests": [ { "name": "cross-origin-workers", "expansion": "*", - "source_protocol": "*", - "target_protocol": "*", + "source_scheme": "*", "redirection": "*", - "delivery_method": "*", - "origin": "cross-origin", + "delivery_type": "*", + "delivery_value": "*", + "origin": [ + "cross-http", + "cross-https" + ], "subresource": [ "worker-request", "module-worker", "shared-worker" ], - "referrer_url": "*" + "expectation": "*" }, { "name": "upgraded-protocol-workers", "expansion": "*", - "source_protocol": "http", - "target_protocol": "https", - "delivery_method": "*", + "source_scheme": "http", + "delivery_type": "*", + "delivery_value": "*", "redirection": "*", - "origin": "*", + "origin": [ + "same-https", + "cross-https" + ], "subresource": [ "worker-request", "module-worker", "shared-worker" ], - "referrer_url": "*" + "expectation": "*" }, { "name": "mixed-content-insecure-subresources", "expansion": "*", - "source_protocol": "https", - "target_protocol": "http", - "delivery_method": "*", - "redirection": "*", - "origin": "*", - "subresource": "*", - "referrer_url": "*" - }, - { - "name": "elements-not-supporting-attr-referrer", - "expansion": "*", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["attr-referrer"], + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "*", "redirection": "*", - "origin": "*", - "subresource": [ - "xhr-request", - "worker-request", - "module-worker", - "shared-worker", - "fetch-request" + "origin": [ + "same-http", + "cross-http" ], - "referrer_url": "*" - }, - { - "name": "elements-not-supporting-rel-noreferrer", - "expansion": "*", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": ["rel-noreferrer"], - "redirection": "*", - "origin": "*", - "subresource": [ - "iframe-tag", - "img-tag", - "script-tag", - "xhr-request", - "worker-request", - "module-worker", - "shared-worker", - "fetch-request", - "area-tag" - ], - "referrer_url": "*" + "subresource": "*", + "expectation": "*" }, { "name": "area-tag", "expansion": "*", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": "*", + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "*", "redirection": "*", "origin": "*", "subresource": "area-tag", - "referrer_url": "*" + "expectation": "*" }, { "name": "worker-requests-with-swap-origin-redirect", "expansion": "*", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": "*", - "redirection": "swap-origin-redirect", + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "*", + "redirection": "swap-origin", "origin": "*", "subresource": [ "worker-request", "module-worker", "shared-worker" ], - "referrer_url": "*" + "expectation": "*" }, { "name": "overhead-for-redirection", "expansion": "*", - "source_protocol": "*", - "target_protocol": "*", - "delivery_method": "*", - "redirection": ["keep-origin-redirect", "swap-origin-redirect"], + "source_scheme": "*", + "delivery_type": "*", + "delivery_value": "*", + "redirection": [ + "keep-origin", + "swap-origin" + ], "origin": "*", - "subresource": ["a-tag", "area-tag"], - "referrer_url": "*" + "subresource": [ + "a-tag", + "area-tag" + ], + "expectation": "*" }, { "name": "source-https-unsupported-by-web-platform-tests-runners", "expansion": "*", - "source_protocol": "https", - "target_protocol": "*", - "delivery_method": "*", + "source_scheme": "https", + "delivery_type": "*", + "delivery_value": "*", + "redirection": "*", + "origin": "*", + "subresource": "*", + "expectation": "*" + }, + { + "name": "<link rel=noreferrer>'s delivery_value should be no-referrer", + "expansion": "*", + "source_scheme": "*", + "delivery_type": "rel-noref", + "delivery_value": [ + null, + "no-referrer-when-downgrade", + "same-origin", + "origin", + "origin-when-cross-origin", + "strict-origin", + "strict-origin-when-cross-origin", + "unsafe-url" + ], "redirection": "*", "origin": "*", "subresource": "*", - "referrer_url": "*" + "expectation": "*" } ], - - "referrer_policy_schema": [ - null, - "no-referrer", - "no-referrer-when-downgrade", - "same-origin", - "origin", - "origin-when-cross-origin", - "strict-origin", - "strict-origin-when-cross-origin", - "unsafe-url" - ], - "test_expansion_schema": { "expansion": [ "default", "override" ], - - "delivery_method": [ + "delivery_type": [ + "attr", + "rel-noref", "http-rp", - "meta-referrer", - "attr-referrer", - "rel-noreferrer" + "meta" ], - - "origin": [ + "delivery_value": [ + null, + "no-referrer", + "no-referrer-when-downgrade", "same-origin", - "cross-origin" + "origin", + "origin-when-cross-origin", + "strict-origin", + "strict-origin-when-cross-origin", + "unsafe-url" ], - - "source_protocol": [ - "http", - "https" + "origin": [ + "same-http", + "same-https", + "cross-http", + "cross-https" ], - - "target_protocol": [ + "source_scheme": [ "http", "https" ], - "redirection": [ "no-redirect", - "keep-origin-redirect", - "swap-origin-redirect" + "keep-origin", + "swap-origin" ], - "subresource": [ "iframe-tag", "img-tag", @@ -634,8 +666,7 @@ "shared-worker", "fetch-request" ], - - "referrer_url": [ + "expectation": [ "omitted", "origin", "stripped-referrer" diff --git a/tests/wpt/web-platform-tests/resources/idlharness.js b/tests/wpt/web-platform-tests/resources/idlharness.js index 9be554d96b6..e7a3abbec44 100644 --- a/tests/wpt/web-platform-tests/resources/idlharness.js +++ b/tests/wpt/web-platform-tests/resources/idlharness.js @@ -251,6 +251,15 @@ IdlArray.prototype.add_dependency_idls = function(raw_idls, options) this.includes[k].forEach(v => all_deps.add(v)); }); this.partials.forEach(p => all_deps.add(p.name)); + // Add 'TypeOfType' for each "typedef TypeOfType MyType;" entry. + Object.entries(this.members).forEach(([k, v]) => { + if (v instanceof IdlTypedef) { + let defs = v.idlType.union + ? v.idlType.idlType.map(t => t.idlType) + : [v.idlType.idlType]; + defs.forEach(d => all_deps.add(d)); + } + }); // Add the attribute idlTypes of all the nested members of idls. const attrDeps = parsedIdls => { @@ -488,8 +497,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options) break; case "callback": - // TODO - console.log("callback not yet supported"); + this.members[parsed_idl.name] = new IdlCallback(parsed_idl); break; case "enum": @@ -1163,9 +1171,13 @@ IdlArray.prototype.assert_type_is = function(value, type) { // TODO: Test when we actually have something to test this on } + else if (this.members[type] instanceof IdlCallback) + { + assert_equals(typeof value, "function"); + } else { - throw new IdlHarnessError("Type " + type + " isn't an interface or dictionary"); + throw new IdlHarnessError("Type " + type + " isn't an interface, callback or dictionary"); } }; @@ -3096,6 +3108,24 @@ function IdlEnum(obj) IdlEnum.prototype = Object.create(IdlObject.prototype); +/// IdlCallback /// +// Used for IdlArray.prototype.assert_type_is +function IdlCallback(obj) +{ + /** + * obj is an object produced by the WebIDLParser.js "callback" + * production. + */ + + /** Self-explanatory. */ + this.name = obj.name; + + /** Arguments for the callback. */ + this.arguments = obj.arguments; +} + +IdlCallback.prototype = Object.create(IdlObject.prototype); + /// IdlTypedef /// // Used for IdlArray.prototype.assert_type_is function IdlTypedef(obj) diff --git a/tests/wpt/web-platform-tests/std-toast/options.html b/tests/wpt/web-platform-tests/std-toast/options.html index 6d4a462d3a9..9f53bf88601 100644 --- a/tests/wpt/web-platform-tests/std-toast/options.html +++ b/tests/wpt/web-platform-tests/std-toast/options.html @@ -101,4 +101,29 @@ async_test(t => { toast.remove(); }); }, 'showToast closes after user specified 50ms'); + +async_test(t => { + const toast = showToast('message', {duration: Infinity}); + + t.step_timeout(() => { + assertToastShown(toast); + t.done(); + }, 50); + + t.add_cleanup(function() { + toast.remove(); + }); +}, 'passing Infinity as the duration leaves the toast open for at least 50ms'); + +test(() => { + assert_throws(new RangeError(), () => { + const toast = showToast('Message', {duration: 0}); + }); +}, 'setting the duration to 0 throws a RangeError'); + +test(() => { + assert_throws(new RangeError(), () => { + const toast = showToast('Message', {duration: -5}); + }); +}, 'setting the duration to a negative number throws a RangeError'); </script> diff --git a/tests/wpt/web-platform-tests/svg/coordinate-systems/support/viewBox-change-repaint-001-ref.html b/tests/wpt/web-platform-tests/svg/coordinate-systems/support/viewBox-change-repaint-001-ref.html new file mode 100644 index 00000000000..e13e368d7b8 --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/coordinate-systems/support/viewBox-change-repaint-001-ref.html @@ -0,0 +1,11 @@ +<!doctype HTML> +<head> + <meta charset="utf-8"> + <title>Reference case for dynamic viewBox change</title> + <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com"> +</head> +<body> + <svg id="mySVG" style="height: 200px; width: 200px;"> + <rect width="200" height="200" fill="lime"></rect> + </svg> +</body> diff --git a/tests/wpt/web-platform-tests/svg/coordinate-systems/viewBox-change-repaint-001.html b/tests/wpt/web-platform-tests/svg/coordinate-systems/viewBox-change-repaint-001.html new file mode 100644 index 00000000000..2a90349754b --- /dev/null +++ b/tests/wpt/web-platform-tests/svg/coordinate-systems/viewBox-change-repaint-001.html @@ -0,0 +1,23 @@ +<!doctype HTML> +<head> + <meta charset="utf-8"> + <title>Testcase for dynamic viewBox change</title> + <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com"> + <link rel="help" href="https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute"> + <link rel="match" href="support/viewBox-change-repaint-001-ref.html"> + <script> + function go() { + var mySVG = document.getElementById("mySVG"); + mySVG.setAttribute("viewBox", "0 0 10 10"); + } + </script> +</head> +<body onload="go()"> + <!-- After we dynamically add viewBox="0 0 10 10", the lime area should + stretch to fill the 200x200 SVG viewport, and no red should be visible. + --> + <svg id="mySVG" style="height: 200px; width: 200px;"> + <rect width="200" height="200" fill="red"></rect> + <rect width="10" height="10" fill="lime"></rect> + </svg> +</body> diff --git a/tests/wpt/web-platform-tests/tools/requirements_flake8.txt b/tests/wpt/web-platform-tests/tools/requirements_flake8.txt index 480aacd4662..d73e7c3dbbe 100644 --- a/tests/wpt/web-platform-tests/tools/requirements_flake8.txt +++ b/tests/wpt/web-platform-tests/tools/requirements_flake8.txt @@ -1,4 +1,4 @@ -flake8==3.7.7 +flake8==3.7.8 pycodestyle==2.5.0 pyflakes==2.1.1 pep8-naming==0.8.2 diff --git a/tests/wpt/web-platform-tests/tools/requirements_mypy.txt b/tests/wpt/web-platform-tests/tools/requirements_mypy.txt index 8f1d67cd212..c1bf4bc088e 100644 --- a/tests/wpt/web-platform-tests/tools/requirements_mypy.txt +++ b/tests/wpt/web-platform-tests/tools/requirements_mypy.txt @@ -1,3 +1,3 @@ -mypy==0.711 +mypy==0.720 mypy-extensions==0.4.1 typed-ast==1.4.0 diff --git a/tests/wpt/web-platform-tests/tools/tox.ini b/tests/wpt/web-platform-tests/tools/tox.ini index ba6dc038a17..63fb8ed9832 100644 --- a/tests/wpt/web-platform-tests/tools/tox.ini +++ b/tests/wpt/web-platform-tests/tools/tox.ini @@ -13,6 +13,7 @@ commands = pytest {posargs} passenv = HYPOTHESIS_PROFILE + PY_COLORS [testenv:py27-flake8] deps = -rrequirements_flake8.txt diff --git a/tests/wpt/web-platform-tests/tools/wpt/run.py b/tests/wpt/web-platform-tests/tools/wpt/run.py index 6acc5b8e740..d5d7e7a21f5 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/run.py +++ b/tests/wpt/web-platform-tests/tools/wpt/run.py @@ -661,7 +661,7 @@ def main(): if __name__ == "__main__": import pdb - from tools import localpaths # noqa: flake8 + from tools import localpaths # noqa: F401 try: main() except Exception: diff --git a/tests/wpt/web-platform-tests/tools/wpt/wpt.py b/tests/wpt/web-platform-tests/tools/wpt/wpt.py index 4130e1eecf8..93301dd86b4 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/wpt.py +++ b/tests/wpt/web-platform-tests/tools/wpt/wpt.py @@ -4,7 +4,7 @@ import logging import os import sys -from tools import localpaths # noqa: flake8 +from tools import localpaths # noqa: F401 from six import iteritems from . import virtualenv diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/README.rst b/tests/wpt/web-platform-tests/tools/wptrunner/README.rst index 76e496dcdbb..d4f976dfca1 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/README.rst +++ b/tests/wpt/web-platform-tests/tools/wptrunner/README.rst @@ -155,6 +155,9 @@ An example of an expectation file is:: if platform == 'osx': ERROR FAIL + [subtest3] + expected: [PASS, TIMEOUT] + [filename.html?query=something] disabled: bug12345 @@ -222,7 +225,9 @@ The web-platform-test harness knows about several keys: `expected` Must evaluate to a possible test status indicating the expected result of the test. The implicit default is PASS or OK when the - field isn't present. + field isn't present. When `expected` is a list, the first status + is the primary expected status and the trailing statuses listed are + expected intermittent statuses. `disabled` Any value indicates that the test is disabled. diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/docs/expectation.rst b/tests/wpt/web-platform-tests/tools/wptrunner/docs/expectation.rst index 7fe89d943eb..9b3e5e05e5c 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/docs/expectation.rst +++ b/tests/wpt/web-platform-tests/tools/wptrunner/docs/expectation.rst @@ -98,6 +98,25 @@ wptupdate takes several useful options: Overwrite all the expectation data for any tests that have a result in the passed log files, not just data for the same platform. +``--disable-intermittent`` + When updating test results, disable tests that have inconsistent + results across many runs. This can precede a message providing a + reason why that test is disable. If no message is provided, + ``unstable`` is the default text. + +``--update-intermittent`` + When this option is used, the ``expected`` key (see below) stores + expected intermittent statuses in addition to the primary expected + status. If there is more than one status, it appears as a list. The + default behaviour of this option is to retain any existing intermittent + statuses in the list unless ``--remove-intermittent`` is specified. + +``--remove-intermittent`` + This option is used in conjunction with ``--update-intermittent``. + When the ``expected`` statuses are updated, any obsolete intermittent + statuses that did not occur in the specified logfiles are removed from + the list. + Examples ~~~~~~~~ @@ -190,7 +209,8 @@ When used for expectation data, manifests have the following format: * A subsection per subtest, with the heading being the title of the subtest. - * A key ``expected`` giving the expectation value of each (sub)test. + * A key ``expected`` giving the expectation value or values of each + (sub)test. * A key ``disabled`` which can be set to any value to indicate that the (sub)test is disabled and should either not be run (for tests) @@ -236,6 +256,9 @@ An simple example manifest might look like:: [Test something unsupported] expected: FAIL + [Test with intermittent statuses] + expected: [PASS, TIMEOUT] + [test.html?variant=broken] expected: ERROR diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements.txt index e25eec38283..d6c7a4ff398 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements.txt @@ -2,7 +2,7 @@ html5lib==1.0.1 mozinfo==1.1.0 mozlog==4.2.0 mozdebug==0.1.1 -pillow==6.0.0 +pillow==6.1.0 urllib3[secure]==1.25.3 requests==2.22.0 six==1.12.0 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py index 2f58022d238..7e6d017d541 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py @@ -160,7 +160,7 @@ def run_info_extras(**kwargs): rv = {"e10s": kwargs["gecko_e10s"], "wasm": kwargs.get("wasm", True), "verify": kwargs["verify"], - "headless": "MOZ_HEADLESS" in os.environ, + "headless": kwargs.get("headless", False) or "MOZ_HEADLESS" in os.environ, "fission": get_bool_pref("fission.autostart"), "sw-e10s": get_bool_pref("dom.serviceWorkers.parent_intercept")} rv.update(run_info_browser_version(kwargs["binary"])) diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox_android.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox_android.py index d8d5c7f7284..b6d7bc8851e 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox_android.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox_android.py @@ -1,13 +1,10 @@ import os -import tempfile import moznetwork from mozprocess import ProcessHandler from mozprofile import FirefoxProfile from mozrunner import FennecEmulatorRunner -from tools.serve.serve import make_hosts_file - from .base import (get_free_port, cmd_arg, browser_command) @@ -34,7 +31,6 @@ __wptrunner__ = {"product": "firefox_android", "timeout_multiplier": "get_timeout_multiplier"} - def check_args(**kwargs): pass @@ -85,21 +81,6 @@ def env_options(): "supports_debugger": True} -def write_hosts_file(config, device): - new_hosts = make_hosts_file(config, moznetwork.get_ip()) - current_hosts = device.get_file("/etc/hosts") - if new_hosts == current_hosts: - return - hosts_fd, hosts_path = tempfile.mkstemp() - try: - with os.fdopen(hosts_fd, "w") as f: - f.write(new_hosts) - device.remount() - device.push(hosts_path, "/etc/hosts") - finally: - os.remove(hosts_path) - - class FirefoxAndroidBrowser(FirefoxBrowser): init_timeout = 300 shutdown_timeout = 60 @@ -132,22 +113,28 @@ class FirefoxAndroidBrowser(FirefoxBrowser): preferences = self.load_prefs() self.profile = FirefoxProfile(preferences=preferences) - self.profile.set_preferences({"marionette.port": self.marionette_port, - "dom.disable_open_during_load": False, - "places.history.enabled": False, - "dom.send_after_paint_to_content": True, - "network.preload": True}) + self.profile.set_preferences({ + "marionette.port": self.marionette_port, + "network.dns.localDomains": ",".join(self.config.domains_set), + "dom.disable_open_during_load": False, + "places.history.enabled": False, + "dom.send_after_paint_to_content": True, + "network.preload": True, + }) + if self.test_type == "reftest": self.logger.info("Setting android reftest preferences") - self.profile.set_preferences({"browser.viewport.desktopWidth": 800, - # Disable high DPI - "layout.css.devPixelsPerPx": "1.0", - # Ensure that the full browser element - # appears in the screenshot - "apz.allow_zooming": False, - "android.widget_paints_background": False, - # Ensure that scrollbars are always painted - "layout.testing.overlay-scrollbars.always-visible": True}) + self.profile.set_preferences({ + "browser.viewport.desktopWidth": 800, + # Disable high DPI + "layout.css.devPixelsPerPx": "1.0", + # Ensure that the full browser element + # appears in the screenshot + "apz.allow_zooming": False, + "android.widget_paints_background": False, + # Ensure that scrollbars are always painted + "layout.testing.overlay-scrollbars.always-visible": True, + }) if self.install_fonts: self.logger.debug("Copying Ahem font to profile") @@ -189,26 +176,30 @@ class FirefoxAndroidBrowser(FirefoxBrowser): # connect to a running emulator self.runner.device.connect() - write_hosts_file(self.config, self.runner.device.device) - self.runner.stop() - self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) + self.runner.start(debug_args=debug_args, + interactive=self.debug_info and self.debug_info.interactive) self.runner.device.device.forward( local="tcp:{}".format(self.marionette_port), remote="tcp:{}".format(self.marionette_port)) + for ports in self.config.ports.values(): + for port in ports: + self.runner.device.device.reverse( + local="tcp:{}".format(port), + remote="tcp:{}".format(port)) + self.logger.debug("%s Started" % self.package_name) def stop(self, force=False): if self.runner is not None: - if (self.runner.device.connected and - len(self.runner.device.device.list_forwards()) > 0): + if self.runner.device.connected: try: - self.runner.device.device.remove_forwards( - "tcp:{}".format(self.marionette_port)) - except Exception: - self.logger.warning("Failed to remove port forwarding") + self.runner.device.device.remove_forwards() + self.runner.device.device.remove_reverses() + except Exception as e: + self.logger.warning("Failed to remove forwarded or reversed ports: %s" % e) # We assume that stopping the runner prompts the # browser to shut down. This allows the leak log to be written self.runner.stop() diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py index 2493f1fa440..92440921641 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py @@ -14,7 +14,7 @@ here = os.path.split(__file__)[0] repo_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir, os.pardir)) sys.path.insert(0, repo_root) -from tools import localpaths # noqa: flake8 +from tools import localpaths # noqa: F401 from wptserve.handlers import StringHandler diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/wptreport.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/wptreport.py index c58422d0de0..d73911f6a94 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/wptreport.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/wptreport.py @@ -104,6 +104,8 @@ class WptreportFormatter(BaseFormatter): subtest["status"] = data["status"] if "expected" in data: subtest["expected"] = data["expected"] + if "known_intermittent" in data: + subtest["known_intermittent"] = data["known_intermittent"] if "message" in data: subtest["message"] = replace_lone_surrogate(data["message"]) @@ -114,6 +116,8 @@ class WptreportFormatter(BaseFormatter): test["status"] = data["status"] if "expected" in data: test["expected"] = data["expected"] + if "known_intermittent" in data: + test["known_intermittent"] = data["known_intermittent"] if "message" in data: test["message"] = replace_lone_surrogate(data["message"]) if "reftest_screenshots" in data.get("extra", {}): diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_formatters.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_formatters.py index ec91cca1c13..72f3a591ad7 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_formatters.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_formatters.py @@ -104,7 +104,9 @@ def test_wptreport_lone_surrogate_ucs2(capfd): logger = structuredlog.StructuredLogger("test_a") logger.add_handler(handlers.StreamHandler(output, WptreportFormatter())) - with mock.patch.object(wptreport, 'surrogate_replacement', wptreport.SurrogateReplacementUcs2()): + with mock.patch.object(wptreport, + 'surrogate_replacement', + wptreport.SurrogateReplacementUcs2()): # output a bunch of stuff logger.suite_start(["test-id-1"]) # no run_info arg! logger.test_start("test-id-1") @@ -131,3 +133,36 @@ def test_wptreport_lone_surrogate_ucs2(capfd): subtest = test["subtests"][0] assert subtest["name"] == u"Name with surrogateU+d800" assert subtest["message"] == u"\U0001F601 U+de0aU+d83d \U0001f60a" + + +def test_wptreport_known_intermittent(capfd): + output = StringIO() + logger = structuredlog.StructuredLogger("test_a") + logger.add_handler(handlers.StreamHandler(output, WptreportFormatter())) + + # output a bunch of stuff + logger.suite_start(["test-id-1"]) # no run_info arg! + logger.test_start("test-id-1") + logger.test_status("test-id-1", + "a-subtest", + status="FAIL", + expected="PASS", + known_intermittent=["FAIL"]) + logger.test_end("test-id-1", + status="OK",) + logger.suite_end() + + # check nothing got output to stdout/stderr + # (note that mozlog outputs exceptions during handling to stderr!) + captured = capfd.readouterr() + assert captured.out == "" + assert captured.err == "" + + # check the actual output of the formatter + output.seek(0) + output_obj = json.load(output) + test = output_obj["results"][0] + assert test["status"] == u"OK" + subtest = test["subtests"][0] + assert subtest["expected"] == u"PASS" + assert subtest["known_intermittent"] == [u'FAIL'] diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py index a0f42377734..0bcaf823b72 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py @@ -10,7 +10,7 @@ from .state import SavedState, UnsavedState def setup_paths(sync_path): sys.path.insert(0, os.path.abspath(sync_path)) - from tools import localpaths # noqa: flake8 + from tools import localpaths # noqa: F401 class LoadConfig(Step): """Step for loading configuration from the ini file and kwargs.""" diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wpttest.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wpttest.py index 5f50fbcef11..2ce15a0d9c7 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wpttest.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wpttest.py @@ -111,8 +111,11 @@ class RunInfo(dict): self["wasm"] = False if extras is not None: self.update(extras) + + self["headless"] = extras.get("headless", False) self["webrender"] = enable_webrender + def _update_mozinfo(self, metadata_root): """Add extra build information from a mozinfo.json file in a parent directory""" diff --git a/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.https.html b/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.https.html index 3074895ba13..8dda8b23c8f 100644 --- a/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.https.html +++ b/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.https.html @@ -6,20 +6,24 @@ </head> <body> <script> - // CSP insists the "trusted-types: ..." directives are deliverd as headers + // CSP insists the "trusted-types: ..." directives are delivered as headers // (rather than as "<meta http-equiv" tags). This test assumes the following // headers are set in the .headers file: // // Content-Security-Policy: trusted-types one // Content-Security-Policy-Report-Only: trusted-types two; report-uri ... // Content-Security-Policy: plugin-types bla/blubb + // Content-Security-Policy: default-src * 'unsafe-inline' // - // The last rule is there so we can provoke a CSP violation report at will. + // The third rule is there so we can provoke a CSP violation report at will. // The intent is that in order to test that a violation has *not* been thrown // (and without resorting to abominations like timeouts), we force a *another* - // CSP violation (by violating the img-src rule) and when that event is + // CSP violation (by violating the plugin-types rule) and when that event is // processed we can we sure that an earlier event - if it indeed occurred - // must have already been processed. + // + // The last rule allows all scripting except 'unsafe-eval', so we can also + // test reporting of this case. const url = "" + document.location; @@ -72,7 +76,6 @@ }); } - promise_test(t => { let p = Promise.resolve() .then(promise_violation("trusted-types one")) @@ -134,10 +137,89 @@ return p; }, "Trusted Type violation report: assign trusted HTML to html; no report"); + // Test the "sample" field of the event. + // TODO(vogelheim): The current set of tests allows for more variance in the + // sample reports than the current spec draft does. Once the spec has + // been finalized, we should clamp this down to check byte-for-byte + // against the values mandated by the spec. + + function expect_sample(s) { return e => { + assert_true(e.sample.includes(s), + `expected "${e.sample}" to include "${s}".`); + return e; + } } + + promise_test(t => { + let p = Promise.resolve() + .then(promise_violation("trusted-types two")) + .then(expect_sample("Element.innerHTML")) + .then(expect_sample("abc")); + expect_throws(_ => { document.getElementById("div").innerHTML = "abc" }); + return p; + }, "Trusted Type violation report: sample for .innerHTML assignment"); + + promise_test(t => { + let p = Promise.resolve() + .then(promise_violation("trusted-types two")) + .then(expect_sample("HTMLAnchorElement.href")); + expect_throws(_ => { document.getElementById("anchor").href = "" }); + return p; + }, "Trusted Type violation report: sample for .href assignment"); + + promise_test(t => { + let p = Promise.resolve() + .then(promise_violation("trusted-types two")) + .then(expect_sample("HTMLElement.innerText")) + .then(expect_sample("2+2;")); + expect_throws(_ => document.getElementById("script").innerText = "2+2;"); + return p; + }, "Trusted Type violation report: sample for script innerText assignment"); + + promise_test(t => { + let p = Promise.resolve() + .then(promise_violation("trusted-types one")) + .then(expect_sample("eval")) + .then(expect_sample("2+2")) + .then(promise_flush()); + expect_throws(_ => eval("2+2")); + flush(); + return p; + }, "Trusted Type violation report: sample for eval"); + + promise_test(t => { + // We expect the sample string to always contain the name, and at least the + // start of the value, but it should not be excessively long. + let p = Promise.resolve() + .then(promise_violation("trusted-types two")) + .then(expect_sample("HTMLElement.innerText")) + .then(expect_sample("abbb")) + .then(e => assert_less_than(e.sample.length, 150)); + const value = "a" + "b".repeat(50000); + expect_throws(_ => document.getElementById("script").innerText = value); + return p; + }, "Trusted Type violation report: large values should be handled sanely."); + + // Test reporting for Custom Elements (where supported). The report should + // refer to the DOM elements being modified, so that Custom Elements cannot + // "mask" the underlying DOM mechanism (for reporting). + if (customElements) { + class CustomLink extends HTMLAnchorElement {}; + customElements.define("custom-link", CustomLink, { extends: "a" }); + + promise_test(t => { + let p = Promise.resolve() + .then(promise_violation("trusted-types one")) + .then(expect_sample("HTMLAnchorElement.href")) + .then(expect_sample("abc")); + expect_throws(_ => document.getElementById("customlink").href = "abc"); + return p; + }, "Trusted Type violation report: sample for custom element assignment"); + } </script> <!-- Some elements for the tests to act on. --> <a id="anchor" href="">anchor</a> <div id="div"></div> - + <script id="script"></script> + <a id="customlink" is="custom-link" href="a"></a> </body> diff --git a/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.https.html.headers b/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.https.html.headers index 8093b8474d6..947a151c874 100644 --- a/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.https.html.headers +++ b/tests/wpt/web-platform-tests/trusted-types/trusted-types-reporting.tentative.https.html.headers @@ -1,4 +1,5 @@ Content-Security-Policy: trusted-types one Content-Security-Policy-Report-Only: trusted-types two; report-uri /content-security-policy/resources/dummy-report.php Content-Security-Policy: plugin-types bla/blubb +Content-Security-Policy: default-src * 'unsafe-inline' diff --git a/tests/wpt/web-platform-tests/upgrade-insecure-requests/support/generate.py b/tests/wpt/web-platform-tests/upgrade-insecure-requests/support/generate.py index 4fb7078e770..1b0c2897fee 100644 --- a/tests/wpt/web-platform-tests/upgrade-insecure-requests/support/generate.py +++ b/tests/wpt/web-platform-tests/upgrade-insecure-requests/support/generate.py @@ -8,7 +8,7 @@ template = '''<!DOCTYPE html> <html> <head> -<!-- Generated by wpt/upgrade-insecure-requests/support/generate.py --> +<!-- Generated by wpt/upgrade-insecure-requests/support/generate.py -->%(additionalMeta)s <title>Upgrade Insecure Requests: %(name)s.</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -26,6 +26,12 @@ tests.forEach(test => testMap['%(name)s'](test)); </html> ''' +def getLong(file): + testsThatNeedMoreTime = [ "worker-subresource-fetch-redirect-upgrade.https.html" ] + if any(file in item for item in testsThatNeedMoreTime ): + return '\n<meta name="timeout" content="long">' + return "" + # resourceType is |ResourceType| in testharness-helper.sub.js. for name, resourceType in [ ('image', 'IMAGE'), ('iframe', 'FRAME'), @@ -40,9 +46,11 @@ for name, resourceType in [ if name == 'module-worker' or resourceType == 'WORKLET': types.append(('-import', 'generateModuleImportTests')) for typeName, generatorName in types: - with open('%s%s-upgrade.https.html' % (name, typeName), 'w') as html_file: + filename = '%s%s-upgrade.https.html' % (name, typeName) + with open(filename, 'w') as html_file: html_file.write(template % { 'name': name, + 'additionalMeta': getLong(filename), 'resourceType': resourceType, 'generatorName': generatorName, 'sameOriginOnly': sameOriginOnly}) diff --git a/tests/wpt/web-platform-tests/upgrade-insecure-requests/worker-subresource-fetch-redirect-upgrade.https.html b/tests/wpt/web-platform-tests/upgrade-insecure-requests/worker-subresource-fetch-redirect-upgrade.https.html index 948dd6566c2..bcda7ed4432 100644 --- a/tests/wpt/web-platform-tests/upgrade-insecure-requests/worker-subresource-fetch-redirect-upgrade.https.html +++ b/tests/wpt/web-platform-tests/upgrade-insecure-requests/worker-subresource-fetch-redirect-upgrade.https.html @@ -2,6 +2,7 @@ <html> <head> <!-- Generated by wpt/upgrade-insecure-requests/support/generate.py --> +<meta name="timeout" content="long"> <title>Upgrade Insecure Requests: worker-subresource-fetch.</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> diff --git a/tests/wpt/web-platform-tests/webdriver/tests/get_window_rect/get.py b/tests/wpt/web-platform-tests/webdriver/tests/get_window_rect/get.py index ee2c9eefd3f..b5103787e15 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/get_window_rect/get.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/get_window_rect/get.py @@ -1,4 +1,4 @@ -from tests.support.asserts import assert_error +from tests.support.asserts import assert_error, assert_success from tests.support.inline import inline @@ -16,15 +16,15 @@ def test_no_browsing_context(session, closed_window): def test_payload(session): - response = get_window_rect(session) - - assert response.status == 200 - assert isinstance(response.body["value"], dict) - value = response.body["value"] expected = session.execute_script("""return { x: window.screenX, y: window.screenY, width: window.outerWidth, height: window.outerHeight }""") - assert expected == value + + response = get_window_rect(session) + value = assert_success(response) + + assert isinstance(value, dict) + assert value == expected diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-helper.js b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-helper.js index 6a4ce854db7..25ddd99bb09 100644 --- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-helper.js +++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-helper.js @@ -331,6 +331,21 @@ function waitForConnectionStateChange(pc, wantedStates) { }); } +// Returns a promise that resolves when |pc.connectionState| is in one of the +// wanted states. +function waitForConnectionStateChange(pc, wantedStates) { + return new Promise((resolve) => { + if (wantedStates.includes(pc.connectionState)) { + resolve(); + return; + } + pc.addEventListener('connectionstatechange', () => { + if (wantedStates.includes(pc.connectionState)) + resolve(); + }); + }); +} + // Resolves when RTP packets have been received. function listenForSSRCs(t, receiver) { return new Promise((resolve) => { diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html new file mode 100644 index 00000000000..4dcce451995 --- /dev/null +++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-restartIce-onnegotiationneeded.https.html @@ -0,0 +1,29 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="RTCPeerConnection-helper.js"></script> +<script> +"use strict"; + +promise_test(async t => { + const pc1 = new RTCPeerConnection(); + const pc2 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + t.add_cleanup(() => pc2.close()); + + pc1.addTransceiver("audio"); + + await pc1.setLocalDescription(await pc1.createOffer()); + pc1.restartIce(); + await pc2.setRemoteDescription(pc1.localDescription); + await pc2.setLocalDescription(await pc2.createAnswer()); + await pc1.setRemoteDescription(pc2.localDescription); + // When the setRemoteDescription() promise above is resolved a task should be + // queued to fire the onnegotiationneeded event. Because of this, we should + // have time to hook up the event listener *after* awaiting the SRD promise. + await new Promise(r => pc1.onnegotiationneeded = r); +}, "Negotiation needed when returning to stable does not fire too early"); + +</script> diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-restartIce.https.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-restartIce.https.html index 6b66975fdad..c069736fa0b 100644 --- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-restartIce.https.html +++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-restartIce.https.html @@ -39,6 +39,19 @@ async function assertNoNegotiationNeeded(t, pc) { assert_equals(event, undefined, "No negotiationneeded event"); } +// In Chromium, assert_equals() produces test expectations with the values +// compared. Because ufrags are different on each run, this would make Chromium +// test expectations different on each run on tests that failed when comparing +// ufrags. To work around this problem, assert_ufrags_equals() and +// assert_ufrags_not_equals() should be preferred over assert_equals() and +// assert_not_equals(). +function assert_ufrags_equals(x, y, description) { + assert_true(x === y, description); +} +function assert_ufrags_not_equals(x, y, description) { + assert_false(x === y, description); +} + promise_test(async t => { const pc1 = new RTCPeerConnection(); const pc2 = new RTCPeerConnection(); @@ -90,21 +103,21 @@ promise_test(async t => { const [oldUfrag1] = getUfrags(pc1.localDescription); const [oldUfrag2] = getUfrags(pc2.localDescription); await doSignalingHandshakeEndOnFirst(pc1, pc2); - assert_equals(getUfrags(pc1.localDescription)[0], oldUfrag1, "control 1"); - assert_equals(getUfrags(pc2.localDescription)[0], oldUfrag2, "control 2"); + assert_ufrags_equals(getUfrags(pc1.localDescription)[0], oldUfrag1, "control 1"); + assert_ufrags_equals(getUfrags(pc2.localDescription)[0], oldUfrag2, "control 2"); pc1.restartIce(); await new Promise(r => pc1.onnegotiationneeded = r); await doSignalingHandshakeEndOnFirst(pc1, pc2); const [newUfrag1] = getUfrags(pc1.localDescription); const [newUfrag2] = getUfrags(pc2.localDescription); - assert_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); - assert_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); await assertNoNegotiationNeeded(t, pc1); await doSignalingHandshakeEndOnFirst(pc1, pc2); - assert_equals(getUfrags(pc1.localDescription)[0], newUfrag1, "Unchanged 1"); - assert_equals(getUfrags(pc2.localDescription)[0], newUfrag2, "Unchanged 2"); + assert_ufrags_equals(getUfrags(pc1.localDescription)[0], newUfrag1, "Unchanged 1"); + assert_ufrags_equals(getUfrags(pc2.localDescription)[0], newUfrag2, "Unchanged 2"); }, "restartIce() causes fresh ufrags"); promise_test(async t => { @@ -124,15 +137,25 @@ promise_test(async t => { pc1.restartIce(); await pc2.setRemoteDescription(pc1.localDescription); await pc2.setLocalDescription(await pc2.createAnswer()); + // Several tests in this file initializes the onnegotiationneeded listener + // before the setLocalDescription() or setRemoteDescription() that we expect + // to trigger negotiation needed. This allows Chrome to exercise these tests + // without timing out due to a bug that causes onnegotiationneeded to fire too + // early. + // TODO(https://crbug.com/985797): Once Chrome does not fire ONN too early, + // simply do "await new Promise(...)" instead of + // "await negotiationNeededPromise" here and in other tests in this file. + const negotiationNeededPromise = + new Promise(r => pc1.onnegotiationneeded = r); await pc1.setRemoteDescription(pc2.localDescription); - assert_equals(getUfrags(pc1.localDescription)[0], oldUfrag1, "Unchanged 1"); - assert_equals(getUfrags(pc2.localDescription)[0], oldUfrag2, "Unchanged 2"); - await new Promise(r => pc1.onnegotiationneeded = r); + assert_ufrags_equals(getUfrags(pc1.localDescription)[0], oldUfrag1, "Unchanged 1"); + assert_ufrags_equals(getUfrags(pc2.localDescription)[0], oldUfrag2, "Unchanged 2"); + await negotiationNeededPromise; await doSignalingHandshakeEndOnFirst(pc1, pc2); const [newUfrag1] = getUfrags(pc1.localDescription); const [newUfrag2] = getUfrags(pc2.localDescription); - assert_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); - assert_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); await assertNoNegotiationNeeded(t, pc1); }, "restartIce() works in have-local-offer"); @@ -148,15 +171,17 @@ promise_test(async t => { pc1.restartIce(); await pc2.setRemoteDescription(pc1.localDescription); await pc2.setLocalDescription(await pc2.createAnswer()); + const negotiationNeededPromise = + new Promise(r => pc1.onnegotiationneeded = r); await pc1.setRemoteDescription(pc2.localDescription); const [oldUfrag1] = getUfrags(pc1.localDescription); const [oldUfrag2] = getUfrags(pc2.localDescription); - await new Promise(r => pc1.onnegotiationneeded = r); + await negotiationNeededPromise; await doSignalingHandshakeEndOnFirst(pc1, pc2); const [newUfrag1] = getUfrags(pc1.localDescription); const [newUfrag2] = getUfrags(pc2.localDescription); - assert_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); - assert_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); await assertNoNegotiationNeeded(t, pc1); }, "restartIce() works in initial have-local-offer"); @@ -177,15 +202,17 @@ promise_test(async t => { await pc1.setRemoteDescription(pc2.localDescription); pc1.restartIce(); await pc2.setRemoteDescription(await pc1.createAnswer()); + const negotiationNeededPromise = + new Promise(r => pc1.onnegotiationneeded = r); await pc1.setLocalDescription(pc2.remoteDescription); // End on pc1. No race - assert_equals(getUfrags(pc1.localDescription)[0], oldUfrag1, "Unchanged 1"); - assert_equals(getUfrags(pc2.localDescription)[0], oldUfrag2, "Unchanged 2"); - await new Promise(r => pc1.onnegotiationneeded = r); + assert_ufrags_equals(getUfrags(pc1.localDescription)[0], oldUfrag1, "Unchanged 1"); + assert_ufrags_equals(getUfrags(pc2.localDescription)[0], oldUfrag2, "Unchanged 2"); + await negotiationNeededPromise; await doSignalingHandshakeEndOnFirst(pc1, pc2); const [newUfrag1] = getUfrags(pc1.localDescription); const [newUfrag2] = getUfrags(pc2.localDescription); - assert_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); - assert_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); await assertNoNegotiationNeeded(t, pc1); }, "restartIce() works in have-remote-offer"); @@ -219,15 +246,17 @@ promise_test(async t => { pc1.restartIce(); await new Promise(r => pc1.onnegotiationneeded = r); + const negotiationNeededPromise = + new Promise(r => pc1.onnegotiationneeded = r); await doSignalingHandshakeEndOnSecond(pc2, pc1); - assert_equals(getUfrags(pc1.localDescription)[0], oldUfrag1, "nothing yet 1"); - assert_equals(getUfrags(pc2.localDescription)[0], oldUfrag2, "nothing yet 2"); - await new Promise(r => pc1.onnegotiationneeded = r); + assert_ufrags_equals(getUfrags(pc1.localDescription)[0], oldUfrag1, "nothing yet 1"); + assert_ufrags_equals(getUfrags(pc2.localDescription)[0], oldUfrag2, "nothing yet 2"); + await negotiationNeededPromise; await doSignalingHandshakeEndOnFirst(pc1, pc2); const [newUfrag1] = getUfrags(pc1.localDescription); const [newUfrag2] = getUfrags(pc2.localDescription); - assert_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); - assert_not_equals(newUfrag2, oldUfrag2, "ufrag 2 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); + assert_ufrags_not_equals(newUfrag2, oldUfrag2, "ufrag 2 changed"); await assertNoNegotiationNeeded(t, pc1); }, "restartIce() survives remote offer"); @@ -250,13 +279,13 @@ promise_test(async t => { await doSignalingHandshakeEndOnSecond(pc2, pc1); const [newUfrag1] = getUfrags(pc1.localDescription); const [newUfrag2] = getUfrags(pc2.localDescription); - assert_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); - assert_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); await assertNoNegotiationNeeded(t, pc1); await doSignalingHandshakeEndOnFirst(pc1, pc2); - assert_equals(getUfrags(pc1.localDescription)[0], newUfrag1, "Unchanged 1"); - assert_equals(getUfrags(pc2.localDescription)[0], newUfrag2, "Unchanged 2"); + assert_ufrags_equals(getUfrags(pc1.localDescription)[0], newUfrag1, "Unchanged 1"); + assert_ufrags_equals(getUfrags(pc2.localDescription)[0], newUfrag2, "Unchanged 2"); await assertNoNegotiationNeeded(t, pc1); }, "restartIce() is satisfied by remote ICE restart"); @@ -281,8 +310,8 @@ promise_test(async t => { await pc1.setRemoteDescription(pc2.localDescription); const [newUfrag1] = getUfrags(pc1.localDescription); const [newUfrag2] = getUfrags(pc2.localDescription); - assert_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); - assert_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); await assertNoNegotiationNeeded(t, pc1); }, "restartIce() trumps {iceRestart: false}"); @@ -302,13 +331,15 @@ promise_test(async t => { pc1.restartIce(); await new Promise(r => pc1.onnegotiationneeded = r); await pc1.setLocalDescription(await pc1.createOffer()); + const negotiationNeededPromise = + new Promise(r => pc1.onnegotiationneeded = r); await pc1.setLocalDescription({type: "rollback"}); - await new Promise(r => pc1.onnegotiationneeded = r); + await negotiationNeededPromise; await doSignalingHandshakeEndOnFirst(pc1, pc2); const [newUfrag1] = getUfrags(pc1.localDescription); const [newUfrag2] = getUfrags(pc2.localDescription); - assert_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); - assert_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag1, "ufrag 1 changed"); + assert_ufrags_not_equals(newUfrag1, oldUfrag2, "ufrag 2 changed"); await assertNoNegotiationNeeded(t, pc1); }, "restartIce() survives rollback"); @@ -340,21 +371,23 @@ promise_test(async t => { sdp = sdp.replace(getPwds({sdp})[0], oldPwds2[0]); const newUfrags2 = getUfrags({sdp}); const newPwds2 = getPwds({sdp}); - assert_equals(newUfrags2[0], oldUfrags2[0], "control ufrag match"); - assert_equals(newPwds2[0], oldPwds2[0], "control pwd match"); - assert_not_equals(newUfrags2[1], oldUfrags2[1], "control ufrag non-match"); - assert_not_equals(newPwds2[1], oldPwds2[1], "control pwd non-match"); + assert_ufrags_equals(newUfrags2[0], oldUfrags2[0], "control ufrag match"); + assert_ufrags_equals(newPwds2[0], oldPwds2[0], "control pwd match"); + assert_ufrags_not_equals(newUfrags2[1], oldUfrags2[1], "control ufrag non-match"); + assert_ufrags_not_equals(newPwds2[1], oldPwds2[1], "control pwd non-match"); await pc1.setRemoteDescription({type, sdp}); } + const negotiationNeededPromise = + new Promise(r => pc1.onnegotiationneeded = r); await pc1.setLocalDescription(await pc1.createAnswer()); const newUfrags1 = getUfrags(pc1.localDescription); - assert_equals(newUfrags1[0], oldUfrags1[0], "Unchanged 1"); - assert_not_equals(newUfrags1[1], oldUfrags1[1], "Restarted 2"); - await new Promise(r => pc1.onnegotiationneeded = r); + assert_ufrags_equals(newUfrags1[0], oldUfrags1[0], "Unchanged 1"); + assert_ufrags_not_equals(newUfrags1[1], oldUfrags1[1], "Restarted 2"); + await negotiationNeededPromise; await pc1.setLocalDescription(await pc1.createOffer()); const newestUfrags1 = getUfrags(pc1.localDescription); - assert_not_equals(newestUfrags1[0], oldUfrag1[0], "Restarted 1"); - assert_not_equals(newestUfrags1[1], oldUfrag1[1], "Restarted 2"); + assert_ufrags_not_equals(newestUfrags1[0], oldUfrags1[0], "Restarted 1"); + assert_ufrags_not_equals(newestUfrags1[1], oldUfrags1[1], "Restarted 2"); await assertNoNegotiationNeeded(t, pc1); }, "restartIce() survives remote offer containing partial restart"); diff --git a/tests/wpt/web-platform-tests/webrtc/RTCRtpTransceiver.https.html b/tests/wpt/web-platform-tests/webrtc/RTCRtpTransceiver.https.html index e3cd68809cc..67571895175 100644 --- a/tests/wpt/web-platform-tests/webrtc/RTCRtpTransceiver.https.html +++ b/tests/wpt/web-platform-tests/webrtc/RTCRtpTransceiver.https.html @@ -456,6 +456,20 @@ const offer = await pc1.createOffer(); await pc1.setLocalDescription(offer); await pc2.setRemoteDescription(offer); + + hasPropsAndUniqueMids(pc1.getTransceivers(), + [ + { + receiver: {track: {kind: "audio"}}, + sender: {track: {kind: "audio"}}, + direction: "sendrecv", + currentDirection: null, + stopped: false + } + ]); + + const lastMid = pc1.getTransceivers()[0].mid; + let answer = await pc2.createAnswer(); // Remove mid attr answer.sdp = answer.sdp.replace("a=mid:", "a=unknownattr:"); @@ -463,19 +477,31 @@ answer.sdp = answer.sdp.replace("a=group:", "a=unknownattr:"); await pc1.setRemoteDescription(answer); - hasPropsAndUniqueMids(pc1.getTransceivers(), + hasProps(pc1.getTransceivers(), [ { receiver: {track: {kind: "audio"}}, sender: {track: {kind: "audio"}}, direction: "sendrecv", currentDirection: "sendonly", - stopped: false + stopped: false, + mid: lastMid } ]); const reoffer = await pc1.createOffer(); await pc1.setLocalDescription(reoffer); + hasProps(pc1.getTransceivers(), + [ + { + receiver: {track: {kind: "audio"}}, + sender: {track: {kind: "audio"}}, + direction: "sendrecv", + currentDirection: "sendonly", + stopped: false, + mid: lastMid + } + ]); }; const checkAddTransceiverNoTrackDoesntPair = async t => { diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50-ref.html index c37ae7a7dfa..4d7553a8b7a 100644 --- a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50-ref.html +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50-ref.html @@ -9,7 +9,6 @@ body { margin:0 } width: 320px; height: 180px; position: relative; - font-size: 9px; } .cue { position: absolute; @@ -17,11 +16,15 @@ body { margin:0 } right: 0px; width: 64px; text-align: center; + font: 20px/1 Ahem; } -.cue > span { - font-family: Ahem, sans-serif; +.cueText { background: rgba(0,0,0,0.8); color: green; } </style> -<div class=video><span class=cue><span>Awesome!!!</span></span></div> +<div class=video> + <div class="cue"> + <span class="cueText">foo</span> + </div> +</div> diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50.html index ec0460f1b73..0f69e572511 100644 --- a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50.html +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50.html @@ -7,8 +7,8 @@ html { overflow:hidden } body { margin:0 } ::cue { - font-family: Ahem, sans-serif; - color: green + font: 20px/1 Ahem; + color: green; } </style> <script src="/common/reftest-wait.js"></script> diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size-ref.html new file mode 100644 index 00000000000..73db73ed6aa --- /dev/null +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size-ref.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<title>Reference for WebVTT rendering, align:center, position greater than 50%, size greater than maximum size</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<style> +html { overflow:hidden } +body { margin:0 } +.video { + display: inline-block; + width: 320px; + height: 180px; + position: relative; +} +.cue { + position: absolute; + bottom: 0px; + right: 0px; + width: 64px; + text-align: center; + font: 20px/1 Ahem; +} +.cueText { + background: rgba(0,0,0,0.8); + color: green; +} +</style> +<div class=video> + <div class="cue"> + <div><span class="cueText">Awe</span></div> + <div><span class="cueText">som</span></div> + <div><span class="cueText">e!!</span></div> + <div><span class="cueText">!</span></div> + </div> +</div> diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size.html new file mode 100644 index 00000000000..869b5f669e1 --- /dev/null +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_gt_50_size_gt_maximum_size.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<title>WebVTT rendering, align:center, position greater than 50%, size greater than maximum size</title> +<link rel="match" href="align_center_position_gt_50_size_gt_maximum_size-ref.html"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<style> +html { overflow:hidden } +body { margin:0 } +::cue { + font: 20px/1 Ahem; + color: green; +} +</style> +<script src="/common/reftest-wait.js"></script> +<video width="320" height="180" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();"> + <source src="/media/white.webm" type="video/webm"> + <source src="/media/white.mp4" type="video/mp4"> + <track src="support/align_center_position_gt_50_size_gt_maximum_size.vtt"> +</video> +<script> +document.getElementsByTagName('track')[0].track.mode = 'showing'; +</script> +</html> diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50-ref.html index 108495e4b00..baa65110463 100644 --- a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50-ref.html +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50-ref.html @@ -9,7 +9,6 @@ body { margin:0 } width: 320px; height: 180px; position: relative; - font-size: 9px; } .cue { position: absolute; @@ -17,12 +16,16 @@ body { margin:0 } left: 0px; right: 0; width: 64px; - text-align: center + text-align: center; + font: 20px/1 Ahem; } -.cue > span { - font-family: Ahem, sans-serif; +.cueText { background: rgba(0,0,0,0.8); color: green; } </style> -<div class=video><span class=cue><span>Awesome!!!</span></span></div> +<div class=video> + <div class="cue"> + <span class="cueText">foo</span> + </div> +</div> diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50.html index 160435c62e3..953e74183b2 100644 --- a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50.html +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50.html @@ -7,8 +7,8 @@ html { overflow:hidden } body { margin:0 } ::cue { - font-family: Ahem, sans-serif; - color: green + font: 20px/1 Ahem; + color: green; } </style> <script src="/common/reftest-wait.js"></script> diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size-ref.html index 296369332cf..aeaf757cc68 100644 --- a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size-ref.html +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size-ref.html @@ -9,20 +9,25 @@ body { margin:0 } width: 320px; height: 180px; position: relative; - font-size: 9px; } .cue { position: absolute; - bottom: 0; + bottom: 0px; left: 0px; - right: 0; width: 64px; text-align: center; + font: 20px/1 Ahem; } -.cue > span { - font-family: Ahem, sans-serif; +.cueText { background: rgba(0,0,0,0.8); color: green; } </style> -<div class=video><span class=cue><span>Awesome!!!</span></span></div> +<div class=video> + <div class="cue"> + <div><span class="cueText">Awe</span></div> + <div><span class="cueText">som</span></div> + <div><span class="cueText">e!!</span></div> + <div><span class="cueText">!</span></div> + </div> +</div> diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size.html index 04d0be47d90..174894bf0c5 100644 --- a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size.html +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50_size_gt_maximum_size.html @@ -7,8 +7,8 @@ html { overflow:hidden } body { margin:0 } ::cue { - font-family: Ahem, sans-serif; - color: green + font: 20px/1 Ahem; + color: green; } </style> <script src="/common/reftest-wait.js"></script> diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50.vtt index 4d8538a2be7..69fd3e00d90 100644 --- a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50.vtt +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50.vtt @@ -1,4 +1,4 @@ WEBVTT 00:00:00.000 --> 00:00:05.000 align:center position:90% -Awesome!!! +foo diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50_size_gt_maximum_size.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50_size_gt_maximum_size.vtt new file mode 100644 index 00000000000..50e80cc3e14 --- /dev/null +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_gt_50_size_gt_maximum_size.vtt @@ -0,0 +1,4 @@ +WEBVTT + +00:00:00.000 --> 00:00:05.000 align:center position:90% size:75% +Awesome!!! diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_lt_50.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_lt_50.vtt index 4ea1e656077..86f8c37ec5e 100644 --- a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_lt_50.vtt +++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_center_position_lt_50.vtt @@ -1,4 +1,4 @@ WEBVTT 00:00:00.000 --> 00:00:05.000 align:center position:10% -Awesome!!! +foo diff --git a/tests/wpt/web-platform-tests/webxr/exclusive_requestFrame_nolayer.https.html b/tests/wpt/web-platform-tests/webxr/exclusive_requestFrame_nolayer.https.html new file mode 100644 index 00000000000..d31b927631f --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/exclusive_requestFrame_nolayer.https.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> +let immersiveTestName = "XRSession requestAnimationFrame must fail if the session has " + + "no baseLayer for immersive"; + +let nonImmersiveTestName = "XRSession requestAnimationFrame must fail if the session has " + + "no baseLayer for non immersive"; + +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; + +let testFunction = (session, controller, t, sessionObjects) => new Promise((resolve, reject) => { + // Clear the base layer that the boilerplate sets. This ensures that the rAF + // won't fire. If the fire *does* fire, it will fail because the baseLayer + // won't match the new baselayer we later create. + session.updateRenderState({ + baseLayer: null + }); + let webglCanvas = document.getElementsByTagName('canvas')[0]; + let gl = sessionObjects.gl; + + // Session must have a baseLayer or frame requests will be ignored. + let webglLayer = new XRWebGLLayer(session, gl, { + compositionDisabled: session.mode == 'inline' }); + + function onEarlyFrame(time, vrFrame) { + // We shouldn't be allowed to reach this callback with no baseLayer + t.step(() => { + assert_equals(session.renderState.baseLayer, webglLayer); + }); + resolve(); + } + + // This callback shouldn't go through, since the session doesn't + // have a baseLayer when this call is made. + let handle = session.requestAnimationFrame(onEarlyFrame); + // Should still give us a valid handle, though. + assert_not_equals(handle, 0); + + // Wait for a bit and set the baseLayer. + t.step_timeout(() => { + // Once the base layer is set the previously registered callback should run. + session.updateRenderState({ + baseLayer: webglLayer + }); + }, 300); +}); + +xr_session_promise_test( + immersiveTestName, testFunction, fakeDeviceInitParams, 'immersive-vr'); +xr_session_promise_test( + nonImmersiveTestName, testFunction, fakeDeviceInitParams, 'inline'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/render_state_vertical_fov_immersive.https.html b/tests/wpt/web-platform-tests/webxr/render_state_vertical_fov_immersive.https.html new file mode 100644 index 00000000000..485438cabf6 --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/render_state_vertical_fov_immersive.https.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> +let testName = "inlineVerticalFieldOfView is set appropriately on immersively sessions"; + +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; + +let testFunction = function(session, fakeDeviceController, t) { + return new Promise((resolve, reject) => { + // inlineVerticalFieldOfView should be null for immersive sessions; + t.step(() => { + assert_equals(session.renderState.inlineVerticalFieldOfView, null); + }); + + // Trying to set it should throw an exception + try { + session.updateRenderState({ + inlineVerticalFieldOfView: 1.0 + }); + + t.step(() => { + assert_unreached("Should not be able to set inlineVerticalFieldOfView on immersive sessions"); + }); + } catch(err) { + t.step(() => { + assert_equals(err.name, "InvalidStateError"); + }); + } + + resolve(); + }); +}; + +xr_session_promise_test( + testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/render_state_vertical_fov_inline.https.html b/tests/wpt/web-platform-tests/webxr/render_state_vertical_fov_inline.https.html new file mode 100644 index 00000000000..8bf384f4f15 --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/render_state_vertical_fov_inline.https.html @@ -0,0 +1,90 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> +let testName = "inlineVerticalFieldOfView is set appropriately on inline sessions"; + +let fakeDeviceInitParams = VALID_NON_IMMERSIVE_DEVICE; + +// These are the min, max, and default from the WebXR Spec +let minFOV = 0.0; +let maxFOV = Math.PI; +let defaultFOV = Math.PI/2; + +function assertNotEquals(n1, n2, message) { + assert_greater_than(Math.abs(n1-n2), FLOAT_EPSILON, message); +} + +let testFunction = function(session, fakeDeviceController, t) { + // Helper method because the renderState does not (per the spec) get updated + // until the next rAF after it was updated, so this method returns a promise + // which will resolve when the updated state should be applied. + function updateAndApplyInlineFOV(fov) { + session.updateRenderState({ + inlineVerticalFieldOfView: fov + }); + + return new Promise((resolve, reject) => { + session.requestAnimationFrame(() => { resolve(); }); + }); + } + + // Helper method to keep the line length reasonable with a long attribute name + // and ensure that the nullable value actually has a value. + function getFOV() { + let fov = session.renderState.inlineVerticalFieldOfView; + t.step(() => { + assert_not_equals(fov, null); + }); + + return fov; + } + + return new Promise((resolve, reject) => { + // Begin by validating that the default is set as expected/specced. + t.step(() => { + assert_approx_equals(getFOV(), defaultFOV, FLOAT_EPSILON, "default"); + }); + + // Set something below min, and assert that it is not set below the min, + // and significantly different from the default. + updateAndApplyInlineFOV(-10).then(() => { + + t.step(() => { + let currentFOV = getFOV(); + assert_greater_than(currentFOV, minFOV, "FOV must be set to something greater than min"); + assert_less_than(currentFOV, maxFOV, "FOV must be set to something less than max"); + assertNotEquals(currentFOV, defaultFOV, "FOV should no longer be set to the default"); + }); + + // Set something above the max and assert that it is set to the max. + updateAndApplyInlineFOV(10).then(()=> { + t.step(()=> { + let currentFOV = getFOV(); + assert_greater_than(currentFOV, minFOV, "FOV must be set to something greater than min"); + assert_less_than(currentFOV, maxFOV, "FOV must be set to something less than max"); + assertNotEquals(currentFOV, defaultFOV, "FOV should not be set to the default"); + }); + + // Set to something reasonable and assert that the value gets set. + let normalFOV = 1.5; + updateAndApplyInlineFOV(normalFOV).then(() => { + t.step(() => { + assert_approx_equals(getFOV(), normalFOV, FLOAT_EPSILON, "FOV within min and max should get set"); + }); + + resolve(); + }); + }); + }); + }); +}; + +xr_session_promise_test( + testName, testFunction, fakeDeviceInitParams, 'inline'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/resources/webxr_util.js b/tests/wpt/web-platform-tests/webxr/resources/webxr_util.js index d75e5c7bd2e..022aca8c93e 100644 --- a/tests/wpt/web-platform-tests/webxr/resources/webxr_util.js +++ b/tests/wpt/web-platform-tests/webxr/resources/webxr_util.js @@ -123,7 +123,7 @@ function forEachWebxrObject(callback) { callback(window.XRCoordinateSystemEvent, 'XRCoordinateSystemEvent'); } -// Code for loading test api in chromium. +// Code for loading test API in Chromium. let loadChromiumResources = Promise.resolve().then(() => { if (!('MojoInterfaceInterceptor' in self)) { // Do nothing on non-Chromium-based browsers or when the Mojo bindings are @@ -131,26 +131,38 @@ let loadChromiumResources = Promise.resolve().then(() => { return; } + let chromiumResources = [ + '/gen/layout_test_data/mojo/public/js/mojo_bindings.js', + '/gen/mojo/public/mojom/base/time.mojom.js', + '/gen/gpu/ipc/common/mailbox_holder.mojom.js', + '/gen/gpu/ipc/common/sync_token.mojom.js', + '/gen/ui/display/mojom/display.mojom.js', + '/gen/ui/gfx/geometry/mojo/geometry.mojom.js', + '/gen/ui/gfx/mojo/gpu_fence_handle.mojom.js', + '/gen/ui/gfx/mojo/transform.mojom.js', + '/gen/device/vr/public/mojom/vr_service.mojom.js', + '/resources/chromium/webxr-test.js', + '/resources/testdriver.js', + '/resources/testdriver-vendor.js', + ]; + + // This infrastructure is also used by Chromium-specific internal tests that + // may need additional resources (e.g. internal API extensions), this allows + // those tests to rely on this infrastructure while ensuring that no tests + // make it into public WPTs that rely on APIs outside of the webxr test API. + if (typeof(additionalChromiumResources) !== 'undefined') { + chromiumResources = chromiumResources.concat(additionalChromiumResources); + } + let chain = Promise.resolve(); - ['/gen/layout_test_data/mojo/public/js/mojo_bindings.js', - '/gen/mojo/public/mojom/base/time.mojom.js', - '/gen/gpu/ipc/common/mailbox_holder.mojom.js', - '/gen/gpu/ipc/common/sync_token.mojom.js', - '/gen/ui/display/mojom/display.mojom.js', - '/gen/ui/gfx/geometry/mojo/geometry.mojom.js', - '/gen/ui/gfx/mojo/gpu_fence_handle.mojom.js', - '/gen/ui/gfx/mojo/transform.mojom.js', - '/gen/device/vr/public/mojom/vr_service.mojom.js', - '/resources/chromium/webxr-test.js', '/resources/testdriver.js', - '/resources/testdriver-vendor.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); + chromiumResources.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; diff --git a/tests/wpt/web-platform-tests/webxr/xrSession_requestAnimationFrame_timestamp.https.html b/tests/wpt/web-platform-tests/webxr/xrSession_requestAnimationFrame_timestamp.https.html new file mode 100644 index 00000000000..daa786b3686 --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/xrSession_requestAnimationFrame_timestamp.https.html @@ -0,0 +1,92 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> +const TEN_SECONDS = 10000; // 10k ms in ten seconds +const ONE_MINUTE = 60000; // 60k ms in one minute + +let immersiveTestName = "XRFrame getViewerPose updates on the next frame for immersive"; +let nonImmersiveTestName = "XRFrame getViewerPose updates on the next frame for non-immersive"; + +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; + +let testFunction = function(session, fakeDeviceController, t) { + return session.requestReferenceSpace('local') + .then((referenceSpace) => new Promise((resolve, reject) => { + let counter = 0; + let windowFrameTime = 0; + let frameTime = 0; + + function onFrameFirst(time, xrFrame) { + frameTime = time; + let now = performance.now(); + + t.step( () => { + // This callback must be the first one called. + assert_equals(counter, 0); + + // window.requestAnimationFrame and session.requestAnimationFrame + // should be providing timestamps that are on the same scale and + // within a resonable margin of error of eachother. This means that + // this frame's timestamp should be larger than one provided to a + // previous window.requestAnimationFrame and should also be within + // a sane delta of it. One minute is probably overly generous here, + // but it will at least catch cases where the times are reported with + // entirely different bases. + assert_greater_than(frameTime, windowFrameTime); + assert_approx_equals(frameTime, windowFrameTime, ONE_MINUTE); + + // There's going to be some disparity between performance.now() and + // the timestamp passed into the callback, but it shouldn't be huge. + // If they're more than ten seconds apart something has gone horribly + // wrong. + assert_approx_equals(frameTime, now, TEN_SECONDS); + }); + + counter++; + } + + function onFrameSubsequent(time, xrFrame) { + t.step( () => { + // The timestamp passed to this callback should be exactly equal to + // the one passed to the first callback in this set. + assert_equals(time, frameTime); + }); + + counter++; + } + + function onFrameLast(time, xrFrame) { + t.step( () => { + // Make sure all the previous callbacks fired as expected. + assert_equals(counter, 11); + }); + + // Finished. + resolve(); + } + + window.requestAnimationFrame((time) => { + windowFrameTime = time; + + // Queue up several callbacks + session.requestAnimationFrame(onFrameFirst); + for (let i = 0; i < 10; ++i) { + session.requestAnimationFrame(onFrameSubsequent); + } + session.requestAnimationFrame(onFrameLast); + }); + + })); +}; + +xr_session_promise_test( + immersiveTestName, testFunction, fakeDeviceInitParams, 'immersive-vr'); +xr_session_promise_test( + nonImmersiveTestName, testFunction, fakeDeviceInitParams, 'inline'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/xrView_match.https.html b/tests/wpt/web-platform-tests/webxr/xrView_match.https.html new file mode 100644 index 00000000000..142f272d36f --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/xrView_match.https.html @@ -0,0 +1,86 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<script src="resources/webxr_test_asserts.js"></script> +<canvas /> + +<script> + +let testName = "XRFrame contains the expected views"; + +const fakeViews = [{ + eye:"left", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewOffset: LEFT_OFFSET, + resolution: VALID_RESOLUTION + }, { + eye:"right", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewOffset: RIGHT_OFFSET, + resolution: VALID_RESOLUTION + }, +]; + +let fakeDeviceInitParams = { + supportsImmersive: true, + views: fakeViews, + viewerOrigin: IDENTITY_TRANSFORM +}; + +let testFunction = function(session, fakeDeviceController, t) { + return session.requestReferenceSpace('viewer').then(function(viewerSpace) { + return session.requestReferenceSpace('local').then((referenceSpace) => new Promise((resolve) => { + function onFrame(time, xrFrame) { + let pose = xrFrame.getViewerPose(referenceSpace); + assert_not_equals(pose, null); + assert_not_equals(pose.views, null); + assert_equals(pose.views.length, 2); + + { + let pose2 = xrFrame.getPose(viewerSpace, referenceSpace); + assert_not_equals(pose2, null); + + // This pose should have the same transform as the viewer pose, but without + // the views array. It should be an XRPose instead of the XRViewerPose derived + // class. + assert_true(pose2 instanceof XRPose); + assert_false(pose2 instanceof XRViewerPose); + assert_not_equals(pose2.transform, null); + assert_not_equals(pose2.transform.matrix, null); + assert_matrix_approx_equals(pose.transform.matrix, pose2.transform.matrix); + } + + // Ensure that two views are provided. + let leftView = pose.views[0]; + let rightView = pose.views[1]; + + // Ensure that the views are the right type. + assert_true(leftView instanceof XRView); + assert_true(rightView instanceof XRView); + + // Ensure that they have the expected eye enums. + assert_equals(leftView.eye, "left"); + assert_equals(rightView.eye, "right"); + + // Ensure they have the expected projection matrices. + assert_not_equals(leftView.projectionMatrix, null); + assert_not_equals(rightView.projectionMatrix, null); + + assert_matrix_approx_equals(leftView.projectionMatrix, VALID_PROJECTION_MATRIX); + assert_matrix_approx_equals(rightView.projectionMatrix, VALID_PROJECTION_MATRIX); + + // Finished test. + resolve(); + } + + session.requestAnimationFrame(onFrame); + })); + }); +}; + +xr_session_promise_test( + testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/xrView_oneframeupdate.https.html b/tests/wpt/web-platform-tests/webxr/xrView_oneframeupdate.https.html new file mode 100644 index 00000000000..9404fcb8aaf --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/xrView_oneframeupdate.https.html @@ -0,0 +1,79 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<script src="resources/webxr_test_asserts.js"></script> +<canvas /> + +<script> + +let testName = "XRView projection matrices update near and far depths on the " + + "next frame"; + +const fakeViews = [{ + eye:"left", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewOffset: LEFT_OFFSET, + resolution: VALID_RESOLUTION + }, { + eye:"right", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewOffset: RIGHT_OFFSET, + resolution: VALID_RESOLUTION + }, +]; + +let fakeDeviceInitParams = { + supportsImmersive: true, + views: fakeViews, + viewerOrigin: IDENTITY_TRANSFORM +}; + +let testFunction = function(session, fakeDeviceController, t) { + return session.requestReferenceSpace('local') + .then((referenceSpace) => new Promise((resolve) =>{ + let counter = 0; + + function onFrame(time, xrFrame) { + let pose = xrFrame.getViewerPose(referenceSpace); + assert_not_equals(pose, null); + assert_not_equals(pose.views, null); + assert_equals(pose.views.length, 2); + if (counter == 0) { + session.requestAnimationFrame(onFrame); + + assert_matrix_approx_equals(pose.views[0].projectionMatrix, VALID_PROJECTION_MATRIX); + assert_matrix_approx_equals(pose.views[1].projectionMatrix, VALID_PROJECTION_MATRIX); + + // Update the near and far depths for the session. + session.updateRenderState({ + depthNear: 1.0, + depthFar: 10.0 }); + + // The projection matrices the views report should not take into + // account the new session depth values this frame. + assert_matrix_approx_equals(pose.views[0].projectionMatrix, VALID_PROJECTION_MATRIX); + assert_matrix_approx_equals(pose.views[1].projectionMatrix, VALID_PROJECTION_MATRIX); + } else { + // New depth values should be retained between frames. + assert_equals(session.renderState.depthNear, 1.0); + assert_equals(session.renderState.depthFar, 10.0); + + // Projection matricies should now reflect the new depth values, i.e. + // have changed. + assert_matrix_significantly_not_equals(pose.views[0].projectionMatrix, VALID_PROJECTION_MATRIX); + assert_matrix_significantly_not_equals(pose.views[1].projectionMatrix, VALID_PROJECTION_MATRIX); + resolve(); + } + counter++; + } + + session.requestAnimationFrame(onFrame); + })); +}; + +xr_session_promise_test( + testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/xrViewport_valid.https.html b/tests/wpt/web-platform-tests/webxr/xrViewport_valid.https.html new file mode 100644 index 00000000000..1b7d982d596 --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/xrViewport_valid.https.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> +let testName = "XRViewport attributes are valid"; + +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; + +let testFunction = function(session, fakeDeviceController, t, sessionObjects) { + return session.requestReferenceSpace('local') + .then((referenceSpace) => new Promise((resolve) =>{ + let webglLayer = sessionObjects.glLayer; + function onFrame(time, xrFrame) { + let pose = xrFrame.getViewerPose(referenceSpace); + assert_not_equals(pose, null); + assert_not_equals(pose.views, null); + assert_equals(pose.views.length, 2); + + let leftView = pose.views[0]; + let rightView = pose.views[1]; + + let leftViewport = webglLayer.getViewport(leftView); + let rightViewport = webglLayer.getViewport(rightView); + + t.step(() => { + // Ensure the views report the expected viewports into the WebGL layer. + assert_true(leftViewport instanceof XRViewport); + assert_true(rightViewport instanceof XRViewport); + + assert_not_equals(leftViewport, null); + assert_not_equals(rightViewport, null); + + // Exact viewport values don't matter, but they must pass several tests: + + // Viewports have non-zero widths and heights. + assert_greater_than(leftViewport.width, 0); + assert_greater_than(leftViewport.height, 0); + assert_greater_than(rightViewport.width, 0); + assert_greater_than(rightViewport.height, 0); + + // Viewports are located within the framebuffer. + assert_greater_than_equal(leftViewport.x, 0); + assert_greater_than_equal(leftViewport.y, 0); + assert_greater_than_equal(leftViewport.x, 0); + assert_greater_than_equal(leftViewport.y, 0); + + assert_less_than_equal( + leftViewport.x + leftViewport.width, webglLayer.framebufferWidth); + assert_less_than_equal( + leftViewport.y + leftViewport.height, webglLayer.framebufferHeight); + assert_less_than_equal( + rightViewport.x + rightViewport.width, webglLayer.framebufferWidth); + assert_less_than_equal( + rightViewport.y + rightViewport.height, webglLayer.framebufferHeight); + + // Assumes that the left viewport will always be physically to the left + // of the right viewport. + assert_less_than_equal(leftViewport.x + leftViewport.width, rightViewport.x); + }); + + resolve(); + } + session.requestAnimationFrame(onFrame); + })); +}; + +xr_session_promise_test( + testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_constructor.https.html b/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_constructor.https.html new file mode 100644 index 00000000000..74f0e7611e5 --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_constructor.https.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> +xr_promise_test("Ensure that XRWebGLLayer's constructor throws appropriate errors", + (t) => { + let webglCanvas = document.getElementsByTagName('canvas')[0]; + let glAttributes = { + alpha: false, + antialias: false, + xrCompatible: false, + }; + let gl = webglCanvas.getContext('webgl', glAttributes); + return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE) + .then((controller) => { + return new Promise((resolve) => { + navigator.xr.test.simulateUserActivation(() => { + navigator.xr.requestSession('immersive-vr') + .then((session) => { + try { + let webglLayerIncompatible = new XRWebGLLayer(session, gl); + assert_unreached("XRWebGLLayer should fail when created with a context that is not XRCompatible") + } catch (err) { + assert_equals(err.name, "InvalidStateError"); + } + + gl.makeXRCompatible(); + + try { + let webglLayerGood = new XRWebGLLayer(session, gl); + } catch (err) { + reject("XRWebGLLayer should not fail with valid arguments"); + } + + let lose_context_ext = gl.getExtension('WEBGL_lose_context'); + + webglCanvas.addEventListener('webglcontextlost', (ev) => { + ev.preventDefault(); + + try { + let webglLayerBadContext = new XRWebGLLayer(session, gl); + reject("XRWebGLLayer should fail when created with a lost context"); + } catch (err) { + assert_equals(err.name, 'InvalidStateError'); + t.step_timeout(() => { lose_context_ext.restoreContext(); }, 100); + } + }); + + webglCanvas.addEventListener('webglcontextrestored', (ev) => { + resolve(session.end().then(() => { + try { + let webglLayerBadSession = new XRWebGLLayer(session, gl); + assert_unreached("XRWebGLLayer should fail when created with an ended session"); + } catch (err) { + assert_equals(err.name, 'InvalidStateError'); + } + })); + }); + + lose_context_ext.loseContext(); + }); + }); + }); + }); +}); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_framebuffer_draw.https.html b/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_framebuffer_draw.https.html new file mode 100644 index 00000000000..dd40865e445 --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_framebuffer_draw.https.html @@ -0,0 +1,93 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> + +let testName = + "Ensure a WebGL layer's framebuffer can only be drawn to inside a XR frame"; + +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; + +// Very simple program setup with no error checking. +function setupProgram(gl, vertexSrc, fragmentSrc) { + let program = gl.createProgram(); + + let vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader, vertexSrc); + gl.compileShader(vertexShader); + gl.attachShader(program, vertexShader); + + let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader, fragmentSrc); + gl.compileShader(fragmentShader); + gl.attachShader(program, fragmentShader); + + gl.linkProgram(program); + gl.useProgram(program); + + return program; +} + +let testFunction = + (session, fakeDeviceController, t, sessionObjects) => new Promise((resolve, reject) => { + let gl = sessionObjects.gl; + let webglLayer = sessionObjects.glLayer; + // Setup simple WebGL geometry to draw with. + let program = setupProgram(gl, + "attribute vec4 vPosition; void main() { gl_Position = vPosition; }", + "void main() { gl_FragColor = vec4(1.0,0.0,0.0,1.0); }" + ); + + let vertexObject = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), + gl.STATIC_DRAW); + gl.enableVertexAttribArray(0); + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); + + let indexObject = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2]), gl.STATIC_DRAW); + + let xrFramebuffer = webglLayer.framebuffer; + + function runDrawTests(expectedError) { + // Make sure we're starting with a clean error slate. + assert_equals(gl.getError(), gl.NO_ERROR); + + gl.bindFramebuffer(gl.FRAMEBUFFER, xrFramebuffer); + assert_equals(gl.getError(), gl.NO_ERROR); + + gl.clear(gl.COLOR_BUFFER_BIT); + assert_equals(gl.getError(), gl[expectedError]); + + gl.clear(gl.DEPTH_BUFFER_BIT); + assert_equals(gl.getError(), gl[expectedError]); + + gl.drawArrays(gl.TRIANGLES, 0, 3); + assert_equals(gl.getError(), gl[expectedError]); + + gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_BYTE, 0); + assert_equals(gl.getError(), gl[expectedError]); + } + + // Drawing operations outside of a XR frame should fail. + runDrawTests("INVALID_FRAMEBUFFER_OPERATION"); + + // Drawing operations within a XR frame should succeed. + session.requestAnimationFrame((time, xrFrame) => { + runDrawTests("NO_ERROR"); + resolve(); + }); +}); + +xr_session_promise_test( + testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_framebuffer_scale.https.html b/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_framebuffer_scale.https.html new file mode 100644 index 00000000000..7b5cedb1c83 --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_framebuffer_scale.https.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> + +let testName = "Ensure framebuffer scaling works as expected."; + +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; + +let testFunction = + (session, fakeDeviceController, t, sessionObjects) => new Promise((resolve, reject) => { + let gl = sessionObjects.gl; + let webglLayer = sessionObjects.glLayer; + let defaultFramebufferWidth = webglLayer.framebufferWidth; + let defaultFramebufferHeight = webglLayer.framebufferHeight; + let nativeScale = XRWebGLLayer.getNativeFramebufferScaleFactor(session); + + t.step(() => { + // Ensure the framebuffer default sizes and native scale are all non-zero. + assert_greater_than(defaultFramebufferWidth, 0); + assert_greater_than(defaultFramebufferHeight, 0); + assert_greater_than(nativeScale, 0); + + // The native scale should be the inverse for the default framebuffer scale. + assert_approx_equals(nativeScale, 1/fakeDeviceController.displayInfo_.webxrDefaultFramebufferScale, FLOAT_EPSILON); + }); + + webglLayer = new XRWebGLLayer(session, gl, { framebufferScaleFactor: nativeScale }); + t.step(() => { + // Ensure that requesting a native scale framebuffer gives the expected result. + assert_approx_equals(webglLayer.framebufferWidth, defaultFramebufferWidth*nativeScale, 2); + assert_approx_equals(webglLayer.framebufferHeight, defaultFramebufferHeight*nativeScale, 2); + }); + + webglLayer = new XRWebGLLayer(session, gl, { framebufferScaleFactor: 0 }); + t.step(() => { + // Ensure that the framebuffer has a lower bounds clamp. + assert_greater_than(webglLayer.framebufferWidth, 0); + assert_greater_than(webglLayer.framebufferHeight, 0); + }); + + webglLayer = new XRWebGLLayer(session, gl, { framebufferScaleFactor: 100 }); + t.step(() => { + // Ensure that the framebuffer has a reasonable upper bounds clamp. + assert_less_than(webglLayer.framebufferWidth, defaultFramebufferWidth*100); + assert_less_than(webglLayer.framebufferHeight, defaultFramebufferHeight*100); + }); + + resolve(); +}); + +xr_session_promise_test( + testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); + +</script> diff --git a/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_opaque_framebuffer.https.html b/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_opaque_framebuffer.https.html new file mode 100644 index 00000000000..ceff6251d56 --- /dev/null +++ b/tests/wpt/web-platform-tests/webxr/xrWebGLLayer_opaque_framebuffer.https.html @@ -0,0 +1,117 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<canvas /> + +<script> +let immersiveTestName = "Ensure that the framebuffer given by the WebGL layer" + + " is opaque for immersive"; +let nonImmersiveTestName = "Ensure that the framebuffer given by the WebGL layer" + + " is opaque for non-immersive"; + +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; + +let testFunction = + (session, fakeDeviceController, t, sessionObjects) => new Promise((resolve, reject) => { + let gl = sessionObjects.gl; + let webglLayer = sessionObjects.glLayer; + let xrFramebuffer = webglLayer.framebuffer; + + // Make sure we're starting with a clean error slate. + assert_equals(gl.getError(), gl.NO_ERROR); + + if (session.mode == 'inline') { + // Creating a layer with compositionDisabled should return a framebuffer of + // null, and as such most of these tests won't apply. + assert_equals(xrFramebuffer, null); + resolve(); + return; + } + + assert_not_equals(xrFramebuffer, null); + assert_greater_than(webglLayer.framebufferWidth, 0); + assert_greater_than(webglLayer.framebufferHeight, 0); + + gl.bindFramebuffer(gl.FRAMEBUFFER, xrFramebuffer); + assert_equals(gl.getError(), gl.NO_ERROR); + + gl.deleteFramebuffer(xrFramebuffer); + assert_equals(gl.getError(), gl.INVALID_OPERATION); + + // Make sure the framebuffer is still bound after failed attempt to delete. + let boundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); + assert_equals(xrFramebuffer, boundFramebuffer); + assert_equals(gl.getError(), gl.NO_ERROR); + + // Ensure the framebuffer attachment properties cannot be inspected. + let attachments = [ + gl.COLOR_ATTACHMENT0, + gl.DEPTH_ATTACHMENT, + gl.STENCIL_ATTACHMENT, + ]; + + let parameters = [ + gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, + gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, + ]; + + for (let attachment of attachments) { + for (let parameter of parameters) { + let value = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, parameter); + assert_equals(value, null); + assert_equals(gl.getError(), gl.INVALID_OPERATION); + } + } + + let width = 64; + let height = 64; + + // Ensure the framebuffer texture 2D attachmentments cannot be changed. + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + assert_equals(gl.getError(), gl.INVALID_OPERATION); + + // Ensure the framebuffer renderbuffer attachmentments cannot be changed. + let renderbuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, + gl.DEPTH_ATTACHMENT, + gl.RENDERBUFFER, + renderbuffer); + assert_equals(gl.getError(), gl.INVALID_OPERATION); + + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer); + assert_equals(gl.getError(), gl.INVALID_OPERATION); + + // Framebuffer status must be unsupported outside of a XR frame callback. + assert_equals(gl.checkFramebufferStatus(gl.FRAMEBUFFER), gl.FRAMEBUFFER_UNSUPPORTED); + + session.requestAnimationFrame((time, xrFrame) => { + // Framebuffer status must be complete inside of a XR frame callback. + assert_equals(gl.checkFramebufferStatus(gl.FRAMEBUFFER), gl.FRAMEBUFFER_COMPLETE); + // Finished. + resolve(); + }); +}); + +xr_session_promise_test( + immersiveTestName, testFunction, fakeDeviceInitParams, 'immersive-vr'); + +xr_session_promise_test( + nonImmersiveTestName, testFunction, fakeDeviceInitParams, 'inline'); + +</script> |