summaryrefslogtreecommitdiff
path: root/extensions/web/06_streams.js
diff options
context:
space:
mode:
authorLuca Casonato <hello@lcas.dev>2021-06-15 13:46:02 +0200
committerGitHub <noreply@github.com>2021-06-15 13:46:02 +0200
commit4cbc4a7eb321ae2808cf3dce9428f45aaed0e338 (patch)
tree593fa6e34cd0d222029ea37b404dbb7dd3fad54a /extensions/web/06_streams.js
parent1eac527adb8263acd6d6cc1147e53caa901d938d (diff)
fix: make WHATWG streams more compliant (#10967)
Diffstat (limited to 'extensions/web/06_streams.js')
-rw-r--r--extensions/web/06_streams.js1060
1 files changed, 790 insertions, 270 deletions
diff --git a/extensions/web/06_streams.js b/extensions/web/06_streams.js
index e59f8e945..b3c55fa85 100644
--- a/extensions/web/06_streams.js
+++ b/extensions/web/06_streams.js
@@ -1,12 +1,15 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
// @ts-check
+/// <reference path="../webidl/internal.d.ts" />
/// <reference path="./06_streams_types.d.ts" />
-/// <reference path="./lib.deno_fetch.d.ts" />
+/// <reference path="./lib.deno_web.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
+ const webidl = window.__bootstrap.webidl;
+
class AssertionError extends Error {
constructor(msg) {
super(msg);
@@ -74,119 +77,6 @@
}
}
- /**
- * @param {(...args: any[]) => any} fn
- * @param {boolean} enforcePromise
- * @returns {(...args: any[]) => any}
- */
- function reflectApply(fn, enforcePromise) {
- if (typeof fn !== "function") {
- throw new TypeError("The property must be a function.");
- }
- return function (...args) {
- if (enforcePromise) {
- try {
- return resolvePromiseWith(Reflect.apply(fn, this, args));
- } catch (err) {
- return Promise.reject(err);
- }
- }
- return Reflect.apply(fn, this, args);
- };
- }
-
- /**
- * @template I
- * @template O
- * @param {Transformer<I, O>} transformer
- * @returns {Transformer<I, O>}
- */
- function convertTransformer(transformer) {
- const transformerDict = Object.create(null);
- if (transformer === null) {
- return transformerDict;
- }
- if ("flush" in transformer) {
- transformerDict.flush = reflectApply(transformer.flush, true);
- }
- if ("readableType" in transformer) {
- transformerDict.readableType = transformer.readableType;
- }
- if ("start" in transformer) {
- transformerDict.start = reflectApply(transformer.start, false);
- }
- if ("transform" in transformer) {
- transformerDict.transform = reflectApply(transformer.transform, true);
- }
- if ("writableType" in transformer) {
- transformerDict.writableType = transformer.writableType;
- }
- return transformerDict;
- }
-
- /**
- * @template W
- * @param {UnderlyingSink<W>} underlyingSink
- * @returns {UnderlyingSink<W>}
- */
- function convertUnderlyingSink(underlyingSink) {
- const underlyingSinkDict = Object.create(null);
- if (underlyingSink === null) {
- return underlyingSinkDict;
- }
- if ("abort" in underlyingSink) {
- underlyingSinkDict.abort = reflectApply(underlyingSink.abort, true);
- }
- if ("close" in underlyingSink) {
- underlyingSinkDict.close = reflectApply(underlyingSink.close, true);
- }
- if ("start" in underlyingSink) {
- underlyingSinkDict.start = reflectApply(underlyingSink.start, false);
- }
- if (underlyingSink.type) {
- underlyingSinkDict.type = underlyingSink.type;
- }
- if ("write" in underlyingSink) {
- underlyingSinkDict.write = reflectApply(underlyingSink.write, true);
- }
- return underlyingSinkDict;
- }
-
- /**
- * @template R
- * @param {UnderlyingSource<R>} underlyingSource
- * @returns {UnderlyingSource<R>}
- */
- function convertUnderlyingSource(underlyingSource) {
- const underlyingSourceDict = Object.create(null);
- if (underlyingSource === null) {
- throw new TypeError("Underlying source cannot be null");
- }
- if (underlyingSource === undefined) {
- return underlyingSourceDict;
- }
- if ("cancel" in underlyingSource) {
- underlyingSourceDict.cancel = reflectApply(underlyingSource.cancel, true);
- }
- if ("pull" in underlyingSource) {
- underlyingSourceDict.pull = reflectApply(underlyingSource.pull, true);
- }
- if ("start" in underlyingSource) {
- underlyingSourceDict.start = reflectApply(underlyingSource.start, false);
- }
- if (underlyingSource.type !== undefined) {
- if (underlyingSourceDict.type === null) {
- throw new TypeError("type cannot be null");
- }
- const type = String(underlyingSource.type);
- if (type !== "bytes") {
- throw new TypeError("invalid underlying source type");
- }
- underlyingSourceDict.type = type;
- }
- return underlyingSourceDict;
- }
-
const originalPromise = Promise;
const originalPromiseThen = Promise.prototype.then;
@@ -323,6 +213,7 @@
const _errorSteps = Symbol("[[ErrorSteps]]");
const _flushAlgorithm = Symbol("[[flushAlgorithm]]");
const _globalObject = Symbol("[[globalObject]]");
+ const _highWaterMark = Symbol("[[highWaterMark]]");
const _inFlightCloseRequest = Symbol("[[inFlightCloseRequest]]");
const _inFlightWriteRequest = Symbol("[[inFlightWriteRequest]]");
const _pendingAbortRequest = Symbol("[pendingAbortRequest]");
@@ -385,9 +276,9 @@
) {
assert(isNonNegativeNumber(highWaterMark));
/** @type {ReadableStream} */
- const stream = Object.create(ReadableStream.prototype);
+ const stream = webidl.createBranded(ReadableStream);
initializeReadableStream(stream);
- const controller = Object.create(ReadableStreamDefaultController.prototype);
+ const controller = webidl.createBranded(ReadableStreamDefaultController);
setUpReadableStreamDefaultController(
stream,
controller,
@@ -419,9 +310,9 @@
sizeAlgorithm,
) {
assert(isNonNegativeNumber(highWaterMark));
- const stream = Object.create(WritableStream.prototype);
+ const stream = webidl.createBranded(WritableStream);
initializeWritableStream(stream);
- const controller = Object.create(WritableStreamDefaultController.prototype);
+ const controller = webidl.createBranded(WritableStreamDefaultController);
setUpWritableStreamDefaultController(
stream,
controller,
@@ -1750,24 +1641,53 @@
underlyingSourceDict,
highWaterMark,
) {
- const controller = new ReadableByteStreamController();
+ const controller = webidl.createBranded(ReadableByteStreamController);
/** @type {() => void} */
let startAlgorithm = () => undefined;
/** @type {() => Promise<void>} */
let pullAlgorithm = () => resolvePromiseWith(undefined);
/** @type {(reason: any) => Promise<void>} */
let cancelAlgorithm = (_reason) => resolvePromiseWith(undefined);
- if ("start" in underlyingSourceDict) {
+ if (underlyingSourceDict.start !== undefined) {
startAlgorithm = () =>
- underlyingSourceDict.start.call(underlyingSource, controller);
+ webidl.invokeCallbackFunction(
+ underlyingSourceDict.start,
+ [controller],
+ underlyingSource,
+ webidl.converters.any,
+ {
+ prefix:
+ "Failed to call 'startAlgorithm' on 'ReadableByteStreamController'",
+ },
+ );
}
- if ("pull" in underlyingSourceDict) {
+ if (underlyingSourceDict.pull !== undefined) {
pullAlgorithm = () =>
- underlyingSourceDict.pull.call(underlyingSource, controller);
+ webidl.invokeCallbackFunction(
+ underlyingSourceDict.pull,
+ [controller],
+ underlyingSource,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'pullAlgorithm' on 'ReadableByteStreamController'",
+ returnsPromise: true,
+ },
+ );
}
- if ("cancel" in underlyingSourceDict) {
+ if (underlyingSourceDict.cancel !== undefined) {
cancelAlgorithm = (reason) =>
- underlyingSourceDict.cancel.call(underlyingSource, reason);
+ webidl.invokeCallbackFunction(
+ underlyingSourceDict.cancel,
+ [reason],
+ underlyingSource,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'cancelAlgorithm' on 'ReadableByteStreamController'",
+ returnsPromise: true,
+ },
+ );
}
// 3.13.27.6 Let autoAllocateChunkSize be ? GetV(underlyingByteSource, "autoAllocateChunkSize").
/** @type {undefined} */
@@ -1839,24 +1759,53 @@
highWaterMark,
sizeAlgorithm,
) {
- const controller = new ReadableStreamDefaultController();
- /** @type {(controller: ReadableStreamDefaultController<R>) => Promise<void>} */
+ const controller = webidl.createBranded(ReadableStreamDefaultController);
+ /** @type {() => Promise<void>} */
let startAlgorithm = () => undefined;
- /** @type {(controller: ReadableStreamDefaultController<R>) => Promise<void>} */
+ /** @type {() => Promise<void>} */
let pullAlgorithm = () => resolvePromiseWith(undefined);
/** @type {(reason?: any) => Promise<void>} */
let cancelAlgorithm = () => resolvePromiseWith(undefined);
- if ("start" in underlyingSourceDict) {
+ if (underlyingSourceDict.start !== undefined) {
startAlgorithm = () =>
- underlyingSourceDict.start.call(underlyingSource, controller);
+ webidl.invokeCallbackFunction(
+ underlyingSourceDict.start,
+ [controller],
+ underlyingSource,
+ webidl.converters.any,
+ {
+ prefix:
+ "Failed to call 'startAlgorithm' on 'ReadableStreamDefaultController'",
+ },
+ );
}
- if ("pull" in underlyingSourceDict) {
+ if (underlyingSourceDict.pull !== undefined) {
pullAlgorithm = () =>
- underlyingSourceDict.pull.call(underlyingSource, controller);
+ webidl.invokeCallbackFunction(
+ underlyingSourceDict.pull,
+ [controller],
+ underlyingSource,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'pullAlgorithm' on 'ReadableStreamDefaultController'",
+ returnsPromise: true,
+ },
+ );
}
- if ("cancel" in underlyingSourceDict) {
+ if (underlyingSourceDict.cancel !== undefined) {
cancelAlgorithm = (reason) =>
- underlyingSourceDict.cancel.call(underlyingSource, reason);
+ webidl.invokeCallbackFunction(
+ underlyingSourceDict.cancel,
+ [reason],
+ underlyingSource,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'cancelAlgorithm' on 'ReadableStreamDefaultController'",
+ returnsPromise: true,
+ },
+ );
}
setUpReadableStreamDefaultController(
stream,
@@ -1916,7 +1865,7 @@
transformerDict,
) {
/** @type {TransformStreamDefaultController<O>} */
- const controller = new TransformStreamDefaultController();
+ const controller = webidl.createBranded(TransformStreamDefaultController);
/** @type {(chunk: O, controller: TransformStreamDefaultController<O>) => Promise<void>} */
let transformAlgorithm = (chunk) => {
try {
@@ -1928,13 +1877,33 @@
};
/** @type {(controller: TransformStreamDefaultController<O>) => Promise<void>} */
let flushAlgorithm = () => resolvePromiseWith(undefined);
- if ("transform" in transformerDict) {
+ if (transformerDict.transform !== undefined) {
transformAlgorithm = (chunk, controller) =>
- transformerDict.transform.call(transformer, chunk, controller);
+ webidl.invokeCallbackFunction(
+ transformerDict.transform,
+ [chunk, controller],
+ transformer,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'transformAlgorithm' on 'TransformStreamDefaultController'",
+ returnsPromise: true,
+ },
+ );
}
- if ("flush" in transformerDict) {
+ if (transformerDict.flush !== undefined) {
flushAlgorithm = (controller) =>
- transformerDict.flush.call(transformer, controller);
+ webidl.invokeCallbackFunction(
+ transformerDict.flush,
+ [controller],
+ transformer,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'flushAlgorithm' on 'TransformStreamDefaultController'",
+ returnsPromise: true,
+ },
+ );
}
setUpTransformStreamDefaultController(
stream,
@@ -2008,27 +1977,69 @@
highWaterMark,
sizeAlgorithm,
) {
- const controller = new WritableStreamDefaultController();
+ const controller = webidl.createBranded(WritableStreamDefaultController);
+ /** @type {(controller: WritableStreamDefaultController<W>) => any} */
let startAlgorithm = () => undefined;
- /** @type {(chunk: W) => Promise<void>} */
+ /** @type {(chunk: W, controller: WritableStreamDefaultController<W>) => Promise<void>} */
let writeAlgorithm = () => resolvePromiseWith(undefined);
let closeAlgorithm = () => resolvePromiseWith(undefined);
/** @type {(reason?: any) => Promise<void>} */
let abortAlgorithm = () => resolvePromiseWith(undefined);
- if ("start" in underlyingSinkDict) {
+
+ if (underlyingSinkDict.start !== undefined) {
startAlgorithm = () =>
- underlyingSinkDict.start.call(underlyingSink, controller);
+ webidl.invokeCallbackFunction(
+ underlyingSinkDict.start,
+ [controller],
+ underlyingSink,
+ webidl.converters.any,
+ {
+ prefix:
+ "Failed to call 'startAlgorithm' on 'WritableStreamDefaultController'",
+ },
+ );
}
- if ("write" in underlyingSinkDict) {
+ if (underlyingSinkDict.write !== undefined) {
writeAlgorithm = (chunk) =>
- underlyingSinkDict.write.call(underlyingSink, chunk, controller);
+ webidl.invokeCallbackFunction(
+ underlyingSinkDict.write,
+ [chunk, controller],
+ underlyingSink,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'writeAlgorithm' on 'WritableStreamDefaultController'",
+ returnsPromise: true,
+ },
+ );
}
- if ("close" in underlyingSinkDict) {
- closeAlgorithm = () => underlyingSinkDict.close.call(underlyingSink);
+ if (underlyingSinkDict.close !== undefined) {
+ closeAlgorithm = () =>
+ webidl.invokeCallbackFunction(
+ underlyingSinkDict.close,
+ [],
+ underlyingSink,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'closeAlgorithm' on 'WritableStreamDefaultController'",
+ returnsPromise: true,
+ },
+ );
}
- if ("abort" in underlyingSinkDict) {
+ if (underlyingSinkDict.abort !== undefined) {
abortAlgorithm = (reason) =>
- underlyingSinkDict.abort.call(underlyingSink, reason);
+ webidl.invokeCallbackFunction(
+ underlyingSinkDict.abort,
+ [reason],
+ underlyingSink,
+ webidl.converters["Promise<undefined>"],
+ {
+ prefix:
+ "Failed to call 'abortAlgorithm' on 'WritableStreamDefaultController'",
+ returnsPromise: true,
+ },
+ );
}
setUpWritableStreamDefaultController(
stream,
@@ -2955,30 +2966,45 @@
}, asyncIteratorPrototype);
class ByteLengthQueuingStrategy {
- /** @type {number} */
- highWaterMark;
-
/** @param {{ highWaterMark: number }} init */
constructor(init) {
- if (
- typeof init !== "object" || init === null || !("highWaterMark" in init)
- ) {
- throw new TypeError(
- "init must be an object that contains a property named highWaterMark",
- );
- }
- const { highWaterMark } = init;
+ const prefix = "Failed to construct 'ByteLengthQueuingStrategy'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ init = webidl.converters.QueuingStrategyInit(init, {
+ prefix,
+ context: "Argument 1",
+ });
+ this[webidl.brand] = webidl.brand;
this[_globalObject] = window;
- this.highWaterMark = Number(highWaterMark);
+ this[_highWaterMark] = init.highWaterMark;
+ }
+
+ /** @returns {number} */
+ get highWaterMark() {
+ webidl.assertBranded(this, ByteLengthQueuingStrategy);
+ return this[_highWaterMark];
}
/** @returns {(chunk: ArrayBufferView) => number} */
get size() {
+ webidl.assertBranded(this, ByteLengthQueuingStrategy);
initializeByteLengthSizeFunction(this[_globalObject]);
return byteSizeFunctionWeakMap.get(this[_globalObject]);
}
+
+ [Symbol.for("Deno.customInspect")](inspect) {
+ return `${this.constructor.name} ${
+ inspect({ highWaterMark: this.highWaterMark, size: this.size })
+ }`;
+ }
+
+ get [Symbol.toStringTag]() {
+ return "ByteLengthQueuingStrategy";
+ }
}
+ webidl.configurePrototype(ByteLengthQueuingStrategy);
+
/** @type {WeakMap<typeof globalThis, (chunk: ArrayBufferView) => number>} */
const byteSizeFunctionWeakMap = new WeakMap();
@@ -2992,30 +3018,45 @@
}
class CountQueuingStrategy {
- /** @type {number} */
- highWaterMark;
-
/** @param {{ highWaterMark: number }} init */
constructor(init) {
- if (
- typeof init !== "object" || init === null || !("highWaterMark" in init)
- ) {
- throw new TypeError(
- "init must be an object that contains a property named highWaterMark",
- );
- }
- const { highWaterMark } = init;
+ const prefix = "Failed to construct 'CountQueuingStrategy'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ init = webidl.converters.QueuingStrategyInit(init, {
+ prefix,
+ context: "Argument 1",
+ });
+ this[webidl.brand] = webidl.brand;
this[_globalObject] = window;
- this.highWaterMark = Number(highWaterMark);
+ this[_highWaterMark] = init.highWaterMark;
+ }
+
+ /** @returns {number} */
+ get highWaterMark() {
+ webidl.assertBranded(this, CountQueuingStrategy);
+ return this[_highWaterMark];
}
/** @returns {(chunk: any) => 1} */
get size() {
+ webidl.assertBranded(this, CountQueuingStrategy);
initializeCountSizeFunction(this[_globalObject]);
return countSizeFunctionWeakMap.get(this[_globalObject]);
}
+
+ [Symbol.for("Deno.customInspect")](inspect) {
+ return `${this.constructor.name} ${
+ inspect({ highWaterMark: this.highWaterMark, size: this.size })
+ }`;
+ }
+
+ get [Symbol.toStringTag]() {
+ return "CountQueuingStrategy";
+ }
}
+ webidl.configurePrototype(CountQueuingStrategy);
+
/** @type {WeakMap<typeof globalThis, () => 1>} */
const countSizeFunctionWeakMap = new WeakMap();
@@ -3048,13 +3089,31 @@
* @param {UnderlyingSource<R>=} underlyingSource
* @param {QueuingStrategy<R>=} strategy
*/
- constructor(underlyingSource, strategy = {}) {
- const underlyingSourceDict = convertUnderlyingSource(underlyingSource);
+ constructor(underlyingSource = undefined, strategy = {}) {
+ const prefix = "Failed to construct 'ReadableStream'";
+ if (underlyingSource !== undefined) {
+ underlyingSource = webidl.converters.object(underlyingSource, {
+ prefix,
+ context: "Argument 1",
+ });
+ }
+ strategy = webidl.converters.QueuingStrategy(strategy, {
+ prefix,
+ context: "Argument 2",
+ });
+ this[webidl.brand] = webidl.brand;
+ if (underlyingSource === undefined) {
+ underlyingSource = null;
+ }
+ const underlyingSourceDict = webidl.converters.UnderlyingSource(
+ underlyingSource,
+ { prefix, context: "underlyingSource" },
+ );
initializeReadableStream(this);
if (underlyingSourceDict.type === "bytes") {
if (strategy.size !== undefined) {
throw new RangeError(
- `When underlying source is "bytes", strategy.size must be undefined.`,
+ `${prefix}: When underlying source is "bytes", strategy.size must be undefined.`,
);
}
const highWaterMark = extractHighWaterMark(strategy, 0);
@@ -3081,6 +3140,7 @@
/** @returns {boolean} */
get locked() {
+ webidl.assertBranded(this, ReadableStream);
return isReadableStreamLocked(this);
}
@@ -3088,7 +3148,15 @@
* @param {any=} reason
* @returns {Promise<void>}
*/
- cancel(reason) {
+ cancel(reason = undefined) {
+ try {
+ webidl.assertBranded(this, ReadableStream);
+ if (reason !== undefined) {
+ reason = webidl.converters.any(reason);
+ }
+ } catch (err) {
+ return Promise.reject(err);
+ }
if (isReadableStreamLocked(this)) {
Promise.reject(new TypeError("Cannot cancel a locked ReadableStream."));
}
@@ -3109,23 +3177,18 @@
* @returns {ReadableStreamDefaultReader<R>}
*/
getReader(options = {}) {
- if (typeof options !== "object") {
- throw new TypeError("options must be an object");
- }
- if (options === null) {
- options = {};
- }
- /** @type {any} */
- let { mode } = options;
+ webidl.assertBranded(this, ReadableStream);
+ const prefix = "Failed to execute 'getReader' on 'ReadableStream'";
+ options = webidl.converters.ReadableStreamGetReaderOptions(options, {
+ prefix,
+ context: "Argument 1",
+ });
+ const { mode } = options;
if (mode === undefined) {
return acquireReadableStreamDefaultReader(this);
}
- mode = String(mode);
- if (mode !== "byob") {
- throw new TypeError("Invalid mode.");
- }
// 3. Return ? AcquireReadableStreamBYOBReader(this).
- throw new RangeError(`Unsupported mode "${String(mode)}"`);
+ throw new RangeError(`${prefix}: Unsupported mode '${mode}'`);
}
/**
@@ -3134,36 +3197,32 @@
* @param {PipeOptions=} options
* @returns {ReadableStream<T>}
*/
- pipeThrough(
- transform,
- { preventClose, preventAbort, preventCancel, signal } = {},
- ) {
- if (!isReadableStream(this)) {
- throw new TypeError("this must be a ReadableStream");
- }
- const { readable } = transform;
- if (!isReadableStream(readable)) {
- throw new TypeError("readable must be a ReadableStream");
- }
- const { writable } = transform;
- if (!isWritableStream(writable)) {
- throw new TypeError("writable must be a WritableStream");
- }
+ pipeThrough(transform, options = {}) {
+ webidl.assertBranded(this, ReadableStream);
+ const prefix = "Failed to execute 'pipeThrough' on 'ReadableStream'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ transform = webidl.converters.ReadableWritablePair(transform, {
+ prefix,
+ context: "Argument 1",
+ });
+ options = webidl.converters.StreamPipeOptions(options, {
+ prefix,
+ context: "Argument 2",
+ });
+ const { readable, writable } = transform;
+ const { preventClose, preventAbort, preventCancel, signal } = options;
if (isReadableStreamLocked(this)) {
throw new TypeError("ReadableStream is already locked.");
}
- if (signal !== undefined && !(signal instanceof AbortSignal)) {
- throw new TypeError("signal must be an AbortSignal");
- }
if (isWritableStreamLocked(writable)) {
throw new TypeError("Target WritableStream is already locked.");
}
const promise = readableStreamPipeTo(
this,
writable,
- Boolean(preventClose),
- Boolean(preventAbort),
- Boolean(preventCancel),
+ preventClose,
+ preventAbort,
+ preventCancel,
signal,
);
setPromiseIsHandledToTrue(promise);
@@ -3175,15 +3234,23 @@
* @param {PipeOptions=} options
* @returns {Promise<void>}
*/
- pipeTo(
- destination,
- {
- preventClose = false,
- preventAbort = false,
- preventCancel = false,
- signal,
- } = {},
- ) {
+ pipeTo(destination, options = {}) {
+ try {
+ webidl.assertBranded(this, ReadableStream);
+ const prefix = "Failed to execute 'pipeTo' on 'ReadableStream'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ destination = webidl.converters.WritableStream(destination, {
+ prefix,
+ context: "Argument 1",
+ });
+ options = webidl.converters.StreamPipeOptions(options, {
+ prefix,
+ context: "Argument 2",
+ });
+ } catch (err) {
+ return Promise.reject(err);
+ }
+ const { preventClose, preventAbort, preventCancel, signal } = options;
if (isReadableStreamLocked(this)) {
return Promise.reject(
new TypeError("ReadableStream is already locked."),
@@ -3206,72 +3273,82 @@
/** @returns {[ReadableStream<R>, ReadableStream<R>]} */
tee() {
+ webidl.assertBranded(this, ReadableStream);
return readableStreamTee(this, false);
}
+ // TODO(lucacasonato): should be moved to webidl crate
/**
* @param {ReadableStreamIteratorOptions=} options
* @returns {AsyncIterableIterator<R>}
*/
- [Symbol.asyncIterator]({ preventCancel } = {}) {
+ values(options = {}) {
+ webidl.assertBranded(this, ReadableStream);
+ const prefix = "Failed to execute 'values' on 'ReadableStream'";
+ options = webidl.converters.ReadableStreamIteratorOptions(options, {
+ prefix,
+ context: "Argument 1",
+ });
/** @type {AsyncIterableIterator<R>} */
const iterator = Object.create(readableStreamAsyncIteratorPrototype);
const reader = acquireReadableStreamDefaultReader(this);
iterator[_reader] = reader;
- iterator[_preventCancel] = preventCancel;
+ iterator[_preventCancel] = options.preventCancel;
return iterator;
}
[Symbol.for("Deno.customInspect")](inspect) {
return `${this.constructor.name} ${inspect({ locked: this.locked })}`;
}
+
+ get [Symbol.toStringTag]() {
+ return "ReadableStream";
+ }
}
+ // TODO(lucacasonato): should be moved to webidl crate
+ ReadableStream.prototype[Symbol.asyncIterator] =
+ ReadableStream.prototype.values;
+ Object.defineProperty(ReadableStream.prototype, Symbol.asyncIterator, {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+ });
+
+ webidl.configurePrototype(ReadableStream);
+
function errorReadableStream(stream, e) {
readableStreamDefaultControllerError(stream[_controller], e);
}
/** @template R */
- class ReadableStreamGenericReader {
+ class ReadableStreamDefaultReader {
/** @type {Deferred<void>} */
[_closedPromise];
/** @type {ReadableStream<R> | undefined} */
[_stream];
-
- get closed() {
- return this[_closedPromise].promise;
- }
-
- /**
- * @param {any} reason
- * @returns {Promise<void>}
- */
- cancel(reason) {
- if (this[_stream] === undefined) {
- return Promise.reject(
- new TypeError("Reader has no associated stream."),
- );
- }
- return readableStreamReaderGenericCancel(this, reason);
- }
- }
-
- /** @template R */
- class ReadableStreamDefaultReader extends ReadableStreamGenericReader {
/** @type {ReadRequest[]} */
[_readRequests];
/** @param {ReadableStream<R>} stream */
constructor(stream) {
- if (!(stream instanceof ReadableStream)) {
- throw new TypeError("stream is not a ReadableStream");
- }
- super();
+ const prefix = "Failed to construct 'ReadableStreamDefaultReader'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ stream = webidl.converters.ReadableStream(stream, {
+ prefix,
+ context: "Argument 1",
+ });
+ this[webidl.brand] = webidl.brand;
setUpReadableStreamDefaultReader(this, stream);
}
/** @returns {Promise<ReadableStreamReadResult<R>>} */
read() {
+ try {
+ webidl.assertBranded(this, ReadableStreamDefaultReader);
+ } catch (err) {
+ return Promise.reject(err);
+ }
if (this[_stream] === undefined) {
return Promise.reject(
new TypeError("Reader has no associated stream."),
@@ -3297,6 +3374,7 @@
/** @returns {void} */
releaseLock() {
+ webidl.assertBranded(this, ReadableStreamDefaultReader);
if (this[_stream] === undefined) {
return;
}
@@ -3308,11 +3386,48 @@
readableStreamReaderGenericRelease(this);
}
+ get closed() {
+ try {
+ webidl.assertBranded(this, ReadableStreamDefaultReader);
+ } catch (err) {
+ return Promise.reject(err);
+ }
+ return this[_closedPromise].promise;
+ }
+
+ /**
+ * @param {any} reason
+ * @returns {Promise<void>}
+ */
+ cancel(reason = undefined) {
+ try {
+ webidl.assertBranded(this, ReadableStreamDefaultReader);
+ if (reason !== undefined) {
+ reason = webidl.converters.any(reason);
+ }
+ } catch (err) {
+ return Promise.reject(err);
+ }
+
+ if (this[_stream] === undefined) {
+ return Promise.reject(
+ new TypeError("Reader has no associated stream."),
+ );
+ }
+ return readableStreamReaderGenericCancel(this, reason);
+ }
+
[Symbol.for("Deno.customInspect")](inspect) {
return `${this.constructor.name} ${inspect({ closed: this.closed })}`;
}
+
+ get [Symbol.toStringTag]() {
+ return "ReadableStreamDefaultReader";
+ }
}
+ webidl.configurePrototype(ReadableStreamDefaultReader);
+
class ReadableByteStreamController {
/** @type {number | undefined} */
[_autoAllocateChunkSize];
@@ -3339,17 +3454,24 @@
/** @type {ReadableStream<ArrayBuffer>} */
[_stream];
+ constructor() {
+ webidl.illegalConstructor();
+ }
+
get byobRequest() {
+ webidl.assertBranded(this, ReadableByteStreamController);
return undefined;
}
/** @returns {number | null} */
get desiredSize() {
+ webidl.assertBranded(this, ReadableByteStreamController);
return readableByteStreamControllerGetDesiredSize(this);
}
/** @returns {void} */
close() {
+ webidl.assertBranded(this, ReadableByteStreamController);
if (this[_closeRequested] === true) {
throw new TypeError("Closed already requested.");
}
@@ -3366,11 +3488,27 @@
* @returns {void}
*/
enqueue(chunk) {
+ webidl.assertBranded(this, ReadableByteStreamController);
+ const prefix =
+ "Failed to execute 'enqueue' on 'ReadableByteStreamController'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ const arg1 = "Argument 1";
+ chunk = webidl.converters.ArrayBufferView(chunk, {
+ prefix,
+ context: arg1,
+ });
if (chunk.byteLength === 0) {
- throw new TypeError("chunk must have a non-zero byteLength.");
+ throw webidl.makeException(TypeError, "length must be non-zero", {
+ prefix,
+ context: arg1,
+ });
}
if (chunk.buffer.byteLength === 0) {
- throw new TypeError("chunk's buffer must have a non-zero byteLength.");
+ throw webidl.makeException(
+ TypeError,
+ "buffer length must be non-zero",
+ { prefix, context: arg1 },
+ );
}
if (this[_closeRequested] === true) {
throw new TypeError(
@@ -3389,10 +3527,24 @@
* @param {any=} e
* @returns {void}
*/
- error(e) {
+ error(e = undefined) {
+ webidl.assertBranded(this, ReadableByteStreamController);
+ if (e !== undefined) {
+ e = webidl.converters.any(e);
+ }
readableByteStreamControllerError(this, e);
}
+ [Symbol.for("Deno.customInspect")](inspect) {
+ return `${this.constructor.name} ${
+ inspect({ desiredSize: this.desiredSize })
+ }`;
+ }
+
+ get [Symbol.toStringTag]() {
+ return "ReadableByteStreamController";
+ }
+
/**
* @param {any} reason
* @returns {Promise<void>}
@@ -3433,6 +3585,8 @@
}
}
+ webidl.configurePrototype(ReadableByteStreamController);
+
/** @template R */
class ReadableStreamDefaultController {
/** @type {(reason: any) => Promise<void>} */
@@ -3458,13 +3612,19 @@
/** @type {ReadableStream<R>} */
[_stream];
+ constructor() {
+ webidl.illegalConstructor();
+ }
+
/** @returns {number | null} */
get desiredSize() {
+ webidl.assertBranded(this, ReadableStreamDefaultController);
return readableStreamDefaultControllerGetDesiredSize(this);
}
/** @returns {void} */
close() {
+ webidl.assertBranded(this, ReadableStreamDefaultController);
if (readableStreamDefaultControllerCanCloseOrEnqueue(this) === false) {
throw new TypeError("The stream controller cannot close or enqueue.");
}
@@ -3475,7 +3635,11 @@
* @param {R} chunk
* @returns {void}
*/
- enqueue(chunk) {
+ enqueue(chunk = undefined) {
+ webidl.assertBranded(this, ReadableStreamDefaultController);
+ if (chunk !== undefined) {
+ chunk = webidl.converters.any(chunk);
+ }
if (readableStreamDefaultControllerCanCloseOrEnqueue(this) === false) {
throw new TypeError("The stream controller cannot close or enqueue.");
}
@@ -3486,10 +3650,24 @@
* @param {any=} e
* @returns {void}
*/
- error(e) {
+ error(e = undefined) {
+ webidl.assertBranded(this, ReadableStreamDefaultController);
+ if (e !== undefined) {
+ e = webidl.converters.any(e);
+ }
readableStreamDefaultControllerError(this, e);
}
+ [Symbol.for("Deno.customInspect")](inspect) {
+ return `${this.constructor.name} ${
+ inspect({ desiredSize: this.desiredSize })
+ }`;
+ }
+
+ get [Symbol.toStringTag]() {
+ return "ReadableStreamDefaultController";
+ }
+
/**
* @param {any} reason
* @returns {Promise<void>}
@@ -3523,6 +3701,8 @@
}
}
+ webidl.configurePrototype(ReadableStreamDefaultController);
+
/**
* @template I
* @template O
@@ -3548,16 +3728,42 @@
* @param {QueuingStrategy<O>} readableStrategy
*/
constructor(
- transformer = null,
+ transformer = undefined,
writableStrategy = {},
readableStrategy = {},
) {
- const transformerDict = convertTransformer(transformer);
- if (transformerDict.readableType) {
- throw new RangeError("readableType transformers not supported.");
+ const prefix = "Failed to construct 'TransformStream'";
+ if (transformer !== undefined) {
+ transformer = webidl.converters.object(transformer, {
+ prefix,
+ context: "Argument 1",
+ });
}
- if (transformerDict.writableType) {
- throw new RangeError("writableType transformers not supported.");
+ writableStrategy = webidl.converters.QueuingStrategy(writableStrategy, {
+ prefix,
+ context: "Argument 2",
+ });
+ readableStrategy = webidl.converters.QueuingStrategy(readableStrategy, {
+ prefix,
+ context: "Argument 2",
+ });
+ this[webidl.brand] = webidl.brand;
+ if (transformer === undefined) {
+ transformer = null;
+ }
+ const transformerDict = webidl.converters.Transformer(transformer, {
+ prefix,
+ context: "transformer",
+ });
+ if (transformerDict.readableType !== undefined) {
+ throw new RangeError(
+ `${prefix}: readableType transformers not supported.`,
+ );
+ }
+ if (transformerDict.writableType !== undefined) {
+ throw new RangeError(
+ `${prefix}: writableType transformers not supported.`,
+ );
}
const readableHighWaterMark = extractHighWaterMark(readableStrategy, 0);
const readableSizeAlgorithm = extractSizeAlgorithm(readableStrategy);
@@ -3578,9 +3784,18 @@
transformer,
transformerDict,
);
- if ("start" in transformerDict) {
+ if (transformerDict.start) {
startPromise.resolve(
- transformerDict.start.call(transformer, this[_controller]),
+ webidl.invokeCallbackFunction(
+ transformerDict.start,
+ [this[_controller]],
+ transformer,
+ webidl.converters.any,
+ {
+ prefix:
+ "Failed to call 'start' on 'TransformStreamDefaultController'",
+ },
+ ),
);
} else {
startPromise.resolve(undefined);
@@ -3589,11 +3804,13 @@
/** @returns {ReadableStream<O>} */
get readable() {
+ webidl.assertBranded(this, TransformStream);
return this[_readable];
}
/** @returns {WritableStream<I>} */
get writable() {
+ webidl.assertBranded(this, TransformStream);
return this[_writable];
}
@@ -3602,8 +3819,14 @@
inspect({ readable: this.readable, writable: this.writable })
}`;
}
+
+ get [Symbol.toStringTag]() {
+ return "TransformStream";
+ }
}
+ webidl.configurePrototype(TransformStream);
+
/** @template O */
class TransformStreamDefaultController {
/** @type {(controller: this) => Promise<void>} */
@@ -3613,8 +3836,13 @@
/** @type {(chunk: O, controller: this) => Promise<void>} */
[_transformAlgorithm];
+ constructor() {
+ webidl.illegalConstructor();
+ }
+
/** @returns {number | null} */
get desiredSize() {
+ webidl.assertBranded(this, TransformStreamDefaultController);
const readableController = this[_stream][_readable][_controller];
return readableStreamDefaultControllerGetDesiredSize(
/** @type {ReadableStreamDefaultController<O>} */ (readableController),
@@ -3625,7 +3853,11 @@
* @param {O} chunk
* @returns {void}
*/
- enqueue(chunk) {
+ enqueue(chunk = undefined) {
+ webidl.assertBranded(this, TransformStreamDefaultController);
+ if (chunk !== undefined) {
+ chunk = webidl.converters.any(chunk);
+ }
transformStreamDefaultControllerEnqueue(this, chunk);
}
@@ -3633,16 +3865,33 @@
* @param {any=} reason
* @returns {void}
*/
- error(reason) {
+ error(reason = undefined) {
+ webidl.assertBranded(this, TransformStreamDefaultController);
+ if (reason !== undefined) {
+ reason = webidl.converters.any(reason);
+ }
transformStreamDefaultControllerError(this, reason);
}
/** @returns {void} */
terminate() {
+ webidl.assertBranded(this, TransformStreamDefaultController);
transformStreamDefaultControllerTerminate(this);
}
+
+ [Symbol.for("Deno.customInspect")](inspect) {
+ return `${this.constructor.name} ${
+ inspect({ desiredSize: this.desiredSize })
+ }`;
+ }
+
+ get [Symbol.toStringTag]() {
+ return "TransformStreamDefaultController";
+ }
}
+ webidl.configurePrototype(TransformStreamDefaultController);
+
/** @template W */
class WritableStream {
/** @type {boolean} */
@@ -3672,11 +3921,29 @@
* @param {UnderlyingSink<W>=} underlyingSink
* @param {QueuingStrategy<W>=} strategy
*/
- constructor(underlyingSink = null, strategy = {}) {
- const underlyingSinkDict = convertUnderlyingSink(underlyingSink);
+ constructor(underlyingSink = undefined, strategy = {}) {
+ const prefix = "Failed to construct 'WritableStream'";
+ if (underlyingSink !== undefined) {
+ underlyingSink = webidl.converters.object(underlyingSink, {
+ prefix,
+ context: "Argument 1",
+ });
+ }
+ strategy = webidl.converters.QueuingStrategy(strategy, {
+ prefix,
+ context: "Argument 2",
+ });
+ this[webidl.brand] = webidl.brand;
+ if (underlyingSink === undefined) {
+ underlyingSink = null;
+ }
+ const underlyingSinkDict = webidl.converters.UnderlyingSink(
+ underlyingSink,
+ { prefix, context: "underlyingSink" },
+ );
if (underlyingSinkDict.type != null) {
throw new RangeError(
- 'WritableStream does not support "type" in the underlying sink.',
+ `${prefix}: WritableStream does not support 'type' in the underlying sink.`,
);
}
initializeWritableStream(this);
@@ -3693,6 +3960,7 @@
/** @returns {boolean} */
get locked() {
+ webidl.assertBranded(this, WritableStream);
return isWritableStreamLocked(this);
}
@@ -3700,7 +3968,15 @@
* @param {any=} reason
* @returns {Promise<void>}
*/
- abort(reason) {
+ abort(reason = undefined) {
+ try {
+ webidl.assertBranded(this, WritableStream);
+ } catch (err) {
+ return Promise.reject(err);
+ }
+ if (reason !== undefined) {
+ reason = webidl.converters.any(reason);
+ }
if (isWritableStreamLocked(this)) {
return Promise.reject(
new TypeError(
@@ -3713,6 +3989,11 @@
/** @returns {Promise<void>} */
close() {
+ try {
+ webidl.assertBranded(this, WritableStream);
+ } catch (err) {
+ return Promise.reject(err);
+ }
if (isWritableStreamLocked(this)) {
return Promise.reject(
new TypeError(
@@ -3730,14 +4011,21 @@
/** @returns {WritableStreamDefaultWriter<W>} */
getWriter() {
+ webidl.assertBranded(this, WritableStream);
return acquireWritableStreamDefaultWriter(this);
}
[Symbol.for("Deno.customInspect")](inspect) {
return `${this.constructor.name} ${inspect({ locked: this.locked })}`;
}
+
+ get [Symbol.toStringTag]() {
+ return "WritableStream";
+ }
}
+ webidl.configurePrototype(WritableStream);
+
/** @template W */
class WritableStreamDefaultWriter {
/** @type {Deferred<void>} */
@@ -3749,17 +4037,33 @@
/** @type {WritableStream<W>} */
[_stream];
+ /**
+ * @param {WritableStream<W>} stream
+ */
constructor(stream) {
+ const prefix = "Failed to construct 'WritableStreamDefaultWriter'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ stream = webidl.converters.WritableStream(stream, {
+ prefix,
+ context: "Argument 1",
+ });
+ this[webidl.brand] = webidl.brand;
setUpWritableStreamDefaultWriter(this, stream);
}
/** @returns {Promise<void>} */
get closed() {
+ try {
+ webidl.assertBranded(this, WritableStreamDefaultWriter);
+ } catch (err) {
+ return Promise.reject(err);
+ }
return this[_closedPromise].promise;
}
/** @returns {number} */
get desiredSize() {
+ webidl.assertBranded(this, WritableStreamDefaultWriter);
if (this[_stream] === undefined) {
throw new TypeError(
"A writable stream is not associated with the writer.",
@@ -3770,6 +4074,11 @@
/** @returns {Promise<void>} */
get ready() {
+ try {
+ webidl.assertBranded(this, WritableStreamDefaultWriter);
+ } catch (err) {
+ return Promise.reject(err);
+ }
return this[_readyPromise].promise;
}
@@ -3777,7 +4086,15 @@
* @param {any} reason
* @returns {Promise<void>}
*/
- abort(reason) {
+ abort(reason = undefined) {
+ try {
+ webidl.assertBranded(this, WritableStreamDefaultWriter);
+ } catch (err) {
+ return Promise.reject(err);
+ }
+ if (reason !== undefined) {
+ reason = webidl.converters.any(reason);
+ }
if (this[_stream] === undefined) {
return Promise.reject(
new TypeError("A writable stream is not associated with the writer."),
@@ -3788,6 +4105,11 @@
/** @returns {Promise<void>} */
close() {
+ try {
+ webidl.assertBranded(this, WritableStreamDefaultWriter);
+ } catch (err) {
+ return Promise.reject(err);
+ }
const stream = this[_stream];
if (stream === undefined) {
return Promise.reject(
@@ -3804,6 +4126,7 @@
/** @returns {void} */
releaseLock() {
+ webidl.assertBranded(this, WritableStreamDefaultWriter);
const stream = this[_stream];
if (stream === undefined) {
return;
@@ -3816,7 +4139,15 @@
* @param {W} chunk
* @returns {Promise<void>}
*/
- write(chunk) {
+ write(chunk = undefined) {
+ try {
+ webidl.assertBranded(this, WritableStreamDefaultWriter);
+ if (chunk !== undefined) {
+ chunk = webidl.converters.any(chunk);
+ }
+ } catch (err) {
+ return Promise.reject(err);
+ }
if (this[_stream] === undefined) {
return Promise.reject(
new TypeError("A writable stream is not associate with the writer."),
@@ -3824,8 +4155,24 @@
}
return writableStreamDefaultWriterWrite(this, chunk);
}
+
+ [Symbol.for("Deno.customInspect")](inspect) {
+ return `${this.constructor.name} ${
+ inspect({
+ closed: this.closed,
+ desiredSize: this.desiredSize,
+ ready: this.ready,
+ })
+ }`;
+ }
+
+ get [Symbol.toStringTag]() {
+ return "WritableStreamDefaultWriter";
+ }
}
+ webidl.configurePrototype(WritableStreamDefaultWriter);
+
/** @template W */
class WritableStreamDefaultController {
/** @type {(reason?: any) => Promise<void>} */
@@ -3847,11 +4194,19 @@
/** @type {(chunk: W, controller: this) => Promise<void>} */
[_writeAlgorithm];
+ constructor() {
+ webidl.illegalConstructor();
+ }
+
/**
* @param {any=} e
* @returns {void}
*/
- error(e) {
+ error(e = undefined) {
+ webidl.assertBranded(this, WritableStreamDefaultController);
+ if (e !== undefined) {
+ e = webidl.converters.any(e);
+ }
const state = this[_stream][_state];
if (state !== "writable") {
return;
@@ -3859,6 +4214,14 @@
writableStreamDefaultControllerError(this, e);
}
+ [Symbol.for("Deno.customInspect")](inspect) {
+ return `${this.constructor.name} ${inspect({})}`;
+ }
+
+ get [Symbol.toStringTag]() {
+ return "WritableStreamDefaultController";
+ }
+
/**
* @param {any=} reason
* @returns {Promise<void>}
@@ -3874,6 +4237,161 @@
}
}
+ webidl.configurePrototype(WritableStreamDefaultController);
+
+ webidl.converters.ReadableStream = webidl
+ .createInterfaceConverter("ReadableStream", ReadableStream);
+ webidl.converters.WritableStream = webidl
+ .createInterfaceConverter("WritableStream", WritableStream);
+
+ webidl.converters.ReadableStreamType = webidl.createEnumConverter(
+ "ReadableStreamType",
+ ["bytes"],
+ );
+
+ webidl.converters.UnderlyingSource = webidl
+ .createDictionaryConverter("UnderlyingSource", [
+ {
+ key: "start",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "pull",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "cancel",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "type",
+ converter: webidl.converters.ReadableStreamType,
+ },
+ {
+ key: "autoAllocateChunkSize",
+ converter: (V, opts) =>
+ webidl.converters["unsigned long long"](V, {
+ ...opts,
+ enforceRange: true,
+ }),
+ },
+ ]);
+ webidl.converters.UnderlyingSink = webidl
+ .createDictionaryConverter("UnderlyingSink", [
+ {
+ key: "start",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "write",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "close",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "abort",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "type",
+ converter: webidl.converters.any,
+ },
+ ]);
+ webidl.converters.Transformer = webidl
+ .createDictionaryConverter("Transformer", [
+ {
+ key: "start",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "transform",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "flush",
+ converter: webidl.converters.Function,
+ },
+ {
+ key: "readableType",
+ converter: webidl.converters.any,
+ },
+ {
+ key: "writableType",
+ converter: webidl.converters.any,
+ },
+ ]);
+ webidl.converters.QueuingStrategy = webidl
+ .createDictionaryConverter("QueuingStrategy", [
+ {
+ key: "highWaterMark",
+ converter: webidl.converters["unrestricted double"],
+ },
+ {
+ key: "size",
+ converter: webidl.converters.Function,
+ },
+ ]);
+ webidl.converters.QueuingStrategyInit = webidl
+ .createDictionaryConverter("QueuingStrategyInit", [
+ {
+ key: "highWaterMark",
+ converter: webidl.converters["unrestricted double"],
+ required: true,
+ },
+ ]);
+
+ webidl.converters.ReadableStreamIteratorOptions = webidl
+ .createDictionaryConverter("ReadableStreamIteratorOptions", [
+ {
+ key: "preventCancel",
+ defaultValue: false,
+ converter: webidl.converters.boolean,
+ },
+ ]);
+
+ webidl.converters.ReadableStreamReaderMode = webidl
+ .createEnumConverter("ReadableStreamReaderMode", ["byob"]);
+ webidl.converters.ReadableStreamGetReaderOptions = webidl
+ .createDictionaryConverter("ReadableStreamGetReaderOptions", [{
+ key: "mode",
+ converter: webidl.converters.ReadableStreamReaderMode,
+ }]);
+
+ webidl.converters.ReadableWritablePair = webidl
+ .createDictionaryConverter("ReadableWritablePair", [
+ {
+ key: "readable",
+ converter: webidl.converters.ReadableStream,
+ required: true,
+ },
+ {
+ key: "writable",
+ converter: webidl.converters.WritableStream,
+ required: true,
+ },
+ ]);
+ webidl.converters.StreamPipeOptions = webidl
+ .createDictionaryConverter("StreamPipeOptions", [
+ {
+ key: "preventClose",
+ defaultValue: false,
+ converter: webidl.converters.boolean,
+ },
+ {
+ key: "preventAbort",
+ defaultValue: false,
+ converter: webidl.converters.boolean,
+ },
+ {
+ key: "preventCancel",
+ defaultValue: false,
+ converter: webidl.converters.boolean,
+ },
+ { key: "signal", converter: webidl.converters.AbortSignal },
+ ]);
+
window.__bootstrap.streams = {
// Non-Public
isReadableStreamDisturbed,
@@ -3886,7 +4404,9 @@
TransformStream,
WritableStream,
WritableStreamDefaultWriter,
+ WritableStreamDefaultController,
ReadableByteStreamController,
+ ReadableStreamDefaultController,
TransformStreamDefaultController,
};
})(this);