diff --git a/cli/tests/wpt.jsonc b/cli/tests/wpt.jsonc index 4628c742267326..bb44aae8dbfe1a 100644 --- a/cli/tests/wpt.jsonc +++ b/cli/tests/wpt.jsonc @@ -58,184 +58,184 @@ "writable-streams/start", "writable-streams/write" ], - // "encoding": [ - // { - // "name": "api-basics", - // "expectFail": [ - // // TODO(lucacasonato): enable when we support utf-16 - // "Decode sample: utf-16le", - // "Decode sample: utf-16be", - // "Decode sample: utf-16" - // ] - // }, - // "api-invalid-label", - // "api-replacement-encodings", - // "api-surrogates-utf8", - // // TODO(lucacasonato): enable encodeInto. We have a bug in implementaiton. - // // { - // // "name": "encodeInto", - // // "expectFail": [ - // // "encodeInto() and a detached output buffer" - // // ] - // // }, - // // "encodeInto", - // // TODO(lucacasonato): enable when we support iso-2022-jp - // // "iso-2022-jp-decoder", - // // TODO(lucacasonato): uses XMLHttpRequest unnecessarily. should be fixed upstream before enabling - // // "replacement-encodings", - // { - // "name": "textdecoder-byte-order-marks", - // "expectFail": [ - // // TODO(lucacasonato): enable when we support utf-16 - // "Byte-order marks: utf-16le", - // "Byte-order marks: utf-16be" - // ] - // }, - // { - // "name": "textdecoder-copy", - // "expectFail": [ - // // TODO(lucacasonato): enable when we have stream support - // "Modify buffer after passing it in (ArrayBuffer)", - // "Modify buffer after passing it in (SharedArrayBuffer)" - // ] - // }, - // "textdecoder-fatal-single-byte", - // { - // "name": "textdecoder-fatal.", - // // TODO(lucacasonato): enable when we support utf-16 - // "expectFail": [ - // "Fatal flag: utf-16le - truncated code unit" - // ] - // }, - // { - // "name": "textdecoder-ignorebom", - // "expectFail": [ - // // TODO(lucacasonato): enable when we support utf-16 - // "BOM is ignored if ignoreBOM option is specified: utf-16le", - // "BOM is ignored if ignoreBOM option is specified: utf-16be" - // ] - // }, - // { - // "name": "textdecoder-labels", - // "expectFail": [ - // "chinese => GBK", - // "csgb2312 => GBK", - // "csiso58gb231280 => GBK", - // "gb2312 => GBK", - // "gb_2312 => GBK", - // "gb_2312-80 => GBK", - // "gbk => GBK", - // "iso-ir-58 => GBK", - // "x-gbk => GBK", - // "gb18030 => gb18030", - // "big5 => Big5", - // "big5-hkscs => Big5", - // "cn-big5 => Big5", - // "csbig5 => Big5", - // "x-x-big5 => Big5", - // "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", - // "unicodefffe => UTF-16BE", - // "utf-16be => UTF-16BE", - // "csunicode => UTF-16LE", - // "iso-10646-ucs-2 => UTF-16LE", - // "ucs-2 => UTF-16LE", - // "unicode => UTF-16LE", - // "unicodefeff => UTF-16LE", - // "utf-16 => UTF-16LE", - // "utf-16le => UTF-16LE", - // "x-user-defined => x-user-defined" - // ] - // }, - // // TODO(lucacasonato): enable when we have stream support - // // "textdecoder-streaming", - // // TODO(lucacasonato): enable when we support utf-16 - // // "textdecoder-utf16-surrogates", - // { - // "name": "textencoder-constructor-non-utf", - // "expectFail": [ - // "Encoding argument supported for decode: GBK", - // "Encoding argument supported for decode: gb18030", - // "Encoding argument supported for decode: Big5", - // "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: UTF-16BE", - // "Encoding argument supported for decode: UTF-16LE", - // "Encoding argument supported for decode: x-user-defined" - // ] - // } - // // TODO(lucacasonato): enable when we support utf-16 - // // "textencoder-utf16-surrogates", - // // TODO(lucacasonato): uses XMLHttpRequest unnecessarily. should be fixed upstream before enabling - // // "unsupported-encodings", - // ], - // "dom": [ - // "abort/event" - // ], - // "hr-time": [ - // "monotonic-clock" - // ], - // "html": [ - // "webappapis/microtask-queuing/queue-microtask-exceptions.any", - // "webappapis/microtask-queuing/queue-microtask.any", - // "webappapis/timers", - // ], - // "user-timing": [ - // "clear_all_marks", - // "clear_all_measures", - // "clear_non_existent_mark", - // "clear_non_existent_measure", - // "clear_one_mark", - // "clear_one_measure", - // "entry_type", - // "mark-entry-constructor", - // "mark-errors", - // "mark-measure-return-objects", - // "mark.any", - // { - // "name": "measure_syntax_err", - // "expectFail": [ - // // TODO(lucacasonato): re-enable when #9009 is fixed. - // "self.performance.measure(\"measure\", \"mark\"), where \"mark\" is a non-existent mark, throws a SyntaxError exception.", - // "self.performance.measure(\"measure\", \"mark\", \"existing_mark\"), where \"mark\" is a non-existent mark, throws a SyntaxError exception.", - // "self.performance.measure(\"measure\", \"existing_mark\", \"mark\"), where \"mark\" is a non-existent mark, throws a SyntaxError exception.", - // "self.performance.measure(\"measure\", \"mark\", \"mark\"), where \"mark\" is a non-existent mark, throws a SyntaxError exception." - // ] - // }, - // "measure-l3", - // "structured-serialize-detail", - // "user_timing_exists" - // ], - // "console": [ - // "console-is-a-namespace", - // "console-label-conversion", - // "console-namespace-object-class-string", - // "console-tests-historical", - // ], - // "WebCryptoApi": [ - // "getRandomValues" - // ] + "encoding": [ + { + "name": "api-basics", + "expectFail": [ + // TODO(lucacasonato): enable when we support utf-16 + "Decode sample: utf-16le", + "Decode sample: utf-16be", + "Decode sample: utf-16" + ] + }, + "api-invalid-label", + "api-replacement-encodings", + "api-surrogates-utf8", + // TODO(lucacasonato): enable encodeInto. We have a bug in implementaiton. + // { + // "name": "encodeInto", + // "expectFail": [ + // "encodeInto() and a detached output buffer" + // ] + // }, + // "encodeInto", + // TODO(lucacasonato): enable when we support iso-2022-jp + // "iso-2022-jp-decoder", + // TODO(lucacasonato): uses XMLHttpRequest unnecessarily. should be fixed upstream before enabling + // "replacement-encodings", + { + "name": "textdecoder-byte-order-marks", + "expectFail": [ + // TODO(lucacasonato): enable when we support utf-16 + "Byte-order marks: utf-16le", + "Byte-order marks: utf-16be" + ] + }, + { + "name": "textdecoder-copy", + "expectFail": [ + // TODO(lucacasonato): enable when we have stream support + "Modify buffer after passing it in (ArrayBuffer)", + "Modify buffer after passing it in (SharedArrayBuffer)" + ] + }, + "textdecoder-fatal-single-byte", + { + "name": "textdecoder-fatal.", + // TODO(lucacasonato): enable when we support utf-16 + "expectFail": [ + "Fatal flag: utf-16le - truncated code unit" + ] + }, + { + "name": "textdecoder-ignorebom", + "expectFail": [ + // TODO(lucacasonato): enable when we support utf-16 + "BOM is ignored if ignoreBOM option is specified: utf-16le", + "BOM is ignored if ignoreBOM option is specified: utf-16be" + ] + }, + { + "name": "textdecoder-labels", + "expectFail": [ + "chinese => GBK", + "csgb2312 => GBK", + "csiso58gb231280 => GBK", + "gb2312 => GBK", + "gb_2312 => GBK", + "gb_2312-80 => GBK", + "gbk => GBK", + "iso-ir-58 => GBK", + "x-gbk => GBK", + "gb18030 => gb18030", + "big5 => Big5", + "big5-hkscs => Big5", + "cn-big5 => Big5", + "csbig5 => Big5", + "x-x-big5 => Big5", + "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", + "unicodefffe => UTF-16BE", + "utf-16be => UTF-16BE", + "csunicode => UTF-16LE", + "iso-10646-ucs-2 => UTF-16LE", + "ucs-2 => UTF-16LE", + "unicode => UTF-16LE", + "unicodefeff => UTF-16LE", + "utf-16 => UTF-16LE", + "utf-16le => UTF-16LE", + "x-user-defined => x-user-defined" + ] + }, + // TODO(lucacasonato): enable when we have stream support + // "textdecoder-streaming", + // TODO(lucacasonato): enable when we support utf-16 + // "textdecoder-utf16-surrogates", + { + "name": "textencoder-constructor-non-utf", + "expectFail": [ + "Encoding argument supported for decode: GBK", + "Encoding argument supported for decode: gb18030", + "Encoding argument supported for decode: Big5", + "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: UTF-16BE", + "Encoding argument supported for decode: UTF-16LE", + "Encoding argument supported for decode: x-user-defined" + ] + } + // TODO(lucacasonato): enable when we support utf-16 + // "textencoder-utf16-surrogates", + // TODO(lucacasonato): uses XMLHttpRequest unnecessarily. should be fixed upstream before enabling + // "unsupported-encodings", + ], + "dom": [ + "abort/event" + ], + "hr-time": [ + "monotonic-clock" + ], + "html": [ + "webappapis/microtask-queuing/queue-microtask-exceptions.any", + "webappapis/microtask-queuing/queue-microtask.any", + "webappapis/timers", + ], + "user-timing": [ + "clear_all_marks", + "clear_all_measures", + "clear_non_existent_mark", + "clear_non_existent_measure", + "clear_one_mark", + "clear_one_measure", + "entry_type", + "mark-entry-constructor", + "mark-errors", + "mark-measure-return-objects", + "mark.any", + { + "name": "measure_syntax_err", + "expectFail": [ + // TODO(lucacasonato): re-enable when #9009 is fixed. + "self.performance.measure(\"measure\", \"mark\"), where \"mark\" is a non-existent mark, throws a SyntaxError exception.", + "self.performance.measure(\"measure\", \"mark\", \"existing_mark\"), where \"mark\" is a non-existent mark, throws a SyntaxError exception.", + "self.performance.measure(\"measure\", \"existing_mark\", \"mark\"), where \"mark\" is a non-existent mark, throws a SyntaxError exception.", + "self.performance.measure(\"measure\", \"mark\", \"mark\"), where \"mark\" is a non-existent mark, throws a SyntaxError exception." + ] + }, + "measure-l3", + "structured-serialize-detail", + "user_timing_exists" + ], + "console": [ + "console-is-a-namespace", + "console-label-conversion", + "console-namespace-object-class-string", + "console-tests-historical", + ], + "WebCryptoApi": [ + "getRandomValues" + ] } \ No newline at end of file diff --git a/op_crates/fetch/11_streams.js b/op_crates/fetch/11_streams.js index 5078d3f691e8ac..6031fa3ef4b4d0 100644 --- a/op_crates/fetch/11_streams.js +++ b/op_crates/fetch/11_streams.js @@ -56,8 +56,9 @@ /** @param {any=} reason */ reject(reason) { + // already settled promises are a no-op if (this.#state !== "pending") { - throw new TypeError("Deferred is already fulfilled."); + return; } this.#state = "fulfilled"; this.#reject(reason); @@ -65,8 +66,9 @@ /** @param {T | PromiseLike} value */ resolve(value) { + // already settled promises are a no-op if (this.#state !== "pending") { - throw new TypeError("Deferred is already fulfilled."); + return; } this.#state = "fulfilled"; this.#resolve(value); @@ -901,7 +903,7 @@ function readableStreamCancel(stream, reason) { stream[_disturbed] = true; if (stream[_state] === "closed") { - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); } if (stream[_state] === "errored") { return Promise.reject(stream[_storedError]); @@ -933,12 +935,9 @@ } reader[_readRequests] = []; } - // this is non-spec, but when using an async iterator to read, and there is - // a pending read request, the `closeSteps()` will resolve the close promise - // causing a promise to be already resolved here. - if (reader[_closedPromise].state === "pending") { - reader[_closedPromise].resolve(undefined); - } + // This promise can be double resolved. + // See: https://github.com/whatwg/streams/issues/1100 + reader[_closedPromise].resolve(undefined); } /** @param {ReadableStreamDefaultController} controller */ @@ -1233,7 +1232,7 @@ const writer = acquireWritableStreamDefaultWriter(dest); source[_disturbed] = true; let shuttingDown = false; - let currentWrite = Promise.resolve(undefined); + let currentWrite = resolvePromiseWith(undefined); /** @type {Deferred} */ const promise = new Deferred(); /** @type {() => void} */ @@ -1248,7 +1247,7 @@ if (dest[_state] === "writable") { return writableStreamAbort(dest, error); } else { - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); } }); } @@ -1257,7 +1256,7 @@ if (source[_state] === "readable") { return readableStreamCancel(source, error); } else { - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); } }); } @@ -1292,7 +1291,7 @@ /** @returns {Promise} */ function pipeStep() { if (shuttingDown === true) { - return Promise.resolve(true); + return resolvePromiseWith(true); } return transformPromiseWith(writer[_readyPromise].promise, () => { @@ -1573,7 +1572,7 @@ function pullAlgorithm() { if (reading === true) { - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); } reading = true; /** @type {ReadRequest} */ @@ -1625,7 +1624,7 @@ }, }; readableStreamDefaultReaderRead(reader, readRequest); - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); } /** @@ -1725,7 +1724,7 @@ // 12. Set controller.[[pendingPullIntos]] to a new empty list. stream[_controller] = controller; const startResult = startAlgorithm(); - const startPromise = Promise.resolve(startResult); + const startPromise = resolvePromiseWith(startResult); setPromiseIsHandledToTrue( startPromise.then( () => { @@ -1757,9 +1756,9 @@ /** @type {() => void} */ let startAlgorithm = () => undefined; /** @type {() => Promise} */ - let pullAlgorithm = () => Promise.resolve(undefined); + let pullAlgorithm = () => resolvePromiseWith(undefined); /** @type {(reason: any) => Promise} */ - let cancelAlgorithm = (_reason) => Promise.resolve(undefined); + let cancelAlgorithm = (_reason) => resolvePromiseWith(undefined); if ("start" in underlyingSourceDict) { startAlgorithm = () => underlyingSourceDict.start.call(underlyingSource, controller); @@ -1846,9 +1845,9 @@ /** @type {(controller: ReadableStreamDefaultController) => Promise} */ let startAlgorithm = () => undefined; /** @type {(controller: ReadableStreamDefaultController) => Promise} */ - let pullAlgorithm = () => Promise.resolve(undefined); + let pullAlgorithm = () => resolvePromiseWith(undefined); /** @type {(reason?: any) => Promise} */ - let cancelAlgorithm = () => Promise.resolve(undefined); + let cancelAlgorithm = () => resolvePromiseWith(undefined); if ("start" in underlyingSourceDict) { startAlgorithm = () => underlyingSourceDict.start.call(underlyingSource, controller); @@ -1927,10 +1926,10 @@ } catch (e) { return Promise.reject(e); } - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); }; /** @type {(controller: TransformStreamDefaultController) => Promise} */ - let flushAlgorithm = () => Promise.resolve(undefined); + let flushAlgorithm = () => resolvePromiseWith(undefined); if ("transform" in transformerDict) { transformAlgorithm = (chunk, controller) => transformerDict.transform.call(transformer, chunk, controller); @@ -1984,7 +1983,7 @@ ); writableStreamUpdateBackpressure(stream, backpressure); const startResult = startAlgorithm(controller); - const startPromise = Promise.resolve(startResult); + const startPromise = resolvePromiseWith(startResult); uponPromise(startPromise, () => { assert(stream[_state] === "writable" || stream[_state] === "erroring"); controller[_started] = true; @@ -2014,10 +2013,10 @@ const controller = new WritableStreamDefaultController(); let startAlgorithm = () => undefined; /** @type {(chunk: W) => Promise} */ - let writeAlgorithm = () => Promise.resolve(undefined); - let closeAlgorithm = () => Promise.resolve(undefined); + let writeAlgorithm = () => resolvePromiseWith(undefined); + let closeAlgorithm = () => resolvePromiseWith(undefined); /** @type {(reason?: any) => Promise} */ - let abortAlgorithm = () => Promise.resolve(undefined); + let abortAlgorithm = () => resolvePromiseWith(undefined); if ("start" in underlyingSinkDict) { startAlgorithm = () => underlyingSinkDict.start.call(underlyingSink, controller); @@ -2169,7 +2168,7 @@ */ function transformStreamDefaultSinkAbortAlgorithm(stream, reason) { transformStreamError(stream, reason); - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); } /** @@ -2286,7 +2285,7 @@ function writableStreamAbort(stream, reason) { const state = stream[_state]; if (state === "closed" || state === "errored") { - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); } if (stream[_pendingAbortRequest] !== undefined) { return stream[_pendingAbortRequest].deferred.promise; @@ -2582,7 +2581,7 @@ if ( writableStreamCloseQueuedOrInFlight(stream) === true || state === "closed" ) { - return Promise.resolve(undefined); + return resolvePromiseWith(undefined); } if (state === "errored") { return Promise.reject(stream[_storedError]);