summaryrefslogtreecommitdiff
path: root/tools/wpt
diff options
context:
space:
mode:
Diffstat (limited to 'tools/wpt')
-rw-r--r--tools/wpt/expectation.json622
-rw-r--r--tools/wpt/runner.ts133
-rw-r--r--tools/wpt/testharnessreport.js12
-rw-r--r--tools/wpt/utils.ts168
4 files changed, 935 insertions, 0 deletions
diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json
new file mode 100644
index 000000000..5bc4d77bc
--- /dev/null
+++ b/tools/wpt/expectation.json
@@ -0,0 +1,622 @@
+{
+ "WebCryptoAPI": {
+ "getRandomValues.any.js": true
+ },
+ "console": {
+ "console-is-a-namespace.any.js": true,
+ "console-label-conversion.any.js": true,
+ "console-namespace-object-class-string.any.js": true,
+ "console-tests-historical.any.js": true,
+ "idlharness.any.js": false
+ },
+ "dom": {
+ "abort": {
+ "event.any.js": true
+ },
+ "events": {
+ "AddEventListenerOptions-signal.any.js": true,
+ "Event-dispatch-listener-order.window.js": true,
+ "Event-isTrusted.any.js": true,
+ "EventListener-addEventListener.sub.window.js": true,
+ "EventTarget-constructible.any.js": true,
+ "event-global-extra.window.js": true,
+ "event-global.worker.js": true,
+ "legacy-pre-activation-behavior.window.js": true,
+ "relatedTarget.window.js": true
+ },
+ "idlharness.any.js": false,
+ "idlharness.window.js": false
+ },
+ "encoding": {
+ "api-basics.any.js": true,
+ "api-invalid-label.any.js": true,
+ "api-replacement-encodings.any.js": true,
+ "api-surrogates-utf8.any.js": true,
+ "encodeInto.any.js": [
+ "encodeInto() into SharedArrayBuffer with Hi and destination length 0, offset 0, filler 0",
+ "encodeInto() into SharedArrayBuffer with Hi and destination length 0, offset 4, filler 0",
+ "encodeInto() into SharedArrayBuffer with Hi and destination length 0, offset 0, filler 128",
+ "encodeInto() into SharedArrayBuffer with Hi and destination length 0, offset 4, filler 128",
+ "encodeInto() into SharedArrayBuffer with Hi and destination length 0, offset 0, filler random",
+ "encodeInto() into SharedArrayBuffer with Hi and destination length 0, offset 4, filler random",
+ "encodeInto() into SharedArrayBuffer with A and destination length 10, offset 0, filler 0",
+ "encodeInto() into SharedArrayBuffer with A and destination length 10, offset 4, filler 0",
+ "encodeInto() into SharedArrayBuffer with A and destination length 10, offset 0, filler 128",
+ "encodeInto() into SharedArrayBuffer with A and destination length 10, offset 4, filler 128",
+ "encodeInto() into SharedArrayBuffer with A and destination length 10, offset 0, filler random",
+ "encodeInto() into SharedArrayBuffer with A and destination length 10, offset 4, filler random",
+ "encodeInto() into SharedArrayBuffer with 𝌆 and destination length 4, offset 0, filler 0",
+ "encodeInto() into SharedArrayBuffer with 𝌆 and destination length 4, offset 4, filler 0",
+ "encodeInto() into SharedArrayBuffer with 𝌆 and destination length 4, offset 0, filler 128",
+ "encodeInto() into SharedArrayBuffer with 𝌆 and destination length 4, offset 4, filler 128",
+ "encodeInto() into SharedArrayBuffer with 𝌆 and destination length 4, offset 0, filler random",
+ "encodeInto() into SharedArrayBuffer with 𝌆 and destination length 4, offset 4, filler random",
+ "encodeInto() into SharedArrayBuffer with 𝌆A and destination length 3, offset 0, filler 0",
+ "encodeInto() into SharedArrayBuffer with 𝌆A and destination length 3, offset 4, filler 0",
+ "encodeInto() into SharedArrayBuffer with 𝌆A and destination length 3, offset 0, filler 128",
+ "encodeInto() into SharedArrayBuffer with 𝌆A and destination length 3, offset 4, filler 128",
+ "encodeInto() into SharedArrayBuffer with 𝌆A and destination length 3, offset 0, filler random",
+ "encodeInto() into SharedArrayBuffer with 𝌆A and destination length 3, offset 4, filler random",
+ "encodeInto() into ArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 0, filler 0",
+ "encodeInto() into SharedArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 0, filler 0",
+ "encodeInto() into ArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 4, filler 0",
+ "encodeInto() into SharedArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 4, filler 0",
+ "encodeInto() into ArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 0, filler 128",
+ "encodeInto() into SharedArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 0, filler 128",
+ "encodeInto() into ArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 4, filler 128",
+ "encodeInto() into SharedArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 4, filler 128",
+ "encodeInto() into ArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 0, filler random",
+ "encodeInto() into SharedArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 0, filler random",
+ "encodeInto() into ArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 4, filler random",
+ "encodeInto() into SharedArrayBuffer with \ud834A\udf06A¥Hi and destination length 10, offset 4, filler random",
+ "encodeInto() into ArrayBuffer with A\udf06 and destination length 4, offset 0, filler 0",
+ "encodeInto() into SharedArrayBuffer with A\udf06 and destination length 4, offset 0, filler 0",
+ "encodeInto() into ArrayBuffer with A\udf06 and destination length 4, offset 4, filler 0",
+ "encodeInto() into SharedArrayBuffer with A\udf06 and destination length 4, offset 4, filler 0",
+ "encodeInto() into ArrayBuffer with A\udf06 and destination length 4, offset 0, filler 128",
+ "encodeInto() into SharedArrayBuffer with A\udf06 and destination length 4, offset 0, filler 128",
+ "encodeInto() into ArrayBuffer with A\udf06 and destination length 4, offset 4, filler 128",
+ "encodeInto() into SharedArrayBuffer with A\udf06 and destination length 4, offset 4, filler 128",
+ "encodeInto() into ArrayBuffer with A\udf06 and destination length 4, offset 0, filler random",
+ "encodeInto() into SharedArrayBuffer with A\udf06 and destination length 4, offset 0, filler random",
+ "encodeInto() into ArrayBuffer with A\udf06 and destination length 4, offset 4, filler random",
+ "encodeInto() into SharedArrayBuffer with A\udf06 and destination length 4, offset 4, filler random",
+ "encodeInto() into SharedArrayBuffer with ¥¥ and destination length 4, offset 0, filler 0",
+ "encodeInto() into SharedArrayBuffer with ¥¥ and destination length 4, offset 4, filler 0",
+ "encodeInto() into SharedArrayBuffer with ¥¥ and destination length 4, offset 0, filler 128",
+ "encodeInto() into SharedArrayBuffer with ¥¥ and destination length 4, offset 4, filler 128",
+ "encodeInto() into SharedArrayBuffer with ¥¥ and destination length 4, offset 0, filler random",
+ "encodeInto() into SharedArrayBuffer with ¥¥ and destination length 4, offset 4, filler random",
+ "encodeInto() and a detached output buffer",
+ "Invalid encodeInto() destination: DataView, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: Int8Array, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: Int16Array, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: Int32Array, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: Uint16Array, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: Uint32Array, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: Uint8ClampedArray, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: Float32Array, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: Float64Array, backed by: SharedArrayBuffer",
+ "Invalid encodeInto() destination: SharedArrayBuffer"
+ ],
+ "idlharness.any.js": false,
+ "iso-2022-jp-decoder.any.js": false,
+ "legacy-mb-schinese": {
+ "gb18030": {
+ "gb18030-decoder.any.js": true
+ },
+ "gbk": {
+ "gbk-decoder.any.js": true
+ }
+ },
+ "replacement-encodings.any.js": false,
+ "streams": {
+ "backpressure.any.js": false,
+ "decode-attributes.any.js": false,
+ "decode-bad-chunks.any.js": false,
+ "decode-ignore-bom.any.js": false,
+ "decode-incomplete-input.any.js": false,
+ "decode-non-utf8.any.js": false,
+ "decode-split-character.any.js": false,
+ "decode-utf8.any.js": false,
+ "encode-bad-chunks.any.js": false,
+ "encode-utf8.any.js": false,
+ "readable-writable-properties.any.js": false,
+ "realms.window.js": false
+ },
+ "textdecoder-byte-order-marks.any.js": true,
+ "textdecoder-copy.any.js": [
+ "Modify buffer after passing it in (ArrayBuffer)",
+ "Modify buffer after passing it in (SharedArrayBuffer)"
+ ],
+ "textdecoder-fatal-single-byte.any.js": true,
+ "textdecoder-fatal-streaming.any.js": [
+ "Fatal flag, streaming cases"
+ ],
+ "textdecoder-fatal.any.js": true,
+ "textdecoder-ignorebom.any.js": true,
+ "textdecoder-labels.any.js": [
+ "cseucpkdfmtjapanese => EUC-JP",
+ "euc-jp => EUC-JP",
+ "x-euc-jp => EUC-JP",
+ "csiso2022jp => ISO-2022-JP",
+ "iso-2022-jp => ISO-2022-JP",
+ "csshiftjis => Shift_JIS",
+ "ms932 => Shift_JIS",
+ "ms_kanji => Shift_JIS",
+ "shift-jis => Shift_JIS",
+ "shift_jis => Shift_JIS",
+ "sjis => Shift_JIS",
+ "windows-31j => Shift_JIS",
+ "x-sjis => Shift_JIS",
+ "cseuckr => EUC-KR",
+ "csksc56011987 => EUC-KR",
+ "euc-kr => EUC-KR",
+ "iso-ir-149 => EUC-KR",
+ "korean => EUC-KR",
+ "ks_c_5601-1987 => EUC-KR",
+ "ks_c_5601-1989 => EUC-KR",
+ "ksc5601 => EUC-KR",
+ "ksc_5601 => EUC-KR",
+ "windows-949 => EUC-KR",
+ "x-user-defined => x-user-defined"
+ ],
+ "textdecoder-streaming.any.js": false,
+ "textdecoder-utf16-surrogates.any.js": true,
+ "textencoder-constructor-non-utf.any.js": [
+ "Encoding argument supported for decode: EUC-JP",
+ "Encoding argument supported for decode: ISO-2022-JP",
+ "Encoding argument supported for decode: Shift_JIS",
+ "Encoding argument supported for decode: EUC-KR",
+ "Encoding argument supported for decode: x-user-defined"
+ ],
+ "textencoder-utf16-surrogates.any.js": true,
+ "unsupported-encodings.any.js": false
+ },
+ "hr-time": {
+ "monotonic-clock.any.js": true,
+ "basic.any.js": [
+ "Performance interface extends EventTarget."
+ ],
+ "idlharness.any.js": false
+ },
+ "streams": {
+ "idlharness.any.js": false,
+ "piping": {
+ "abort.any.js": [
+ "a signal argument 'null' should cause pipeTo() to reject",
+ "a signal argument 'AbortSignal' should cause pipeTo() to reject",
+ "a signal argument 'true' should cause pipeTo() to reject",
+ "a signal argument '-1' should cause pipeTo() to reject",
+ "a signal argument '[object AbortSignal]' should cause pipeTo() to reject"
+ ],
+ "close-propagation-backward.any.js": [
+ "Closing must be propagated backward: starts closed; preventCancel = null (falsy); fulfilled cancel promise",
+ "Closing must be propagated backward: starts closed; preventCancel = 0 (falsy); fulfilled cancel promise",
+ "Closing must be propagated backward: starts closed; preventCancel = -0 (falsy); fulfilled cancel promise",
+ "Closing must be propagated backward: starts closed; preventCancel = NaN (falsy); fulfilled cancel promise",
+ "Closing must be propagated backward: starts closed; preventCancel = (falsy); fulfilled cancel promise",
+ "Closing must be propagated backward: starts closed; preventCancel = a (truthy)",
+ "Closing must be propagated backward: starts closed; preventCancel = 1 (truthy)",
+ "Closing must be propagated backward: starts closed; preventCancel = Symbol() (truthy)",
+ "Closing must be propagated backward: starts closed; preventCancel = [object Object] (truthy)"
+ ],
+ "close-propagation-forward.any.js": [
+ "Closing must be propagated forward: starts closed; preventClose = null (falsy); fulfilled close promise",
+ "Closing must be propagated forward: starts closed; preventClose = 0 (falsy); fulfilled close promise",
+ "Closing must be propagated forward: starts closed; preventClose = -0 (falsy); fulfilled close promise",
+ "Closing must be propagated forward: starts closed; preventClose = NaN (falsy); fulfilled close promise",
+ "Closing must be propagated forward: starts closed; preventClose = (falsy); fulfilled close promise",
+ "Closing must be propagated forward: starts closed; preventClose = a (truthy)",
+ "Closing must be propagated forward: starts closed; preventClose = 1 (truthy)",
+ "Closing must be propagated forward: starts closed; preventClose = Symbol() (truthy)",
+ "Closing must be propagated forward: starts closed; preventClose = [object Object] (truthy)"
+ ],
+ "error-propagation-backward.any.js": [
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = null (falsy); fulfilled cancel promise",
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = 0 (falsy); fulfilled cancel promise",
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = -0 (falsy); fulfilled cancel promise",
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = NaN (falsy); fulfilled cancel promise",
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = (falsy); fulfilled cancel promise",
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = a (truthy)",
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = 1 (truthy)",
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = Symbol() (truthy)",
+ "Errors must be propagated backward: becomes errored before piping due to write; preventCancel = [object Object] (truthy)"
+ ],
+ "error-propagation-forward.any.js": [
+ "Errors must be propagated forward: starts errored; preventAbort = null (falsy); fulfilled abort promise",
+ "Errors must be propagated forward: starts errored; preventAbort = 0 (falsy); fulfilled abort promise",
+ "Errors must be propagated forward: starts errored; preventAbort = -0 (falsy); fulfilled abort promise",
+ "Errors must be propagated forward: starts errored; preventAbort = NaN (falsy); fulfilled abort promise",
+ "Errors must be propagated forward: starts errored; preventAbort = (falsy); fulfilled abort promise",
+ "Errors must be propagated forward: starts errored; preventAbort = a (truthy)",
+ "Errors must be propagated forward: starts errored; preventAbort = 1 (truthy)",
+ "Errors must be propagated forward: starts errored; preventAbort = Symbol() (truthy)",
+ "Errors must be propagated forward: starts errored; preventAbort = [object Object] (truthy)"
+ ],
+ "flow-control.any.js": true,
+ "general.any.js": [
+ "pipeTo must check the brand of its ReadableStream this value",
+ "pipeTo must check the brand of its WritableStream argument",
+ "pipeTo() promise should resolve if null is passed"
+ ],
+ "multiple-propagation.any.js": true,
+ "pipe-through.any.js": true,
+ "then-interception.any.js": true,
+ "throwing-options.any.js": false,
+ "transform-streams.any.js": true
+ },
+ "queuing-strategies-size-function-per-global.window.js": false,
+ "queuing-strategies.any.js": true,
+ "readable-byte-streams": {
+ "bad-buffers-and-views.any.js": [
+ "ReadableStream with byte source: respond() throws if the BYOB request's buffer has been detached (in the readable state)",
+ "ReadableStream with byte source: respond() throws if the BYOB request's buffer has been detached (in the closed state)",
+ "ReadableStream with byte source: respondWithNewView() throws if the supplied view's buffer has been detached (in the readable state)",
+ "ReadableStream with byte source: respondWithNewView() throws if the supplied view's buffer is zero-length (in the readable state)",
+ "ReadableStream with byte source: respondWithNewView() throws if the supplied view is zero-length on a non-zero-length buffer (in the readable state)",
+ "ReadableStream with byte source: respondWithNewView() throws if the supplied view's buffer has been detached (in the closed state)",
+ "ReadableStream with byte source: respondWithNewView() throws if the supplied view's buffer is zero-length (in the closed state)",
+ "ReadableStream with byte source: respondWithNewView() throws if the supplied view is zero-length on a non-zero-length buffer (in the closed state)",
+ "ReadableStream with byte source: read()ing from a closed stream still transfers the buffer",
+ "ReadableStream with byte source: read()ing from a stream with queued chunks still transfers the buffer",
+ "ReadableStream with byte source: reading into an already-detached buffer rejects",
+ "ReadableStream with byte source: reading into a zero-length buffer rejects",
+ "ReadableStream with byte source: reading into a zero-length view on a non-zero-length buffer rejects"
+ ],
+ "construct-byob-request.any.js": false,
+ "general.any.js": [
+ "getReader({mode: \"byob\"}) throws on non-bytes streams",
+ "ReadableStream with byte source can be constructed with no errors",
+ "getReader({mode}) must perform ToString()",
+ "ReadableStream with byte source: autoAllocateChunkSize cannot be 0",
+ "ReadableStreamBYOBReader can be constructed directly",
+ "ReadableStreamBYOBReader constructor requires a ReadableStream argument",
+ "ReadableStreamBYOBReader constructor requires an unlocked ReadableStream",
+ "ReadableStreamBYOBReader constructor requires a ReadableStream with type \"bytes\"",
+ "ReadableStream with byte source: getReader() with mode set to byob, then releaseLock()",
+ "ReadableStream with byte source: Test that closing a stream does not release a BYOB reader automatically",
+ "ReadableStream with byte source: Test that erroring a stream does not release a BYOB reader automatically",
+ "ReadableStream with byte source: autoAllocateChunkSize",
+ "ReadableStream with byte source: Mix of auto allocate and BYOB",
+ "ReadableStream with byte source: enqueue(), read(view) partially, then read()",
+ "ReadableStream with byte source: Respond to pull() by enqueue()",
+ "ReadableStream with byte source: Respond to pull() by enqueue() asynchronously",
+ "ReadableStream with byte source: Respond to multiple pull() by separate enqueue()",
+ "ReadableStream with byte source: read(view), then respond()",
+ "ReadableStream with byte source: read(view), then respond() with a transferred ArrayBuffer",
+ "ReadableStream with byte source: read(view), then respond() with too big value",
+ "ReadableStream with byte source: respond(3) to read(view) with 2 element Uint16Array enqueues the 1 byte remainder",
+ "ReadableStream with byte source: enqueue(), getReader(), then read(view)",
+ "ReadableStream with byte source: enqueue(), getReader(), then cancel() (mode = BYOB)",
+ "ReadableStream with byte source: getReader(), read(view), then cancel()",
+ "ReadableStream with byte source: cancel() with partially filled pending pull() request",
+ "ReadableStream with byte source: enqueue(), getReader(), then read(view) where view.buffer is not fully covered by view",
+ "ReadableStream with byte source: Multiple enqueue(), getReader(), then read(view)",
+ "ReadableStream with byte source: enqueue(), getReader(), then read(view) with a bigger view",
+ "ReadableStream with byte source: enqueue(), getReader(), then read(view) with smaller views",
+ "ReadableStream with byte source: enqueue() 1 byte, getReader(), then read(view) with Uint16Array",
+ "ReadableStream with byte source: enqueue() 3 byte, getReader(), then read(view) with 2-element Uint16Array",
+ "ReadableStream with byte source: read(view) with Uint16Array on close()-d stream with 1 byte enqueue()-d must fail",
+ "ReadableStream with byte source: A stream must be errored if close()-d before fulfilling read(view) with Uint16Array",
+ "ReadableStream with byte source: read(view), then respond() and close() in pull()",
+ "ReadableStream with byte source: read(view) with Uint32Array, then fill it by multiple respond() calls",
+ "ReadableStream with byte source: read() twice, then enqueue() twice",
+ "ReadableStream with byte source: Multiple read(view), close() and respond()",
+ "ReadableStream with byte source: Multiple read(view), big enqueue()",
+ "ReadableStream with byte source: Multiple read(view) and multiple enqueue()",
+ "ReadableStream with byte source: read(view) with passing undefined as view must fail",
+ "ReadableStream with byte source: read(view) with passing an empty object as view must fail",
+ "ReadableStream with byte source: Even read(view) with passing ArrayBufferView like object as view must fail",
+ "ReadableStream with byte source: read(view) on an errored stream",
+ "ReadableStream with byte source: read(view), then error()",
+ "ReadableStream with byte source: Throwing in pull function must error the stream",
+ "ReadableStream with byte source: Throwing in pull in response to read() must be ignored if the stream is errored in it",
+ "ReadableStream with byte source: Throwing in pull in response to read(view) function must error the stream",
+ "ReadableStream with byte source: Throwing in pull in response to read(view) must be ignored if the stream is errored in it",
+ "calling respond() twice on the same byobRequest should throw",
+ "calling respondWithNewView() twice on the same byobRequest should throw",
+ "calling respond(0) twice on the same byobRequest should throw even when closed",
+ "pull() resolving should not make releaseLock() possible",
+ "ReadableStream with byte source: default reader + autoAllocateChunkSize + byobRequest interaction"
+ ]
+ },
+ "readable-streams": {
+ "async-iterator.any.js": [
+ "Async iterator instances should have the correct list of properties",
+ "values() throws if there's already a lock",
+ "return() should unlock the stream synchronously when preventCancel = false",
+ "return() should unlock the stream synchronously when preventCancel = true",
+ "Async-iterating a pull source manually",
+ "Cancellation behavior when throwing inside loop body; preventCancel = false",
+ "Cancellation behavior when throwing inside loop body; preventCancel = true",
+ "Cancellation behavior when breaking inside loop body; preventCancel = false",
+ "Cancellation behavior when breaking inside loop body; preventCancel = true",
+ "Cancellation behavior when returning inside loop body; preventCancel = false",
+ "Cancellation behavior when returning inside loop body; preventCancel = true",
+ "Cancellation behavior when manually calling return(); preventCancel = false",
+ "Cancellation behavior when manually calling return(); preventCancel = true",
+ "next() rejects if the stream errors",
+ "return() does not rejects if the stream has not errored yet",
+ "return() rejects if the stream has errored",
+ "next() that succeeds; next() that reports an error; next()"
+ ],
+ "bad-strategies.any.js": true,
+ "bad-underlying-sources.any.js": true,
+ "cancel.any.js": false,
+ "constructor.any.js": false,
+ "count-queuing-strategy-integration.any.js": true,
+ "default-reader.any.js": true,
+ "floating-point-total-queue-size.any.js": true,
+ "garbage-collection.any.js": true,
+ "general.any.js": true,
+ "patched-global.any.js": true,
+ "reentrant-strategies.any.js": true,
+ "tee.any.js": true,
+ "templated.any.js": [
+ "ReadableStream (empty) reader: canceling via the stream should fail"
+ ]
+ },
+ "transform-streams": {
+ "backpressure.any.js": true,
+ "errors.any.js": true,
+ "flush.any.js": true,
+ "general.any.js": true,
+ "lipfuzz.any.js": true,
+ "patched-global.any.js": false,
+ "properties.any.js": true,
+ "reentrant-strategies.any.js": true,
+ "strategies.any.js": true,
+ "terminate.any.js": [
+ "controller.terminate() inside flush() should not prevent writer.close() from succeeding"
+ ]
+ },
+ "writable-streams": {
+ "aborting.any.js": false,
+ "bad-strategies.any.js": [
+ "reject any non-function value for strategy.size",
+ "Writable stream: invalid size beats invalid highWaterMark"
+ ],
+ "bad-underlying-sinks.any.js": true,
+ "byte-length-queuing-strategy.any.js": true,
+ "close.any.js": false,
+ "constructor.any.js": [
+ "underlyingSink argument should be converted after queuingStrategy argument",
+ "WritableStreamDefaultController constructor should throw",
+ "WritableStreamDefaultController constructor should throw when passed an initialised WritableStream",
+ "WritableStreamDefaultWriter should throw unless passed a WritableStream"
+ ],
+ "count-queuing-strategy.any.js": true,
+ "error.any.js": true,
+ "floating-point-total-queue-size.any.js": true,
+ "general.any.js": true,
+ "properties.any.js": true,
+ "reentrant-strategy.any.js": true,
+ "start.any.js": true,
+ "write.any.js": true
+ }
+ },
+ "user-timing": {
+ "buffered-flag.any.js": false,
+ "case-sensitivity.any.js": false,
+ "clear_all_marks.any.js": true,
+ "clear_all_measures.any.js": true,
+ "clear_non_existent_mark.any.js": true,
+ "clear_non_existent_measure.any.js": true,
+ "clear_one_mark.any.js": true,
+ "clear_one_measure.any.js": true,
+ "entry_type.any.js": true,
+ "idlharness.any.js": false,
+ "mark-entry-constructor.any.js": true,
+ "mark-errors.any.js": true,
+ "mark-l3.any.js": false,
+ "mark-measure-return-objects.any.js": true,
+ "mark.any.js": true,
+ "measure-l3.any.js": true,
+ "measure-with-dict.any.js": [
+ "measure entries' detail and start/end are customizable"
+ ],
+ "measure_syntax_err.any.js": true,
+ "structured-serialize-detail.any.js": true,
+ "supported-usertiming-types.any.js": false,
+ "user_timing_exists.any.js": true
+ },
+ "wasm": {
+ "jsapi": {
+ "constructor": {
+ "compile.any.js": true,
+ "instantiate-bad-imports.any.js": false,
+ "instantiate.any.js": [
+ "Synchronous options handling: Buffer argument"
+ ],
+ "multi-value.any.js": true,
+ "toStringTag.any.js": true,
+ "validate.any.js": true
+ },
+ "global": {
+ "constructor.any.js": true,
+ "toString.any.js": true,
+ "type.tentative.any.js": false,
+ "value-get-set.any.js": true,
+ "valueOf.any.js": true
+ },
+ "idlharness.any.js": false,
+ "instance": {
+ "constructor-bad-imports.any.js": false,
+ "constructor-caching.any.js": true,
+ "constructor.any.js": true,
+ "exports.any.js": [
+ "Setting (sloppy mode)"
+ ],
+ "toString.any.js": true
+ },
+ "interface.any.js": [
+ "WebAssembly: property descriptor"
+ ],
+ "memory": {
+ "buffer.any.js": [
+ "Setting (sloppy mode)"
+ ],
+ "constructor.any.js": true,
+ "grow.any.js": [
+ "Growing shared memory does not detach old buffer"
+ ],
+ "toString.any.js": true,
+ "type.tentative.any.js": false
+ },
+ "module": {
+ "constructor.any.js": true,
+ "customSections.any.js": true,
+ "exports.any.js": true,
+ "imports.any.js": true,
+ "toString.any.js": true
+ },
+ "prototypes.any.js": false,
+ "table": {
+ "constructor.any.js": true,
+ "get-set.any.js": true,
+ "grow.any.js": true,
+ "length.any.js": [
+ "Setting (sloppy mode)"
+ ],
+ "toString.any.js": true
+ }
+ },
+ "serialization": {
+ "arraybuffer": {
+ "transfer.window.js": false
+ },
+ "module": {
+ "nested-worker-success.any.js": false,
+ "serialization-via-idb.any.js": false,
+ "serialization-via-notifications-api.any.js": false
+ }
+ },
+ "webapi": {
+ "abort.any.js": false,
+ "body.any.js": true,
+ "contenttype.any.js": [
+ "Response with Content-Type \"application/wasm\": compileStreaming",
+ "Response with Content-Type \"application/wasm\": instantiateStreaming",
+ "Response with Content-Type \"APPLICATION/wasm\": compileStreaming",
+ "Response with Content-Type \"APPLICATION/wasm\": instantiateStreaming",
+ "Response with Content-Type \"APPLICATION/WASM\": compileStreaming",
+ "Response with Content-Type \"APPLICATION/WASM\": instantiateStreaming"
+ ],
+ "empty-body.any.js": false,
+ "historical.any.js": false,
+ "idlharness.any.js": false,
+ "instantiateStreaming-bad-imports.any.js": [
+ "Importing a function with an incorrectly-typed value: undefined",
+ "Importing a function with an incorrectly-typed value: null",
+ "Importing a function with an incorrectly-typed value: true",
+ "Importing a function with an incorrectly-typed value: \"\"",
+ "Importing a function with an incorrectly-typed value: symbol \"Symbol()\"",
+ "Importing a function with an incorrectly-typed value: 1",
+ "Importing a function with an incorrectly-typed value: 0.1",
+ "Importing a function with an incorrectly-typed value: NaN",
+ "Importing a function with an incorrectly-typed value: object \"[object Object]\"",
+ "Importing an i32 global with an incorrectly-typed value: undefined",
+ "Importing an i32 global with an incorrectly-typed value: null",
+ "Importing an i32 global with an incorrectly-typed value: true",
+ "Importing an i32 global with an incorrectly-typed value: \"\"",
+ "Importing an i32 global with an incorrectly-typed value: symbol \"Symbol()\"",
+ "Importing an i32 global with an incorrectly-typed value: plain object",
+ "Importing an i32 global with an incorrectly-typed value: WebAssembly.Global",
+ "Importing an i32 global with an incorrectly-typed value: WebAssembly.Global.prototype",
+ "Importing an i32 global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype)",
+ "Importing an i32 global with an incorrectly-typed value: BigInt",
+ "Importing an i32 global with an incorrectly-typed value: WebAssembly.Global object (wrong value type)",
+ "Importing an i64 global with an incorrectly-typed value: undefined",
+ "Importing an i64 global with an incorrectly-typed value: null",
+ "Importing an i64 global with an incorrectly-typed value: true",
+ "Importing an i64 global with an incorrectly-typed value: \"\"",
+ "Importing an i64 global with an incorrectly-typed value: symbol \"Symbol()\"",
+ "Importing an i64 global with an incorrectly-typed value: plain object",
+ "Importing an i64 global with an incorrectly-typed value: WebAssembly.Global",
+ "Importing an i64 global with an incorrectly-typed value: WebAssembly.Global.prototype",
+ "Importing an i64 global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype)",
+ "Importing an i64 global with an incorrectly-typed value: Number",
+ "Importing an i64 global with an incorrectly-typed value: WebAssembly.Global object (wrong value type)",
+ "Importing an f32 global with an incorrectly-typed value: undefined",
+ "Importing an f32 global with an incorrectly-typed value: null",
+ "Importing an f32 global with an incorrectly-typed value: true",
+ "Importing an f32 global with an incorrectly-typed value: \"\"",
+ "Importing an f32 global with an incorrectly-typed value: symbol \"Symbol()\"",
+ "Importing an f32 global with an incorrectly-typed value: plain object",
+ "Importing an f32 global with an incorrectly-typed value: WebAssembly.Global",
+ "Importing an f32 global with an incorrectly-typed value: WebAssembly.Global.prototype",
+ "Importing an f32 global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype)",
+ "Importing an f32 global with an incorrectly-typed value: BigInt",
+ "Importing an f32 global with an incorrectly-typed value: WebAssembly.Global object (wrong value type)",
+ "Importing an f64 global with an incorrectly-typed value: undefined",
+ "Importing an f64 global with an incorrectly-typed value: null",
+ "Importing an f64 global with an incorrectly-typed value: true",
+ "Importing an f64 global with an incorrectly-typed value: \"\"",
+ "Importing an f64 global with an incorrectly-typed value: symbol \"Symbol()\"",
+ "Importing an f64 global with an incorrectly-typed value: plain object",
+ "Importing an f64 global with an incorrectly-typed value: WebAssembly.Global",
+ "Importing an f64 global with an incorrectly-typed value: WebAssembly.Global.prototype",
+ "Importing an f64 global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype)",
+ "Importing an f64 global with an incorrectly-typed value: BigInt",
+ "Importing an f64 global with an incorrectly-typed value: WebAssembly.Global object (wrong value type)",
+ "Importing an i32 mutable global with a primitive value",
+ "Importing an i32 mutable global with an immutable Global object",
+ "Importing an i64 mutable global with a primitive value",
+ "Importing an i64 mutable global with an immutable Global object",
+ "Importing an f32 mutable global with a primitive value",
+ "Importing an f32 mutable global with an immutable Global object",
+ "Importing an f64 mutable global with a primitive value",
+ "Importing an f64 mutable global with an immutable Global object",
+ "Importing memory with an incorrectly-typed value: undefined",
+ "Importing memory with an incorrectly-typed value: null",
+ "Importing memory with an incorrectly-typed value: true",
+ "Importing memory with an incorrectly-typed value: \"\"",
+ "Importing memory with an incorrectly-typed value: symbol \"Symbol()\"",
+ "Importing memory with an incorrectly-typed value: 1",
+ "Importing memory with an incorrectly-typed value: 0.1",
+ "Importing memory with an incorrectly-typed value: NaN",
+ "Importing memory with an incorrectly-typed value: plain object",
+ "Importing memory with an incorrectly-typed value: WebAssembly.Memory",
+ "Importing memory with an incorrectly-typed value: WebAssembly.Memory.prototype",
+ "Importing memory with an incorrectly-typed value: Object.create(WebAssembly.Memory.prototype)",
+ "Importing memory with an incorrectly-typed value: WebAssembly.Memory object (too large)",
+ "Importing table with an incorrectly-typed value: undefined",
+ "Importing table with an incorrectly-typed value: null",
+ "Importing table with an incorrectly-typed value: true",
+ "Importing table with an incorrectly-typed value: \"\"",
+ "Importing table with an incorrectly-typed value: symbol \"Symbol()\"",
+ "Importing table with an incorrectly-typed value: 1",
+ "Importing table with an incorrectly-typed value: 0.1",
+ "Importing table with an incorrectly-typed value: NaN",
+ "Importing table with an incorrectly-typed value: plain object",
+ "Importing table with an incorrectly-typed value: WebAssembly.Table",
+ "Importing table with an incorrectly-typed value: WebAssembly.Table.prototype",
+ "Importing table with an incorrectly-typed value: Object.create(WebAssembly.Table.prototype)",
+ "Importing table with an incorrectly-typed value: WebAssembly.Table object (too large)"
+ ],
+ "instantiateStreaming.any.js": false,
+ "invalid-args.any.js": true,
+ "invalid-code.any.js": false,
+ "modified-contenttype.any.js": [
+ "compileStreaming with Content-Type set late",
+ "instantiateStreaming with Content-Type set late"
+ ],
+ "origin.sub.any.js": true,
+ "rejected-arg.any.js": true,
+ "status.any.js": true
+ }
+ },
+ "WebIDL": {
+ "ecmascript-binding": {
+ "es-exceptions": {
+ "DOMException-constants.any.js": true,
+ "DOMException-constructor-and-prototype.any.js": true,
+ "DOMException-constructor-behavior.any.js": true,
+ "DOMException-custom-bindings.any.js": [
+ "does not inherit from Error: class-side"
+ ]
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/wpt/runner.ts b/tools/wpt/runner.ts
new file mode 100644
index 000000000..28b2db0ee
--- /dev/null
+++ b/tools/wpt/runner.ts
@@ -0,0 +1,133 @@
+import { delay, join, readLines, ROOT_PATH } from "../util.js";
+import { assert, ManifestTestOptions, release, runPy } from "./utils.ts";
+import { DOMParser } from "https://deno.land/x/deno_dom@v0.1.3-alpha2/deno-dom-wasm.ts";
+
+export async function runWithTestUtil<T>(
+ verbose: boolean,
+ f: () => Promise<T>,
+): Promise<T> {
+ const proc = runPy(["wpt", "serve"], {
+ stdout: verbose ? "inherit" : "piped",
+ stderr: verbose ? "inherit" : "piped",
+ });
+
+ const start = performance.now();
+ while (true) {
+ await delay(1000);
+ try {
+ const req = await fetch("http://localhost:8000/");
+ await req.body?.cancel();
+ if (req.status == 200) {
+ break;
+ }
+ } catch (err) {
+ // do nothing if this fails
+ }
+ const passedTime = performance.now() - start;
+ if (passedTime > 15000) {
+ throw new Error("Timed out while trying to start wpt test util.");
+ }
+ }
+
+ if (verbose) console.log(`Started wpt test util.`);
+
+ try {
+ return await f();
+ } finally {
+ if (verbose) console.log("Killing wpt test util.");
+ proc.kill(2);
+ await proc.status();
+ proc.close();
+ }
+}
+
+export interface TestResult {
+ cases: TestCaseResult[];
+ status: number;
+ stderr: string;
+}
+
+export interface TestCaseResult {
+ name: string;
+ passed: boolean;
+ status: number;
+ message: string | null;
+ stack: string | null;
+}
+
+export async function runSingleTest(
+ url: URL,
+ options: ManifestTestOptions,
+ reporter: (result: TestCaseResult) => void,
+): Promise<TestResult> {
+ const bundle = await generateBundle(url);
+ const tempFile = await Deno.makeTempFile({
+ prefix: "wpt-bundle-",
+ suffix: ".js",
+ });
+ await Deno.writeTextFile(tempFile, bundle);
+
+ const proc = Deno.run({
+ cmd: [
+ join(ROOT_PATH, `./target/${release ? "release" : "debug"}/deno`),
+ "run",
+ "-A",
+ "--location",
+ url.toString(),
+ tempFile,
+ "[]",
+ ],
+ env: {
+ NO_COLOR: "1",
+ },
+ stdout: "null",
+ stderr: "piped",
+ });
+
+ const cases = [];
+ let stderr = "";
+
+ const lines = readLines(proc.stderr);
+ for await (const line of lines) {
+ if (line.startsWith("{")) {
+ const data = JSON.parse(line);
+ const result = { ...data, passed: data.status == 0 };
+ cases.push(result);
+ reporter(result);
+ } else {
+ stderr += line + "\n";
+ }
+ }
+
+ const { code } = await proc.status();
+ return {
+ status: code,
+ cases,
+ stderr,
+ };
+}
+
+async function generateBundle(location: URL): Promise<string> {
+ const res = await fetch(location);
+ const body = await res.text();
+ const doc = new DOMParser().parseFromString(body, "text/html");
+ assert(doc, "document should have been parsed");
+ const scripts = doc.getElementsByTagName("script");
+ const scriptContents = [];
+ for (const script of scripts) {
+ const src = script.getAttribute("src");
+ if (src === "/resources/testharnessreport.js") {
+ scriptContents.push(
+ await Deno.readTextFile(
+ join(ROOT_PATH, "./tools/wpt/testharnessreport.js"),
+ ),
+ );
+ } else if (src) {
+ const res = await fetch(new URL(src, location));
+ scriptContents.push(await res.text());
+ } else {
+ scriptContents.push(script.textContent);
+ }
+ }
+ return scriptContents.join("\n");
+}
diff --git a/tools/wpt/testharnessreport.js b/tools/wpt/testharnessreport.js
new file mode 100644
index 000000000..13c8ef683
--- /dev/null
+++ b/tools/wpt/testharnessreport.js
@@ -0,0 +1,12 @@
+window.add_result_callback(({ message, name, stack, status }) => {
+ Deno.writeAllSync(
+ Deno.stderr,
+ new TextEncoder().encode(
+ `${JSON.stringify({ name, status, message, stack })}\n`,
+ ),
+ );
+});
+
+window.add_completion_callback((tests, harnessStatus) => {
+ Deno.exit(0);
+});
diff --git a/tools/wpt/utils.ts b/tools/wpt/utils.ts
new file mode 100644
index 000000000..3efd252b4
--- /dev/null
+++ b/tools/wpt/utils.ts
@@ -0,0 +1,168 @@
+/// FLAGS
+
+import { parse } from "https://deno.land/std@0.84.0/flags/mod.ts";
+import { join, ROOT_PATH } from "../util.js";
+
+export const {
+ json,
+ quiet,
+ release,
+ ["--"]: rest,
+ ["auto-config"]: autoConfig,
+} = parse(Deno.args, {
+ "--": true,
+ boolean: ["quiet", "release", "no-interactive"],
+ string: ["json"],
+});
+
+/// PAGE ROOT
+
+/// WPT TEST MANIFEST
+
+export interface Manifest {
+ items: {
+ testharness: ManifestFolder;
+ };
+}
+export interface ManifestFolder {
+ [key: string]: ManifestFolder | ManifestTest;
+}
+export type ManifestTest = [
+ hash: string,
+ ...variations: ManifestTestVariation[],
+];
+export type ManifestTestVariation = [
+ path: string,
+ options: ManifestTestOptions,
+];
+export interface ManifestTestOptions {
+ name?: string;
+}
+
+const MANIFEST_PATH = join(ROOT_PATH, "./tools/wpt/manifest.json");
+
+export async function updateManifest() {
+ const proc = runPy(
+ ["wpt", "manifest", "--tests-root", ".", "-p", MANIFEST_PATH],
+ {},
+ );
+ const status = await proc.status();
+ assert(status.success, "updating wpt manifest should succeed");
+}
+
+export function getManifest(): Manifest {
+ const manifestText = Deno.readTextFileSync(MANIFEST_PATH);
+ return JSON.parse(manifestText);
+}
+
+/// WPT TEST EXPECTATIONS
+
+const EXPECTATION_PATH = join(ROOT_PATH, "./tools/wpt/expectation.json");
+
+export interface Expectation {
+ [key: string]: Expectation | boolean | string[];
+}
+
+export function getExpectation(): Expectation {
+ const expectationText = Deno.readTextFileSync(EXPECTATION_PATH);
+ return JSON.parse(expectationText);
+}
+
+export function saveExpectation(expectation: Expectation) {
+ Deno.writeTextFileSync(
+ EXPECTATION_PATH,
+ JSON.stringify(expectation, undefined, " "),
+ );
+}
+
+export function generateTestExpectations(filter: string[]) {
+ const manifest = getManifest();
+
+ function walk(folder: ManifestFolder, prefix: string): Expectation {
+ const expectation: Expectation = {};
+ for (const key in folder) {
+ const path = `${prefix}/${key}`;
+ const entry = folder[key];
+ if (Array.isArray(entry)) {
+ if (!filter.find((filter) => path.startsWith(filter))) continue;
+ if (key.endsWith(".js")) {
+ expectation[key] = false;
+ }
+ } else {
+ if (!filter.find((filter) => `${path}/`.startsWith(filter))) continue;
+ expectation[key] = walk(entry, path);
+ }
+ }
+ for (const key in expectation) {
+ const entry = expectation[key];
+ if (typeof entry === "object") {
+ if (Object.keys(expectation[key]).length === 0) {
+ delete expectation[key];
+ }
+ }
+ }
+ return expectation;
+ }
+
+ return walk(manifest.items.testharness, "");
+}
+
+export function getExpectFailForCase(
+ expectation: boolean | string[],
+ caseName: string,
+): boolean {
+ if (typeof expectation == "boolean") {
+ return !expectation;
+ }
+ return expectation.includes(caseName);
+}
+
+/// UTILS
+
+class AssertionError extends Error {
+ name = "AssertionError";
+ constructor(message: string) {
+ super(message);
+ }
+}
+
+export function assert(condition: unknown, message: string): asserts condition {
+ if (!condition) {
+ throw new AssertionError(message);
+ }
+}
+
+export function runPy(
+ args: string[],
+ options: Omit<Omit<Deno.RunOptions, "cmd">, "cwd">,
+): Deno.Process {
+ const cmd = Deno.build.os == "windows" ? "python.exe" : "python3";
+ return Deno.run({
+ cmd: [cmd, ...args],
+ cwd: join(ROOT_PATH, "./test_util/wpt/"),
+ ...options,
+ });
+}
+
+export async function checkPy3Available() {
+ const proc = runPy(["--version"], { stdout: "piped" });
+ const status = await proc.status();
+ assert(status.success, "failed to run python --version");
+ const output = new TextDecoder().decode(await proc.output());
+ assert(
+ output.includes("Python 3."),
+ `The ${
+ Deno.build.os == "windows" ? "python.exe" : "python3"
+ } in your path is not is not Python 3.`,
+ );
+}
+
+export async function cargoBuild() {
+ const proc = Deno.run({
+ cmd: ["cargo", "build", ...(release ? ["--release"] : [])],
+ cwd: ROOT_PATH,
+ });
+ const status = await proc.status();
+ proc.close();
+ assert(status.success, "cargo build failed");
+}