Update web-platform-tests to revision b9d4748d6a7f9b21bd420486955b44349aa005ea

This commit is contained in:
WPT Sync Bot 2019-05-30 10:23:26 +00:00
parent 0a9a222356
commit 28ed236c3a
76 changed files with 2158 additions and 581 deletions

View file

@ -14,6 +14,9 @@
[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]
@ -34,6 +37,3 @@
[Revoke blob URL after creating Request, will fetch]
expected: FAIL
[Revoke blob URL after calling fetch, fetch should succeed]
expected: FAIL

View file

@ -12205,18 +12205,36 @@
{}
]
],
"fullscreen/api/element-request-fullscreen-twice-manual.tentative.html": [
[
"fullscreen/api/element-request-fullscreen-twice-manual.tentative.html",
{}
]
],
"fullscreen/api/element-request-fullscreen-two-elements-manual.html": [
[
"fullscreen/api/element-request-fullscreen-two-elements-manual.html",
{}
]
],
"fullscreen/api/element-request-fullscreen-two-elements-manual.tentative.html": [
[
"fullscreen/api/element-request-fullscreen-two-elements-manual.tentative.html",
{}
]
],
"fullscreen/api/element-request-fullscreen-two-iframes-manual.html": [
[
"fullscreen/api/element-request-fullscreen-two-iframes-manual.html",
{}
]
],
"fullscreen/api/element-request-fullscreen-two-iframes-manual.tentative.html": [
[
"fullscreen/api/element-request-fullscreen-two-iframes-manual.tentative.html",
{}
]
],
"fullscreen/api/promises-resolve-manual.html": [
[
"fullscreen/api/promises-resolve-manual.html",
@ -69501,6 +69519,18 @@
{}
]
],
"css/CSS2/normal-flow/margin-collapse-through-percentage-padding.html": [
[
"css/CSS2/normal-flow/margin-collapse-through-percentage-padding.html",
[
[
"/css/reference/ref-filled-green-100px-square-only.html",
"=="
]
],
{}
]
],
"css/CSS2/normal-flow/margin-collapse-through-zero-height-block.html": [
[
"css/CSS2/normal-flow/margin-collapse-through-zero-height-block.html",
@ -109365,6 +109395,18 @@
{}
]
],
"css/css-backgrounds/border-radius-dynamic-from-no-radius.html": [
[
"css/css-backgrounds/border-radius-dynamic-from-no-radius.html",
[
[
"/css/css-backgrounds/border-radius-dynamic-from-no-radius-ref.html",
"=="
]
],
{}
]
],
"css/css-backgrounds/border-radius-horizontal-value-is-zero.html": [
[
"css/css-backgrounds/border-radius-horizontal-value-is-zero.html",
@ -178009,6 +178051,18 @@
{}
]
],
"css/motion/animation/reftests/offset-distance-interpolation-001.html": [
[
"css/motion/animation/reftests/offset-distance-interpolation-001.html",
[
[
"/css/motion/animation/reftests/offset-path-path-interpolation-ref.html",
"=="
]
],
{}
]
],
"css/motion/animation/reftests/offset-path-path-interpolation-001.html": [
[
"css/motion/animation/reftests/offset-path-path-interpolation-001.html",
@ -178021,6 +178075,18 @@
{}
]
],
"css/motion/animation/reftests/offset-rotate-interpolation-001.html": [
[
"css/motion/animation/reftests/offset-rotate-interpolation-001.html",
[
[
"/css/motion/animation/reftests/offset-path-path-interpolation-ref.html",
"=="
]
],
{}
]
],
"css/motion/offset-anchor-transform-box-fill-box.html": [
[
"css/motion/offset-anchor-transform-box-fill-box.html",
@ -261366,6 +261432,11 @@
{}
]
],
"css/css-backgrounds/border-radius-dynamic-from-no-radius-ref.html": [
[
{}
]
],
"css/css-backgrounds/border-radius-shorthand-002-ref.html": [
[
{}
@ -294646,6 +294717,26 @@
{}
]
],
"docs/writing-tests/python-handlers/index.md": [
[
{}
]
],
"docs/writing-tests/python-handlers/request.md": [
[
{}
]
],
"docs/writing-tests/python-handlers/response.md": [
[
{}
]
],
"docs/writing-tests/python-handlers/stash.md": [
[
{}
]
],
"docs/writing-tests/reftests.md": [
[
{}
@ -294661,6 +294752,11 @@
{}
]
],
"docs/writing-tests/server-pipes.md": [
[
{}
]
],
"docs/writing-tests/submission-process.md": [
[
{}
@ -307646,6 +307742,21 @@
{}
]
],
"html/semantics/embedded-content/the-img-element/srcset/resources/image.png": [
[
{}
]
],
"html/semantics/embedded-content/the-img-element/srcset/resources/image.png.headers": [
[
{}
]
],
"html/semantics/embedded-content/the-img-element/srcset/resources/resized.html": [
[
{}
]
],
"html/semantics/embedded-content/the-object-element/test0.html": [
[
{}
@ -322116,6 +322227,11 @@
{}
]
],
"service-workers/service-worker/resources/update-during-installation-worker.py": [
[
{}
]
],
"service-workers/service-worker/resources/update-fetch-worker.py": [
[
{}
@ -330671,6 +330787,11 @@
{}
]
],
"tools/wptrunner/wptrunner/wptmanifest/backends/base.py": [
[
{}
]
],
"tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py": [
[
{}
@ -358769,6 +358890,12 @@
{}
]
],
"css/css-box/box-chrome-crash-001.html": [
[
"css/css-box/box-chrome-crash-001.html",
{}
]
],
"css/css-box/inheritance.html": [
[
"css/css-box/inheritance.html",
@ -362465,6 +362592,12 @@
{}
]
],
"css/css-logical/inheritance.html": [
[
"css/css-logical/inheritance.html",
{}
]
],
"css/css-logical/logical-box-border-color.html": [
[
"css/css-logical/logical-box-border-color.html",
@ -362609,6 +362742,12 @@
{}
]
],
"css/css-logical/parsing/border-block-valid.html": [
[
"css/css-logical/parsing/border-block-valid.html",
{}
]
],
"css/css-logical/parsing/border-block-width-computed.html": [
[
"css/css-logical/parsing/border-block-width-computed.html",
@ -362627,6 +362766,66 @@
{}
]
],
"css/css-logical/parsing/border-inline-color-computed.html": [
[
"css/css-logical/parsing/border-inline-color-computed.html",
{}
]
],
"css/css-logical/parsing/border-inline-color-invalid.html": [
[
"css/css-logical/parsing/border-inline-color-invalid.html",
{}
]
],
"css/css-logical/parsing/border-inline-color-valid.html": [
[
"css/css-logical/parsing/border-inline-color-valid.html",
{}
]
],
"css/css-logical/parsing/border-inline-style-computed.html": [
[
"css/css-logical/parsing/border-inline-style-computed.html",
{}
]
],
"css/css-logical/parsing/border-inline-style-invalid.html": [
[
"css/css-logical/parsing/border-inline-style-invalid.html",
{}
]
],
"css/css-logical/parsing/border-inline-style-valid.html": [
[
"css/css-logical/parsing/border-inline-style-valid.html",
{}
]
],
"css/css-logical/parsing/border-inline-valid.html": [
[
"css/css-logical/parsing/border-inline-valid.html",
{}
]
],
"css/css-logical/parsing/border-inline-width-computed.html": [
[
"css/css-logical/parsing/border-inline-width-computed.html",
{}
]
],
"css/css-logical/parsing/border-inline-width-invalid.html": [
[
"css/css-logical/parsing/border-inline-width-invalid.html",
{}
]
],
"css/css-logical/parsing/border-inline-width-valid.html": [
[
"css/css-logical/parsing/border-inline-width-valid.html",
{}
]
],
"css/css-logical/parsing/inline-size-invalid.html": [
[
"css/css-logical/parsing/inline-size-invalid.html",
@ -398515,6 +398714,12 @@
{}
]
],
"html/semantics/embedded-content/the-img-element/srcset/avoid-reload-on-resize.html": [
[
"html/semantics/embedded-content/the-img-element/srcset/avoid-reload-on-resize.html",
{}
]
],
"html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html": [
[
"html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html",
@ -451870,6 +452075,12 @@
{}
]
],
"webrtc/RTCRtpSender-setStreams.https.html": [
[
"webrtc/RTCRtpSender-setStreams.https.html",
{}
]
],
"webrtc/RTCRtpSender-transport.https.html": [
[
"webrtc/RTCRtpSender-transport.https.html",
@ -456786,6 +456997,12 @@
{}
]
],
"webxr/xrWebGLLayer_viewports.https.html": [
[
"webxr/xrWebGLLayer_viewports.https.html",
{}
]
],
"workers/SharedWorker-MessageEvent-source.any.js": [
[
"workers/SharedWorker-MessageEvent-source.any.sharedworker.html",
@ -514849,7 +515066,7 @@
"support"
],
"cookies/http-state/resources/iframe-expectation-doc.html.py-str": [
"f2cf31312d7f6f5c1d1b406ff23ba4a48e6bf084",
"9b782a15f8451dada48b73e836f1dd716dd4f2d7",
"support"
],
"cookies/http-state/resources/test-files/0001-expected": [
@ -549144,6 +549361,10 @@
"0248ccb910a8de03bf5d0f989b0844cf4bd2cc45",
"reftest"
],
"css/CSS2/normal-flow/margin-collapse-through-percentage-padding.html": [
"dfd5015d050689c3c3a01d785ab7b75025794505",
"reftest"
],
"css/CSS2/normal-flow/margin-collapse-through-zero-height-block.html": [
"471a4c7f5a4c054b1141162f88fdda9416343a5b",
"reftest"
@ -580220,6 +580441,14 @@
"ceb41be975c90380e6def93961169b5082b9a3d6",
"visual"
],
"css/css-backgrounds/border-radius-dynamic-from-no-radius-ref.html": [
"72ada88416255c18c4e6606bee4b6cf8dc353698",
"support"
],
"css/css-backgrounds/border-radius-dynamic-from-no-radius.html": [
"335548f33ad4bb9d7c42b4b07323c0a398aa28fc",
"reftest"
],
"css/css-backgrounds/border-radius-horizontal-value-is-zero.html": [
"3a461699b2375d62e63b35e5437d871272e73870",
"reftest"
@ -581416,6 +581645,10 @@
"dde409360faf79a301c3ae3ea34a995d154d7bb4",
"support"
],
"css/css-box/box-chrome-crash-001.html": [
"351df37f1550ab40818b7f7f1c51191cfae5583e",
"testharness"
],
"css/css-box/inheritance.html": [
"5047b8b1df07cb1c774b5f579101d69b2482058a",
"testharness"
@ -600944,6 +601177,10 @@
"653925552f870f740d3c9fc397b4dc2267994103",
"reftest"
],
"css/css-logical/inheritance.html": [
"5546a20d6cd8aa3887735c1f9955929dedbadaab",
"testharness"
],
"css/css-logical/logical-box-border-color.html": [
"b33528d9cd16b6de169cbd03e98b867403f090a6",
"testharness"
@ -601044,6 +601281,10 @@
"860a1052b8346aadbbbf18faf818ab9248f35535",
"testharness"
],
"css/css-logical/parsing/border-block-valid.html": [
"973a1199c285f99713c4ef3790b77a391bf09926",
"testharness"
],
"css/css-logical/parsing/border-block-width-computed.html": [
"3b4d934f8b23b29cd5d7b3aae039ac51ac4ab410",
"testharness"
@ -601056,6 +601297,46 @@
"98987df9a703ef38d20c6bc1581b2ca136342615",
"testharness"
],
"css/css-logical/parsing/border-inline-color-computed.html": [
"e9eff2419fea7bfdbf204aca4879910bae103ebf",
"testharness"
],
"css/css-logical/parsing/border-inline-color-invalid.html": [
"f0070c787bcd7c71d1a61d11b22265dd49f9ef6e",
"testharness"
],
"css/css-logical/parsing/border-inline-color-valid.html": [
"6bf240006e1995af716dad92b3d4927cebe928d4",
"testharness"
],
"css/css-logical/parsing/border-inline-style-computed.html": [
"adcd6d02976fca309f0479aa522128e704e92f60",
"testharness"
],
"css/css-logical/parsing/border-inline-style-invalid.html": [
"6684dc19ecb426508a86fbce9d1db4c3b00eb10d",
"testharness"
],
"css/css-logical/parsing/border-inline-style-valid.html": [
"4fd0cbbb0946d380ff0f78edfec85e7688f8b53e",
"testharness"
],
"css/css-logical/parsing/border-inline-valid.html": [
"b7207c0f23541e958eeea0bbe0a8c527af67af23",
"testharness"
],
"css/css-logical/parsing/border-inline-width-computed.html": [
"d421329bb28a3da8d70218ba4c13fc0498d0f202",
"testharness"
],
"css/css-logical/parsing/border-inline-width-invalid.html": [
"8624fcf0fe104ec9703dda31390ff2518c0d1b94",
"testharness"
],
"css/css-logical/parsing/border-inline-width-valid.html": [
"03c3e0fca2fb56b7116aae6b25eae020538ecf57",
"testharness"
],
"css/css-logical/parsing/inline-size-invalid.html": [
"d3d5d3f84d9d01392533e787b9e6755d592ec96e",
"testharness"
@ -626069,7 +626350,7 @@
"reftest"
],
"css/css-ui/appearance-menulist-button-002.html": [
"0477f2d52ef16a44c16833d919c12c07014eae4c",
"60a4312b16cdc02f79a9592d446177954ac0d5b2",
"reftest"
],
"css/css-ui/appearance-meter-001.html": [
@ -628641,7 +628922,7 @@
"reftest"
],
"css/css-ui/webkit-appearance-menulist-button-002.html": [
"c8d61508d28fea5269bee40d016cd45fac79b20a",
"078d568faa1795e3b86b7e623c2abc1d667b1c66",
"reftest"
],
"css/css-ui/webkit-appearance-meter-001.html": [
@ -629013,7 +629294,7 @@
"reftest"
],
"css/css-values/initial-background-color.html": [
"7a6c6173c4f6998f56bbcb7f992ad38fca45ce58",
"01543397ab6138f06acfcd85ec65d44f9fb7a54d",
"reftest"
],
"css/css-values/lh-rlh-on-root-001.html": [
@ -639049,9 +639330,13 @@
"testharness"
],
"css/motion/animation/offset-rotate-interpolation.html": [
"a73c1a41dc86a532c8f6431c73065f1b4d6ace65",
"3b3d755f4f1faec257abd1a75eba11f8d4616d05",
"testharness"
],
"css/motion/animation/reftests/offset-distance-interpolation-001.html": [
"88441f5b547646274d95e8cf59e8bf29982f279e",
"reftest"
],
"css/motion/animation/reftests/offset-path-path-interpolation-001.html": [
"0f2765189684c345cc173868ecd612952d1ab6ca",
"reftest"
@ -639060,6 +639345,10 @@
"9bc2409061d0ca3df287d33fdfb84bdecf522d01",
"support"
],
"css/motion/animation/reftests/offset-rotate-interpolation-001.html": [
"360caeea68242cc80cbdb131884c633a6f3f7b47",
"reftest"
],
"css/motion/animation/resources/interpolation-testcommon.js": [
"6933733e1970d06fd5473b74f7ba63a9a821624a",
"support"
@ -651313,7 +651602,7 @@
"support"
],
"docs/conf.py": [
"b3bce7971129bc2b4f62a86f4798ec69c49d7cc8",
"73777025cbdc648dbb6fe0944eabd867ce9af6aa",
"support"
],
"docs/index.rst": [
@ -651420,6 +651709,22 @@
"122a22b3f367d36d749c567c62c09ae9454c2aee",
"support"
],
"docs/writing-tests/python-handlers/index.md": [
"174f79aad900a5e3c1a873b26e2c060c22709db1",
"support"
],
"docs/writing-tests/python-handlers/request.md": [
"e2e4efc87410f157e5233dc32f2a6cdfb08bdc29",
"support"
],
"docs/writing-tests/python-handlers/response.md": [
"0db95e57bf608a6717cdd35c6d4c3e6c4c81bde3",
"support"
],
"docs/writing-tests/python-handlers/stash.md": [
"fdf50b216f7cf79f2ca0a84eb4ce788297cd5978",
"support"
],
"docs/writing-tests/reftests.md": [
"577b27d0db57cf0c6a6d49c89529611d507ca9f6",
"support"
@ -651429,7 +651734,11 @@
"support"
],
"docs/writing-tests/server-features.md": [
"16bf4e0ccdcfa0ce46aa3febf7a8b689ee3b39bb",
"17fa1a887a779cedc8fdbbf40758ae0b1f26f68e",
"support"
],
"docs/writing-tests/server-pipes.md": [
"a2a09854a98ada790032fe31a2f5829322c37d87",
"support"
],
"docs/writing-tests/submission-process.md": [
@ -653265,7 +653574,7 @@
"testharness"
],
"domxpath/interfaces.tentative.html": [
"780844ee7b11ce6ea1ee051d63166f1700cee3bf",
"9036ad834a764798d2871a71a8b5734051949d8d",
"testharness"
],
"domxpath/xml_xpath_runner.html": [
@ -659652,14 +659961,26 @@
"06641deb48b119f8236f391adae6ef252dcdcb1b",
"manual"
],
"fullscreen/api/element-request-fullscreen-twice-manual.tentative.html": [
"a8b5531fa1835af333c7faab4ce041ce429cc4ca",
"manual"
],
"fullscreen/api/element-request-fullscreen-two-elements-manual.html": [
"3291664c63ab4880dd844e5f75046d2f93c8f92f",
"manual"
],
"fullscreen/api/element-request-fullscreen-two-elements-manual.tentative.html": [
"f46fb80490e2d626f2217777a6a75d1f546e54a3",
"manual"
],
"fullscreen/api/element-request-fullscreen-two-iframes-manual.html": [
"c581a1575b77052f67d153e140613f91ba42e57b",
"manual"
],
"fullscreen/api/element-request-fullscreen-two-iframes-manual.tentative.html": [
"5dce676910f6d0c7a02efdb5a9bd15d2001f5b9e",
"manual"
],
"fullscreen/api/element-request-fullscreen.html": [
"23b4d2f5bfbed1f84f0b51494bdc394fe56ebcb8",
"testharness"
@ -670557,7 +670878,7 @@
"testharness"
],
"html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html": [
"9495bfc3c89ee27e6d81d074b5fd39ae820af376",
"df0985d6fb435c25dce510f924b1470878c5602f",
"testharness"
],
"html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html": [
@ -671369,7 +671690,7 @@
"testharness"
],
"html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list.html": [
"5b11bfdea4cf935d96b21505b8681288793ee2c4",
"73241ce0d4a1b82f9763f8410420ac59fa14d379",
"testharness"
],
"html/semantics/embedded-content/media-elements/track/track-element/track-texttracks.html": [
@ -673092,6 +673413,10 @@
"c564a5845d5d44c477e57c6f1d8eb6e8c0f457b0",
"support"
],
"html/semantics/embedded-content/the-img-element/srcset/avoid-reload-on-resize.html": [
"a8038e5605760b4bcdd4c8bdca47cede880ad7a9",
"testharness"
],
"html/semantics/embedded-content/the-img-element/srcset/common.js": [
"d4d2c7534c7fadac56a59a09455180f57697a6d9",
"support"
@ -673100,6 +673425,18 @@
"ce1e4cebe5fac34441081915eddc9ab2514770ef",
"testharness"
],
"html/semantics/embedded-content/the-img-element/srcset/resources/image.png": [
"d26878c9f22d53bb44be515fa9f0ffbb90a71cbd",
"support"
],
"html/semantics/embedded-content/the-img-element/srcset/resources/image.png.headers": [
"edaec7ad154133f0d8ae4e69c2933a2905e82e87",
"support"
],
"html/semantics/embedded-content/the-img-element/srcset/resources/resized.html": [
"6fb6847a66bdc33e2e3fbb6e5ddf86dfe313f343",
"support"
],
"html/semantics/embedded-content/the-img-element/srcset/select-an-image-source.html": [
"292395d3aef45b01dec8d9db576b42b4cde61749",
"testharness"
@ -680557,7 +680894,7 @@
"support"
],
"interfaces/dedicated-workers.idl": [
"eaed7af3d20c2ac2ca41bd3e2307363005855c0e",
"8d7255f2a564e3dd648592db59e84dc3529359d1",
"support"
],
"interfaces/dom.idl": [
@ -681421,7 +681758,7 @@
"support"
],
"lifecycle/resources/subframe.html": [
"2f1d70a80a792401891d93f6ddebaea0876400b3",
"b80ba9540a804bb326407935410d50c5fa2cfdbd",
"support"
],
"lifecycle/resources/subframe_worker.html": [
@ -682425,7 +682762,7 @@
"testharness"
],
"media-source/mediasource-getvideoplaybackquality.html": [
"1823d0b34a342a80395e420c49486d0e86d38de4",
"ec5894304040d401e12fb98773027eeae86b17e6",
"testharness"
],
"media-source/mediasource-invalid-codec.html": [
@ -682949,7 +683286,7 @@
"testharness"
],
"mediacapture-image/resources/imagecapture-helpers.js": [
"6d5ffa1695d807a05edeb75a21d472856bdda252",
"8252f42a637eb7f9c24917d63113f0adc1bf415a",
"support"
],
"mediacapture-image/setOptions-reject.html": [
@ -709189,7 +709526,7 @@
"support"
],
"service-workers/service-worker/resources/test-helpers.sub.js": [
"14101319fa9d9e4c76f33a471098d280f117a15f",
"af8dad3a5be8aa831900b183ad7ee9a10417ba1a",
"support"
],
"service-workers/service-worker/resources/test-request-headers-worker.js": [
@ -709217,7 +709554,11 @@
"support"
],
"service-workers/service-worker/resources/update-during-installation-worker.js": [
"dabeec077f77d5e8d1924eb5f3bd5d8667b129f5",
"3f89881c04384590b8b132c392977256bfb847ed",
"support"
],
"service-workers/service-worker/resources/update-during-installation-worker.py": [
"95e4522007c1d2be14045f7582ebe2b5347abd87",
"support"
],
"service-workers/service-worker/resources/update-fetch-worker.py": [
@ -709453,7 +709794,7 @@
"testharness"
],
"service-workers/service-worker/update-not-allowed.https.html": [
"71fe1730e0d68e4e7e0949cfa408d3c2d4ed9d39",
"0a54aa9350382bb082f407a1ea30b265575baae9",
"testharness"
],
"service-workers/service-worker/update-on-navigation.https.html": [
@ -710265,7 +710606,7 @@
"testharness"
],
"shape-detection/resources/shapedetection-helpers.js": [
"09cea09c6fe0c1fb20c707a766e746b8246cfc02",
"91d36658aab0bf9435cfc9d283be45ef1292e2ed",
"support"
],
"shape-detection/shapedetection-cross-origin.sub.html": [
@ -715825,7 +716166,7 @@
"support"
],
"tools/manifest/vcs.py": [
"d900012212eb32b2a4df01c781cabf0b48968bad",
"5c3b118216ce3cfc1ff1096dd8c8bd4b112cc76a",
"support"
],
"tools/mypy.ini": [
@ -720281,7 +720622,7 @@
"support"
],
"tools/wpt/browser.py": [
"ddc7837f192ae9307be0028636e92d4faf9b9ced",
"1b883b93bbffc5e76cb59bed3b140cd25e020598",
"support"
],
"tools/wpt/commands.json": [
@ -720309,7 +720650,7 @@
"support"
],
"tools/wpt/run.py": [
"98bcc2111ec45161c907581a4455730e98e33cfa",
"0b306aee2554385e86c5ed042d030c3b2c3b78d0",
"support"
],
"tools/wpt/testfiles.py": [
@ -720345,7 +720686,7 @@
"support"
],
"tools/wpt/virtualenv.py": [
"b99d15d1f6a466b975312b0ffde4f3161ae200c2",
"4b7aa71a505734e48650064e7a2fd876c5a3d4e9",
"support"
],
"tools/wpt/wpt.py": [
@ -720785,7 +721126,7 @@
"support"
],
"tools/wptrunner/wptrunner/manifestexpected.py": [
"7a93fe41ec7a81e223c51fb6a0f57ac890b51f7a",
"0ea4082efc2afecc63ee00504edb7e1b44e0d4d8",
"support"
],
"tools/wptrunner/wptrunner/manifestinclude.py": [
@ -720837,7 +721178,7 @@
"support"
],
"tools/wptrunner/wptrunner/testrunner.py": [
"9228af6369654f9e63e58c8cce2c1905ab11e458",
"44b5401e4f8410b8ed68940b6845c6db590b68c5",
"support"
],
"tools/wptrunner/wptrunner/tests/__init__.py": [
@ -720925,7 +721266,7 @@
"support"
],
"tools/wptrunner/wptrunner/wptlogging.py": [
"9e3ff54593ffe27daf604694e8a9d5b486fa9f7c",
"2070f77591dd7ba2dc9690e5f06809299a9eeb50",
"support"
],
"tools/wptrunner/wptrunner/wptmanifest/__init__.py": [
@ -720936,12 +721277,16 @@
"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
"support"
],
"tools/wptrunner/wptrunner/wptmanifest/backends/base.py": [
"45e2147fc4ca509a9de28fcdcbb707d823459711",
"support"
],
"tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py": [
"5719a859fa4bc7e4ab4d1e9329ca74b2af6666f7",
"support"
],
"tools/wptrunner/wptrunner/wptmanifest/backends/static.py": [
"7b4f5613c384929cfd48196f4412ffc9d1824e88",
"6efad1c0e47b114b51259bb369a4ad15971268d7",
"support"
],
"tools/wptrunner/wptrunner/wptmanifest/node.py": [
@ -720981,7 +721326,7 @@
"support"
],
"tools/wptrunner/wptrunner/wptrunner.py": [
"79ec2844ebfe79b24ab1bba533976082569e2173",
"42712f6bc753575a3beaf37639df72e134477508",
"support"
],
"tools/wptrunner/wptrunner/wpttest.py": [
@ -721013,7 +721358,7 @@
"support"
],
"tools/wptserve/docs/handlers.rst": [
"c15aab635d96976af59c606d84d0a5750743544b",
"f35a7b983ed89d43cd1a546f4715c00e18a395b5",
"support"
],
"tools/wptserve/docs/index.rst": [
@ -721029,7 +721374,7 @@
"support"
],
"tools/wptserve/docs/pipes.rst": [
"507631c51986cc0fdea1c0cd5ec273a48fc7b3b7",
"2c9966d0b238d249944140681a02fc671c48c3e6",
"support"
],
"tools/wptserve/docs/request.rst": [
@ -727285,7 +727630,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-onnegotiationneeded.html": [
"336b100de058200ab49400fac9ae00f8524b9da9",
"3e31c327ac2480bb9d526e5c6665c3486449ff31",
"testharness"
],
"webrtc/RTCPeerConnection-onsignalingstatechanged.https.html": [
@ -727440,6 +727785,10 @@
"1278737414c418a2b1604eae32590c0999e0d645",
"testharness"
],
"webrtc/RTCRtpSender-setStreams.https.html": [
"08592da4d528889565825f9147d789c89b7e18fc",
"testharness"
],
"webrtc/RTCRtpSender-transport.https.html": [
"8c0552dd68aba8c707c6cbe2c7d6f9f3c5f64f17",
"testharness"
@ -732053,7 +732402,7 @@
"support"
],
"webxr/resources/webxr_util.js": [
"3b010a43598af1dff31f501df0beb530ca729e07",
"505a9281f57ecd13443dfff380e0028d74708990",
"support"
],
"webxr/resources/xr-test-asserts.js": [
@ -732180,6 +732529,10 @@
"8090bcebadb39902189c716b8434de949e9c5ae9",
"testharness"
],
"webxr/xrWebGLLayer_viewports.https.html": [
"f789e473354890e39bc0ffa5abc410daea7615cf",
"testharness"
],
"workers/META.yml": [
"a7297d3844728b8bb2f7c82a2c4f32d65040a919",
"support"

View file

@ -0,0 +1,2 @@
[margin-collapse-through-percentage-padding.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[border-radius-dynamic-from-no-radius.html]
expected: TIMEOUT

View file

@ -2,7 +2,6 @@
type: testharness
[single-byte-decoder.html?document]
expected: TIMEOUT
[ISO-8859-4: iso_8859-4:1988 (document.characterSet and document.inputEncoding)]
expected: FAIL

View file

@ -315,21 +315,21 @@
[<iframe>: combined response Content-Type: */* text/html]
expected: FAIL
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;charset=gbk text/plain text/html]
expected: FAIL
[<iframe>: separate response Content-Type: */* text/html]
[<iframe>: combined response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;x=" text/plain]
[<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 */*;charset=gbk]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
expected: FAIL

View file

@ -11,6 +11,3 @@
[X-Content-Type-Options%3A%20nosniff%0C]
expected: FAIL
[X-Content-Type-Options%3A%20%22nosniFF%22]
expected: FAIL

View file

@ -1,4 +1,4 @@
[traverse_the_history_2.html]
[traverse_the_history_5.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -1,4 +0,0 @@
[DOMContentLoaded-defer.html]
[The end: DOMContentLoaded and defer scripts]
expected: FAIL

View file

@ -1,5 +1,4 @@
[realtimeanalyser-fft-scaling.html]
expected: TIMEOUT
[X 2048-point FFT peak position is not equal to 64. Got 0.]
expected: FAIL

View file

@ -1,2 +0,0 @@
[transition_calc_implicit.html]
expected: TIMEOUT

View file

@ -5,7 +5,7 @@
<title>Cookie Test Expectation Document</title>
</head>
<body>
<div id="data">{data}</div>
<div id="data" style="white-space: pre">{data}</div>
<script src="iframe-content-pushing.js"></script>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<link rel="help" href="https://www.w3.org/TR/CSS22/box.html#collapsing-margins">
<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=967193">
<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
<meta name="assert" content="A vertical percentage padding that resolves to 0 shouldn't prevent margins from collapsing through the box">
<p>Test passes if there is a filled green square.</p>
<div style="float:left; width:100px; background:green;">
<div id="container" style="width:100px;">
<div style="width:100px; margin-bottom:100px;"></div>
<div style="padding:100% 0;"></div>
<div style="width:100px; margin-top:100px;"></div>
</div>
</div>
<script>
document.body.offsetTop;
container.style.width = "0";
</script>

View file

@ -0,0 +1,20 @@
<!doctype html>
<title>CSS Test Reference</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<style>
#outer {
width: 100px;
height: 100px;
}
#inner {
width: 100%;
height: 100%;
background: green;
border-radius: 50px;
}
</style>
<p>Should be a green circle below</p>
<div id="outer">
<div id="inner"></div>
</div>

View file

@ -0,0 +1,36 @@
<!doctype html>
<html class="reftest-wait">
<title>CSS Test: Relative dynamic border-radius change</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1554755">
<link rel="match" href="border-radius-dynamic-from-no-radius-ref.html">
<style>
#outer {
width: 100px;
height: 100px;
}
#inner {
width: 100%;
height: 100%;
background: green;
/* The key is that this starts off computing to zero */
border-radius: calc(100% - 1px);
}
</style>
<p>Should be a green circle below</p>
<div id="outer" style="width: 1px; height: 1px;">
<div id="inner"></div>
</div>
<script>
onload = function() {
requestAnimationFrame(function() {
requestAnimationFrame(function() {
outer.style.height = "";
outer.style.width = "";
document.documentElement.className = "";
});
});
}
</script>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<title>CSS Box: chrome crash</title>
<link rel="author" href="mailto:atotic@google.com">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://crbug.com/967361">
<meta name="assert" content="Chrome does not crash on narrow div with scrollbars.">
<style>
body {
writing-mode: vertical-lr;
}
#target {
overflow-y: scroll;
max-height: 5px;
background: gray;
}
</style>
<!-- -->
<div>
<span>
<div id="container">
<div id="target">anon</div>
</div>
</span>
</div>
<script>
test(() => {
}, 'test passes if it does not crash');
</script>

View file

@ -0,0 +1,95 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Inheritance of CSS Logical Properties and Values properties</title>
<link rel="help" href="https://www.w3.org/TR/css-logical-1/#property-index">
<meta name="assert" content="Properties do not inherit.">
<meta name="assert" content="Properties have initial values according to the spec.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/inheritance-testcommon.js"></script>
</head>
<body>
<div id="reference-container">
<div id="reference"></div>
</div>
<div id="container">
<div id="target"></div>
</div>
<style>
#reference-container {
width: 300px;
}
#reference-container, #reference {
border-style: solid; /* Avoid border-top-width computed style 0 */
border-top-width: medium;
}
#container, #target {
border-block-end-style: solid; /* Avoid border-block-end-width computed style 0 */
border-block-start-style: solid;
border-inline-end-style: solid;
border-inline-start-style: solid;
}
#container {
color: blue;
width: 300px;
}
</style>
<script>
'use strict';
const blue = "rgb(0, 0, 255)";
const green = "rgb(0, 128, 0)";
const mediumWidth = getComputedStyle(reference).borderTopWidth; // e.g. 3px
const referenceWidth = getComputedStyle(reference).width; // e.g. 294px
assert_not_inherited('block-size', '0px', '10px');
assert_not_inherited('border-block-end-color', blue, green);
assert_not_inherited('border-block-end-style', 'none', 'dotted');
assert_not_inherited('border-block-end-width', mediumWidth, '10px');
assert_not_inherited('border-block-start-color', blue, green);
assert_not_inherited('border-block-start-style', 'none', 'dotted');
assert_not_inherited('border-block-start-width', mediumWidth, '10px');
assert_not_inherited('border-end-end-radius', '0px', '10px 20px');
assert_not_inherited('border-end-start-radius', '0px', '10px 20px');
assert_not_inherited('border-inline-end-color', blue, green);
assert_not_inherited('border-inline-end-style', 'none', 'dotted');
assert_not_inherited('border-inline-end-width', mediumWidth, '10px');
assert_not_inherited('border-inline-start-color', blue, green);
assert_not_inherited('border-inline-start-style', 'none', 'dotted');
assert_not_inherited('border-inline-start-width', mediumWidth, '10px');
assert_not_inherited('border-start-end-radius', '0px', '10px 20px');
assert_not_inherited('border-start-start-radius', '0px', '10px 20px');
assert_not_inherited('inline-size', referenceWidth, '10px');
assert_not_inherited('inset-block-end', 'auto', '10px');
assert_not_inherited('inset-block-start', 'auto', '10px');
assert_not_inherited('inset-inline-end', 'auto', '10px');
assert_not_inherited('inset-inline-start', 'auto', '10px');
assert_not_inherited('margin-block-end', '0px', '10px');
assert_not_inherited('margin-block-start', '0px', '10px');
assert_not_inherited('margin-inline-end', '0px', '10px');
assert_not_inherited('margin-inline-start', '0px', '10px');
assert_not_inherited('max-block-size', 'none', '10px');
assert_not_inherited('max-inline-size', 'none', '10px');
assert_not_inherited('min-block-size', '0px', '10px');
assert_not_inherited('min-inline-size', '0px', '10px');
assert_not_inherited('padding-block-end', '0px', '10px');
assert_not_inherited('padding-block-start', '0px', '10px');
assert_not_inherited('padding-inline-end', '0px', '10px');
assert_not_inherited('padding-inline-start', '0px', '10px');
</script>
</body>
</html>

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: parsing border-block with valid values</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-block">
<meta name="assert" content="border-block supports the full grammar '<line-width> || <line-style> || <color>'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
// Similar to css-backgrounds/parsing/border-valid.html
test_valid_value("border-block", "1px dotted red");
test_valid_value("border-block", "double", ["double", "medium double"]);
test_valid_value("border-block-start", "green double thin", "thin double green");
test_valid_value("border-block-start", "green", ["green", "medium none green"]);
test_valid_value("border-block-end", "thin", ["thin", "thin none"]);
test_valid_value("border-block-end", "calc(10px - 0.5em) dotted red");
</script>
</body>
</html>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: getComputedValue().borderInlineColor</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline-color">
<meta name="assert" content="border-inline-color is computed color(s).">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
</head>
<body>
<div id="box"></div>
<div id="target"></div>
<style>
#target {
color: lime;
}
</style>
<script>
test_computed_value("border-inline-start-color", "currentcolor", 'rgb(0, 255, 0)');
test_computed_value("border-inline-start-color", "rgb(2, 3, 4)");
test_computed_value("border-inline-end-color", "rgb(34, 51, 68)");
test_computed_value("border-inline-end-color", "transparent", "rgba(0, 0, 0, 0)");
test_computed_value("border-inline-color", "rgb(34, 51, 68)");
test_computed_value("border-inline-color", "transparent rgb(2, 3, 4)", "rgba(0, 0, 0, 0) rgb(2, 3, 4)");
test_computed_value("border-inline-color", "rgb(2, 3, 4) rgb(2, 3, 4)", "rgb(2, 3, 4)");
test_computed_value("border-inline-color", "currentcolor lime", 'rgb(0, 255, 0)');
</script>
</body>
</html>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: parsing border-inline-color with invalid values</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline-color">
<meta name="assert" content="border-inline-color supports only the grammar '<color>{1,2}'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
test_invalid_value("border-inline-start-color", "#12");
test_invalid_value("border-inline-start-color", "auto");
test_invalid_value("border-inline-start-color", "red green");
test_invalid_value("border-inline-start-color", "rgb");
test_invalid_value("border-inline-start-color", "rgb(1,2,3,4,5)");
test_invalid_value("border-inline-start-color", "rgb(10%, 20, 30%)");
test_invalid_value("border-inline-end-color", "#123456789");
test_invalid_value("border-inline-end-color", "123");
test_invalid_value("border-inline-end-color", "hsla(1,2,3,4,5)");
test_invalid_value("border-inline-end-color", "red, green");
test_invalid_value("border-inline-end-color", "rgb(1)");
test_invalid_value("border-inline-end-color", "rgba(-2, 300, 400%, -0.5)");
test_invalid_value("border-inline-color", "auto");
test_invalid_value("border-inline-color", "lime, transparent");
test_invalid_value("border-inline-color", "red green blue");
</script>
</body>
</html>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: parsing border-inline-color with valid values</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline-color">
<meta name="assert" content="border-inline-color supports the full grammar '<color>{1,2}'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
test_valid_value("border-inline-start-color", "currentcolor");
test_valid_value("border-inline-start-color", "rgb(2, 3, 4)");
test_valid_value("border-inline-end-color", "#234", "rgb(34, 51, 68)");
test_valid_value("border-inline-end-color", "transparent");
test_valid_value("border-inline-color", "#234", "rgb(34, 51, 68)");
test_valid_value("border-inline-color", "transparent rgb(2, 3, 4)");
test_valid_value("border-inline-color", "rgb(2, 3, 4) rgb(2, 3, 4)", "rgb(2, 3, 4)");
</script>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: getComputedValue().borderInlineStyle</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline-style">
<meta name="assert" content="border-inline-style is specified keyword(s).">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
</head>
<body>
<div id="target"></div>
<script>
test_computed_value("border-inline-start-style", "dotted");
test_computed_value("border-inline-start-style", "groove");
test_computed_value("border-inline-start-style", "inset");
test_computed_value("border-inline-start-style", "none");
test_computed_value("border-inline-start-style", "solid");
test_computed_value("border-inline-end-style", "dashed");
test_computed_value("border-inline-end-style", "double");
test_computed_value("border-inline-end-style", "hidden");
test_computed_value("border-inline-end-style", "outset");
test_computed_value("border-inline-end-style", "ridge");
test_computed_value("border-inline-style", "dotted");
test_computed_value("border-inline-style", "double groove");
test_computed_value("border-inline-style", "hidden hidden", "hidden");
</script>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: parsing border-inline-style with invalid values</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline-style">
<meta name="assert" content="border-inline-style supports only the grammar '<line-style>{1,2}'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
test_invalid_value("border-inline-start-style", "auto");
test_invalid_value("border-inline-start-style", "hidden, outset");
test_invalid_value("border-inline-end-style", "solid double");
test_invalid_value("border-inline-style", "auto");
test_invalid_value("border-inline-style", "groove, ridge");
test_invalid_value("border-inline-style", "hidden inset dashed");
</script>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: parsing border-inline-style with valid values</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-block">
<meta name="assert" content="border-inline-style supports the full grammar '<line-style>{1,2}'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
// none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset
test_valid_value("border-inline-start-style", "dotted");
test_valid_value("border-inline-start-style", "groove");
test_valid_value("border-inline-start-style", "inset");
test_valid_value("border-inline-start-style", "none");
test_valid_value("border-inline-start-style", "solid");
test_valid_value("border-inline-end-style", "dashed");
test_valid_value("border-inline-end-style", "double");
test_valid_value("border-inline-end-style", "hidden");
test_valid_value("border-inline-end-style", "outset");
test_valid_value("border-inline-end-style", "ridge");
test_valid_value("border-inline-style", "dotted");
test_valid_value("border-inline-style", "double groove");
test_valid_value("border-inline-style", "hidden hidden", "hidden");
</script>
</body>
</html>

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: parsing border-inline with valid values</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline">
<meta name="assert" content="border-inline supports the full grammar '<line-width> || <line-style> || <color>'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
// Similar to css-backgrounds/parsing/border-valid.html
test_valid_value("border-inline", "1px dotted red");
test_valid_value("border-inline", "double", ["double", "medium double"]);
test_valid_value("border-inline-start", "green double thin", "thin double green");
test_valid_value("border-inline-start", "green", ["green", "medium none green"]);
test_valid_value("border-inline-end", "thin", ["thin", "thin none"]);
test_valid_value("border-inline-end", "calc(10px - 0.5em) dotted red");
</script>
</body>
</html>

View file

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: getComputedValue().borderInlineWidth</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline-width">
<meta name="assert" content="border-inline-width is absolute length; zero if the border block style is none or hidden.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/computed-testcommon.js"></script>
</head>
<body>
<div id="box"></div>
<div id="target"></div>
<style>
#box {
border-style: dotted; /* Avoid border-*-width computed style 0 */
border-top-width: thin;
border-right-width: medium;
border-bottom-width: thick;
}
#target {
font-size: 40px;
border-inline-style: dotted; /* Avoid border-inline-*-width computed style 0 */
}
</style>
<script>
'use strict';
const box = document.getElementById('box');
const thinWidth = getComputedStyle(box).borderTopWidth;
const mediumWidth = getComputedStyle(box).borderRightWidth;
const thickWidth = getComputedStyle(box).borderBottomWidth;
test_computed_value("border-inline-start-width", "calc(10px + 0.5em)", "30px");
test_computed_value("border-inline-start-width", "calc(10px - 0.5em)", "0px");
test_computed_value("border-inline-start-width", "thin", thinWidth);
test_computed_value("border-inline-start-width", "medium", mediumWidth);
test_computed_value("border-inline-end-width", "calc(10px + 0.5em)", "30px");
test_computed_value("border-inline-end-width", "calc(10px - 0.5em)", "0px");
test_computed_value("border-inline-end-width", "thick", thickWidth);
test_computed_value("border-inline-width", "10px");
test_computed_value("border-inline-width", "10px 20px");
test_computed_value("border-inline-width", "10px 10px", "10px");
test(() => {
box.style.borderInlineStartWidth = '10px';
box.style.borderInlineEndWidth = '10px';
box.style.borderInlineStartStyle = 'groove';
box.style.borderInlineEndStyle = 'solid';
assert_equals(getComputedStyle(box).borderInlineStartWidth, '10px');
assert_equals(getComputedStyle(box).borderInlineEndWidth, '10px');
assert_equals(getComputedStyle(box).borderInlineWidth, '10px');
box.style.borderInlineStartStyle = 'hidden';
box.style.borderInlineEndStyle = 'dashed';
assert_equals(getComputedStyle(box).borderInlineStartWidth, '0px');
assert_equals(getComputedStyle(box).borderInlineEndWidth, '10px');
assert_equals(getComputedStyle(box).borderInlineWidth, '0px 10px');
box.style.borderInlineStartStyle = 'inset';
box.style.borderInlineEndStyle = 'none';
assert_equals(getComputedStyle(box).borderInlineStartWidth, '10px');
assert_equals(getComputedStyle(box).borderInlineEndWidth, '0px');
assert_equals(getComputedStyle(box).borderInlineWidth, '10px 0px');
box.style.borderInlineStartStyle = 'none';
box.style.borderInlineEndStyle = 'hidden';
assert_equals(getComputedStyle(box).borderInlineStartWidth, '0px');
assert_equals(getComputedStyle(box).borderInlineEndWidth, '0px');
assert_equals(getComputedStyle(box).borderInlineWidth, '0px');
}, 'width is zero if the border block style is none or hidden');
</script>
</body>
</html>

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: parsing border-inline-width with invalid values</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline-width">
<meta name="assert" content="border-inline-width supports only the grammar '<line-width>{1,2}'.">
<meta name="assert" content="Negative lengths are not allowed.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
test_invalid_value("border-inline-start-width", "-20px");
test_invalid_value("border-inline-start-width", "auto");
test_invalid_value("border-inline-start-width", "medium 40px");
test_invalid_value("border-inline-end-width", "10");
test_invalid_value("border-inline-end-width", "30%");
test_invalid_value("border-inline-width", "thick, thin");
test_invalid_value("border-inline-width", "10px 20px 30px");
</script>
</body>
</html>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Logical Properties and Values: parsing border-inline-width with valid values</title>
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-border-inline-width">
<meta name="assert" content="border-inline-width supports the full grammar '<line-width>{1,2}'.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
</head>
<body>
<script>
// <length> | thin | medium | thick
test_valid_value("border-inline-start-width", "10px");
test_valid_value("border-inline-start-width", "calc(10px + 0.5em)");
test_valid_value("border-inline-start-width", "thick");
test_valid_value("border-inline-start-width", "thin");
test_valid_value("border-inline-end-width", "0", "0px");
test_valid_value("border-inline-end-width", "calc(10px - 0.5em)");
test_valid_value("border-inline-end-width", "medium");
test_valid_value("border-inline-width", "10px");
test_valid_value("border-inline-width", "medium calc(10px + 0.5em)");
test_valid_value("border-inline-width", "10px 10px", "10px");
</script>
</body>
</html>

View file

@ -6,7 +6,7 @@
<link rel="mismatch" href="appearance-auto-ref.html">
<style>
#container { width: 500px; }
#container > #drop-down-select { -webkit-appearance: none; -webkit-appearance: menulist-button; }
#container > #drop-down-select { appearance: none; appearance: menulist-button; }
</style>
<div id="container">
<a>a</a>

View file

@ -10,7 +10,7 @@ Edit the appearance-* file instead and then run:
<link rel="mismatch" href="appearance-auto-ref.html">
<style>
#container { width: 500px; }
#container > #drop-down-select { -webkit--webkit-appearance: none; -webkit--webkit-appearance: menulist-button; }
#container > #drop-down-select { -webkit-appearance: none; -webkit-appearance: menulist-button; }
</style>
<div id="container">
<a>a</a>

View file

@ -28,7 +28,7 @@
html, body { margin: 0px; padding: 0px; }
html { background: green; overflow: hidden; }
#outer { position: absolute; top: 0px; left: 0px; red; width: 100%; height: 100%; }
#outer { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; }
#outer { background: red; background-color: initial; }
</style>

View file

@ -25,6 +25,45 @@
{at: 2, expect: '260deg'}
]);
test_interpolation({
property: 'offset-rotate',
from: 'auto 45deg',
to: 'auto 125deg',
}, [
{at: -1, expect: 'auto -35deg'},
{at: 0, expect: 'auto 45deg'},
{at: 0.125, expect: 'auto 55deg'},
{at: 0.875, expect: 'auto 115deg'},
{at: 1, expect: 'auto 125deg'},
{at: 2, expect: 'auto 205deg'}
]);
test_interpolation({
property: 'offset-rotate',
from: 'auto 170deg',
to: '100grad auto',
}, [
{at: -1, expect: 'auto 250deg'},
{at: 0, expect: 'auto 170deg'},
{at: 0.125, expect: 'auto 160deg'},
{at: 0.875, expect: 'auto 100deg'},
{at: 1, expect: '100grad auto'},
{at: 2, expect: 'auto 10deg'}
]);
test_interpolation({
property: 'offset-rotate',
from: 'auto -280deg',
to: 'auto calc(90deg - 0.5turn - 300grad + 0rad)',
}, [
{at: -1, expect: 'auto -200deg'},
{at: 0, expect: 'auto -280deg'},
{at: 0.125, expect: 'auto -290deg'},
{at: 0.875, expect: 'auto -350deg'},
{at: 1, expect: 'auto calc(90deg - 0.5turn - 300grad + 0rad)'},
{at: 2, expect: 'auto -440deg'}
]);
test_interpolation({
property: 'offset-rotate',
from: 'auto 100deg',

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<title>offset-distance interpolation</title>
<link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-distance-property">
<link rel="match" href="offset-path-path-interpolation-ref.html">
<meta name="assert" content="offset-distance supports animation.">
<style>
@keyframes anim {
from { offset-distance: 0%; }
to { offset-distance: 100%; }
}
#target {
position: absolute;
left: 300px;
top: 0px;
width: 300px;
height: 200px;
background-color: lime;
transform-origin: 0px 0px;
offset-path: path("m 50 150 h 100");
animation: anim 10s -5s paused linear;
}
</style>
</head>
<body>
<div id="target"></div>
</body>
<script>
requestAnimationFrame(() => {
document.documentElement.classList.remove('reftest-wait');
});
</script>
</html>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<title>offset-rotate interpolation</title>
<link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-rotate-property">
<link rel="match" href="offset-path-path-interpolation-ref.html">
<meta name="assert" content="offset-rotate supports animation.">
<style>
@keyframes anim {
from { offset-rotate: auto; }
to { offset-rotate: reverse; }
}
#target {
position: absolute;
left: 300px;
top: 0px;
width: 300px;
height: 200px;
background-color: lime;
transform-origin: 0px 0px;
offset-path: path("m 100 150 v -100");
animation: anim 10s -5s paused linear;
}
</style>
</head>
<body>
<div id="target"></div>
</body>
<script>
requestAnimationFrame(() => {
document.documentElement.classList.remove('reftest-wait');
});
</script>
</html>

View file

@ -42,7 +42,8 @@ release = u''
# ones.
extensions = [
'recommonmark',
'sphinxarg.ext'
'sphinxarg.ext',
'sphinx.ext.autodoc'
]
# Add any paths that contain templates here, relative to this directory.

View file

@ -0,0 +1,22 @@
# Python Handlers
Python file handlers are Python files which the server executes in response to
requests made to the corresponding URL. This is hooked up to a route like
`("*", "*.py", python_file_handler)`, meaning that any .py file will be
treated as a handler file (note that this makes it easy to write unsafe
handlers, particularly when running the server in a web-exposed setting).
The Python files must define a single function `main` with the signature::
main(request, response)
The wptserver implements a number of Python APIs for controlling traffic.
```eval_rst
.. toctree::
:maxdepth: 1
request
response
stash
```

View file

@ -0,0 +1,3 @@
```eval_rst
.. include:: ../../../tools/wptserve/docs/request.rst
```

View file

@ -0,0 +1,3 @@
```eval_rst
.. include:: ../../../tools/wptserve/docs/response.rst
```

View file

@ -0,0 +1,3 @@
```eval_rst
.. include:: ../../../tools/wptserve/docs/stash.rst
```

View file

@ -82,12 +82,20 @@ the file e.g. `test.html.sub.headers`.
### Tests Requiring Full Control Over The HTTP Response
```eval_rst
.. toctree::
:maxdepth: 1
python-handlers/index
server-pipes
```
For full control over the request and response the server provides the
ability to write `.asis` files; these are served as literal HTTP
responses. It also provides the ability to write Python scripts that
have access to request data and can manipulate the content and timing
of the response. For details see the
[wptserve documentation](https://wptserve.readthedocs.org).
responses. It also provides the ability to write [Python
"handlers"](python-handlers/index)--Python scripts that have access to request
data and can manipulate the content and timing of the response. Responses are
also influenced by [the `pipe` query string parameter](server-pipes).
### Writing tests for HTTP/2.0

View file

@ -0,0 +1,136 @@
# wptserve Pipes
## Enabling
Pipes are functions that may be used when serving files to alter parts
of the response. These are invoked by adding a pipe= query parameter
taking a | separated list of pipe functions and parameters. The pipe
functions are applied to the response from left to right. For example:
GET /sample.txt?pipe=slice(1,200)|status(404).
This would serve bytes 1 to 199, inclusive, of foo.txt with the HTTP status
code 404.
Note: If you write directly to the response socket using ResponseWriter, or
when using the asis handler, only the trickle pipe will affect the response.
There are several built-in pipe functions, and it is possible to add
more using the `@pipe` decorator on a function, if required.
Note: Because of the way pipes compose, using some pipe functions prevents the
content-length of the response from being known in advance. In these cases the
server will close the connection to indicate the end of the response,
preventing the use of HTTP 1.1 keepalive.
## Built-In Pipes
### `sub`
Used to substitute variables from the server environment, or from the
request into the response.
Substitutions are marked in a file using a block delimited by `{{`
and `}}`. Inside the block the following variables are available:
- `{{host}}` - The host name of the server excluding any subdomain part.
- `{{domains[]}}` - The domain name of a particular subdomain e.g.
`{{domains[www]}}` for the `www` subdomain.
- `{{ports[][]}}` - The port number of servers, by protocol e.g.
`{{ports[http][0]}}` for the first (and, depending on setup, possibly only)
http server
- `{{headers[]}}` The HTTP headers in the request e.g. `{{headers[X-Test]}}`
for a hypothetical `X-Test` header.
- `{{header_or_default(header, default)}}` The value of an HTTP header, or a
default value if it is absent. e.g. `{{header_or_default(X-Test,
test-header-absent)}}`
- `{{GET[]}}` The query parameters for the request e.g. `{{GET[id]}}` for an id
parameter sent with the request.
So, for example, to write a JavaScript file called `xhr.js` that
depends on the host name of the server, without hardcoding, one might
write:
var server_url = http://{{host}}:{{ports[http][0]}}/path/to/resource;
//Create the actual XHR and so on
The file would then be included as:
<script src="xhr.js?pipe=sub"></script>
This pipe can also be enabled by using a filename `*.sub.ext`, e.g. the file above could be called `xhr.sub.js`.
### `status`
Used to set the HTTP status of the response, for example:
example.js?pipe=status(410)
### `headers`
Used to add or replace http headers in the response. Takes two or
three arguments; the header name, the header value and whether to
append the header rather than replace an existing header (default:
False). So, for example, a request for:
example.html?pipe=header(Content-Type,text/plain)
causes example.html to be returned with a text/plain content type
whereas:
example.html?pipe=header(Content-Type,text/plain,True)
Will cause example.html to be returned with both text/html and
text/plain content-type headers.
### `slice`
Used to send only part of a response body. Takes the start and,
optionally, end bytes as arguments, although either can be null to
indicate the start or end of the file, respectively. So for example:
example.txt?pipe=slice(10,20)
Would result in a response with a body containing 10 bytes of
example.txt including byte 10 but excluding byte 20.
example.txt?pipe=slice(10)
Would cause all bytes from byte 10 of example.txt to be sent, but:
example.txt?pipe=slice(null,20)
Would send the first 20 bytes of example.txt.
### `trickle`
Note: Using this function will force a connection close.
Used to send the body of a response in chunks with delays. Takes a
single argument that is a microsyntax consisting of colon-separated
commands. There are three types of commands:
* Bare numbers represent a number of bytes to send
* Numbers prefixed `d` indicate a delay in seconds
* Numbers prefixed `r` must only appear at the end of the command, and
indicate that the preceding N items must be repeated until there is
no more content to send. The number of items to repeat must be even.
In the absence of a repetition command, the entire remainder of the content is
sent at once when the command list is exhausted. So for example:
example.txt?pipe=trickle(d1)
causes a 1s delay before sending the entirety of example.txt.
example.txt?pipe=trickle(100:d1)
causes 100 bytes of example.txt to be sent, followed by a 1s delay,
and then the remainder of the file to be sent. On the other hand:
example.txt?pipe=trickle(100:d1:r2)
Will cause the file to be sent in 100 byte chunks separated by a 1s
delay until the whole content has been sent.

View file

@ -8,26 +8,7 @@
<script src='/resources/WebIDLParser.js'></script>
<script src='/resources/idlharness.js'></script>
<script type='text/plain'>
[Constructor] interface XPathEvaluator {
[NewObject] XPathExpression createExpression(DOMString expression,
optional XPathNSResolver? resolver);
Node createNSResolver(Node nodeResolver);
XPathResult evaluate(DOMString expression, Node contextNode,
optional XPathNSResolver? resolver,
optional unsigned short type,
optional object? result);
};
interface XPathExpression {
XPathResult evaluate(Node contextNode,
optional unsigned short type,
optional object? result);
};
callback interface XPathNSResolver {
DOMString? lookupNamespaceURI(DOMString? prefix);
};
[Exposed=Window]
interface XPathResult {
const unsigned short ANY_TYPE = 0;
const unsigned short NUMBER_TYPE = 1;
@ -39,8 +20,10 @@ interface XPathResult {
const unsigned short ORDERED_NODE_SNAPSHOT_TYPE = 7;
const unsigned short ANY_UNORDERED_NODE_TYPE = 8;
const unsigned short FIRST_ORDERED_NODE_TYPE = 9;
readonly attribute unsigned short resultType;
readonly attribute double numberValue;
readonly attribute unrestricted double numberValue;
// Maybe "DOMString?".
readonly attribute DOMString stringValue;
readonly attribute boolean booleanValue;
readonly attribute Node? singleNodeValue;
@ -49,10 +32,37 @@ interface XPathResult {
Node? iterateNext();
Node? snapshotItem(unsigned long index);
};
[Exposed=Window]
interface XPathExpression {
XPathResult evaluate(Node contextNode,
optional unsigned short type,
optional XPathResult? result);
};
callback interface XPathNSResolver {
DOMString? lookupNamespaceURI(DOMString? prefix);
};
interface mixin XPathEvaluatorBase {
[NewObject] XPathExpression createExpression(DOMString expression,
optional XPathNSResolver? resolver);
XPathNSResolver createNSResolver(Node nodeResolver);
XPathResult evaluate(DOMString expression,
Node contextNode,
optional XPathNSResolver? resolver,
optional unsigned short type,
optional XPathResult? result);
};
[Exposed=Window, Constructor]
interface XPathEvaluator {};
XPathEvaluator includes XPathEvaluatorBase;
</script>
<script type='text/plain' class='untested'>
interface Document {};
Document implements XPathEvaluator;
Document includes XPathEvaluatorBase;
</script>
<script>
"use strict";

View file

@ -0,0 +1,46 @@
<!DOCTYPE html>
<!--
Tentative due to:
https://github.com/whatwg/fullscreen/issues/152
-->
<title>Element#requestFullscreen() twice</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../trusted-click.js"></script>
<div id="log"></div>
<script>
promise_test(async (test) => {
const div = document.querySelector("div");
const fullscreenChangePromise = new Promise((resolve, reject) => {
document.onfullscreenchange = test.step_func(() => {
assert_equals(document.fullscreenElement, div);
// Ensure that there's only one fullscreenchange event.
document.onfullscreenchange = test.unreached_func("second fullscreenchange event");
resolve();
});
});
const fullscreenErrorPromise = new Promise((resolve, reject) => {
document.onfullscreenerror = test.step_func(() => {
resolve();
});
});
trusted_click(test, () => {
// Request fullscreen twice.
div.requestFullscreen();
assert_equals(document.fullscreenElement, null, "fullscreenElement after first requestFullscreen()");
var p = div.requestFullscreen();
if (p) {
p.then(test.unreached_func("promise unexpectedly resolved"), ()=>{});
}
}, document.body);
await Promise.all([
fullscreenChangePromise,
fullscreenErrorPromise,
]);
});
</script>

View file

@ -0,0 +1,56 @@
<!DOCTYPE html>
<!--
Tentative due to:
https://github.com/whatwg/fullscreen/issues/152
-->
<title>Element#requestFullscreen() on two elements in the same document</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../trusted-click.js"></script>
<div id="log"></div>
<div id="a"></div>
<div id="b"></div>
<script>
promise_test(async (test) => {
// Request fullscreen on both elements, but in reverse tree order.
const a = document.getElementById('a');
const b = document.getElementById('b');
// Expect two fullscreenchange events, with document.fullscreenElement
// changing in the same order as the requests.
const order = [];
const fullscreenChangePromise = new Promise((resolve, reject) => {
document.onfullscreenchange = test.step_func(() => {
assert_in_array(document.fullscreenElement, [a, b]);
order.push(document.fullscreenElement.id);
if (order.length == 2) {
// Since fullscreenchange event occurs at animation frame timing we might
// have not seen the transition from null -> 'b' but just see the
// resulting 'a' transition twice.
assert_true(order[0] == 'a' || order[0] == 'b', 'first id seen is a or b');
assert_true(order[1] == 'a', 'second id seen is b');
}
resolve();
});
});
const fullscreenErrorPromise = new Promise((resolve, reject) => {
document.onfullscreenerror = test.step_func(() => {
resolve();
});
});
trusted_click(test, () => {
b.requestFullscreen();
var p = a.requestFullscreen();
if (p) {
p.then(test.unreached_func("promise unexpectedly resolved"), ()=>{});
}
}, document.body);
await Promise.all([
fullscreenChangePromise,
fullscreenErrorPromise,
]);
});
</script>

View file

@ -0,0 +1,65 @@
<!DOCTYPE html>
<!--
Tentative due to:
https://github.com/whatwg/fullscreen/issues/152
-->
<title>Element#requestFullscreen() on two elements in different iframes</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../trusted-click.js"></script>
<div id="log"></div>
<iframe id="a" allowfullscreen></iframe>
<iframe id="b" allowfullscreen></iframe>
<script>
promise_test(async (test) => {
// Request fullscreen on the body elements of both iframes, but in reverse
// tree order.
const a = document.getElementById('a');
const b = document.getElementById('b');
var rejected = false;
// Expect two fullscreenchange events, with document.fullscreenElement
// changing in the same order as the requests. (Events should also fire on the
// iframes' documents, but this is not covered by this test.)
const order = [];
const fullscreenChangePromise = new Promise((resolve, reject) => {
document.onfullscreenchange = test.step_func(() => {
assert_in_array(document.fullscreenElement, [a, b]);
order.push(document.fullscreenElement.id);
if (order.length == 2) {
// When the second event arrived, the fullscreen element may still be the
// old one.
//
// TODO(mustaq): We need a better explanation here to cover the tree-order
// idea of the spec.
assert_true(order[0] == 'a' || order[0] == 'b', 'first id seen is a or b');
assert_true(order[1] == 'a', 'second id seen is a');
}
resolve();
});
});
const fullscreenErrorPromise = new Promise((resolve, reject) => {
document.onfullscreenerror = test.step_func(() => {
resolve();
});
});
// Make a trusted click on frame 'b' to activate it.
trusted_click(test, () => {
// Now queue a trusted click on frame 'a' to make back-to-back calls.
setTimeout(() => {
trusted_click(test, () => {
b.contentDocument.body.requestFullscreen();
a.contentDocument.body.requestFullscreen().catch(test.step_func_done());
}, a.contentDocument.body);
}, 0);
}, b.contentDocument.body);
await Promise.all([
fullscreenChangePromise,
fullscreenErrorPromise,
]);
});
</script>

View file

@ -7,16 +7,21 @@
<video hidden></video>
<script>
// Negative test for the specified behavior prior to HTML r8447.
async_test(function(t) {
promise_test(async function(t) {
var v = document.querySelector('video');
v.play();
t.step_timeout(function() {
var watcher = new EventWatcher(t, v, [ 'pause' ]);
var p = v.play();
await new Promise(resolve => t.step_timeout(resolve, 0));
assert_equals(v.networkState, v.NETWORK_EMPTY,
'networkState after stable state');
assert_false(v.paused, 'paused after stable state');
v.parentNode.removeChild(v);
assert_false(v.paused, 'paused after removing');
v.onpause = t.step_func_done();
}, 0);
await watcher.wait_for('pause');
await promise_rejects(t, 'AbortError', p, 'We expect promise being rejected');
assert_true(v.paused, 'paused after removing and stable state');
});
</script>

View file

@ -17,12 +17,12 @@
// Testing TextTrackCueList [] operator.
assert_equals(cues[0].id, "1");
assert_equals(cues[3].id, "4");
assert_object_equals(cues[4], undefined);
assert_equals(cues[4], undefined);
// Testing TextTrackCueList getCueById().
assert_equals(cues.getCueById("1").startTime, 0);
assert_equals(cues.getCueById("4").startTime, 121);
assert_object_equals(cues.getCueById("junk"), undefined);
assert_equals(cues.getCueById("junk"), null);
});
});
</script>

View file

@ -0,0 +1,20 @@
<!doctype html>
<title>Avoid srcset image reloads when viewport resizes</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
setup({explicit_done:true});
const image_was_loaded = () => {
const iframe = document.getElementById("iframe");
// Resize the iframe
iframe.width="400";
// Wait 500 ms
step_timeout(() => {
// Check that the iframe only loaded a single resource
const entries = iframe.contentWindow.performance.getEntriesByType("resource");
assert_equals(entries.length, 1);
done();
}, 500);
}
</script>
<iframe id=iframe width="401" src="resources/resized.html" onload="image_was_loaded()"></iframe>

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

View file

@ -0,0 +1,2 @@
<!DOCTYPE html>
<img srcset="image.png?400 400w, image.png?800 800w, image.png?1600 1600w" sizes="50vw">

View file

@ -61,8 +61,8 @@ interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
typedef (DOMString or Function) TimerHandler;
[NoInterfaceObject, Exposed=(Window,Worker)]
interface WindowOrWorkerGlobalScope {
[Exposed=(Window,Worker)]
interface mixin WindowOrWorkerGlobalScope {
[Replaceable] readonly attribute USVString origin;
// base64 utility methods
@ -79,17 +79,17 @@ interface WindowOrWorkerGlobalScope {
Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, optional ImageBitmapOptions options);
Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, long sx, long sy, long sw, long sh, optional ImageBitmapOptions options);
};
WorkerGlobalScope implements WindowOrWorkerGlobalScope;
WorkerGlobalScope includes WindowOrWorkerGlobalScope;
[Exposed=Worker]
interface WorkerNavigator {};
WorkerNavigator implements NavigatorID;
WorkerNavigator implements NavigatorLanguage;
WorkerNavigator implements NavigatorOnLine;
WorkerNavigator implements NavigatorConcurrentHardware;
WorkerNavigator includes NavigatorID;
WorkerNavigator includes NavigatorLanguage;
WorkerNavigator includes NavigatorOnLine;
WorkerNavigator includes NavigatorConcurrentHardware;
[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorID {
[Exposed=(Window,Worker)]
interface mixin NavigatorID {
readonly attribute DOMString appCodeName; // constant "Mozilla"
readonly attribute DOMString appName; // constant "Netscape"
readonly attribute DOMString appVersion;
@ -103,19 +103,19 @@ interface NavigatorID {
// also has additional members in a partial interface
};
[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorLanguage {
[Exposed=(Window,Worker)]
interface mixin NavigatorLanguage {
readonly attribute DOMString language;
readonly attribute FrozenArray<DOMString> languages;
};
[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorOnLine {
[Exposed=(Window,Worker)]
interface mixin NavigatorOnLine {
readonly attribute boolean onLine;
};
[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorConcurrentHardware {
[Exposed=(Window,Worker)]
interface mixin NavigatorConcurrentHardware {
readonly attribute unsigned long long hardwareConcurrency;
};

View file

@ -1,5 +1,6 @@
<!DOCTYPE html>
<meta charset="utf-8">
<img src="/common/slow.py">
<script>
window.addEventListener('load', () => {
window.parent.postMessage('load');

View file

@ -60,7 +60,7 @@
assert_false(sourceBuffer.updating, "updating");
mediaSource.endOfStream();
assert_less_than(mediaSource.duration, 10, "duration");
mediaElement.play();
mediaElement.play().catch(test.unreached_func("Unexpected promise rejection"));;
test.expectEvent(mediaElement, 'ended', 'mediaElement');
});
@ -103,7 +103,7 @@
mediaSource.endOfStream();
assert_less_than(mediaSource.duration, 10, "duration");
startTime = window.performance.now();
mediaElement.play();
mediaElement.play().catch(test.unreached_func("Unexpected promise rejection"));
test.expectEvent(mediaElement, 'ended', 'mediaElement');
});

View file

@ -10,7 +10,7 @@
// --enable-blink-features=MojoJS,MojoJSTest
let loadChromiumResources = Promise.resolve().then(() => {
if (!MojoInterfaceInterceptor) {
if (!('MojoInterfaceInterceptor' in self)) {
// Do nothing on non-Chromium-based browsers or when the Mojo bindings are
// not present in the global namespace.
return;

View file

@ -75,9 +75,11 @@ function wait_for_update(test, registration) {
}
return new Promise(test.step_func(function(resolve) {
registration.addEventListener('updatefound', test.step_func(function() {
var handler = test.step_func(function() {
registration.removeEventListener('updatefound', handler);
resolve(registration.installing);
}));
});
registration.addEventListener('updatefound', handler);
}));
}

View file

@ -1,23 +1,57 @@
'use strict';
const installMayFinish = new Promise(resolve => {
const installEventFired = new Promise(resolve => {
self.fireInstallEvent = resolve;
});
const installFinished = new Promise(resolve => {
self.finishInstall = resolve;
});
let report = { installEventFired: false };
addEventListener('install', event => {
report.installEventFired = true;
let attemptUpdate = registration.update().catch(exception => {
report.exception = exception.name;
});
event.waitUntil(Promise.all([installMayFinish, attemptUpdate]));
fireInstallEvent();
event.waitUntil(installFinished);
});
addEventListener('message', event => {
if (event.data === 'finishInstall') {
// Use a dedicated MessageChannel for every request so senders can wait for
// individual requests to finish, and concurrent requests (to different
// workers) don't cause race conditions.
const port = event.data;
port.onmessage = (event) => {
switch (event.data) {
case 'awaitInstallEvent':
installEventFired.then(() => {
port.postMessage('installEventFired');
});
break;
case 'finishInstall':
installFinished.then(() => {
port.postMessage('installFinished');
});
finishInstall();
} else {
event.source.postMessage(report);
break;
case 'callUpdate': {
const channel = new MessageChannel();
registration.update().then(() => {
channel.port2.postMessage({
success: true,
});
}).catch((exception) => {
channel.port2.postMessage({
success: false,
exception: exception.name,
});
});
port.postMessage(channel.port1, [channel.port1]);
break;
}
default:
port.postMessage('Unexpected command ' + event.data);
break;
}
};
});

View file

@ -0,0 +1,11 @@
import time
def main(request, response):
headers = [('Content-Type', 'application/javascript'),
('Cache-Control', 'max-age=0')]
# Add timestamp to the worker so update() finds a new worker every time.
body = '''
// %s
importScripts('update-during-installation-worker.js');
'''.strip() % time.clock()
return headers, body

View file

@ -5,16 +5,85 @@
<script>
'use strict';
function send_message_to_worker_and_wait_for_response(worker, message) {
return new Promise(resolve => {
// Use a dedicated channel for every request to avoid race conditions on
// concurrent requests.
const channel = new MessageChannel();
worker.postMessage(channel.port1, [channel.port1]);
let messageReceived = false;
channel.port2.onmessage = event => {
assert_false(messageReceived, 'Already received response for ' + message);
messageReceived = true;
resolve(event.data);
};
channel.port2.postMessage(message);
});
}
async function ensure_install_event_fired(worker) {
const response = await send_message_to_worker_and_wait_for_response(worker, 'awaitInstallEvent');
assert_equals('installEventFired', response);
assert_equals('installing', worker.state, 'Expected worker to be installing.');
}
async function finish_install(worker) {
await ensure_install_event_fired(worker);
const response = await send_message_to_worker_and_wait_for_response(worker, 'finishInstall');
assert_equals('installFinished', response);
}
async function activate_service_worker(t, worker) {
await finish_install(worker);
// By waiting for both states at the same time, the test fails
// quickly if the installation fails, avoiding a timeout.
await Promise.race([wait_for_state(t, worker, 'activated'),
wait_for_state(t, worker, 'redundant')]);
assert_equals('activated', worker.state, 'Service worker should be activated.');
}
async function update_within_service_worker(worker) {
// This function returns a Promise that resolves when update()
// has been called but is not necessarily finished yet.
// Call finish() on the returned object to wait for update() settle.
const port = await send_message_to_worker_and_wait_for_response(worker, 'callUpdate');
let messageReceived = false;
return {
finish: () => {
return new Promise(resolve => {
port.onmessage = event => {
assert_false(messageReceived, 'Update already finished.');
messageReceived = true;
resolve(event.data);
};
});
},
};
}
async function update_from_client_and_await_installing_version(test, registration) {
const updatefound = wait_for_update(test, registration);
registration.update();
await updatefound;
return registration.installing;
}
async function spin_up_service_worker(test) {
const script = 'resources/update-during-installation-worker.js';
const script = 'resources/update-during-installation-worker.py';
const scope = 'resources/blank.html';
let registration = await service_worker_unregister_and_register(test, script, scope);
test.add_cleanup(() => {
const registration = await service_worker_unregister_and_register(test, script, scope);
test.add_cleanup(async () => {
if (registration.installing) {
registration.installing.postMessage('finishInstall');
// If there is an installing worker, we need to finish installing it.
// Otherwise, the tests fails with an timeout because unregister() blocks
// until the install-event-handler finishes.
const worker = registration.installing;
await send_message_to_worker_and_wait_for_response(worker, 'awaitInstallEvent');
await send_message_to_worker_and_wait_for_response(worker, 'finishInstall');
}
registration.unregister();
return registration.unregister();
});
return registration;
@ -23,36 +92,49 @@ async function spin_up_service_worker(test) {
promise_test(async t => {
const registration = await spin_up_service_worker(t);
const worker = registration.installing;
await ensure_install_event_fired(worker);
// spin_up_service_worker installs a cleanup hook that ensures the
// worker finished its installation by sending it a
// 'finishInstall' message, thus making sure that the registration
// will be cleanly removed at the end of the test.
assert_equals(worker.state, 'installing');
promise_rejects(t, 'InvalidStateError', registration.update());
}, 'ServiceWorkerRegistration.update() from client throws while installing service worker.')
const result = registration.update();
await activate_service_worker(t, worker);
return result;
}, 'ServiceWorkerRegistration.update() from client succeeds while installing service worker.');
promise_test(async t => {
const registration = await spin_up_service_worker(t);
const worker = registration.installing;
worker.postMessage('finishInstall');
await ensure_install_event_fired(worker);
// By waiting for both states at the same time, the test fails
// quickly if the installation fails, avoiding a timeout.
await Promise.race([wait_for_state(t, worker, 'activated'),
wait_for_state(t, worker, 'redundant')]);
assert_equals(worker.state, 'activated', 'Service worker should be activated.');
const response = await new Promise(resolve => {
navigator.serviceWorker.onmessage = event => { resolve(event.data); };
worker.postMessage('PING');
// Add event listener to fail the test if update() succeeds.
const updatefound = t.step_func(async () => {
registration.removeEventListener('updatefound', updatefound);
// Activate new worker so non-compliant browsers don't fail with timeout.
await activate_service_worker(t, registration.installing);
assert_unreached("update() should have failed");
});
registration.addEventListener('updatefound', updatefound);
// We check that the service worker instance that replied to the
// message is the same one that received the 'install' event since
// it's possible for them to be two distinct execution
// environments.
assert_true(response.installEventFired, 'Service worker should have been installed.');
assert_equals(response.exception, 'InvalidStateError', 'update() should have thrown.');
const update = await update_within_service_worker(worker);
// Activate worker to ensure update() finishes and the test doesn't timeout
// in non-compliant browsers.
await activate_service_worker(t, worker);
const response = await update.finish();
assert_false(response.success, 'update() should have failed.');
assert_equals('InvalidStateError', response.exception, 'update() should have thrown InvalidStateError.');
}, 'ServiceWorkerRegistration.update() from installing service worker throws.');
promise_test(async t => {
const registration = await spin_up_service_worker(t);
const worker1 = registration.installing;
await activate_service_worker(t, worker1);
const worker2 = await update_from_client_and_await_installing_version(t, registration);
await ensure_install_event_fired(worker2);
const update = await update_within_service_worker(worker1);
// Activate the new version so that update() finishes and the test doesn't timeout.
await activate_service_worker(t, worker2);
const response = await update.finish();
assert_true(response.success, 'update() from active service worker should have succeeded.');
}, 'ServiceWorkerRegistration.update() from active service worker succeeds while installing service worker.');
</script>

View file

@ -10,7 +10,7 @@
// --enable-blink-features=MojoJS,MojoJSTest
let loadChromiumResources = Promise.resolve().then(() => {
if (!MojoInterfaceInterceptor) {
if (!('MojoInterfaceInterceptor' in self)) {
// Do nothing on non-Chromium-based browsers or when the Mojo bindings are
// not present in the global namespace.
return;

View file

@ -153,7 +153,7 @@ class MtimeCache(CacheFile):
def __init__(self, cache_root, tests_root, manifest_path, rebuild=False):
self.manifest_path = manifest_path
super(MtimeCache, self).__init__(cache_root, tests_root, rebuild=False)
super(MtimeCache, self).__init__(cache_root, tests_root, rebuild)
def updated(self, rel_path, stat):
"""Return a boolean indicating whether the file changed since the cache was last updated.

View file

@ -179,7 +179,11 @@ class Firefox(Browser):
binary = find_executable("firefox", os.path.join(path, "firefox"))
elif self.platform == "win":
import mozinstall
try:
binary = mozinstall.get_binary(path, "firefox")
except mozinstall.InvalidBinary:
# ignore the case where we fail to get a binary
pass
elif self.platform == "macos":
binary = find_executable("firefox", os.path.join(path, self.application_name.get(channel, "Firefox Nightly.app"),
"Contents", "MacOS"))

View file

@ -125,6 +125,11 @@ def check_environ(product):
else:
hosts_path = "/etc/hosts"
if os.path.abspath(os.curdir) == wpt_root:
wpt_path = "wpt"
else:
wpt_path = os.path.join(wpt_root, "wpt")
with open(hosts_path, "r") as f:
for line in f:
line = line.split("#", 1)[0].strip()
@ -136,13 +141,14 @@ def check_environ(product):
if is_windows:
message = """Missing hosts file configuration. Run
python wpt make-hosts-file | Out-File %s -Encoding ascii -Append
python %s make-hosts-file | Out-File %s -Encoding ascii -Append
in PowerShell with Administrator privileges.""" % hosts_path
in PowerShell with Administrator privileges.""" % (wpt_path, hosts_path)
else:
message = """Missing hosts file configuration. Run
./wpt make-hosts-file | sudo tee -a %s""" % hosts_path
%s make-hosts-file | sudo tee -a %s""" % ("./wpt" if wpt_path == "wpt" else wpt_path,
hosts_path)
raise WptrunError(message)

View file

@ -85,7 +85,7 @@ class Virtualenv(object):
def install(self, *requirements):
try:
self.working_set.require(*requirements)
except pkg_resources.ResolutionError:
except Exception:
pass
else:
return
@ -98,7 +98,7 @@ class Virtualenv(object):
with open(requirements_path) as f:
try:
self.working_set.require(f.read())
except pkg_resources.ResolutionError:
except Exception:
pass
else:
return

View file

@ -3,7 +3,7 @@ from six.moves.urllib.parse import urljoin
from collections import deque
from wptmanifest.backends import static
from wptmanifest.backends.static import ManifestItem
from wptmanifest.backends.base import ManifestItem
import expected
@ -198,7 +198,7 @@ def fuzzy_prop(node):
class ExpectedManifest(ManifestItem):
def __init__(self, name, test_path, url_base):
def __init__(self, node, test_path, url_base):
"""Object representing all the tests in a particular manifest
:param name: Name of the AST Node associated with this object.
@ -207,13 +207,14 @@ class ExpectedManifest(ManifestItem):
:param test_path: Path of the test file associated with this manifest.
:param url_base: Base url for serving the tests in this manifest
"""
name = node.data
if name is not None:
raise ValueError("ExpectedManifest should represent the root node")
if test_path is None:
raise ValueError("ExpectedManifest requires a test path")
if url_base is None:
raise ValueError("ExpectedManifest requires a base url")
ManifestItem.__init__(self, name)
ManifestItem.__init__(self, node)
self.child_map = {}
self.test_path = test_path
self.url_base = url_base
@ -339,12 +340,12 @@ class DirectoryManifest(ManifestItem):
class TestNode(ManifestItem):
def __init__(self, name):
def __init__(self, node, **kwargs):
"""Tree node associated with a particular test in a manifest
:param name: name of the test"""
assert name is not None
ManifestItem.__init__(self, name)
assert node.data is not None
ManifestItem.__init__(self, node, **kwargs)
self.updated_expected = []
self.new_expected = []
self.subtests = {}
@ -431,12 +432,6 @@ class TestNode(ManifestItem):
class SubtestNode(TestNode):
def __init__(self, name):
"""Tree node associated with a particular subtest in a manifest
:param name: name of the subtest"""
TestNode.__init__(self, name)
@property
def is_empty(self):
if self._data:

View file

@ -7,9 +7,7 @@ from six.moves.queue import Empty
from collections import namedtuple
from multiprocessing import Process, current_process, Queue
from mozlog import structuredlog
import wptlogging
from mozlog import structuredlog, capture
# Special value used as a sentinal in various commands
Stop = object()
@ -142,7 +140,7 @@ def start_runner(runner_command_queue, runner_result_queue,
logger = MessageLogger(send_message)
with wptlogging.CaptureIO(logger, capture_stdio):
with capture.CaptureIO(logger, capture_stdio):
try:
browser = executor_browser_cls(**executor_browser_kwargs)
executor = executor_cls(browser, **executor_kwargs)

View file

@ -1,12 +1,9 @@
import logging
import sys
import threading
from six import StringIO
from multiprocessing import Queue
from mozlog import commandline, stdadapter, set_default_logger
from mozlog.structuredlog import StructuredLogger
def setup(args, defaults):
logger = args.pop('log', None)
if logger:
@ -49,86 +46,3 @@ class LogLevelRewriter(object):
data = data.copy()
data["level"] = self.to_level
return self.inner(data)
class LogThread(threading.Thread):
def __init__(self, queue, logger, level):
self.queue = queue
self.log_func = getattr(logger, level)
threading.Thread.__init__(self, name="Thread-Log")
self.daemon = True
def run(self):
while True:
try:
msg = self.queue.get()
except (EOFError, IOError):
break
if msg is None:
break
else:
self.log_func(msg)
class LoggingWrapper(StringIO):
"""Wrapper for file like objects to redirect output to logger
instead"""
def __init__(self, queue, prefix=None):
StringIO.__init__(self)
self.queue = queue
self.prefix = prefix
def write(self, data):
if isinstance(data, str):
try:
data = data.decode("utf8")
except UnicodeDecodeError:
data = data.encode("string_escape").decode("ascii")
if data.endswith("\n"):
data = data[:-1]
if data.endswith("\r"):
data = data[:-1]
if not data:
return
if self.prefix is not None:
data = "%s: %s" % (self.prefix, data)
self.queue.put(data)
def flush(self):
pass
class CaptureIO(object):
def __init__(self, logger, do_capture):
self.logger = logger
self.do_capture = do_capture
self.logging_queue = None
self.logging_thread = None
self.original_stdio = None
def __enter__(self):
if self.do_capture:
self.original_stdio = (sys.stdout, sys.stderr)
self.logging_queue = Queue()
self.logging_thread = LogThread(self.logging_queue, self.logger, "info")
sys.stdout = LoggingWrapper(self.logging_queue, prefix="STDOUT")
sys.stderr = LoggingWrapper(self.logging_queue, prefix="STDERR")
self.logging_thread.start()
def __exit__(self, *args, **kwargs):
if self.do_capture:
sys.stdout, sys.stderr = self.original_stdio
if self.logging_queue is not None:
self.logger.info("Closing logging queue")
self.logging_queue.put(None)
if self.logging_thread is not None:
self.logging_thread.join(10)
while not self.logging_queue.empty():
try:
self.logger.warning("Dropping log message: %r", self.logging_queue.get())
except Exception:
pass
self.logging_queue.close()
self.logger.info("queue closed")

View file

@ -0,0 +1,222 @@
import abc
from ..node import NodeVisitor
from ..parser import parse
class Compiler(NodeVisitor):
__metaclass__ = abc.ABCMeta
def compile(self, tree, data_cls_getter=None, **kwargs):
self._kwargs = kwargs
return self._compile(tree, data_cls_getter, **kwargs)
def _compile(self, tree, data_cls_getter=None, **kwargs):
"""Compile a raw AST into a form where conditional expressions
are represented by ConditionalValue objects that can be evaluated
at runtime.
tree - The root node of the wptmanifest AST to compile
data_cls_getter - A function taking two parameters; the previous
output node and the current ast node and returning
the class of the output node to use for the current
ast node
"""
if data_cls_getter is None:
self.data_cls_getter = lambda x, y: ManifestItem
else:
self.data_cls_getter = data_cls_getter
self.tree = tree
self.output_node = self._initial_output_node(tree, **kwargs)
self.visit(tree)
if hasattr(self.output_node, "set_defaults"):
self.output_node.set_defaults()
assert self.output_node is not None
return self.output_node
def _initial_output_node(self, node, **kwargs):
return self.data_cls_getter(None, None)(node, **kwargs)
def visit_DataNode(self, node):
if node != self.tree:
output_parent = self.output_node
self.output_node = self.data_cls_getter(self.output_node, node)(node, **self._kwargs)
else:
output_parent = None
assert self.output_node is not None
for child in node.children:
self.visit(child)
if output_parent is not None:
# Append to the parent *after* processing all the node data
output_parent.append(self.output_node)
self.output_node = self.output_node.parent
assert self.output_node is not None
@abc.abstractmethod
def visit_KeyValueNode(self, node):
pass
def visit_ListNode(self, node):
return [self.visit(child) for child in node.children]
def visit_ValueNode(self, node):
return node.data
def visit_AtomNode(self, node):
return node.data
@abc.abstractmethod
def visit_ConditionalNode(self, node):
pass
def visit_StringNode(self, node):
indexes = [self.visit(child) for child in node.children]
def value(x):
rv = node.data
for index in indexes:
rv = rv[index(x)]
return rv
return value
def visit_NumberNode(self, node):
if "." in node.data:
return float(node.data)
else:
return int(node.data)
def visit_VariableNode(self, node):
indexes = [self.visit(child) for child in node.children]
def value(x):
data = x[node.data]
for index in indexes:
data = data[index(x)]
return data
return value
def visit_IndexNode(self, node):
assert len(node.children) == 1
return self.visit(node.children[0])
@abc.abstractmethod
def visit_UnaryExpressionNode(self, node):
pass
@abc.abstractmethod
def visit_BinaryExpressionNode(self, node):
pass
@abc.abstractmethod
def visit_UnaryOperatorNode(self, node):
pass
@abc.abstractmethod
def visit_BinaryOperatorNode(self, node):
pass
class ManifestItem(object):
def __init__(self, node, **kwargs):
self.parent = None
self.node = node
self.children = []
self._data = {}
def __repr__(self):
return "<%s %s>" % (self.__class__, self.node.data)
def __str__(self):
rv = [repr(self)]
for item in self.children:
rv.extend(" %s" % line for line in str(item).split("\n"))
return "\n".join(rv)
def set_defaults(self):
pass
@property
def is_empty(self):
if self._data:
return False
return all(child.is_empty for child in self.children)
@property
def root(self):
node = self
while node.parent is not None:
node = node.parent
return node
@property
def name(self):
return self.node.data
def get(self, key):
for node in [self, self.root]:
if key in node._data:
return node._data[key]
raise KeyError
def set(self, name, value):
self._data[name] = value
def remove(self):
if self.parent:
self.parent.children.remove(self)
self.parent = None
def iterchildren(self, name=None):
for item in self.children:
if item.name == name or name is None:
yield item
def has_key(self, key):
for node in [self, self.root]:
if key in node._data:
return True
return False
def _flatten(self):
rv = {}
for node in [self, self.root]:
for name, value in node._data.iteritems():
if name not in rv:
rv[name] = value
return rv
def iteritems(self):
for item in self._flatten().iteritems():
yield item
def iterkeys(self):
for item in self._flatten().iterkeys():
yield item
def itervalues(self):
for item in self._flatten().itervalues():
yield item
def append(self, child):
child.parent = self
self.children.append(child)
return child
def compile_ast(compiler, ast, data_cls_getter=None, **kwargs):
return compiler().compile(ast,
data_cls_getter=data_cls_getter,
**kwargs)
def compile(compiler, stream, data_cls_getter=None, **kwargs):
return compile_ast(compiler,
parse(stream),
data_cls_getter=data_cls_getter,
**kwargs)

View file

@ -1,10 +1,10 @@
import operator
from ..node import NodeVisitor
from . import base
from ..parser import parse
class Compiler(NodeVisitor):
class Compiler(base.Compiler):
"""Compiler backend that evaluates conditional expressions
to give static output"""
@ -26,29 +26,7 @@ class Compiler(NodeVisitor):
self._kwargs = kwargs
self.expr_data = expr_data
if data_cls_getter is None:
self.data_cls_getter = lambda x, y: ManifestItem
else:
self.data_cls_getter = data_cls_getter
self.output_node = None
self.visit(tree)
return self.output_node
def visit_DataNode(self, node):
output_parent = self.output_node
if self.output_node is None:
assert node.parent is None
self.output_node = self.data_cls_getter(None, None)(None, **self._kwargs)
else:
self.output_node = self.data_cls_getter(self.output_node, node)(node.data)
for child in node.children:
self.visit(child)
if output_parent is not None:
output_parent.append(self.output_node)
self.output_node = self.output_node.parent
return self._compile(tree, data_cls_getter, **kwargs)
def visit_KeyValueNode(self, node):
key_name = node.data
@ -61,15 +39,6 @@ class Compiler(NodeVisitor):
if key_value is not None:
self.output_node.set(key_name, key_value)
def visit_ValueNode(self, node):
return node.data
def visit_AtomNode(self, node):
return node.data
def visit_ListNode(self, node):
return [self.visit(child) for child in node.children]
def visit_ConditionalNode(self, node):
assert len(node.children) == 2
if self.visit(node.children[0]):
@ -81,12 +50,6 @@ class Compiler(NodeVisitor):
value = self.visit(child)(value)
return value
def visit_NumberNode(self, node):
if "." in node.data:
return float(node.data)
else:
return int(node.data)
def visit_VariableNode(self, node):
value = self.expr_data[node.data]
for child in node.children:
@ -123,92 +86,6 @@ class Compiler(NodeVisitor):
"!=": operator.ne}[node.data]
class ManifestItem(object):
def __init__(self, name, **kwargs):
self.parent = None
self.name = name
self.children = []
self._data = {}
def __repr__(self):
return "<static.ManifestItem %s>" % (self.name)
def __str__(self):
rv = [repr(self)]
for item in self.children:
rv.extend(" %s" % line for line in str(item).split("\n"))
return "\n".join(rv)
def set_defaults(self):
pass
@property
def is_empty(self):
if self._data:
return False
return all(child.is_empty for child in self.children)
@property
def root(self):
node = self
while node.parent is not None:
node = node.parent
return node
def has_key(self, key):
for node in [self, self.root]:
if key in node._data:
return True
return False
def get(self, key):
for node in [self, self.root]:
if key in node._data:
return node._data[key]
raise KeyError
def set(self, name, value):
self._data[name] = value
def remove(self):
if self.parent:
self.parent._remove_child(self)
def _remove_child(self, child):
self.children.remove(child)
child.parent = None
def iterchildren(self, name=None):
for item in self.children:
if item.name == name or name is None:
yield item
def _flatten(self):
rv = {}
for node in [self, self.root]:
for name, value in node._data.iteritems():
if name not in rv:
rv[name] = value
return rv
def iteritems(self):
for item in self._flatten().iteritems():
yield item
def iterkeys(self):
for item in self._flatten().iterkeys():
yield item
def itervalues(self):
for item in self._flatten().itervalues():
yield item
def append(self, child):
child.parent = self
self.children.append(child)
return child
def compile_ast(ast, expr_data, data_cls_getter=None, **kwargs):
return Compiler().compile(ast,
expr_data,

View file

@ -12,6 +12,7 @@ import testloader
import wptcommandline
import wptlogging
import wpttest
from mozlog import capture
from font import FontInstaller
from testrunner import ManagerGroup
from browsers.base import NullBrowser
@ -132,7 +133,7 @@ def get_pause_after_test(test_loader, **kwargs):
def run_tests(config, test_paths, product, **kwargs):
with wptlogging.CaptureIO(logger, not kwargs["no_capture_stdio"]):
with capture.CaptureIO(logger, not kwargs["no_capture_stdio"]):
env.do_delayed_imports(logger, test_paths)
product = products.load_product(config, product, load_cls=True)

View file

@ -71,16 +71,13 @@ decorator::
Python File Handlers
--------------------
Python file handlers are designed to provide a vaguely PHP-like interface
where each resource corresponds to a particular python file on the
filesystem. Typically this is hooked up to a route like ``("*",
"*.py", python_file_handler)``, meaning that any .py file will be
treated as a handler file (note that this makes python files unsafe in
much the same way that .php files are when using PHP).
Python file handlers are Python files which the server executes in response to
requests made to the corresponding URL. This is hooked up to a route like
``("*", "*.py", python_file_handler)``, meaning that any .py file will be
treated as a handler file (note that this makes it easy to write unsafe
handlers, particularly when running the server in a web-exposed setting).
Unlike PHP, the python files don't work by outputting text to stdout
from the global scope. Instead they must define a single function
`main` with the signature::
The Python files must define a single function `main` with the signature::
main(request, response)

View file

@ -1,163 +1,6 @@
Pipes
======
Pipes are functions that may be used when serving files to alter parts
of the response. These are invoked by adding a pipe= query parameter
taking a | separated list of pipe functions and parameters. The pipe
functions are applied to the response from left to right. For example::
GET /sample.txt?pipe=slice(1,200)|status(404).
This would serve bytes 1 to 199, inclusive, of foo.txt with the HTTP status
code 404.
.. note::
If you write directly to the response socket using ResponseWriter,
or when using the asis handler, only the trickle pipe will affect the response.
There are several built-in pipe functions, and it is possible to add
more using the `@pipe` decorator on a function, if required.
.. note::
Because of the way pipes compose, using some pipe functions prevents the
content-length of the response from being known in advance. In these cases
the server will close the connection to indicate the end of the response,
preventing the use of HTTP 1.1 keepalive.
Built-In Pipes
--------------
sub
~~~
Used to substitute variables from the server environment, or from the
request into the response.
Substitutions are marked in a file using a block delimited by `{{`
and `}}`. Inside the block the following variables are available:
`{{host}}`
The host name of the server excluding any subdomain part.
`{{domains[]}}`
The domain name of a particular subdomain
e.g. `{{domains[www]}}` for the `www` subdomain.
`{{ports[][]}}`
The port number of servers, by protocol
e.g. `{{ports[http][0]}}` for the first (and, depending on setup,
possibly only) http server
`{{headers[]}}`
The HTTP headers in the request
e.g. `{{headers[X-Test]}}` for a hypothetical `X-Test` header.
`{{header_or_default(header, default)}}`
The value of an HTTP header, or a default value if it is absent.
e.g. `{{header_or_default(X-Test, test-header-absent)}}`
`{{GET[]}}`
The query parameters for the request
e.g. `{{GET[id]}}` for an id parameter sent with the request.
So, for example, to write a JavaScript file called `xhr.js` that
depends on the host name of the server, without hardcoding, one might
write::
var server_url = http://{{host}}:{{ports[http][0]}}/path/to/resource;
//Create the actual XHR and so on
The file would then be included as:
<script src="xhr.js?pipe=sub"></script>
This pipe can also be enabled by using a filename `*.sub.ext`, e.g. the file above could be called `xhr.sub.js`.
status
~~~~~~
Used to set the HTTP status of the response, for example::
example.js?pipe=status(410)
headers
~~~~~~~
Used to add or replace http headers in the response. Takes two or
three arguments; the header name, the header value and whether to
append the header rather than replace an existing header (default:
False). So, for example, a request for::
example.html?pipe=header(Content-Type,text/plain)
causes example.html to be returned with a text/plain content type
whereas::
example.html?pipe=header(Content-Type,text/plain,True)
Will cause example.html to be returned with both text/html and
text/plain content-type headers.
slice
~~~~~
Used to send only part of a response body. Takes the start and,
optionally, end bytes as arguments, although either can be null to
indicate the start or end of the file, respectively. So for example::
example.txt?pipe=slice(10,20)
Would result in a response with a body containing 10 bytes of
example.txt including byte 10 but excluding byte 20.
::
example.txt?pipe=slice(10)
Would cause all bytes from byte 10 of example.txt to be sent, but::
example.txt?pipe=slice(null,20)
Would send the first 20 bytes of example.txt.
trickle
~~~~~~~
.. note::
Using this function will force a connection close.
Used to send the body of a response in chunks with delays. Takes a
single argument that is a microsyntax consisting of colon-separated
commands. There are three types of commands:
* Bare numbers represent a number of bytes to send
* Numbers prefixed `d` indicate a delay in seconds
* Numbers prefixed `r` must only appear at the end of the command, and
indicate that the preceding N items must be repeated until there is
no more content to send. The number of items to repeat must be even.
In the absence of a repetition command, the entire remainder of the content is
sent at once when the command list is exhausted. So for example::
example.txt?pipe=trickle(d1)
causes a 1s delay before sending the entirety of example.txt.
::
example.txt?pipe=trickle(100:d1)
causes 100 bytes of example.txt to be sent, followed by a 1s delay,
and then the remainder of the file to be sent. On the other hand::
example.txt?pipe=trickle(100:d1:r2)
Will cause the file to be sent in 100 byte chunks separated by a 1s
delay until the whole content has been sent.
:mod:`Interface <pipes>`
------------------------

View file

@ -327,6 +327,27 @@
await new Promise(resolve => pc.onnegotiationneeded = resolve);
}, 'Updating the direction of the transceiver should cause negotiationneeded to fire');
/*
5.2. RTCRtpSender Interface
setStreams
7. Update the negotiation-needed flag for connection.
*/
promise_test(async t => {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const answer = await generateAnswer(offer);
await pc.setRemoteDescription(answer);
const stream = new MediaStream();
transceiver.sender.setStreams(stream);
await new Promise(resolve => pc.onnegotiationneeded = resolve);
}, 'Calling setStreams should cause negotiationneeded to fire');
/*
TODO
4.7.3. Updating the Negotiation-Needed flag

View file

@ -0,0 +1,128 @@
<!doctype html>
<meta charset=utf-8>
<title>RTCRtpSender.prototype.setStreams</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 caller = new RTCPeerConnection();
t.add_cleanup(() => caller.close());
const callee = new RTCPeerConnection();
t.add_cleanup(() => callee.close());
const stream = await getNoiseStream({audio: true});
t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
const [track] = stream.getTracks();
const sender = caller.addTrack(track);
const stream1 = new MediaStream();
const stream2 = new MediaStream();
sender.setStreams(stream1, stream2);
const offer = await caller.createOffer();
callee.setRemoteDescription(offer);
return new Promise(resolve => callee.ontrack = t.step_func(event =>{
assert_equals(event.streams.length, 2);
const calleeStreamIds = event.streams.map(s => s.id);
assert_in_array(stream1.id, calleeStreamIds);
assert_in_array(stream2.id, calleeStreamIds);
resolve();
}));
}, 'setStreams causes streams to be reported via ontrack on callee');
promise_test(async t => {
const caller = new RTCPeerConnection();
t.add_cleanup(() => caller.close());
const callee = new RTCPeerConnection();
t.add_cleanup(() => callee.close());
const stream = await getNoiseStream({audio: true});
t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
const [track] = stream.getTracks();
const sender = caller.addTrack(track);
sender.setStreams(stream);
const offer = await caller.createOffer();
callee.setRemoteDescription(offer);
return new Promise(resolve => callee.ontrack = t.step_func(event =>{
assert_equals(event.streams.length, 1);
assert_equals(stream.id, event.streams[0].id);
assert_equals(track.id, event.track.id);
assert_equals(event.streams[0].getTracks()[0], event.track);
resolve();
}));
}, 'setStreams can be used to reconstruct a stream with a track on the remote side');
promise_test(async t => {
const caller = new RTCPeerConnection();
t.add_cleanup(() => caller.close());
const callee = new RTCPeerConnection();
t.add_cleanup(() => callee.close());
callee.ontrack = t.unreached_func();
const transceiver = caller.addTransceiver('audio', {direction: 'inactive'});
await exchangeOfferAnswer(caller, callee);
const stream1 = new MediaStream();
const stream2 = new MediaStream();
transceiver.direction = 'sendrecv';
transceiver.sender.setStreams(stream1, stream2);
const offer = await caller.createOffer();
callee.setRemoteDescription(offer);
return new Promise(resolve => callee.ontrack = t.step_func(event =>{
assert_equals(event.streams.length, 2);
const calleeStreamIds = event.streams.map(s => s.id);
assert_in_array(stream1.id, calleeStreamIds);
assert_in_array(stream2.id, calleeStreamIds);
assert_in_array(event.track, event.streams[0].getTracks());
assert_in_array(event.track, event.streams[1].getTracks());
resolve();
}));
}, 'Adding streams and changing direction causes new streams to be reported via ontrack on callee');
promise_test(async t => {
const caller = new RTCPeerConnection();
t.add_cleanup(() => caller.close());
const callee = new RTCPeerConnection();
t.add_cleanup(() => callee.close());
const stream1 = new MediaStream();
const stream2 = new MediaStream();
let calleeTrack = null;
callee.ontrack = t.step_func(event => {
assert_equals(event.streams.length, 0);
calleeTrack = event.track;
});
const transceiver = caller.addTransceiver('audio', {direction: 'sendrecv'});
await exchangeOfferAnswer(caller, callee);
assert_true(calleeTrack instanceof MediaStreamTrack);
transceiver.sender.setStreams(stream1, stream2);
const offer = await caller.createOffer();
callee.setRemoteDescription(offer);
return new Promise(resolve => callee.ontrack = t.step_func(event =>{
assert_equals(event.streams.length, 2);
const calleeStreamIds = event.streams.map(s => s.id);
assert_in_array(stream1.id, calleeStreamIds);
assert_in_array(stream2.id, calleeStreamIds);
assert_in_array(event.track, event.streams[0].getTracks());
assert_in_array(event.track, event.streams[1].getTracks());
assert_equals(event.track, calleeTrack);
resolve();
}));
}, 'Adding streams to an active transceiver causes new streams to be reported via ontrack on callee');
test(t => {
const pc = new RTCPeerConnection();
const stream1 = new MediaStream();
const stream2 = new MediaStream();
const transceiver = pc.addTransceiver('audio');
pc.close();
assert_throws('InvalidStateError', () => transceiver.sender.setStreams(stream1, stream2));
}, 'setStreams() fires InvalidStateError on a closed peer connection.');
</script>

View file

@ -116,7 +116,7 @@ function forEachWebxrObject(callback) {
// Code for loading test api in chromium.
let loadChromiumResources = Promise.resolve().then(() => {
if (!MojoInterfaceInterceptor) {
if (!('MojoInterfaceInterceptor' in self)) {
// Do nothing on non-Chromium-based browsers or when the Mojo bindings are
// not present in the global namespace.
return;

View file

@ -0,0 +1,61 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-constants.js"></script>
<script src="resources/webxr_util.js"></script>
<script src="resources/xr-test-asserts.js"></script>
<canvas></canvas>
<script>
let immersiveTestName = "XRWebGLLayer reports a valid viewports for immersive sessions";
let inlineTestName = "XRWebGLLayer reports a valid viewports for inline sessions";
let fakeDeviceInitParams = { supportsImmersive:true };
let testFunction = function(session, fakeDeviceController, t) {
// Need to have a valid pose.
fakeDeviceController.setXRPresentationFrameData(VALID_POSE_MATRIX, [{
eye:"left",
projectionMatrix: VALID_PROJECTION_MATRIX,
viewMatrix: VALID_VIEW_MATRIX
}, {
eye:"right",
projectionMatrix: VALID_PROJECTION_MATRIX,
viewMatrix: VALID_VIEW_MATRIX
}]);
return session.requestReferenceSpace('viewer')
.then((space) => new Promise((resolve) => {
function onFrame(time, xrFrame) {
let viewer_pose = xrFrame.getViewerPose(space);
let layer = xrFrame.session.renderState.baseLayer;
for (view of viewer_pose.views) {
let viewport = layer.getViewport(view);
// Ensure the returned object is an XRViewport object
assert_not_equals(viewport, null);
assert_true(viewport instanceof XRViewport);
// Ensure the viewport dimensions are valid
assert_greater_than_equal(viewport.x, 0);
assert_greater_than_equal(viewport.y, 0);
assert_greater_than_equal(viewport.width, 1);
assert_greater_than_equal(viewport.height, 1);
}
// Finished test.
resolve();
}
session.requestAnimationFrame(onFrame);
}));
};
xr_session_promise_test(immersiveTestName, testFunction,
fakeDeviceInitParams, 'immersive-vr');
xr_session_promise_test(inlineTestName, testFunction,
fakeDeviceInitParams, 'inline');
</script>