summaryrefslogtreecommitdiff
path: root/extensions/web
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/web')
-rw-r--r--extensions/web/00_infra.js264
-rw-r--r--extensions/web/01_dom_exception.js171
-rw-r--r--extensions/web/01_mimesniff.js211
-rw-r--r--extensions/web/02_event.js1294
-rw-r--r--extensions/web/02_structured_clone.js85
-rw-r--r--extensions/web/03_abort_signal.js123
-rw-r--r--extensions/web/04_global_interfaces.js79
-rw-r--r--extensions/web/05_base64.js73
-rw-r--r--extensions/web/06_streams.js4473
-rw-r--r--extensions/web/06_streams_types.d.ts55
-rw-r--r--extensions/web/08_text_encoding.js420
-rw-r--r--extensions/web/09_file.js569
-rw-r--r--extensions/web/10_filereader.js461
-rw-r--r--extensions/web/11_blob_url.js59
-rw-r--r--extensions/web/12_location.js409
-rw-r--r--extensions/web/13_message_port.js286
-rw-r--r--extensions/web/Cargo.toml26
-rw-r--r--extensions/web/README.md6
-rw-r--r--extensions/web/blob.rs265
-rw-r--r--extensions/web/internal.d.ts98
-rw-r--r--extensions/web/lib.deno_web.d.ts752
-rw-r--r--extensions/web/lib.rs390
-rw-r--r--extensions/web/message_port.rs217
23 files changed, 0 insertions, 10786 deletions
diff --git a/extensions/web/00_infra.js b/extensions/web/00_infra.js
deleted file mode 100644
index 7c065bcd3..000000000
--- a/extensions/web/00_infra.js
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference path="../../core/internal.d.ts" />
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-
-"use strict";
-
-((window) => {
- const core = Deno.core;
- const {
- RegExp,
- ArrayPrototypeMap,
- StringPrototypeCharCodeAt,
- NumberPrototypeToString,
- StringPrototypePadStart,
- TypeError,
- ArrayPrototypeJoin,
- StringPrototypeCharAt,
- StringPrototypeSlice,
- String,
- StringPrototypeReplace,
- StringPrototypeToUpperCase,
- StringPrototypeToLowerCase,
- StringPrototypeSubstring,
- } = window.__bootstrap.primordials;
-
- const ASCII_DIGIT = ["\u0030-\u0039"];
- const ASCII_UPPER_ALPHA = ["\u0041-\u005A"];
- const ASCII_LOWER_ALPHA = ["\u0061-\u007A"];
- const ASCII_ALPHA = [...ASCII_UPPER_ALPHA, ...ASCII_LOWER_ALPHA];
- const ASCII_ALPHANUMERIC = [...ASCII_DIGIT, ...ASCII_ALPHA];
-
- const HTTP_TAB_OR_SPACE = ["\u0009", "\u0020"];
- const HTTP_WHITESPACE = ["\u000A", "\u000D", ...HTTP_TAB_OR_SPACE];
-
- const HTTP_TOKEN_CODE_POINT = [
- "\u0021",
- "\u0023",
- "\u0024",
- "\u0025",
- "\u0026",
- "\u0027",
- "\u002A",
- "\u002B",
- "\u002D",
- "\u002E",
- "\u005E",
- "\u005F",
- "\u0060",
- "\u007C",
- "\u007E",
- ...ASCII_ALPHANUMERIC,
- ];
- const HTTP_TOKEN_CODE_POINT_RE = new RegExp(
- `^[${regexMatcher(HTTP_TOKEN_CODE_POINT)}]+$`,
- );
- const HTTP_QUOTED_STRING_TOKEN_POINT = [
- "\u0009",
- "\u0020-\u007E",
- "\u0080-\u00FF",
- ];
- const HTTP_QUOTED_STRING_TOKEN_POINT_RE = new RegExp(
- `^[${regexMatcher(HTTP_QUOTED_STRING_TOKEN_POINT)}]+$`,
- );
- const HTTP_TAB_OR_SPACE_MATCHER = regexMatcher(HTTP_TAB_OR_SPACE);
- const HTTP_TAB_OR_SPACE_PREFIX_RE = new RegExp(
- `^[${HTTP_TAB_OR_SPACE_MATCHER}]+`,
- "g",
- );
- const HTTP_TAB_OR_SPACE_SUFFIX_RE = new RegExp(
- `[${HTTP_TAB_OR_SPACE_MATCHER}]+$`,
- "g",
- );
- const HTTP_WHITESPACE_MATCHER = regexMatcher(HTTP_WHITESPACE);
- const HTTP_WHITESPACE_PREFIX_RE = new RegExp(
- `^[${HTTP_WHITESPACE_MATCHER}]+`,
- "g",
- );
- const HTTP_WHITESPACE_SUFFIX_RE = new RegExp(
- `[${HTTP_WHITESPACE_MATCHER}]+$`,
- "g",
- );
-
- /**
- * Turn a string of chars into a regex safe matcher.
- * @param {string[]} chars
- * @returns {string}
- */
- function regexMatcher(chars) {
- const matchers = ArrayPrototypeMap(chars, (char) => {
- if (char.length === 1) {
- const a = StringPrototypePadStart(
- NumberPrototypeToString(StringPrototypeCharCodeAt(char, 0), 16),
- 4,
- "0",
- );
- return `\\u${a}`;
- } else if (char.length === 3 && char[1] === "-") {
- const a = StringPrototypePadStart(
- NumberPrototypeToString(StringPrototypeCharCodeAt(char, 0), 16),
- 4,
- "0",
- );
- const b = StringPrototypePadStart(
- NumberPrototypeToString(StringPrototypeCharCodeAt(char, 2), 16),
- 4,
- "0",
- );
- return `\\u${a}-\\u${b}`;
- } else {
- throw TypeError("unreachable");
- }
- });
- return ArrayPrototypeJoin(matchers, "");
- }
-
- /**
- * https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
- * @param {string} input
- * @param {number} position
- * @param {(char: string) => boolean} condition
- * @returns {{result: string, position: number}}
- */
- function collectSequenceOfCodepoints(input, position, condition) {
- const start = position;
- for (
- let c = StringPrototypeCharAt(input, position);
- position < input.length && condition(c);
- c = StringPrototypeCharAt(input, ++position)
- );
- return { result: StringPrototypeSlice(input, start, position), position };
- }
-
- /**
- * @param {string} s
- * @returns {string}
- */
- function byteUpperCase(s) {
- return StringPrototypeReplace(
- String(s),
- /[a-z]/g,
- function byteUpperCaseReplace(c) {
- return StringPrototypeToUpperCase(c);
- },
- );
- }
-
- /**
- * @param {string} s
- * @returns {string}
- */
- function byteLowerCase(s) {
- return StringPrototypeReplace(
- String(s),
- /[A-Z]/g,
- function byteUpperCaseReplace(c) {
- return StringPrototypeToLowerCase(c);
- },
- );
- }
-
- /**
- * https://fetch.spec.whatwg.org/#collect-an-http-quoted-string
- * @param {string} input
- * @param {number} position
- * @param {boolean} extractValue
- * @returns {{result: string, position: number}}
- */
- function collectHttpQuotedString(input, position, extractValue) {
- // 1.
- const positionStart = position;
- // 2.
- let value = "";
- // 3.
- if (input[position] !== "\u0022") throw new TypeError('must be "');
- // 4.
- position++;
- // 5.
- while (true) {
- // 5.1.
- const res = collectSequenceOfCodepoints(
- input,
- position,
- (c) => c !== "\u0022" && c !== "\u005C",
- );
- value += res.result;
- position = res.position;
- // 5.2.
- if (position >= input.length) break;
- // 5.3.
- const quoteOrBackslash = input[position];
- // 5.4.
- position++;
- // 5.5.
- if (quoteOrBackslash === "\u005C") {
- // 5.5.1.
- if (position >= input.length) {
- value += "\u005C";
- break;
- }
- // 5.5.2.
- value += input[position];
- // 5.5.3.
- position++;
- } else { // 5.6.
- // 5.6.1
- if (quoteOrBackslash !== "\u0022") throw new TypeError('must be "');
- // 5.6.2
- break;
- }
- }
- // 6.
- if (extractValue) return { result: value, position };
- // 7.
- return {
- result: StringPrototypeSubstring(input, positionStart, position + 1),
- position,
- };
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {string}
- */
- function forgivingBase64Encode(data) {
- return core.opSync("op_base64_encode", data);
- }
-
- /**
- * @param {string} data
- * @returns {Uint8Array}
- */
- function forgivingBase64Decode(data) {
- return core.opSync("op_base64_decode", data);
- }
-
- window.__bootstrap.infra = {
- collectSequenceOfCodepoints,
- ASCII_DIGIT,
- ASCII_UPPER_ALPHA,
- ASCII_LOWER_ALPHA,
- ASCII_ALPHA,
- ASCII_ALPHANUMERIC,
- HTTP_TAB_OR_SPACE,
- HTTP_WHITESPACE,
- HTTP_TOKEN_CODE_POINT,
- HTTP_TOKEN_CODE_POINT_RE,
- HTTP_QUOTED_STRING_TOKEN_POINT,
- HTTP_QUOTED_STRING_TOKEN_POINT_RE,
- HTTP_TAB_OR_SPACE_PREFIX_RE,
- HTTP_TAB_OR_SPACE_SUFFIX_RE,
- HTTP_WHITESPACE_PREFIX_RE,
- HTTP_WHITESPACE_SUFFIX_RE,
- regexMatcher,
- byteUpperCase,
- byteLowerCase,
- collectHttpQuotedString,
- forgivingBase64Encode,
- forgivingBase64Decode,
- };
-})(globalThis);
diff --git a/extensions/web/01_dom_exception.js b/extensions/web/01_dom_exception.js
deleted file mode 100644
index c6f60ae2f..000000000
--- a/extensions/web/01_dom_exception.js
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference path="../../core/internal.d.ts" />
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../webidl/internal.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-
-"use strict";
-
-((window) => {
- const {
- ErrorPrototype,
- ObjectDefineProperty,
- ObjectEntries,
- ObjectSetPrototypeOf,
- SymbolFor,
- SymbolToStringTag,
- } = window.__bootstrap.primordials;
- const webidl = window.__bootstrap.webidl;
- const consoleInternal = window.__bootstrap.console;
-
- // Defined in WebIDL 4.3.
- // https://heycam.github.io/webidl/#idl-DOMException
- const INDEX_SIZE_ERR = 1;
- const DOMSTRING_SIZE_ERR = 2;
- const HIERARCHY_REQUEST_ERR = 3;
- const WRONG_DOCUMENT_ERR = 4;
- const INVALID_CHARACTER_ERR = 5;
- const NO_DATA_ALLOWED_ERR = 6;
- const NO_MODIFICATION_ALLOWED_ERR = 7;
- const NOT_FOUND_ERR = 8;
- const NOT_SUPPORTED_ERR = 9;
- const INUSE_ATTRIBUTE_ERR = 10;
- const INVALID_STATE_ERR = 11;
- const SYNTAX_ERR = 12;
- const INVALID_MODIFICATION_ERR = 13;
- const NAMESPACE_ERR = 14;
- const INVALID_ACCESS_ERR = 15;
- const VALIDATION_ERR = 16;
- const TYPE_MISMATCH_ERR = 17;
- const SECURITY_ERR = 18;
- const NETWORK_ERR = 19;
- const ABORT_ERR = 20;
- const URL_MISMATCH_ERR = 21;
- const QUOTA_EXCEEDED_ERR = 22;
- const TIMEOUT_ERR = 23;
- const INVALID_NODE_TYPE_ERR = 24;
- const DATA_CLONE_ERR = 25;
-
- // Defined in WebIDL 2.8.1.
- // https://heycam.github.io/webidl/#dfn-error-names-table
- /** @type {Record<string, number>} */
- const nameToCodeMapping = {
- IndexSizeError: INDEX_SIZE_ERR,
- HierarchyRequestError: HIERARCHY_REQUEST_ERR,
- WrongDocumentError: WRONG_DOCUMENT_ERR,
- InvalidCharacterError: INVALID_CHARACTER_ERR,
- NoModificationAllowedError: NO_MODIFICATION_ALLOWED_ERR,
- NotFoundError: NOT_FOUND_ERR,
- NotSupportedError: NOT_SUPPORTED_ERR,
- InUseAttributeError: INUSE_ATTRIBUTE_ERR,
- InvalidStateError: INVALID_STATE_ERR,
- SyntaxError: SYNTAX_ERR,
- InvalidModificationError: INVALID_MODIFICATION_ERR,
- NamespaceError: NAMESPACE_ERR,
- InvalidAccessError: INVALID_ACCESS_ERR,
- TypeMismatchError: TYPE_MISMATCH_ERR,
- SecurityError: SECURITY_ERR,
- NetworkError: NETWORK_ERR,
- AbortError: ABORT_ERR,
- URLMismatchError: URL_MISMATCH_ERR,
- QuotaExceededError: QUOTA_EXCEEDED_ERR,
- TimeoutError: TIMEOUT_ERR,
- InvalidNodeTypeError: INVALID_NODE_TYPE_ERR,
- DataCloneError: DATA_CLONE_ERR,
- };
-
- // Defined in WebIDL 4.3.
- // https://heycam.github.io/webidl/#idl-DOMException
- class DOMException {
- #message = "";
- #name = "";
- #code = 0;
-
- constructor(message = "", name = "Error") {
- this.#message = webidl.converters.DOMString(message, {
- prefix: "Failed to construct 'DOMException'",
- context: "Argument 1",
- });
- this.#name = webidl.converters.DOMString(name, {
- prefix: "Failed to construct 'DOMException'",
- context: "Argument 2",
- });
- this.#code = nameToCodeMapping[this.#name] ?? 0;
- }
-
- get message() {
- return this.#message;
- }
-
- get name() {
- return this.#name;
- }
-
- get code() {
- return this.#code;
- }
-
- get [SymbolToStringTag]() {
- return "DOMException";
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- if (this instanceof DOMException) {
- return `DOMException: ${this.#message}`;
- } else {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: false,
- keys: [
- "message",
- "name",
- "code",
- ],
- }));
- }
- }
- }
-
- ObjectSetPrototypeOf(DOMException.prototype, ErrorPrototype);
-
- webidl.configurePrototype(DOMException);
-
- for (
- const [key, value] of ObjectEntries({
- INDEX_SIZE_ERR,
- DOMSTRING_SIZE_ERR,
- HIERARCHY_REQUEST_ERR,
- WRONG_DOCUMENT_ERR,
- INVALID_CHARACTER_ERR,
- NO_DATA_ALLOWED_ERR,
- NO_MODIFICATION_ALLOWED_ERR,
- NOT_FOUND_ERR,
- NOT_SUPPORTED_ERR,
- INUSE_ATTRIBUTE_ERR,
- INVALID_STATE_ERR,
- SYNTAX_ERR,
- INVALID_MODIFICATION_ERR,
- NAMESPACE_ERR,
- INVALID_ACCESS_ERR,
- VALIDATION_ERR,
- TYPE_MISMATCH_ERR,
- SECURITY_ERR,
- NETWORK_ERR,
- ABORT_ERR,
- URL_MISMATCH_ERR,
- QUOTA_EXCEEDED_ERR,
- TIMEOUT_ERR,
- INVALID_NODE_TYPE_ERR,
- DATA_CLONE_ERR,
- })
- ) {
- const desc = { value, enumerable: true };
- ObjectDefineProperty(DOMException, key, desc);
- ObjectDefineProperty(DOMException.prototype, key, desc);
- }
-
- window.__bootstrap.domException = { DOMException };
-})(this);
diff --git a/extensions/web/01_mimesniff.js b/extensions/web/01_mimesniff.js
deleted file mode 100644
index 360d1ffe4..000000000
--- a/extensions/web/01_mimesniff.js
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference path="../../core/internal.d.ts" />
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-
-"use strict";
-
-((window) => {
- const {
- ArrayPrototypeIncludes,
- Map,
- MapPrototypeHas,
- MapPrototypeSet,
- RegExpPrototypeTest,
- StringPrototypeReplaceAll,
- StringPrototypeToLowerCase,
- } = window.__bootstrap.primordials;
- const {
- collectSequenceOfCodepoints,
- HTTP_WHITESPACE,
- HTTP_WHITESPACE_PREFIX_RE,
- HTTP_WHITESPACE_SUFFIX_RE,
- HTTP_QUOTED_STRING_TOKEN_POINT_RE,
- HTTP_TOKEN_CODE_POINT_RE,
- collectHttpQuotedString,
- } = window.__bootstrap.infra;
-
- /**
- * @typedef MimeType
- * @property {string} type
- * @property {string} subtype
- * @property {Map<string,string>} parameters
- */
-
- /**
- * @param {string} input
- * @returns {MimeType | null}
- */
- function parseMimeType(input) {
- // 1.
- input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_PREFIX_RE, "");
- input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_SUFFIX_RE, "");
-
- // 2.
- let position = 0;
- const endOfInput = input.length;
-
- // 3.
- const res1 = collectSequenceOfCodepoints(
- input,
- position,
- (c) => c != "\u002F",
- );
- const type = res1.result;
- position = res1.position;
-
- // 4.
- if (type === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, type)) {
- return null;
- }
-
- // 5.
- if (position >= endOfInput) return null;
-
- // 6.
- position++;
-
- // 7.
- const res2 = collectSequenceOfCodepoints(
- input,
- position,
- (c) => c != "\u003B",
- );
- let subtype = res2.result;
- position = res2.position;
-
- // 8.
- subtype = StringPrototypeReplaceAll(subtype, HTTP_WHITESPACE_SUFFIX_RE, "");
-
- // 9.
- if (
- subtype === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, subtype)
- ) {
- return null;
- }
-
- // 10.
- const mimeType = {
- type: StringPrototypeToLowerCase(type),
- subtype: StringPrototypeToLowerCase(subtype),
- /** @type {Map<string, string>} */
- parameters: new Map(),
- };
-
- // 11.
- while (position < endOfInput) {
- // 11.1.
- position++;
-
- // 11.2.
- const res1 = collectSequenceOfCodepoints(
- input,
- position,
- (c) => ArrayPrototypeIncludes(HTTP_WHITESPACE, c),
- );
- position = res1.position;
-
- // 11.3.
- const res2 = collectSequenceOfCodepoints(
- input,
- position,
- (c) => c !== "\u003B" && c !== "\u003D",
- );
- let parameterName = res2.result;
- position = res2.position;
-
- // 11.4.
- parameterName = StringPrototypeToLowerCase(parameterName);
-
- // 11.5.
- if (position < endOfInput) {
- if (input[position] == "\u003B") continue;
- position++;
- }
-
- // 11.6.
- if (position >= endOfInput) break;
-
- // 11.7.
- let parameterValue = null;
-
- // 11.8.
- if (input[position] === "\u0022") {
- // 11.8.1.
- const res = collectHttpQuotedString(input, position, true);
- parameterValue = res.result;
- position = res.position;
-
- // 11.8.2.
- position++;
- } else { // 11.9.
- // 11.9.1.
- const res = collectSequenceOfCodepoints(
- input,
- position,
- (c) => c !== "\u003B",
- );
- parameterValue = res.result;
- position = res.position;
-
- // 11.9.2.
- parameterValue = StringPrototypeReplaceAll(
- parameterValue,
- HTTP_WHITESPACE_SUFFIX_RE,
- "",
- );
-
- // 11.9.3.
- if (parameterValue === "") continue;
- }
-
- // 11.10.
- if (
- parameterName !== "" &&
- RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, parameterName) &&
- RegExpPrototypeTest(
- HTTP_QUOTED_STRING_TOKEN_POINT_RE,
- parameterValue,
- ) &&
- !MapPrototypeHas(mimeType.parameters, parameterName)
- ) {
- MapPrototypeSet(mimeType.parameters, parameterName, parameterValue);
- }
- }
-
- // 12.
- return mimeType;
- }
-
- /**
- * @param {MimeType} mimeType
- * @returns {string}
- */
- function essence(mimeType) {
- return `${mimeType.type}/${mimeType.subtype}`;
- }
-
- /**
- * @param {MimeType} mimeType
- * @returns {string}
- */
- function serializeMimeType(mimeType) {
- let serialization = essence(mimeType);
- for (const param of mimeType.parameters) {
- serialization += `;${param[0]}=`;
- let value = param[1];
- if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, value)) {
- value = StringPrototypeReplaceAll(value, "\\", "\\\\");
- value = StringPrototypeReplaceAll(value, '"', '\\"');
- value = `"${value}"`;
- }
- serialization += value;
- }
- return serialization;
- }
-
- window.__bootstrap.mimesniff = { parseMimeType, essence, serializeMimeType };
-})(this);
diff --git a/extensions/web/02_event.js b/extensions/web/02_event.js
deleted file mode 100644
index 4cca20e00..000000000
--- a/extensions/web/02_event.js
+++ /dev/null
@@ -1,1294 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// This module follows most of the WHATWG Living Standard for the DOM logic.
-// Many parts of the DOM are not implemented in Deno, but the logic for those
-// parts still exists. This means you will observe a lot of strange structures
-// and impossible logic branches based on what Deno currently supports.
-"use strict";
-
-((window) => {
- const webidl = window.__bootstrap.webidl;
- const { DOMException } = window.__bootstrap.domException;
- const consoleInternal = window.__bootstrap.console;
- const {
- ArrayPrototypeFilter,
- ArrayPrototypeIncludes,
- ArrayPrototypeIndexOf,
- ArrayPrototypeMap,
- ArrayPrototypePush,
- ArrayPrototypeSlice,
- ArrayPrototypeSplice,
- ArrayPrototypeUnshift,
- Boolean,
- DateNow,
- Error,
- FunctionPrototypeCall,
- Map,
- MapPrototypeGet,
- MapPrototypeSet,
- ObjectCreate,
- ObjectDefineProperty,
- ObjectGetOwnPropertyDescriptor,
- ReflectDefineProperty,
- Symbol,
- SymbolFor,
- SymbolToStringTag,
- TypeError,
- WeakMap,
- WeakMapPrototypeGet,
- WeakMapPrototypeSet,
- } = window.__bootstrap.primordials;
-
- // accessors for non runtime visible data
-
- function getDispatched(event) {
- return Boolean(event[_dispatched]);
- }
-
- function getPath(event) {
- return event[_path] ?? [];
- }
-
- function getStopImmediatePropagation(event) {
- return Boolean(event[_stopImmediatePropagationFlag]);
- }
-
- function setCurrentTarget(
- event,
- value,
- ) {
- event[_attributes].currentTarget = value;
- }
-
- function setIsTrusted(event, value) {
- event[_isTrusted] = value;
- }
-
- function setDispatched(event, value) {
- event[_dispatched] = value;
- }
-
- function setEventPhase(event, value) {
- event[_attributes].eventPhase = value;
- }
-
- function setInPassiveListener(event, value) {
- event[_inPassiveListener] = value;
- }
-
- function setPath(event, value) {
- event[_path] = value;
- }
-
- function setRelatedTarget(
- event,
- value,
- ) {
- event[_attributes].relatedTarget = value;
- }
-
- function setTarget(event, value) {
- event[_attributes].target = value;
- }
-
- function setStopImmediatePropagation(
- event,
- value,
- ) {
- event[_stopImmediatePropagationFlag] = value;
- }
-
- // Type guards that widen the event type
-
- function hasRelatedTarget(
- event,
- ) {
- return "relatedTarget" in event;
- }
-
- const isTrusted = ObjectGetOwnPropertyDescriptor({
- get isTrusted() {
- return this[_isTrusted];
- },
- }, "isTrusted").get;
-
- const eventInitConverter = webidl.createDictionaryConverter("EventInit", [{
- key: "bubbles",
- defaultValue: false,
- converter: webidl.converters.boolean,
- }, {
- key: "cancelable",
- defaultValue: false,
- converter: webidl.converters.boolean,
- }, {
- key: "composed",
- defaultValue: false,
- converter: webidl.converters.boolean,
- }]);
-
- const _attributes = Symbol("[[attributes]]");
- const _canceledFlag = Symbol("[[canceledFlag]]");
- const _stopPropagationFlag = Symbol("[[stopPropagationFlag]]");
- const _stopImmediatePropagationFlag = Symbol(
- "[[stopImmediatePropagationFlag]]",
- );
- const _inPassiveListener = Symbol("[[inPassiveListener]]");
- const _dispatched = Symbol("[[dispatched]]");
- const _isTrusted = Symbol("[[isTrusted]]");
- const _path = Symbol("[[path]]");
-
- class Event {
- [_attributes] = {};
- [_canceledFlag] = false;
- [_stopPropagationFlag] = false;
- [_stopImmediatePropagationFlag] = false;
- [_inPassiveListener] = false;
- [_dispatched] = false;
- [_isTrusted] = false;
- [_path] = [];
-
- constructor(type, eventInitDict = {}) {
- webidl.requiredArguments(arguments.length, 1, {
- prefix: "Failed to construct 'Event'",
- });
- type = webidl.converters.DOMString(type, {
- prefix: "Failed to construct 'Event'",
- context: "Argument 1",
- });
- const eventInit = eventInitConverter(eventInitDict, {
- prefix: "Failed to construct 'Event'",
- context: "Argument 2",
- });
- this[_attributes] = {
- type,
- ...eventInit,
- currentTarget: null,
- eventPhase: Event.NONE,
- target: null,
- timeStamp: DateNow(),
- };
- ReflectDefineProperty(this, "isTrusted", {
- enumerable: true,
- get: isTrusted,
- });
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof Event,
- keys: EVENT_PROPS,
- }));
- }
-
- get type() {
- return this[_attributes].type;
- }
-
- get target() {
- return this[_attributes].target;
- }
-
- get srcElement() {
- return null;
- }
-
- set srcElement(_) {
- // this member is deprecated
- }
-
- get currentTarget() {
- return this[_attributes].currentTarget;
- }
-
- composedPath() {
- const path = this[_path];
- if (path.length === 0) {
- return [];
- }
-
- if (!this.currentTarget) {
- throw new Error("assertion error");
- }
- const composedPath = [
- {
- item: this.currentTarget,
- itemInShadowTree: false,
- relatedTarget: null,
- rootOfClosedTree: false,
- slotInClosedTree: false,
- target: null,
- touchTargetList: [],
- },
- ];
-
- let currentTargetIndex = 0;
- let currentTargetHiddenSubtreeLevel = 0;
-
- for (let index = path.length - 1; index >= 0; index--) {
- const { item, rootOfClosedTree, slotInClosedTree } = path[index];
-
- if (rootOfClosedTree) {
- currentTargetHiddenSubtreeLevel++;
- }
-
- if (item === this.currentTarget) {
- currentTargetIndex = index;
- break;
- }
-
- if (slotInClosedTree) {
- currentTargetHiddenSubtreeLevel--;
- }
- }
-
- let currentHiddenLevel = currentTargetHiddenSubtreeLevel;
- let maxHiddenLevel = currentTargetHiddenSubtreeLevel;
-
- for (let i = currentTargetIndex - 1; i >= 0; i--) {
- const { item, rootOfClosedTree, slotInClosedTree } = path[i];
-
- if (rootOfClosedTree) {
- currentHiddenLevel++;
- }
-
- if (currentHiddenLevel <= maxHiddenLevel) {
- ArrayPrototypeUnshift(composedPath, {
- item,
- itemInShadowTree: false,
- relatedTarget: null,
- rootOfClosedTree: false,
- slotInClosedTree: false,
- target: null,
- touchTargetList: [],
- });
- }
-
- if (slotInClosedTree) {
- currentHiddenLevel--;
-
- if (currentHiddenLevel < maxHiddenLevel) {
- maxHiddenLevel = currentHiddenLevel;
- }
- }
- }
-
- currentHiddenLevel = currentTargetHiddenSubtreeLevel;
- maxHiddenLevel = currentTargetHiddenSubtreeLevel;
-
- for (let index = currentTargetIndex + 1; index < path.length; index++) {
- const { item, rootOfClosedTree, slotInClosedTree } = path[index];
-
- if (slotInClosedTree) {
- currentHiddenLevel++;
- }
-
- if (currentHiddenLevel <= maxHiddenLevel) {
- ArrayPrototypePush(composedPath, {
- item,
- itemInShadowTree: false,
- relatedTarget: null,
- rootOfClosedTree: false,
- slotInClosedTree: false,
- target: null,
- touchTargetList: [],
- });
- }
-
- if (rootOfClosedTree) {
- currentHiddenLevel--;
-
- if (currentHiddenLevel < maxHiddenLevel) {
- maxHiddenLevel = currentHiddenLevel;
- }
- }
- }
- return ArrayPrototypeMap(composedPath, (p) => p.item);
- }
-
- get NONE() {
- return Event.NONE;
- }
-
- get CAPTURING_PHASE() {
- return Event.CAPTURING_PHASE;
- }
-
- get AT_TARGET() {
- return Event.AT_TARGET;
- }
-
- get BUBBLING_PHASE() {
- return Event.BUBBLING_PHASE;
- }
-
- static get NONE() {
- return 0;
- }
-
- static get CAPTURING_PHASE() {
- return 1;
- }
-
- static get AT_TARGET() {
- return 2;
- }
-
- static get BUBBLING_PHASE() {
- return 3;
- }
-
- get eventPhase() {
- return this[_attributes].eventPhase;
- }
-
- stopPropagation() {
- this[_stopPropagationFlag] = true;
- }
-
- get cancelBubble() {
- return this[_stopPropagationFlag];
- }
-
- set cancelBubble(value) {
- this[_stopPropagationFlag] = webidl.converters.boolean(value);
- }
-
- stopImmediatePropagation() {
- this[_stopPropagationFlag] = true;
- this[_stopImmediatePropagationFlag] = true;
- }
-
- get bubbles() {
- return this[_attributes].bubbles;
- }
-
- get cancelable() {
- return this[_attributes].cancelable;
- }
-
- get returnValue() {
- return !this[_canceledFlag];
- }
-
- set returnValue(value) {
- if (!webidl.converters.boolean(value)) {
- this[_canceledFlag] = true;
- }
- }
-
- preventDefault() {
- if (this[_attributes].cancelable && !this[_inPassiveListener]) {
- this[_canceledFlag] = true;
- }
- }
-
- get defaultPrevented() {
- return this[_canceledFlag];
- }
-
- get composed() {
- return this[_attributes].composed;
- }
-
- get initialized() {
- return true;
- }
-
- get timeStamp() {
- return this[_attributes].timeStamp;
- }
- }
-
- function defineEnumerableProps(
- Ctor,
- props,
- ) {
- for (const prop of props) {
- ReflectDefineProperty(Ctor.prototype, prop, { enumerable: true });
- }
- }
-
- const EVENT_PROPS = [
- "bubbles",
- "cancelable",
- "composed",
- "currentTarget",
- "defaultPrevented",
- "eventPhase",
- "srcElement",
- "target",
- "returnValue",
- "timeStamp",
- "type",
- ];
-
- defineEnumerableProps(Event, EVENT_PROPS);
-
- // This is currently the only node type we are using, so instead of implementing
- // the whole of the Node interface at the moment, this just gives us the one
- // value to power the standards based logic
- const DOCUMENT_FRAGMENT_NODE = 11;
-
- // DOM Logic Helper functions and type guards
-
- /** Get the parent node, for event targets that have a parent.
- *
- * Ref: https://dom.spec.whatwg.org/#get-the-parent */
- function getParent(eventTarget) {
- return isNode(eventTarget) ? eventTarget.parentNode : null;
- }
-
- function getRoot(eventTarget) {
- return isNode(eventTarget)
- ? eventTarget.getRootNode({ composed: true })
- : null;
- }
-
- function isNode(
- eventTarget,
- ) {
- return Boolean(eventTarget && "nodeType" in eventTarget);
- }
-
- // https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor
- function isShadowInclusiveAncestor(
- ancestor,
- node,
- ) {
- while (isNode(node)) {
- if (node === ancestor) {
- return true;
- }
-
- if (isShadowRoot(node)) {
- node = node && getHost(node);
- } else {
- node = getParent(node);
- }
- }
-
- return false;
- }
-
- function isShadowRoot(nodeImpl) {
- return Boolean(
- nodeImpl &&
- isNode(nodeImpl) &&
- nodeImpl.nodeType === DOCUMENT_FRAGMENT_NODE &&
- getHost(nodeImpl) != null,
- );
- }
-
- function isSlotable(
- nodeImpl,
- ) {
- return Boolean(isNode(nodeImpl) && "assignedSlot" in nodeImpl);
- }
-
- // DOM Logic functions
-
- /** Append a path item to an event's path.
- *
- * Ref: https://dom.spec.whatwg.org/#concept-event-path-append
- */
- function appendToEventPath(
- eventImpl,
- target,
- targetOverride,
- relatedTarget,
- touchTargets,
- slotInClosedTree,
- ) {
- const itemInShadowTree = isNode(target) && isShadowRoot(getRoot(target));
- const rootOfClosedTree = isShadowRoot(target) &&
- getMode(target) === "closed";
-
- ArrayPrototypePush(getPath(eventImpl), {
- item: target,
- itemInShadowTree,
- target: targetOverride,
- relatedTarget,
- touchTargetList: touchTargets,
- rootOfClosedTree,
- slotInClosedTree,
- });
- }
-
- function dispatch(
- targetImpl,
- eventImpl,
- targetOverride,
- ) {
- let clearTargets = false;
- let activationTarget = null;
-
- setDispatched(eventImpl, true);
-
- targetOverride = targetOverride ?? targetImpl;
- const eventRelatedTarget = hasRelatedTarget(eventImpl)
- ? eventImpl.relatedTarget
- : null;
- let relatedTarget = retarget(eventRelatedTarget, targetImpl);
-
- if (targetImpl !== relatedTarget || targetImpl === eventRelatedTarget) {
- const touchTargets = [];
-
- appendToEventPath(
- eventImpl,
- targetImpl,
- targetOverride,
- relatedTarget,
- touchTargets,
- false,
- );
-
- const isActivationEvent = eventImpl.type === "click";
-
- if (isActivationEvent && getHasActivationBehavior(targetImpl)) {
- activationTarget = targetImpl;
- }
-
- let slotInClosedTree = false;
- let slotable = isSlotable(targetImpl) && getAssignedSlot(targetImpl)
- ? targetImpl
- : null;
- let parent = getParent(targetImpl);
-
- // Populate event path
- // https://dom.spec.whatwg.org/#event-path
- while (parent !== null) {
- if (slotable !== null) {
- slotable = null;
-
- const parentRoot = getRoot(parent);
- if (
- isShadowRoot(parentRoot) &&
- parentRoot &&
- getMode(parentRoot) === "closed"
- ) {
- slotInClosedTree = true;
- }
- }
-
- relatedTarget = retarget(eventRelatedTarget, parent);
-
- if (
- isNode(parent) &&
- isShadowInclusiveAncestor(getRoot(targetImpl), parent)
- ) {
- appendToEventPath(
- eventImpl,
- parent,
- null,
- relatedTarget,
- touchTargets,
- slotInClosedTree,
- );
- } else if (parent === relatedTarget) {
- parent = null;
- } else {
- targetImpl = parent;
-
- if (
- isActivationEvent &&
- activationTarget === null &&
- getHasActivationBehavior(targetImpl)
- ) {
- activationTarget = targetImpl;
- }
-
- appendToEventPath(
- eventImpl,
- parent,
- targetImpl,
- relatedTarget,
- touchTargets,
- slotInClosedTree,
- );
- }
-
- if (parent !== null) {
- parent = getParent(parent);
- }
-
- slotInClosedTree = false;
- }
-
- let clearTargetsTupleIndex = -1;
- const path = getPath(eventImpl);
- for (
- let i = path.length - 1;
- i >= 0 && clearTargetsTupleIndex === -1;
- i--
- ) {
- if (path[i].target !== null) {
- clearTargetsTupleIndex = i;
- }
- }
- const clearTargetsTuple = path[clearTargetsTupleIndex];
-
- clearTargets = (isNode(clearTargetsTuple.target) &&
- isShadowRoot(getRoot(clearTargetsTuple.target))) ||
- (isNode(clearTargetsTuple.relatedTarget) &&
- isShadowRoot(getRoot(clearTargetsTuple.relatedTarget)));
-
- setEventPhase(eventImpl, Event.CAPTURING_PHASE);
-
- for (let i = path.length - 1; i >= 0; --i) {
- const tuple = path[i];
-
- if (tuple.target === null) {
- invokeEventListeners(tuple, eventImpl);
- }
- }
-
- for (let i = 0; i < path.length; i++) {
- const tuple = path[i];
-
- if (tuple.target !== null) {
- setEventPhase(eventImpl, Event.AT_TARGET);
- } else {
- setEventPhase(eventImpl, Event.BUBBLING_PHASE);
- }
-
- if (
- (eventImpl.eventPhase === Event.BUBBLING_PHASE &&
- eventImpl.bubbles) ||
- eventImpl.eventPhase === Event.AT_TARGET
- ) {
- invokeEventListeners(tuple, eventImpl);
- }
- }
- }
-
- setEventPhase(eventImpl, Event.NONE);
- setCurrentTarget(eventImpl, null);
- setPath(eventImpl, []);
- setDispatched(eventImpl, false);
- eventImpl.cancelBubble = false;
- setStopImmediatePropagation(eventImpl, false);
-
- if (clearTargets) {
- setTarget(eventImpl, null);
- setRelatedTarget(eventImpl, null);
- }
-
- // TODO(bartlomieju): invoke activation targets if HTML nodes will be implemented
- // if (activationTarget !== null) {
- // if (!eventImpl.defaultPrevented) {
- // activationTarget._activationBehavior();
- // }
- // }
-
- return !eventImpl.defaultPrevented;
- }
-
- /** Inner invoking of the event listeners where the resolved listeners are
- * called.
- *
- * Ref: https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke */
- function innerInvokeEventListeners(
- eventImpl,
- targetListeners,
- ) {
- let found = false;
-
- const { type } = eventImpl;
-
- if (!targetListeners || !targetListeners[type]) {
- return found;
- }
-
- // Copy event listeners before iterating since the list can be modified during the iteration.
- const handlers = ArrayPrototypeSlice(targetListeners[type]);
-
- for (let i = 0; i < handlers.length; i++) {
- const listener = handlers[i];
-
- let capture, once, passive;
- if (typeof listener.options === "boolean") {
- capture = listener.options;
- once = false;
- passive = false;
- } else {
- capture = listener.options.capture;
- once = listener.options.once;
- passive = listener.options.passive;
- }
-
- // Check if the event listener has been removed since the listeners has been cloned.
- if (!ArrayPrototypeIncludes(targetListeners[type], listener)) {
- continue;
- }
-
- found = true;
-
- if (
- (eventImpl.eventPhase === Event.CAPTURING_PHASE && !capture) ||
- (eventImpl.eventPhase === Event.BUBBLING_PHASE && capture)
- ) {
- continue;
- }
-
- if (once) {
- ArrayPrototypeSplice(
- targetListeners[type],
- ArrayPrototypeIndexOf(targetListeners[type], listener),
- 1,
- );
- }
-
- if (passive) {
- setInPassiveListener(eventImpl, true);
- }
-
- if (typeof listener.callback === "object") {
- if (typeof listener.callback.handleEvent === "function") {
- listener.callback.handleEvent(eventImpl);
- }
- } else {
- FunctionPrototypeCall(
- listener.callback,
- eventImpl.currentTarget,
- eventImpl,
- );
- }
-
- setInPassiveListener(eventImpl, false);
-
- if (getStopImmediatePropagation(eventImpl)) {
- return found;
- }
- }
-
- return found;
- }
-
- /** Invokes the listeners on a given event path with the supplied event.
- *
- * Ref: https://dom.spec.whatwg.org/#concept-event-listener-invoke */
- function invokeEventListeners(tuple, eventImpl) {
- const path = getPath(eventImpl);
- const tupleIndex = ArrayPrototypeIndexOf(path, tuple);
- for (let i = tupleIndex; i >= 0; i--) {
- const t = path[i];
- if (t.target) {
- setTarget(eventImpl, t.target);
- break;
- }
- }
-
- setRelatedTarget(eventImpl, tuple.relatedTarget);
-
- if (eventImpl.cancelBubble) {
- return;
- }
-
- setCurrentTarget(eventImpl, tuple.item);
-
- innerInvokeEventListeners(eventImpl, getListeners(tuple.item));
- }
-
- function normalizeAddEventHandlerOptions(
- options,
- ) {
- if (typeof options === "boolean" || typeof options === "undefined") {
- return {
- capture: Boolean(options),
- once: false,
- passive: false,
- };
- } else {
- return options;
- }
- }
-
- function normalizeEventHandlerOptions(
- options,
- ) {
- if (typeof options === "boolean" || typeof options === "undefined") {
- return {
- capture: Boolean(options),
- };
- } else {
- return options;
- }
- }
-
- /** Retarget the target following the spec logic.
- *
- * Ref: https://dom.spec.whatwg.org/#retarget */
- function retarget(a, b) {
- while (true) {
- if (!isNode(a)) {
- return a;
- }
-
- const aRoot = a.getRootNode();
-
- if (aRoot) {
- if (
- !isShadowRoot(aRoot) ||
- (isNode(b) && isShadowInclusiveAncestor(aRoot, b))
- ) {
- return a;
- }
-
- a = getHost(aRoot);
- }
- }
- }
-
- // Accessors for non-public data
-
- const eventTargetData = new WeakMap();
-
- function setEventTargetData(value) {
- WeakMapPrototypeSet(eventTargetData, value, getDefaultTargetData());
- }
-
- function getAssignedSlot(target) {
- return Boolean(WeakMapPrototypeGet(eventTargetData, target)?.assignedSlot);
- }
-
- function getHasActivationBehavior(target) {
- return Boolean(
- WeakMapPrototypeGet(eventTargetData, target)?.hasActivationBehavior,
- );
- }
-
- function getHost(target) {
- return WeakMapPrototypeGet(eventTargetData, target)?.host ?? null;
- }
-
- function getListeners(target) {
- return WeakMapPrototypeGet(eventTargetData, target)?.listeners ?? {};
- }
-
- function getMode(target) {
- return WeakMapPrototypeGet(eventTargetData, target)?.mode ?? null;
- }
-
- function getDefaultTargetData() {
- return {
- assignedSlot: false,
- hasActivationBehavior: false,
- host: null,
- listeners: ObjectCreate(null),
- mode: "",
- };
- }
-
- class EventTarget {
- constructor() {
- WeakMapPrototypeSet(eventTargetData, this, getDefaultTargetData());
- }
-
- addEventListener(
- type,
- callback,
- options,
- ) {
- webidl.requiredArguments(arguments.length, 2, {
- prefix: "Failed to execute 'addEventListener' on 'EventTarget'",
- });
- if (callback === null) {
- return;
- }
-
- options = normalizeAddEventHandlerOptions(options);
- const { listeners } = WeakMapPrototypeGet(
- eventTargetData,
- this ?? globalThis,
- );
-
- if (!(type in listeners)) {
- listeners[type] = [];
- }
-
- for (const listener of listeners[type]) {
- if (
- ((typeof listener.options === "boolean" &&
- listener.options === options.capture) ||
- (typeof listener.options === "object" &&
- listener.options.capture === options.capture)) &&
- listener.callback === callback
- ) {
- return;
- }
- }
- if (options?.signal) {
- const signal = options?.signal;
- if (signal.aborted) {
- // If signal is not null and its aborted flag is set, then return.
- return;
- } else {
- // If listener’s signal is not null, then add the following abort
- // abort steps to it: Remove an event listener.
- signal.addEventListener("abort", () => {
- this.removeEventListener(type, callback, options);
- });
- }
- } else if (options?.signal === null) {
- throw new TypeError("signal must be non-null");
- }
-
- ArrayPrototypePush(listeners[type], { callback, options });
- }
-
- removeEventListener(
- type,
- callback,
- options,
- ) {
- webidl.requiredArguments(arguments.length, 2, {
- prefix: "Failed to execute 'removeEventListener' on 'EventTarget'",
- });
-
- const listeners =
- WeakMapPrototypeGet(eventTargetData, this ?? globalThis).listeners;
- if (callback !== null && type in listeners) {
- listeners[type] = ArrayPrototypeFilter(
- listeners[type],
- (listener) => listener.callback !== callback,
- );
- } else if (callback === null || !listeners[type]) {
- return;
- }
-
- options = normalizeEventHandlerOptions(options);
-
- for (let i = 0; i < listeners[type].length; ++i) {
- const listener = listeners[type][i];
- if (
- ((typeof listener.options === "boolean" &&
- listener.options === options.capture) ||
- (typeof listener.options === "object" &&
- listener.options.capture === options.capture)) &&
- listener.callback === callback
- ) {
- ArrayPrototypeSplice(listeners[type], i, 1);
- break;
- }
- }
- }
-
- dispatchEvent(event) {
- webidl.requiredArguments(arguments.length, 1, {
- prefix: "Failed to execute 'dispatchEvent' on 'EventTarget'",
- });
- const self = this ?? globalThis;
-
- const listeners = WeakMapPrototypeGet(eventTargetData, self).listeners;
- if (!(event.type in listeners)) {
- setTarget(event, this);
- return true;
- }
-
- if (getDispatched(event)) {
- throw new DOMException("Invalid event state.", "InvalidStateError");
- }
-
- if (event.eventPhase !== Event.NONE) {
- throw new DOMException("Invalid event state.", "InvalidStateError");
- }
-
- return dispatch(self, event);
- }
-
- get [SymbolToStringTag]() {
- return "EventTarget";
- }
-
- getParent(_event) {
- return null;
- }
- }
-
- defineEnumerableProps(EventTarget, [
- "addEventListener",
- "removeEventListener",
- "dispatchEvent",
- ]);
-
- class ErrorEvent extends Event {
- #message = "";
- #filename = "";
- #lineno = "";
- #colno = "";
- #error = "";
-
- get message() {
- return this.#message;
- }
- get filename() {
- return this.#filename;
- }
- get lineno() {
- return this.#lineno;
- }
- get colno() {
- return this.#colno;
- }
- get error() {
- return this.#error;
- }
-
- constructor(
- type,
- {
- bubbles,
- cancelable,
- composed,
- message = "",
- filename = "",
- lineno = 0,
- colno = 0,
- error = null,
- } = {},
- ) {
- super(type, {
- bubbles: bubbles,
- cancelable: cancelable,
- composed: composed,
- });
-
- this.#message = message;
- this.#filename = filename;
- this.#lineno = lineno;
- this.#colno = colno;
- this.#error = error;
- }
-
- get [SymbolToStringTag]() {
- return "ErrorEvent";
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof ErrorEvent,
- keys: [
- ...EVENT_PROPS,
- "message",
- "filename",
- "lineno",
- "colno",
- "error",
- ],
- }));
- }
- }
-
- defineEnumerableProps(ErrorEvent, [
- "message",
- "filename",
- "lineno",
- "colno",
- "error",
- ]);
-
- class CloseEvent extends Event {
- #wasClean = "";
- #code = "";
- #reason = "";
-
- get wasClean() {
- return this.#wasClean;
- }
- get code() {
- return this.#code;
- }
- get reason() {
- return this.#reason;
- }
-
- constructor(type, {
- bubbles,
- cancelable,
- composed,
- wasClean = false,
- code = 0,
- reason = "",
- } = {}) {
- super(type, {
- bubbles: bubbles,
- cancelable: cancelable,
- composed: composed,
- });
-
- this.#wasClean = wasClean;
- this.#code = code;
- this.#reason = reason;
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof CloseEvent,
- keys: [
- ...EVENT_PROPS,
- "wasClean",
- "code",
- "reason",
- ],
- }));
- }
- }
-
- class MessageEvent extends Event {
- get source() {
- return null;
- }
-
- constructor(type, eventInitDict) {
- super(type, {
- bubbles: eventInitDict?.bubbles ?? false,
- cancelable: eventInitDict?.cancelable ?? false,
- composed: eventInitDict?.composed ?? false,
- });
-
- this.data = eventInitDict?.data ?? null;
- this.ports = eventInitDict?.ports ?? [];
- this.origin = eventInitDict?.origin ?? "";
- this.lastEventId = eventInitDict?.lastEventId ?? "";
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof MessageEvent,
- keys: [
- ...EVENT_PROPS,
- "data",
- "origin",
- "lastEventId",
- ],
- }));
- }
- }
-
- class CustomEvent extends Event {
- #detail = null;
-
- constructor(type, eventInitDict = {}) {
- super(type, eventInitDict);
- webidl.requiredArguments(arguments.length, 1, {
- prefix: "Failed to construct 'CustomEvent'",
- });
- const { detail } = eventInitDict;
- this.#detail = detail;
- }
-
- get detail() {
- return this.#detail;
- }
-
- get [SymbolToStringTag]() {
- return "CustomEvent";
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof CustomEvent,
- keys: [
- ...EVENT_PROPS,
- "detail",
- ],
- }));
- }
- }
-
- ReflectDefineProperty(CustomEvent.prototype, "detail", {
- enumerable: true,
- });
-
- // ProgressEvent could also be used in other DOM progress event emits.
- // Current use is for FileReader.
- class ProgressEvent extends Event {
- constructor(type, eventInitDict = {}) {
- super(type, eventInitDict);
-
- this.lengthComputable = eventInitDict?.lengthComputable ?? false;
- this.loaded = eventInitDict?.loaded ?? 0;
- this.total = eventInitDict?.total ?? 0;
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof ProgressEvent,
- keys: [
- ...EVENT_PROPS,
- "lengthComputable",
- "loaded",
- "total",
- ],
- }));
- }
- }
-
- const _eventHandlers = Symbol("eventHandlers");
-
- function makeWrappedHandler(handler) {
- function wrappedHandler(...args) {
- if (typeof wrappedHandler.handler !== "function") {
- return;
- }
- return FunctionPrototypeCall(wrappedHandler.handler, this, ...args);
- }
- wrappedHandler.handler = handler;
- return wrappedHandler;
- }
-
- // TODO(benjamingr) reuse this here and websocket where possible
- function defineEventHandler(emitter, name, init) {
- // HTML specification section 8.1.5.1
- ObjectDefineProperty(emitter, `on${name}`, {
- get() {
- const map = this[_eventHandlers];
-
- if (!map) return undefined;
- return MapPrototypeGet(map, name)?.handler;
- },
- set(value) {
- if (!this[_eventHandlers]) {
- this[_eventHandlers] = new Map();
- }
- let handlerWrapper = MapPrototypeGet(this[_eventHandlers], name);
- if (handlerWrapper) {
- handlerWrapper.handler = value;
- } else {
- handlerWrapper = makeWrappedHandler(value);
- this.addEventListener(name, handlerWrapper);
- init?.(this);
- }
- MapPrototypeSet(this[_eventHandlers], name, handlerWrapper);
- },
- configurable: true,
- enumerable: true,
- });
- }
-
- window.Event = Event;
- window.EventTarget = EventTarget;
- window.ErrorEvent = ErrorEvent;
- window.CloseEvent = CloseEvent;
- window.MessageEvent = MessageEvent;
- window.CustomEvent = CustomEvent;
- window.ProgressEvent = ProgressEvent;
- window.dispatchEvent = EventTarget.prototype.dispatchEvent;
- window.addEventListener = EventTarget.prototype.addEventListener;
- window.removeEventListener = EventTarget.prototype.removeEventListener;
- window.__bootstrap.eventTarget = {
- EventTarget,
- setEventTargetData,
- };
- window.__bootstrap.event = {
- setIsTrusted,
- setTarget,
- defineEventHandler,
- };
-})(this);
diff --git a/extensions/web/02_structured_clone.js b/extensions/web/02_structured_clone.js
deleted file mode 100644
index 4845c6508..000000000
--- a/extensions/web/02_structured_clone.js
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../../core/internal.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-
-"use strict";
-
-((window) => {
- const core = window.Deno.core;
- const { DOMException } = window.__bootstrap.domException;
- const {
- ArrayBuffer,
- ArrayBufferIsView,
- DataView,
- TypedArrayPrototypeSlice,
- TypeError,
- WeakMap,
- WeakMapPrototypeSet,
- } = window.__bootstrap.primordials;
-
- const objectCloneMemo = new WeakMap();
-
- function cloneArrayBuffer(
- srcBuffer,
- srcByteOffset,
- srcLength,
- _cloneConstructor,
- ) {
- // this function fudges the return type but SharedArrayBuffer is disabled for a while anyway
- return TypedArrayPrototypeSlice(
- srcBuffer,
- srcByteOffset,
- srcByteOffset + srcLength,
- );
- }
-
- /** Clone a value in a similar way to structured cloning. It is similar to a
-* StructureDeserialize(StructuredSerialize(...)). */
- function structuredClone(value) {
- // Performance optimization for buffers, otherwise
- // `serialize/deserialize` will allocate new buffer.
- if (value instanceof ArrayBuffer) {
- const cloned = cloneArrayBuffer(
- value,
- 0,
- value.byteLength,
- ArrayBuffer,
- );
- WeakMapPrototypeSet(objectCloneMemo, value, cloned);
- return cloned;
- }
- if (ArrayBufferIsView(value)) {
- const clonedBuffer = structuredClone(value.buffer);
- // Use DataViewConstructor type purely for type-checking, can be a
- // DataView or TypedArray. They use the same constructor signature,
- // only DataView has a length in bytes and TypedArrays use a length in
- // terms of elements, so we adjust for that.
- let length;
- if (value instanceof DataView) {
- length = value.byteLength;
- } else {
- length = value.length;
- }
- return new (value.constructor)(
- clonedBuffer,
- value.byteOffset,
- length,
- );
- }
-
- try {
- return core.deserialize(core.serialize(value));
- } catch (e) {
- if (e instanceof TypeError) {
- throw new DOMException("Uncloneable value", "DataCloneError");
- }
- throw e;
- }
- }
-
- window.__bootstrap.structuredClone = structuredClone;
-})(globalThis);
diff --git a/extensions/web/03_abort_signal.js b/extensions/web/03_abort_signal.js
deleted file mode 100644
index d67bfef26..000000000
--- a/extensions/web/03_abort_signal.js
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-"use strict";
-
-// @ts-check
-/// <reference path="../../core/internal.d.ts" />
-
-((window) => {
- const webidl = window.__bootstrap.webidl;
- const { setIsTrusted, defineEventHandler } = window.__bootstrap.event;
- const {
- Boolean,
- Set,
- SetPrototypeAdd,
- SetPrototypeClear,
- SetPrototypeDelete,
- Symbol,
- SymbolToStringTag,
- TypeError,
- } = window.__bootstrap.primordials;
-
- const add = Symbol("add");
- const signalAbort = Symbol("signalAbort");
- const remove = Symbol("remove");
-
- const illegalConstructorKey = Symbol("illegalConstructorKey");
-
- class AbortSignal extends EventTarget {
- #aborted = false;
- #abortAlgorithms = new Set();
-
- static abort() {
- const signal = new AbortSignal(illegalConstructorKey);
- signal[signalAbort]();
- return signal;
- }
-
- [add](algorithm) {
- SetPrototypeAdd(this.#abortAlgorithms, algorithm);
- }
-
- [signalAbort]() {
- if (this.#aborted) {
- return;
- }
- this.#aborted = true;
- for (const algorithm of this.#abortAlgorithms) {
- algorithm();
- }
- SetPrototypeClear(this.#abortAlgorithms);
- const event = new Event("abort");
- setIsTrusted(event, true);
- this.dispatchEvent(event);
- }
-
- [remove](algorithm) {
- SetPrototypeDelete(this.#abortAlgorithms, algorithm);
- }
-
- constructor(key = null) {
- if (key != illegalConstructorKey) {
- throw new TypeError("Illegal constructor.");
- }
- super();
- this[webidl.brand] = webidl.brand;
- }
-
- get aborted() {
- return Boolean(this.#aborted);
- }
-
- get [SymbolToStringTag]() {
- return "AbortSignal";
- }
- }
- defineEventHandler(AbortSignal.prototype, "abort");
-
- webidl.configurePrototype(AbortSignal);
-
- class AbortController {
- #signal = new AbortSignal(illegalConstructorKey);
-
- get signal() {
- return this.#signal;
- }
-
- abort() {
- this.#signal[signalAbort]();
- }
-
- get [SymbolToStringTag]() {
- return "AbortController";
- }
- }
-
- webidl.configurePrototype(AbortController);
-
- webidl.converters["AbortSignal"] = webidl.createInterfaceConverter(
- "AbortSignal",
- AbortSignal,
- );
-
- function newSignal() {
- return new AbortSignal(illegalConstructorKey);
- }
-
- function follow(followingSignal, parentSignal) {
- if (parentSignal.aborted) {
- followingSignal[signalAbort]();
- } else {
- parentSignal[add](() => followingSignal[signalAbort]());
- }
- }
-
- window.AbortSignal = AbortSignal;
- window.AbortController = AbortController;
- window.__bootstrap.abortSignal = {
- add,
- signalAbort,
- remove,
- follow,
- newSignal,
- };
-})(this);
diff --git a/extensions/web/04_global_interfaces.js b/extensions/web/04_global_interfaces.js
deleted file mode 100644
index 8117bface..000000000
--- a/extensions/web/04_global_interfaces.js
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-"use strict";
-
-// @ts-check
-/// <reference path="../../core/internal.d.ts" />
-
-((window) => {
- const { EventTarget } = window;
- const {
- Symbol,
- SymbolToStringTag,
- TypeError,
- } = window.__bootstrap.primordials;
-
- const illegalConstructorKey = Symbol("illegalConstructorKey");
-
- class Window extends EventTarget {
- constructor(key = null) {
- if (key !== illegalConstructorKey) {
- throw new TypeError("Illegal constructor.");
- }
- super();
- }
-
- get [SymbolToStringTag]() {
- return "Window";
- }
- }
-
- class WorkerGlobalScope extends EventTarget {
- constructor(key = null) {
- if (key != illegalConstructorKey) {
- throw new TypeError("Illegal constructor.");
- }
- super();
- }
-
- get [SymbolToStringTag]() {
- return "WorkerGlobalScope";
- }
- }
-
- class DedicatedWorkerGlobalScope extends WorkerGlobalScope {
- constructor(key = null) {
- if (key != illegalConstructorKey) {
- throw new TypeError("Illegal constructor.");
- }
- super();
- }
-
- get [SymbolToStringTag]() {
- return "DedicatedWorkerGlobalScope";
- }
- }
-
- window.__bootstrap.globalInterfaces = {
- DedicatedWorkerGlobalScope,
- Window,
- WorkerGlobalScope,
- dedicatedWorkerGlobalScopeConstructorDescriptor: {
- configurable: true,
- enumerable: false,
- value: DedicatedWorkerGlobalScope,
- writable: true,
- },
- windowConstructorDescriptor: {
- configurable: true,
- enumerable: false,
- value: Window,
- writable: true,
- },
- workerGlobalScopeConstructorDescriptor: {
- configurable: true,
- enumerable: false,
- value: WorkerGlobalScope,
- writable: true,
- },
- };
-})(this);
diff --git a/extensions/web/05_base64.js b/extensions/web/05_base64.js
deleted file mode 100644
index 9c9c23b0f..000000000
--- a/extensions/web/05_base64.js
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference path="../../core/internal.d.ts" />
-/// <reference path="../webidl/internal.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference lib="esnext" />
-
-"use strict";
-
-((window) => {
- const webidl = window.__bootstrap.webidl;
- const {
- forgivingBase64Encode,
- forgivingBase64Decode,
- } = window.__bootstrap.infra;
- const { DOMException } = window.__bootstrap.domException;
- const {
- ArrayPrototypeMap,
- StringPrototypeCharCodeAt,
- ArrayPrototypeJoin,
- StringFromCharCode,
- TypedArrayFrom,
- Uint8Array,
- } = window.__bootstrap.primordials;
-
- /**
- * @param {string} data
- * @returns {string}
- */
- function atob(data) {
- data = webidl.converters.DOMString(data, {
- prefix: "Failed to execute 'atob'",
- context: "Argument 1",
- });
-
- const uint8Array = forgivingBase64Decode(data);
- const result = ArrayPrototypeMap(
- [...uint8Array],
- (byte) => StringFromCharCode(byte),
- );
- return ArrayPrototypeJoin(result, "");
- }
-
- /**
- * @param {string} data
- * @returns {string}
- */
- function btoa(data) {
- const prefix = "Failed to execute 'btoa'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- data = webidl.converters.DOMString(data, {
- prefix,
- context: "Argument 1",
- });
- const byteArray = ArrayPrototypeMap([...data], (char) => {
- const charCode = StringPrototypeCharCodeAt(char, 0);
- if (charCode > 0xff) {
- throw new DOMException(
- "The string to be encoded contains characters outside of the Latin1 range.",
- "InvalidCharacterError",
- );
- }
- return charCode;
- });
- return forgivingBase64Encode(TypedArrayFrom(Uint8Array, byteArray));
- }
-
- window.__bootstrap.base64 = {
- atob,
- btoa,
- };
-})(globalThis);
diff --git a/extensions/web/06_streams.js b/extensions/web/06_streams.js
deleted file mode 100644
index c4bfad0c8..000000000
--- a/extensions/web/06_streams.js
+++ /dev/null
@@ -1,4473 +0,0 @@
-// 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_web.d.ts" />
-/// <reference lib="esnext" />
-"use strict";
-
-((window) => {
- const webidl = window.__bootstrap.webidl;
- // TODO(lucacasonato): get AbortSignal from __bootstrap.
- const {
- ArrayPrototypeMap,
- ArrayPrototypePush,
- ArrayPrototypeShift,
- Error,
- NumberIsInteger,
- NumberIsNaN,
- ObjectCreate,
- ObjectDefineProperties,
- ObjectDefineProperty,
- ObjectGetPrototypeOf,
- ObjectSetPrototypeOf,
- Promise,
- PromiseAll,
- PromisePrototypeThen,
- PromiseReject,
- queueMicrotask,
- RangeError,
- Symbol,
- SymbolAsyncIterator,
- SymbolFor,
- SymbolToStringTag,
- TypeError,
- Uint8Array,
- WeakMap,
- WeakMapPrototypeGet,
- WeakMapPrototypeHas,
- WeakMapPrototypeSet,
- } = globalThis.__bootstrap.primordials;
- const consoleInternal = window.__bootstrap.console;
- const { DOMException } = window.__bootstrap.domException;
-
- class AssertionError extends Error {
- constructor(msg) {
- super(msg);
- this.name = "AssertionError";
- }
- }
-
- /**
- * @param {unknown} cond
- * @param {string=} msg
- * @returns {asserts cond}
- */
- function assert(cond, msg = "Assertion failed.") {
- if (!cond) {
- throw new AssertionError(msg);
- }
- }
-
- /** @template T */
- class Deferred {
- /** @type {Promise<T>} */
- #promise;
- /** @type {(reject?: any) => void} */
- #reject;
- /** @type {(value: T | PromiseLike<T>) => void} */
- #resolve;
- /** @type {"pending" | "fulfilled"} */
- #state = "pending";
-
- constructor() {
- this.#promise = new Promise((resolve, reject) => {
- this.#resolve = resolve;
- this.#reject = reject;
- });
- }
-
- /** @returns {Promise<T>} */
- get promise() {
- return this.#promise;
- }
-
- /** @returns {"pending" | "fulfilled"} */
- get state() {
- return this.#state;
- }
-
- /** @param {any=} reason */
- reject(reason) {
- // already settled promises are a no-op
- if (this.#state !== "pending") {
- return;
- }
- this.#state = "fulfilled";
- this.#reject(reason);
- }
-
- /** @param {T | PromiseLike<T>} value */
- resolve(value) {
- // already settled promises are a no-op
- if (this.#state !== "pending") {
- return;
- }
- this.#state = "fulfilled";
- this.#resolve(value);
- }
- }
-
- /**
- * @template T
- * @param {T | PromiseLike<T>} value
- * @returns {Promise<T>}
- */
- function resolvePromiseWith(value) {
- return new Promise((resolve) => resolve(value));
- }
-
- /** @param {any} e */
- function rethrowAssertionErrorRejection(e) {
- if (e && e instanceof AssertionError) {
- queueMicrotask(() => {
- console.error(`Internal Error: ${e.stack}`);
- });
- }
- }
-
- /** @param {Promise<any>} promise */
- function setPromiseIsHandledToTrue(promise) {
- PromisePrototypeThen(promise, undefined, rethrowAssertionErrorRejection);
- }
-
- /**
- * @template T
- * @template TResult1
- * @template TResult2
- * @param {Promise<T>} promise
- * @param {(value: T) => TResult1 | PromiseLike<TResult1>} fulfillmentHandler
- * @param {(reason: any) => TResult2 | PromiseLike<TResult2>=} rejectionHandler
- * @returns {Promise<TResult1 | TResult2>}
- */
- function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) {
- return PromisePrototypeThen(promise, fulfillmentHandler, rejectionHandler);
- }
-
- /**
- * @template T
- * @template TResult
- * @param {Promise<T>} promise
- * @param {(value: T) => TResult | PromiseLike<TResult>} onFulfilled
- * @returns {void}
- */
- function uponFulfillment(promise, onFulfilled) {
- uponPromise(promise, onFulfilled);
- }
-
- /**
- * @template T
- * @template TResult
- * @param {Promise<T>} promise
- * @param {(value: T) => TResult | PromiseLike<TResult>} onRejected
- * @returns {void}
- */
- function uponRejection(promise, onRejected) {
- uponPromise(promise, undefined, onRejected);
- }
-
- /**
- * @template T
- * @template TResult1
- * @template TResult2
- * @param {Promise<T>} promise
- * @param {(value: T) => TResult1 | PromiseLike<TResult1>} onFulfilled
- * @param {(reason: any) => TResult2 | PromiseLike<TResult2>=} onRejected
- * @returns {void}
- */
- function uponPromise(promise, onFulfilled, onRejected) {
- PromisePrototypeThen(
- PromisePrototypeThen(promise, onFulfilled, onRejected),
- undefined,
- rethrowAssertionErrorRejection,
- );
- }
-
- const isFakeDetached = Symbol("<<detached>>");
-
- /**
- * @param {ArrayBufferLike} O
- * @returns {boolean}
- */
- function isDetachedBuffer(O) {
- return isFakeDetached in O;
- }
-
- /**
- * @param {ArrayBufferLike} O
- * @returns {ArrayBufferLike}
- */
- function transferArrayBuffer(O) {
- assert(!isDetachedBuffer(O));
- const transferredIshVersion = O.slice(0);
- ObjectDefineProperty(O, "byteLength", {
- get() {
- return 0;
- },
- });
- O[isFakeDetached] = true;
- return transferredIshVersion;
- }
-
- const _abortAlgorithm = Symbol("[[abortAlgorithm]]");
- const _abortSteps = Symbol("[[AbortSteps]]");
- const _autoAllocateChunkSize = Symbol("[[autoAllocateChunkSize]]");
- const _backpressure = Symbol("[[backpressure]]");
- const _backpressureChangePromise = Symbol("[[backpressureChangePromise]]");
- const _byobRequest = Symbol("[[byobRequest]]");
- const _cancelAlgorithm = Symbol("[[cancelAlgorithm]]");
- const _cancelSteps = Symbol("[[CancelSteps]]");
- const _close = Symbol("close sentinel");
- const _closeAlgorithm = Symbol("[[closeAlgorithm]]");
- const _closedPromise = Symbol("[[closedPromise]]");
- const _closeRequest = Symbol("[[closeRequest]]");
- const _closeRequested = Symbol("[[closeRequested]]");
- const _controller = Symbol("[[controller]]");
- const _detached = Symbol("[[Detached]]");
- const _disturbed = Symbol("[[disturbed]]");
- 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]");
- const _preventCancel = Symbol("[[preventCancel]]");
- const _pullAgain = Symbol("[[pullAgain]]");
- const _pullAlgorithm = Symbol("[[pullAlgorithm]]");
- const _pulling = Symbol("[[pulling]]");
- const _pullSteps = Symbol("[[PullSteps]]");
- const _queue = Symbol("[[queue]]");
- const _queueTotalSize = Symbol("[[queueTotalSize]]");
- const _readable = Symbol("[[readable]]");
- const _reader = Symbol("[[reader]]");
- const _readRequests = Symbol("[[readRequests]]");
- const _readyPromise = Symbol("[[readyPromise]]");
- const _started = Symbol("[[started]]");
- const _state = Symbol("[[state]]");
- const _storedError = Symbol("[[storedError]]");
- const _strategyHWM = Symbol("[[strategyHWM]]");
- const _strategySizeAlgorithm = Symbol("[[strategySizeAlgorithm]]");
- const _stream = Symbol("[[stream]]");
- const _transformAlgorithm = Symbol("[[transformAlgorithm]]");
- const _writable = Symbol("[[writable]]");
- const _writeAlgorithm = Symbol("[[writeAlgorithm]]");
- const _writer = Symbol("[[writer]]");
- const _writeRequests = Symbol("[[writeRequests]]");
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @returns {ReadableStreamDefaultReader<R>}
- */
- function acquireReadableStreamDefaultReader(stream) {
- return new ReadableStreamDefaultReader(stream);
- }
-
- /**
- * @template W
- * @param {WritableStream<W>} stream
- * @returns {WritableStreamDefaultWriter<W>}
- */
- function acquireWritableStreamDefaultWriter(stream) {
- return new WritableStreamDefaultWriter(stream);
- }
-
- /**
- * @template R
- * @param {() => void} startAlgorithm
- * @param {() => Promise<void>} pullAlgorithm
- * @param {(reason: any) => Promise<void>} cancelAlgorithm
- * @param {number=} highWaterMark
- * @param {((chunk: R) => number)=} sizeAlgorithm
- * @returns {ReadableStream<R>}
- */
- function createReadableStream(
- startAlgorithm,
- pullAlgorithm,
- cancelAlgorithm,
- highWaterMark = 1,
- sizeAlgorithm = () => 1,
- ) {
- assert(isNonNegativeNumber(highWaterMark));
- /** @type {ReadableStream} */
- const stream = webidl.createBranded(ReadableStream);
- initializeReadableStream(stream);
- const controller = webidl.createBranded(ReadableStreamDefaultController);
- setUpReadableStreamDefaultController(
- stream,
- controller,
- startAlgorithm,
- pullAlgorithm,
- cancelAlgorithm,
- highWaterMark,
- sizeAlgorithm,
- );
- return stream;
- }
-
- /**
- * @template W
- * @param {(controller: WritableStreamDefaultController<W>) => Promise<void>} startAlgorithm
- * @param {(chunk: W) => Promise<void>} writeAlgorithm
- * @param {() => Promise<void>} closeAlgorithm
- * @param {(reason: any) => Promise<void>} abortAlgorithm
- * @param {number} highWaterMark
- * @param {(chunk: W) => number} sizeAlgorithm
- * @returns {WritableStream<W>}
- */
- function createWritableStream(
- startAlgorithm,
- writeAlgorithm,
- closeAlgorithm,
- abortAlgorithm,
- highWaterMark,
- sizeAlgorithm,
- ) {
- assert(isNonNegativeNumber(highWaterMark));
- const stream = webidl.createBranded(WritableStream);
- initializeWritableStream(stream);
- const controller = webidl.createBranded(WritableStreamDefaultController);
- setUpWritableStreamDefaultController(
- stream,
- controller,
- startAlgorithm,
- writeAlgorithm,
- closeAlgorithm,
- abortAlgorithm,
- highWaterMark,
- sizeAlgorithm,
- );
- return stream;
- }
-
- /**
- * @template T
- * @param {{ [_queue]: Array<ValueWithSize<T>>, [_queueTotalSize]: number }} container
- * @returns {T}
- */
- function dequeueValue(container) {
- assert(_queue in container && _queueTotalSize in container);
- assert(container[_queue].length);
- const valueWithSize = ArrayPrototypeShift(container[_queue]);
- container[_queueTotalSize] -= valueWithSize.size;
- if (container[_queueTotalSize] < 0) {
- container[_queueTotalSize] = 0;
- }
- return valueWithSize.value;
- }
-
- /**
- * @template T
- * @param {{ [_queue]: Array<ValueWithSize<T | _close>>, [_queueTotalSize]: number }} container
- * @param {T} value
- * @param {number} size
- * @returns {void}
- */
- function enqueueValueWithSize(container, value, size) {
- assert(_queue in container && _queueTotalSize in container);
- if (isNonNegativeNumber(size) === false) {
- throw RangeError("chunk size isn't a positive number");
- }
- if (size === Infinity) {
- throw RangeError("chunk size is invalid");
- }
- ArrayPrototypePush(container[_queue], { value, size });
- container[_queueTotalSize] += size;
- }
-
- /**
- * @param {QueuingStrategy} strategy
- * @param {number} defaultHWM
- */
- function extractHighWaterMark(strategy, defaultHWM) {
- if (strategy.highWaterMark === undefined) {
- return defaultHWM;
- }
- const highWaterMark = strategy.highWaterMark;
- if (NumberIsNaN(highWaterMark) || highWaterMark < 0) {
- throw RangeError(
- `Expected highWaterMark to be a positive number or Infinity, got "${highWaterMark}".`,
- );
- }
- return highWaterMark;
- }
-
- /**
- * @template T
- * @param {QueuingStrategy<T>} strategy
- * @return {(chunk: T) => number}
- */
- function extractSizeAlgorithm(strategy) {
- if (strategy.size === undefined) {
- return () => 1;
- }
- return (chunk) =>
- webidl.invokeCallbackFunction(
- strategy.size,
- [chunk],
- undefined,
- webidl.converters["unrestricted double"],
- { prefix: "Failed to call `sizeAlgorithm`" },
- );
- }
-
- /**
- * @param {ReadableStream} stream
- * @returns {void}
- */
- function initializeReadableStream(stream) {
- stream[_state] = "readable";
- stream[_reader] = stream[_storedError] = undefined;
- stream[_disturbed] = false;
- }
-
- /**
- * @template I
- * @template O
- * @param {TransformStream<I, O>} stream
- * @param {Deferred<void>} startPromise
- * @param {number} writableHighWaterMark
- * @param {(chunk: I) => number} writableSizeAlgorithm
- * @param {number} readableHighWaterMark
- * @param {(chunk: O) => number} readableSizeAlgorithm
- */
- function initializeTransformStream(
- stream,
- startPromise,
- writableHighWaterMark,
- writableSizeAlgorithm,
- readableHighWaterMark,
- readableSizeAlgorithm,
- ) {
- function startAlgorithm() {
- return startPromise.promise;
- }
-
- function writeAlgorithm(chunk) {
- return transformStreamDefaultSinkWriteAlgorithm(stream, chunk);
- }
-
- function abortAlgorithm(reason) {
- return transformStreamDefaultSinkAbortAlgorithm(stream, reason);
- }
-
- function closeAlgorithm() {
- return transformStreamDefaultSinkCloseAlgorithm(stream);
- }
-
- stream[_writable] = createWritableStream(
- startAlgorithm,
- writeAlgorithm,
- closeAlgorithm,
- abortAlgorithm,
- writableHighWaterMark,
- writableSizeAlgorithm,
- );
-
- function pullAlgorithm() {
- return transformStreamDefaultSourcePullAlgorithm(stream);
- }
-
- function cancelAlgorithm(reason) {
- transformStreamErrorWritableAndUnblockWrite(stream, reason);
- return resolvePromiseWith(undefined);
- }
-
- stream[_readable] = createReadableStream(
- startAlgorithm,
- pullAlgorithm,
- cancelAlgorithm,
- readableHighWaterMark,
- readableSizeAlgorithm,
- );
-
- stream[_backpressure] = stream[_backpressureChangePromise] = undefined;
- transformStreamSetBackpressure(stream, true);
- stream[_controller] = undefined;
- }
-
- /** @param {WritableStream} stream */
- function initializeWritableStream(stream) {
- stream[_state] = "writable";
- stream[_storedError] = stream[_writer] = stream[_controller] =
- stream[_inFlightWriteRequest] = stream[_closeRequest] =
- stream[_inFlightCloseRequest] = stream[_pendingAbortRequest] =
- undefined;
- stream[_writeRequests] = [];
- stream[_backpressure] = false;
- }
-
- /**
- * @param {unknown} v
- * @returns {v is number}
- */
- function isNonNegativeNumber(v) {
- if (typeof v !== "number") {
- return false;
- }
- if (NumberIsNaN(v)) {
- return false;
- }
- if (v < 0) {
- return false;
- }
- return true;
- }
-
- /**
- * @param {unknown} value
- * @returns {value is ReadableStream}
- */
- function isReadableStream(value) {
- return !(typeof value !== "object" || value === null ||
- !(_controller in value));
- }
-
- /**
- * @param {ReadableStream} stream
- * @returns {boolean}
- */
- function isReadableStreamLocked(stream) {
- if (stream[_reader] === undefined) {
- return false;
- }
- return true;
- }
-
- /**
- * @param {unknown} value
- * @returns {value is ReadableStreamDefaultReader}
- */
- function isReadableStreamDefaultReader(value) {
- return !(typeof value !== "object" || value === null ||
- !(_readRequests in value));
- }
-
- /**
- * @param {ReadableStream} stream
- * @returns {boolean}
- */
- function isReadableStreamDisturbed(stream) {
- assert(isReadableStream(stream));
- return stream[_disturbed];
- }
-
- /**
- * @param {unknown} value
- * @returns {value is WritableStream}
- */
- function isWritableStream(value) {
- return !(typeof value !== "object" || value === null ||
- !(_controller in value));
- }
-
- /**
- * @param {WritableStream} stream
- * @returns {boolean}
- */
- function isWritableStreamLocked(stream) {
- if (stream[_writer] === undefined) {
- return false;
- }
- return true;
- }
-
- /**
- * @template T
- * @param {{ [_queue]: Array<ValueWithSize<T | _close>>, [_queueTotalSize]: number }} container
- * @returns {T | _close}
- */
- function peekQueueValue(container) {
- assert(_queue in container && _queueTotalSize in container);
- assert(container[_queue].length);
- const valueWithSize = container[_queue][0];
- return valueWithSize.value;
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @returns {void}
- */
- function readableByteStreamControllerCallPullIfNeeded(controller) {
- const shouldPull = readableByteStreamControllerShouldCallPull(controller);
- if (!shouldPull) {
- return;
- }
- if (controller[_pulling]) {
- controller[_pullAgain] = true;
- return;
- }
- assert(controller[_pullAgain] === false);
- controller[_pulling] = true;
- /** @type {Promise<void>} */
- const pullPromise = controller[_pullAlgorithm](controller);
- setPromiseIsHandledToTrue(
- PromisePrototypeThen(
- pullPromise,
- () => {
- controller[_pulling] = false;
- if (controller[_pullAgain]) {
- controller[_pullAgain] = false;
- readableByteStreamControllerCallPullIfNeeded(controller);
- }
- },
- (e) => {
- readableByteStreamControllerError(controller, e);
- },
- ),
- );
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @returns {void}
- */
- function readableByteStreamControllerClearAlgorithms(controller) {
- controller[_pullAlgorithm] = undefined;
- controller[_cancelAlgorithm] = undefined;
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @param {any} e
- */
- function readableByteStreamControllerError(controller, e) {
- /** @type {ReadableStream<ArrayBuffer>} */
- const stream = controller[_stream];
- if (stream[_state] !== "readable") {
- return;
- }
- // 3. Perform ! ReadableByteStreamControllerClearPendingPullIntos(controller).
- resetQueue(controller);
- readableByteStreamControllerClearAlgorithms(controller);
- readableStreamError(stream, e);
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @returns {void}
- */
- function readableByteStreamControllerClose(controller) {
- /** @type {ReadableStream<ArrayBuffer>} */
- const stream = controller[_stream];
- if (controller[_closeRequested] || stream[_state] !== "readable") {
- return;
- }
- if (controller[_queueTotalSize] > 0) {
- controller[_closeRequested] = true;
- return;
- }
- // 3.13.6.4 If controller.[[pendingPullIntos]] is not empty, (BYOB Support)
- readableByteStreamControllerClearAlgorithms(controller);
- readableStreamClose(stream);
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @param {ArrayBufferView} chunk
- */
- function readableByteStreamControllerEnqueue(controller, chunk) {
- /** @type {ReadableStream<ArrayBuffer>} */
- const stream = controller[_stream];
- if (
- controller[_closeRequested] ||
- controller[_stream][_state] !== "readable"
- ) {
- return;
- }
-
- const { buffer, byteOffset, byteLength } = chunk;
- const transferredBuffer = transferArrayBuffer(buffer);
- if (readableStreamHasDefaultReader(stream)) {
- if (readableStreamGetNumReadRequests(stream) === 0) {
- readableByteStreamControllerEnqueueChunkToQueue(
- controller,
- transferredBuffer,
- byteOffset,
- byteLength,
- );
- } else {
- assert(controller[_queue].length === 0);
- const transferredView = new Uint8Array(
- transferredBuffer,
- byteOffset,
- byteLength,
- );
- readableStreamFulfillReadRequest(stream, transferredView, false);
- }
- // 8 Otherwise, if ! ReadableStreamHasBYOBReader(stream) is true,
- } else {
- assert(isReadableStreamLocked(stream) === false);
- readableByteStreamControllerEnqueueChunkToQueue(
- controller,
- transferredBuffer,
- byteOffset,
- byteLength,
- );
- }
- readableByteStreamControllerCallPullIfNeeded(controller);
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @param {ArrayBufferLike} buffer
- * @param {number} byteOffset
- * @param {number} byteLength
- * @returns {void}
- */
- function readableByteStreamControllerEnqueueChunkToQueue(
- controller,
- buffer,
- byteOffset,
- byteLength,
- ) {
- ArrayPrototypePush(controller[_queue], { buffer, byteOffset, byteLength });
- controller[_queueTotalSize] += byteLength;
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @returns {number | null}
- */
- function readableByteStreamControllerGetDesiredSize(controller) {
- const state = controller[_stream][_state];
- if (state === "errored") {
- return null;
- }
- if (state === "closed") {
- return 0;
- }
- return controller[_strategyHWM] - controller[_queueTotalSize];
- }
-
- /**
- * @param {{ [_queue]: any[], [_queueTotalSize]: number }} container
- * @returns {void}
- */
- function resetQueue(container) {
- container[_queue] = [];
- container[_queueTotalSize] = 0;
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @returns {void}
- */
- function readableByteStreamControllerHandleQueueDrain(controller) {
- assert(controller[_stream][_state] === "readable");
- if (
- controller[_queueTotalSize] === 0 && controller[_closeRequested]
- ) {
- readableByteStreamControllerClearAlgorithms(controller);
- readableStreamClose(controller[_stream]);
- } else {
- readableByteStreamControllerCallPullIfNeeded(controller);
- }
- }
-
- /**
- * @param {ReadableByteStreamController} controller
- * @returns {boolean}
- */
- function readableByteStreamControllerShouldCallPull(controller) {
- /** @type {ReadableStream<ArrayBuffer>} */
- const stream = controller[_stream];
- if (
- stream[_state] !== "readable" ||
- controller[_closeRequested] ||
- !controller[_started]
- ) {
- return false;
- }
- if (
- readableStreamHasDefaultReader(stream) &&
- readableStreamGetNumReadRequests(stream) > 0
- ) {
- return true;
- }
- // 3.13.25.6 If ! ReadableStreamHasBYOBReader(stream) is true and !
- // ReadableStreamGetNumReadIntoRequests(stream) > 0, return true.
- const desiredSize = readableByteStreamControllerGetDesiredSize(controller);
- assert(desiredSize !== null);
- return desiredSize > 0;
- }
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @param {ReadRequest<R>} readRequest
- * @returns {void}
- */
- function readableStreamAddReadRequest(stream, readRequest) {
- assert(isReadableStreamDefaultReader(stream[_reader]));
- assert(stream[_state] === "readable");
- ArrayPrototypePush(stream[_reader][_readRequests], readRequest);
- }
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @param {any=} reason
- * @returns {Promise<void>}
- */
- function readableStreamCancel(stream, reason) {
- stream[_disturbed] = true;
- if (stream[_state] === "closed") {
- return resolvePromiseWith(undefined);
- }
- if (stream[_state] === "errored") {
- return PromiseReject(stream[_storedError]);
- }
- readableStreamClose(stream);
- /** @type {Promise<void>} */
- const sourceCancelPromise = stream[_controller][_cancelSteps](reason);
- return PromisePrototypeThen(sourceCancelPromise, () => undefined);
- }
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @returns {void}
- */
- function readableStreamClose(stream) {
- assert(stream[_state] === "readable");
- stream[_state] = "closed";
- /** @type {ReadableStreamDefaultReader<R> | undefined} */
- const reader = stream[_reader];
- if (!reader) {
- return;
- }
- if (isReadableStreamDefaultReader(reader)) {
- /** @type {Array<ReadRequest<R>>} */
- const readRequests = reader[_readRequests];
- for (const readRequest of readRequests) {
- readRequest.closeSteps();
- }
- reader[_readRequests] = [];
- }
- // This promise can be double resolved.
- // See: https://github.com/whatwg/streams/issues/1100
- reader[_closedPromise].resolve(undefined);
- }
-
- /** @param {ReadableStreamDefaultController<any>} controller */
- function readableStreamDefaultControllerCallPullIfNeeded(controller) {
- const shouldPull = readableStreamDefaultcontrollerShouldCallPull(
- controller,
- );
- if (shouldPull === false) {
- return;
- }
- if (controller[_pulling] === true) {
- controller[_pullAgain] = true;
- return;
- }
- assert(controller[_pullAgain] === false);
- controller[_pulling] = true;
- const pullPromise = controller[_pullAlgorithm](controller);
- uponFulfillment(pullPromise, () => {
- controller[_pulling] = false;
- if (controller[_pullAgain] === true) {
- controller[_pullAgain] = false;
- readableStreamDefaultControllerCallPullIfNeeded(controller);
- }
- });
- uponRejection(pullPromise, (e) => {
- readableStreamDefaultControllerError(controller, e);
- });
- }
-
- /**
- * @param {ReadableStreamDefaultController<any>} controller
- * @returns {boolean}
- */
- function readableStreamDefaultControllerCanCloseOrEnqueue(controller) {
- const state = controller[_stream][_state];
- if (controller[_closeRequested] === false && state === "readable") {
- return true;
- } else {
- return false;
- }
- }
-
- /** @param {ReadableStreamDefaultController<any>} controller */
- function readableStreamDefaultControllerClearAlgorithms(controller) {
- controller[_pullAlgorithm] = undefined;
- controller[_cancelAlgorithm] = undefined;
- controller[_strategySizeAlgorithm] = undefined;
- }
-
- /** @param {ReadableStreamDefaultController<any>} controller */
- function readableStreamDefaultControllerClose(controller) {
- if (
- readableStreamDefaultControllerCanCloseOrEnqueue(controller) === false
- ) {
- return;
- }
- const stream = controller[_stream];
- controller[_closeRequested] = true;
- if (controller[_queue].length === 0) {
- readableStreamDefaultControllerClearAlgorithms(controller);
- readableStreamClose(stream);
- }
- }
-
- /**
- * @template R
- * @param {ReadableStreamDefaultController<R>} controller
- * @param {R} chunk
- * @returns {void}
- */
- function readableStreamDefaultControllerEnqueue(controller, chunk) {
- if (
- readableStreamDefaultControllerCanCloseOrEnqueue(controller) === false
- ) {
- return;
- }
- const stream = controller[_stream];
- if (
- isReadableStreamLocked(stream) === true &&
- readableStreamGetNumReadRequests(stream) > 0
- ) {
- readableStreamFulfillReadRequest(stream, chunk, false);
- } else {
- let chunkSize;
- try {
- chunkSize = controller[_strategySizeAlgorithm](chunk);
- } catch (e) {
- readableStreamDefaultControllerError(controller, e);
- throw e;
- }
-
- try {
- enqueueValueWithSize(controller, chunk, chunkSize);
- } catch (e) {
- readableStreamDefaultControllerError(controller, e);
- throw e;
- }
- }
- readableStreamDefaultControllerCallPullIfNeeded(controller);
- }
-
- /**
- * @param {ReadableStreamDefaultController<any>} controller
- * @param {any} e
- */
- function readableStreamDefaultControllerError(controller, e) {
- const stream = controller[_stream];
- if (stream[_state] !== "readable") {
- return;
- }
- resetQueue(controller);
- readableStreamDefaultControllerClearAlgorithms(controller);
- readableStreamError(stream, e);
- }
-
- /**
- * @param {ReadableStreamDefaultController<any>} controller
- * @returns {number | null}
- */
- function readableStreamDefaultControllerGetDesiredSize(controller) {
- const state = controller[_stream][_state];
- if (state === "errored") {
- return null;
- }
- if (state === "closed") {
- return 0;
- }
- return controller[_strategyHWM] - controller[_queueTotalSize];
- }
-
- /** @param {ReadableStreamDefaultController} controller */
- function readableStreamDefaultcontrollerHasBackpressure(controller) {
- if (readableStreamDefaultcontrollerShouldCallPull(controller) === true) {
- return false;
- } else {
- return true;
- }
- }
-
- /**
- * @param {ReadableStreamDefaultController<any>} controller
- * @returns {boolean}
- */
- function readableStreamDefaultcontrollerShouldCallPull(controller) {
- const stream = controller[_stream];
- if (
- readableStreamDefaultControllerCanCloseOrEnqueue(controller) === false
- ) {
- return false;
- }
- if (controller[_started] === false) {
- return false;
- }
- if (
- isReadableStreamLocked(stream) &&
- readableStreamGetNumReadRequests(stream) > 0
- ) {
- return true;
- }
- const desiredSize = readableStreamDefaultControllerGetDesiredSize(
- controller,
- );
- assert(desiredSize !== null);
- if (desiredSize > 0) {
- return true;
- }
- return false;
- }
-
- /**
- * @template R
- * @param {ReadableStreamDefaultReader<R>} reader
- * @param {ReadRequest<R>} readRequest
- * @returns {void}
- */
- function readableStreamDefaultReaderRead(reader, readRequest) {
- const stream = reader[_stream];
- assert(stream);
- stream[_disturbed] = true;
- if (stream[_state] === "closed") {
- readRequest.closeSteps();
- } else if (stream[_state] === "errored") {
- readRequest.errorSteps(stream[_storedError]);
- } else {
- assert(stream[_state] === "readable");
- stream[_controller][_pullSteps](readRequest);
- }
- }
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @param {any} e
- */
- function readableStreamError(stream, e) {
- assert(stream[_state] === "readable");
- stream[_state] = "errored";
- stream[_storedError] = e;
- /** @type {ReadableStreamDefaultReader<R> | undefined} */
- const reader = stream[_reader];
- if (reader === undefined) {
- return;
- }
- /** @type {Deferred<void>} */
- const closedPromise = reader[_closedPromise];
- closedPromise.reject(e);
- setPromiseIsHandledToTrue(closedPromise.promise);
- if (isReadableStreamDefaultReader(reader)) {
- /** @type {Array<ReadRequest<R>>} */
- const readRequests = reader[_readRequests];
- for (const readRequest of readRequests) {
- readRequest.errorSteps(e);
- }
- reader[_readRequests] = [];
- }
- // 3.5.6.8 Otherwise, support BYOB Reader
- }
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @param {R} chunk
- * @param {boolean} done
- */
- function readableStreamFulfillReadRequest(stream, chunk, done) {
- assert(readableStreamHasDefaultReader(stream) === true);
- /** @type {ReadableStreamDefaultReader<R>} */
- const reader = stream[_reader];
- assert(reader[_readRequests].length);
- /** @type {ReadRequest<R>} */
- const readRequest = ArrayPrototypeShift(reader[_readRequests]);
- if (done) {
- readRequest.closeSteps();
- } else {
- readRequest.chunkSteps(chunk);
- }
- }
-
- /**
- * @param {ReadableStream} stream
- * @return {number}
- */
- function readableStreamGetNumReadRequests(stream) {
- assert(readableStreamHasDefaultReader(stream) === true);
- return stream[_reader][_readRequests].length;
- }
-
- /**
- * @param {ReadableStream} stream
- * @returns {boolean}
- */
- function readableStreamHasDefaultReader(stream) {
- const reader = stream[_reader];
- if (reader === undefined) {
- return false;
- }
- if (isReadableStreamDefaultReader(reader)) {
- return true;
- }
- return false;
- }
-
- /**
- * @template T
- * @param {ReadableStream<T>} source
- * @param {WritableStream<T>} dest
- * @param {boolean} preventClose
- * @param {boolean} preventAbort
- * @param {boolean} preventCancel
- * @param {AbortSignal=} signal
- * @returns {Promise<void>}
- */
- function readableStreamPipeTo(
- source,
- dest,
- preventClose,
- preventAbort,
- preventCancel,
- signal,
- ) {
- assert(isReadableStream(source));
- assert(isWritableStream(dest));
- assert(
- typeof preventClose === "boolean" && typeof preventAbort === "boolean" &&
- typeof preventCancel === "boolean",
- );
- assert(signal === undefined || signal instanceof AbortSignal);
- assert(!isReadableStreamLocked(source));
- assert(!isWritableStreamLocked(dest));
- const reader = acquireReadableStreamDefaultReader(source);
- const writer = acquireWritableStreamDefaultWriter(dest);
- source[_disturbed] = true;
- let shuttingDown = false;
- let currentWrite = resolvePromiseWith(undefined);
- /** @type {Deferred<void>} */
- const promise = new Deferred();
- /** @type {() => void} */
- let abortAlgorithm;
- if (signal) {
- abortAlgorithm = () => {
- const error = new DOMException("Aborted", "AbortError");
- /** @type {Array<() => Promise<void>>} */
- const actions = [];
- if (preventAbort === false) {
- ArrayPrototypePush(actions, () => {
- if (dest[_state] === "writable") {
- return writableStreamAbort(dest, error);
- } else {
- return resolvePromiseWith(undefined);
- }
- });
- }
- if (preventCancel === false) {
- ArrayPrototypePush(actions, () => {
- if (source[_state] === "readable") {
- return readableStreamCancel(source, error);
- } else {
- return resolvePromiseWith(undefined);
- }
- });
- }
- shutdownWithAction(
- () => PromiseAll(ArrayPrototypeMap(actions, (action) => action())),
- true,
- error,
- );
- };
-
- if (signal.aborted) {
- abortAlgorithm();
- return promise.promise;
- }
- // TODO(lucacasonato): use the internal API to listen for abort.
- signal.addEventListener("abort", abortAlgorithm);
- }
-
- function pipeLoop() {
- return new Promise((resolveLoop, rejectLoop) => {
- /** @param {boolean} done */
- function next(done) {
- if (done) {
- resolveLoop();
- } else {
- uponPromise(pipeStep(), next, rejectLoop);
- }
- }
- next(false);
- });
- }
-
- /** @returns {Promise<boolean>} */
- function pipeStep() {
- if (shuttingDown === true) {
- return resolvePromiseWith(true);
- }
-
- return transformPromiseWith(writer[_readyPromise].promise, () => {
- return new Promise((resolveRead, rejectRead) => {
- readableStreamDefaultReaderRead(
- reader,
- {
- chunkSteps(chunk) {
- currentWrite = transformPromiseWith(
- writableStreamDefaultWriterWrite(writer, chunk),
- undefined,
- () => {},
- );
- resolveRead(false);
- },
- closeSteps() {
- resolveRead(true);
- },
- errorSteps: rejectRead,
- },
- );
- });
- });
- }
-
- isOrBecomesErrored(
- source,
- reader[_closedPromise].promise,
- (storedError) => {
- if (preventAbort === false) {
- shutdownWithAction(
- () => writableStreamAbort(dest, storedError),
- true,
- storedError,
- );
- } else {
- shutdown(true, storedError);
- }
- },
- );
-
- isOrBecomesErrored(dest, writer[_closedPromise].promise, (storedError) => {
- if (preventCancel === false) {
- shutdownWithAction(
- () => readableStreamCancel(source, storedError),
- true,
- storedError,
- );
- } else {
- shutdown(true, storedError);
- }
- });
-
- isOrBecomesClosed(source, reader[_closedPromise].promise, () => {
- if (preventClose === false) {
- shutdownWithAction(() =>
- writableStreamDefaultWriterCloseWithErrorPropagation(writer)
- );
- } else {
- shutdown();
- }
- });
-
- if (
- writableStreamCloseQueuedOrInFlight(dest) === true ||
- dest[_state] === "closed"
- ) {
- const destClosed = new TypeError(
- "The destination writable stream closed before all the data could be piped to it.",
- );
- if (preventCancel === false) {
- shutdownWithAction(
- () => readableStreamCancel(source, destClosed),
- true,
- destClosed,
- );
- } else {
- shutdown(true, destClosed);
- }
- }
-
- setPromiseIsHandledToTrue(pipeLoop());
-
- return promise.promise;
-
- /** @returns {Promise<void>} */
- function waitForWritesToFinish() {
- const oldCurrentWrite = currentWrite;
- return transformPromiseWith(
- currentWrite,
- () =>
- oldCurrentWrite !== currentWrite
- ? waitForWritesToFinish()
- : undefined,
- );
- }
-
- /**
- * @param {ReadableStream | WritableStream} stream
- * @param {Promise<any>} promise
- * @param {(e: any) => void} action
- */
- function isOrBecomesErrored(stream, promise, action) {
- if (stream[_state] === "errored") {
- action(stream[_storedError]);
- } else {
- uponRejection(promise, action);
- }
- }
-
- /**
- * @param {ReadableStream} stream
- * @param {Promise<any>} promise
- * @param {() => void} action
- */
- function isOrBecomesClosed(stream, promise, action) {
- if (stream[_state] === "closed") {
- action();
- } else {
- uponFulfillment(promise, action);
- }
- }
-
- /**
- * @param {() => Promise<void[] | void>} action
- * @param {boolean=} originalIsError
- * @param {any=} originalError
- */
- function shutdownWithAction(action, originalIsError, originalError) {
- function doTheRest() {
- uponPromise(
- action(),
- () => finalize(originalIsError, originalError),
- (newError) => finalize(true, newError),
- );
- }
-
- if (shuttingDown === true) {
- return;
- }
- shuttingDown = true;
-
- if (
- dest[_state] === "writable" &&
- writableStreamCloseQueuedOrInFlight(dest) === false
- ) {
- uponFulfillment(waitForWritesToFinish(), doTheRest);
- } else {
- doTheRest();
- }
- }
-
- /**
- * @param {boolean=} isError
- * @param {any=} error
- */
- function shutdown(isError, error) {
- if (shuttingDown) {
- return;
- }
- shuttingDown = true;
- if (
- dest[_state] === "writable" &&
- writableStreamCloseQueuedOrInFlight(dest) === false
- ) {
- uponFulfillment(
- waitForWritesToFinish(),
- () => finalize(isError, error),
- );
- } else {
- finalize(isError, error);
- }
- }
-
- /**
- * @param {boolean=} isError
- * @param {any=} error
- */
- function finalize(isError, error) {
- writableStreamDefaultWriterRelease(writer);
- readableStreamReaderGenericRelease(reader);
-
- if (signal !== undefined) {
- // TODO(lucacasonato): use the internal API to remove the listener.
- signal.removeEventListener("abort", abortAlgorithm);
- }
- if (isError) {
- promise.reject(error);
- } else {
- promise.resolve(undefined);
- }
- }
- }
-
- /**
- * @param {ReadableStreamGenericReader<any>} reader
- * @param {any} reason
- * @returns {Promise<void>}
- */
- function readableStreamReaderGenericCancel(reader, reason) {
- const stream = reader[_stream];
- assert(stream !== undefined);
- return readableStreamCancel(stream, reason);
- }
-
- /**
- * @template R
- * @param {ReadableStreamDefaultReader<R>} reader
- * @param {ReadableStream<R>} stream
- */
- function readableStreamReaderGenericInitialize(reader, stream) {
- reader[_stream] = stream;
- stream[_reader] = reader;
- if (stream[_state] === "readable") {
- reader[_closedPromise] = new Deferred();
- } else if (stream[_state] === "closed") {
- reader[_closedPromise] = new Deferred();
- reader[_closedPromise].resolve(undefined);
- } else {
- assert(stream[_state] === "errored");
- reader[_closedPromise] = new Deferred();
- reader[_closedPromise].reject(stream[_storedError]);
- setPromiseIsHandledToTrue(reader[_closedPromise].promise);
- }
- }
-
- /**
- * @template R
- * @param {ReadableStreamGenericReader<R>} reader
- */
- function readableStreamReaderGenericRelease(reader) {
- assert(reader[_stream] !== undefined);
- assert(reader[_stream][_reader] === reader);
- if (reader[_stream][_state] === "readable") {
- reader[_closedPromise].reject(
- new TypeError(
- "Reader was released and can no longer be used to monitor the stream's closedness.",
- ),
- );
- } else {
- reader[_closedPromise] = new Deferred();
- reader[_closedPromise].reject(
- new TypeError(
- "Reader was released and can no longer be used to monitor the stream's closedness.",
- ),
- );
- }
- setPromiseIsHandledToTrue(reader[_closedPromise].promise);
- reader[_stream][_reader] = undefined;
- reader[_stream] = undefined;
- }
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @param {boolean} cloneForBranch2
- * @returns {[ReadableStream<R>, ReadableStream<R>]}
- */
- function readableStreamTee(stream, cloneForBranch2) {
- assert(isReadableStream(stream));
- assert(typeof cloneForBranch2 === "boolean");
- const reader = acquireReadableStreamDefaultReader(stream);
- let reading = false;
- let canceled1 = false;
- let canceled2 = false;
- /** @type {any} */
- let reason1;
- /** @type {any} */
- let reason2;
- /** @type {ReadableStream<R>} */
- // deno-lint-ignore prefer-const
- let branch1;
- /** @type {ReadableStream<R>} */
- // deno-lint-ignore prefer-const
- let branch2;
-
- /** @type {Deferred<void>} */
- const cancelPromise = new Deferred();
-
- function pullAlgorithm() {
- if (reading === true) {
- return resolvePromiseWith(undefined);
- }
- reading = true;
- /** @type {ReadRequest<R>} */
- const readRequest = {
- chunkSteps(value) {
- queueMicrotask(() => {
- reading = false;
- const value1 = value;
- const value2 = value;
-
- // TODO(lucacasonato): respect clonedForBranch2.
-
- if (canceled1 === false) {
- readableStreamDefaultControllerEnqueue(
- /** @type {ReadableStreamDefaultController<any>} */ (branch1[
- _controller
- ]),
- value1,
- );
- }
- if (canceled2 === false) {
- readableStreamDefaultControllerEnqueue(
- /** @type {ReadableStreamDefaultController<any>} */ (branch2[
- _controller
- ]),
- value2,
- );
- }
- });
- },
- closeSteps() {
- reading = false;
- if (canceled1 === false) {
- readableStreamDefaultControllerClose(
- /** @type {ReadableStreamDefaultController<any>} */ (branch1[
- _controller
- ]),
- );
- }
- if (canceled2 === false) {
- readableStreamDefaultControllerClose(
- /** @type {ReadableStreamDefaultController<any>} */ (branch2[
- _controller
- ]),
- );
- }
- cancelPromise.resolve(undefined);
- },
- errorSteps() {
- reading = false;
- },
- };
- readableStreamDefaultReaderRead(reader, readRequest);
- return resolvePromiseWith(undefined);
- }
-
- /**
- * @param {any} reason
- * @returns {Promise<void>}
- */
- function cancel1Algorithm(reason) {
- canceled1 = true;
- reason1 = reason;
- if (canceled2 === true) {
- const compositeReason = [reason1, reason2];
- const cancelResult = readableStreamCancel(stream, compositeReason);
- cancelPromise.resolve(cancelResult);
- }
- return cancelPromise.promise;
- }
-
- /**
- * @param {any} reason
- * @returns {Promise<void>}
- */
- function cancel2Algorithm(reason) {
- canceled2 = true;
- reason2 = reason;
- if (canceled1 === true) {
- const compositeReason = [reason1, reason2];
- const cancelResult = readableStreamCancel(stream, compositeReason);
- cancelPromise.resolve(cancelResult);
- }
- return cancelPromise.promise;
- }
-
- function startAlgorithm() {}
-
- branch1 = createReadableStream(
- startAlgorithm,
- pullAlgorithm,
- cancel1Algorithm,
- );
- branch2 = createReadableStream(
- startAlgorithm,
- pullAlgorithm,
- cancel2Algorithm,
- );
-
- uponRejection(reader[_closedPromise].promise, (r) => {
- readableStreamDefaultControllerError(
- /** @type {ReadableStreamDefaultController<any>} */ (branch1[
- _controller
- ]),
- r,
- );
- readableStreamDefaultControllerError(
- /** @type {ReadableStreamDefaultController<any>} */ (branch2[
- _controller
- ]),
- r,
- );
- if (canceled1 === false || canceled2 === false) {
- cancelPromise.resolve(undefined);
- }
- });
-
- return [branch1, branch2];
- }
-
- /**
- * @param {ReadableStream<ArrayBuffer>} stream
- * @param {ReadableByteStreamController} controller
- * @param {() => void} startAlgorithm
- * @param {() => Promise<void>} pullAlgorithm
- * @param {(reason: any) => Promise<void>} cancelAlgorithm
- * @param {number} highWaterMark
- * @param {number | undefined} autoAllocateChunkSize
- */
- function setUpReadableByteStreamController(
- stream,
- controller,
- startAlgorithm,
- pullAlgorithm,
- cancelAlgorithm,
- highWaterMark,
- autoAllocateChunkSize,
- ) {
- assert(stream[_controller] === undefined);
- if (autoAllocateChunkSize !== undefined) {
- assert(NumberIsInteger(autoAllocateChunkSize));
- assert(autoAllocateChunkSize >= 0);
- }
- controller[_stream] = stream;
- controller[_pullAgain] = controller[_pulling] = false;
- controller[_byobRequest] = undefined;
- resetQueue(controller);
- controller[_closeRequested] = controller[_started] = false;
- controller[_strategyHWM] = highWaterMark;
- controller[_pullAlgorithm] = pullAlgorithm;
- controller[_cancelAlgorithm] = cancelAlgorithm;
- controller[_autoAllocateChunkSize] = autoAllocateChunkSize;
- // 12. Set controller.[[pendingPullIntos]] to a new empty list.
- stream[_controller] = controller;
- const startResult = startAlgorithm();
- const startPromise = resolvePromiseWith(startResult);
- setPromiseIsHandledToTrue(
- PromisePrototypeThen(
- startPromise,
- () => {
- controller[_started] = true;
- assert(controller[_pulling] === false);
- assert(controller[_pullAgain] === false);
- readableByteStreamControllerCallPullIfNeeded(controller);
- },
- (r) => {
- readableByteStreamControllerError(controller, r);
- },
- ),
- );
- }
-
- /**
- * @param {ReadableStream<ArrayBuffer>} stream
- * @param {UnderlyingSource<ArrayBuffer>} underlyingSource
- * @param {UnderlyingSource<ArrayBuffer>} underlyingSourceDict
- * @param {number} highWaterMark
- */
- function setUpReadableByteStreamControllerFromUnderlyingSource(
- stream,
- underlyingSource,
- underlyingSourceDict,
- highWaterMark,
- ) {
- 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 (underlyingSourceDict.start !== undefined) {
- startAlgorithm = () =>
- webidl.invokeCallbackFunction(
- underlyingSourceDict.start,
- [controller],
- underlyingSource,
- webidl.converters.any,
- {
- prefix:
- "Failed to call 'startAlgorithm' on 'ReadableByteStreamController'",
- },
- );
- }
- if (underlyingSourceDict.pull !== undefined) {
- pullAlgorithm = () =>
- webidl.invokeCallbackFunction(
- underlyingSourceDict.pull,
- [controller],
- underlyingSource,
- webidl.converters["Promise<undefined>"],
- {
- prefix:
- "Failed to call 'pullAlgorithm' on 'ReadableByteStreamController'",
- returnsPromise: true,
- },
- );
- }
- if (underlyingSourceDict.cancel !== undefined) {
- cancelAlgorithm = (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} */
- const autoAllocateChunkSize = undefined;
- setUpReadableByteStreamController(
- stream,
- controller,
- startAlgorithm,
- pullAlgorithm,
- cancelAlgorithm,
- highWaterMark,
- autoAllocateChunkSize,
- );
- }
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @param {ReadableStreamDefaultController<R>} controller
- * @param {(controller: ReadableStreamDefaultController<R>) => void | Promise<void>} startAlgorithm
- * @param {(controller: ReadableStreamDefaultController<R>) => Promise<void>} pullAlgorithm
- * @param {(reason: any) => Promise<void>} cancelAlgorithm
- * @param {number} highWaterMark
- * @param {(chunk: R) => number} sizeAlgorithm
- */
- function setUpReadableStreamDefaultController(
- stream,
- controller,
- startAlgorithm,
- pullAlgorithm,
- cancelAlgorithm,
- highWaterMark,
- sizeAlgorithm,
- ) {
- assert(stream[_controller] === undefined);
- controller[_stream] = stream;
- resetQueue(controller);
- controller[_started] = controller[_closeRequested] =
- controller[_pullAgain] = controller[_pulling] = false;
- controller[_strategySizeAlgorithm] = sizeAlgorithm;
- controller[_strategyHWM] = highWaterMark;
- controller[_pullAlgorithm] = pullAlgorithm;
- controller[_cancelAlgorithm] = cancelAlgorithm;
- stream[_controller] = controller;
- const startResult = startAlgorithm(controller);
- const startPromise = resolvePromiseWith(startResult);
- uponPromise(startPromise, () => {
- controller[_started] = true;
- assert(controller[_pulling] === false);
- assert(controller[_pullAgain] === false);
- readableStreamDefaultControllerCallPullIfNeeded(controller);
- }, (r) => {
- readableStreamDefaultControllerError(controller, r);
- });
- }
-
- /**
- * @template R
- * @param {ReadableStream<R>} stream
- * @param {UnderlyingSource<R>} underlyingSource
- * @param {UnderlyingSource<R>} underlyingSourceDict
- * @param {number} highWaterMark
- * @param {(chunk: R) => number} sizeAlgorithm
- */
- function setUpReadableStreamDefaultControllerFromUnderlyingSource(
- stream,
- underlyingSource,
- underlyingSourceDict,
- highWaterMark,
- sizeAlgorithm,
- ) {
- const controller = webidl.createBranded(ReadableStreamDefaultController);
- /** @type {() => Promise<void>} */
- let startAlgorithm = () => undefined;
- /** @type {() => Promise<void>} */
- let pullAlgorithm = () => resolvePromiseWith(undefined);
- /** @type {(reason?: any) => Promise<void>} */
- let cancelAlgorithm = () => resolvePromiseWith(undefined);
- if (underlyingSourceDict.start !== undefined) {
- startAlgorithm = () =>
- webidl.invokeCallbackFunction(
- underlyingSourceDict.start,
- [controller],
- underlyingSource,
- webidl.converters.any,
- {
- prefix:
- "Failed to call 'startAlgorithm' on 'ReadableStreamDefaultController'",
- },
- );
- }
- if (underlyingSourceDict.pull !== undefined) {
- pullAlgorithm = () =>
- webidl.invokeCallbackFunction(
- underlyingSourceDict.pull,
- [controller],
- underlyingSource,
- webidl.converters["Promise<undefined>"],
- {
- prefix:
- "Failed to call 'pullAlgorithm' on 'ReadableStreamDefaultController'",
- returnsPromise: true,
- },
- );
- }
- if (underlyingSourceDict.cancel !== undefined) {
- cancelAlgorithm = (reason) =>
- webidl.invokeCallbackFunction(
- underlyingSourceDict.cancel,
- [reason],
- underlyingSource,
- webidl.converters["Promise<undefined>"],
- {
- prefix:
- "Failed to call 'cancelAlgorithm' on 'ReadableStreamDefaultController'",
- returnsPromise: true,
- },
- );
- }
- setUpReadableStreamDefaultController(
- stream,
- controller,
- startAlgorithm,
- pullAlgorithm,
- cancelAlgorithm,
- highWaterMark,
- sizeAlgorithm,
- );
- }
-
- /**
- * @template R
- * @param {ReadableStreamDefaultReader<R>} reader
- * @param {ReadableStream<R>} stream
- */
- function setUpReadableStreamDefaultReader(reader, stream) {
- if (isReadableStreamLocked(stream)) {
- throw new TypeError("ReadableStream is locked.");
- }
- readableStreamReaderGenericInitialize(reader, stream);
- reader[_readRequests] = [];
- }
-
- /**
- * @template O
- * @param {TransformStream<any, O>} stream
- * @param {TransformStreamDefaultController<O>} controller
- * @param {(chunk: O, controller: TransformStreamDefaultController<O>) => Promise<void>} transformAlgorithm
- * @param {(controller: TransformStreamDefaultController<O>) => Promise<void>} flushAlgorithm
- */
- function setUpTransformStreamDefaultController(
- stream,
- controller,
- transformAlgorithm,
- flushAlgorithm,
- ) {
- assert(stream instanceof TransformStream);
- assert(stream[_controller] === undefined);
- controller[_stream] = stream;
- stream[_controller] = controller;
- controller[_transformAlgorithm] = transformAlgorithm;
- controller[_flushAlgorithm] = flushAlgorithm;
- }
-
- /**
- * @template I
- * @template O
- * @param {TransformStream<I, O>} stream
- * @param {Transformer<I, O>} transformer
- * @param {Transformer<I, O>} transformerDict
- */
- function setUpTransformStreamDefaultControllerFromTransformer(
- stream,
- transformer,
- transformerDict,
- ) {
- /** @type {TransformStreamDefaultController<O>} */
- const controller = webidl.createBranded(TransformStreamDefaultController);
- /** @type {(chunk: O, controller: TransformStreamDefaultController<O>) => Promise<void>} */
- let transformAlgorithm = (chunk) => {
- try {
- transformStreamDefaultControllerEnqueue(controller, chunk);
- } catch (e) {
- return PromiseReject(e);
- }
- return resolvePromiseWith(undefined);
- };
- /** @type {(controller: TransformStreamDefaultController<O>) => Promise<void>} */
- let flushAlgorithm = () => resolvePromiseWith(undefined);
- if (transformerDict.transform !== undefined) {
- transformAlgorithm = (chunk, controller) =>
- webidl.invokeCallbackFunction(
- transformerDict.transform,
- [chunk, controller],
- transformer,
- webidl.converters["Promise<undefined>"],
- {
- prefix:
- "Failed to call 'transformAlgorithm' on 'TransformStreamDefaultController'",
- returnsPromise: true,
- },
- );
- }
- if (transformerDict.flush !== undefined) {
- flushAlgorithm = (controller) =>
- webidl.invokeCallbackFunction(
- transformerDict.flush,
- [controller],
- transformer,
- webidl.converters["Promise<undefined>"],
- {
- prefix:
- "Failed to call 'flushAlgorithm' on 'TransformStreamDefaultController'",
- returnsPromise: true,
- },
- );
- }
- setUpTransformStreamDefaultController(
- stream,
- controller,
- transformAlgorithm,
- flushAlgorithm,
- );
- }
-
- /**
- * @template W
- * @param {WritableStream<W>} stream
- * @param {WritableStreamDefaultController<W>} controller
- * @param {(controller: WritableStreamDefaultController<W>) => Promise<void>} startAlgorithm
- * @param {(chunk: W, controller: WritableStreamDefaultController<W>) => Promise<void>} writeAlgorithm
- * @param {() => Promise<void>} closeAlgorithm
- * @param {(reason?: any) => Promise<void>} abortAlgorithm
- * @param {number} highWaterMark
- * @param {(chunk: W) => number} sizeAlgorithm
- */
- function setUpWritableStreamDefaultController(
- stream,
- controller,
- startAlgorithm,
- writeAlgorithm,
- closeAlgorithm,
- abortAlgorithm,
- highWaterMark,
- sizeAlgorithm,
- ) {
- assert(isWritableStream(stream));
- assert(stream[_controller] === undefined);
- controller[_stream] = stream;
- stream[_controller] = controller;
- resetQueue(controller);
- controller[_started] = false;
- controller[_strategySizeAlgorithm] = sizeAlgorithm;
- controller[_strategyHWM] = highWaterMark;
- controller[_writeAlgorithm] = writeAlgorithm;
- controller[_closeAlgorithm] = closeAlgorithm;
- controller[_abortAlgorithm] = abortAlgorithm;
- const backpressure = writableStreamDefaultControllerGetBackpressure(
- controller,
- );
- writableStreamUpdateBackpressure(stream, backpressure);
- const startResult = startAlgorithm(controller);
- const startPromise = resolvePromiseWith(startResult);
- uponPromise(startPromise, () => {
- assert(stream[_state] === "writable" || stream[_state] === "erroring");
- controller[_started] = true;
- writableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }, (r) => {
- assert(stream[_state] === "writable" || stream[_state] === "erroring");
- controller[_started] = true;
- writableStreamDealWithRejection(stream, r);
- });
- }
-
- /**
- * @template W
- * @param {WritableStream<W>} stream
- * @param {UnderlyingSink<W>} underlyingSink
- * @param {UnderlyingSink<W>} underlyingSinkDict
- * @param {number} highWaterMark
- * @param {(chunk: W) => number} sizeAlgorithm
- */
- function setUpWritableStreamDefaultControllerFromUnderlyingSink(
- stream,
- underlyingSink,
- underlyingSinkDict,
- highWaterMark,
- sizeAlgorithm,
- ) {
- const controller = webidl.createBranded(WritableStreamDefaultController);
- /** @type {(controller: WritableStreamDefaultController<W>) => any} */
- let startAlgorithm = () => undefined;
- /** @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 (underlyingSinkDict.start !== undefined) {
- startAlgorithm = () =>
- webidl.invokeCallbackFunction(
- underlyingSinkDict.start,
- [controller],
- underlyingSink,
- webidl.converters.any,
- {
- prefix:
- "Failed to call 'startAlgorithm' on 'WritableStreamDefaultController'",
- },
- );
- }
- if (underlyingSinkDict.write !== undefined) {
- writeAlgorithm = (chunk) =>
- webidl.invokeCallbackFunction(
- underlyingSinkDict.write,
- [chunk, controller],
- underlyingSink,
- webidl.converters["Promise<undefined>"],
- {
- prefix:
- "Failed to call 'writeAlgorithm' on 'WritableStreamDefaultController'",
- returnsPromise: true,
- },
- );
- }
- if (underlyingSinkDict.close !== undefined) {
- closeAlgorithm = () =>
- webidl.invokeCallbackFunction(
- underlyingSinkDict.close,
- [],
- underlyingSink,
- webidl.converters["Promise<undefined>"],
- {
- prefix:
- "Failed to call 'closeAlgorithm' on 'WritableStreamDefaultController'",
- returnsPromise: true,
- },
- );
- }
- if (underlyingSinkDict.abort !== undefined) {
- abortAlgorithm = (reason) =>
- webidl.invokeCallbackFunction(
- underlyingSinkDict.abort,
- [reason],
- underlyingSink,
- webidl.converters["Promise<undefined>"],
- {
- prefix:
- "Failed to call 'abortAlgorithm' on 'WritableStreamDefaultController'",
- returnsPromise: true,
- },
- );
- }
- setUpWritableStreamDefaultController(
- stream,
- controller,
- startAlgorithm,
- writeAlgorithm,
- closeAlgorithm,
- abortAlgorithm,
- highWaterMark,
- sizeAlgorithm,
- );
- }
-
- /**
- * @template W
- * @param {WritableStreamDefaultWriter<W>} writer
- * @param {WritableStream<W>} stream
- */
- function setUpWritableStreamDefaultWriter(writer, stream) {
- if (isWritableStreamLocked(stream) === true) {
- throw new TypeError("The stream is already locked.");
- }
- writer[_stream] = stream;
- stream[_writer] = writer;
- const state = stream[_state];
- if (state === "writable") {
- if (
- writableStreamCloseQueuedOrInFlight(stream) === false &&
- stream[_backpressure] === true
- ) {
- writer[_readyPromise] = new Deferred();
- } else {
- writer[_readyPromise] = new Deferred();
- writer[_readyPromise].resolve(undefined);
- }
- writer[_closedPromise] = new Deferred();
- } else if (state === "erroring") {
- writer[_readyPromise] = new Deferred();
- writer[_readyPromise].reject(stream[_storedError]);
- setPromiseIsHandledToTrue(writer[_readyPromise].promise);
- writer[_closedPromise] = new Deferred();
- } else if (state === "closed") {
- writer[_readyPromise] = new Deferred();
- writer[_readyPromise].resolve(undefined);
- writer[_closedPromise] = new Deferred();
- writer[_closedPromise].resolve(undefined);
- } else {
- assert(state === "errored");
- const storedError = stream[_storedError];
- writer[_readyPromise] = new Deferred();
- writer[_readyPromise].reject(storedError);
- setPromiseIsHandledToTrue(writer[_readyPromise].promise);
- writer[_closedPromise] = new Deferred();
- writer[_closedPromise].reject(storedError);
- setPromiseIsHandledToTrue(writer[_closedPromise].promise);
- }
- }
-
- /** @param {TransformStreamDefaultController} controller */
- function transformStreamDefaultControllerClearAlgorithms(controller) {
- controller[_transformAlgorithm] = undefined;
- controller[_flushAlgorithm] = undefined;
- }
-
- /**
- * @template O
- * @param {TransformStreamDefaultController<O>} controller
- * @param {O} chunk
- */
- function transformStreamDefaultControllerEnqueue(controller, chunk) {
- const stream = controller[_stream];
- const readableController = stream[_readable][_controller];
- if (
- readableStreamDefaultControllerCanCloseOrEnqueue(
- /** @type {ReadableStreamDefaultController<O>} */ (readableController),
- ) === false
- ) {
- throw new TypeError("Readable stream is unavailable.");
- }
- try {
- readableStreamDefaultControllerEnqueue(
- /** @type {ReadableStreamDefaultController<O>} */ (readableController),
- chunk,
- );
- } catch (e) {
- transformStreamErrorWritableAndUnblockWrite(stream, e);
- throw stream[_readable][_storedError];
- }
- const backpressure = readableStreamDefaultcontrollerHasBackpressure(
- /** @type {ReadableStreamDefaultController<O>} */ (readableController),
- );
- if (backpressure !== stream[_backpressure]) {
- assert(backpressure === true);
- transformStreamSetBackpressure(stream, true);
- }
- }
-
- /**
- * @param {TransformStreamDefaultController} controller
- * @param {any=} e
- */
- function transformStreamDefaultControllerError(controller, e) {
- transformStreamError(controller[_stream], e);
- }
-
- /**
- * @template O
- * @param {TransformStreamDefaultController<O>} controller
- * @param {any} chunk
- * @returns {Promise<void>}
- */
- function transformStreamDefaultControllerPerformTransform(controller, chunk) {
- const transformPromise = controller[_transformAlgorithm](chunk, controller);
- return transformPromiseWith(transformPromise, undefined, (r) => {
- transformStreamError(controller[_stream], r);
- throw r;
- });
- }
-
- /** @param {TransformStreamDefaultController} controller */
- function transformStreamDefaultControllerTerminate(controller) {
- const stream = controller[_stream];
- const readableController = stream[_readable][_controller];
- readableStreamDefaultControllerClose(
- /** @type {ReadableStreamDefaultController} */ (readableController),
- );
- const error = new TypeError("The stream has been terminated.");
- transformStreamErrorWritableAndUnblockWrite(stream, error);
- }
-
- /**
- * @param {TransformStream} stream
- * @param {any=} reason
- * @returns {Promise<void>}
- */
- function transformStreamDefaultSinkAbortAlgorithm(stream, reason) {
- transformStreamError(stream, reason);
- return resolvePromiseWith(undefined);
- }
-
- /**
- * @template I
- * @template O
- * @param {TransformStream<I, O>} stream
- * @returns {Promise<void>}
- */
- function transformStreamDefaultSinkCloseAlgorithm(stream) {
- const readable = stream[_readable];
- const controller = stream[_controller];
- const flushPromise = controller[_flushAlgorithm](controller);
- transformStreamDefaultControllerClearAlgorithms(controller);
- return transformPromiseWith(flushPromise, () => {
- if (readable[_state] === "errored") {
- throw readable[_storedError];
- }
- readableStreamDefaultControllerClose(
- /** @type {ReadableStreamDefaultController} */ (readable[_controller]),
- );
- }, (r) => {
- transformStreamError(stream, r);
- throw readable[_storedError];
- });
- }
-
- /**
- * @template I
- * @template O
- * @param {TransformStream<I, O>} stream
- * @param {I} chunk
- * @returns {Promise<void>}
- */
- function transformStreamDefaultSinkWriteAlgorithm(stream, chunk) {
- assert(stream[_writable][_state] === "writable");
- const controller = stream[_controller];
- if (stream[_backpressure] === true) {
- const backpressureChangePromise = stream[_backpressureChangePromise];
- assert(backpressureChangePromise !== undefined);
- return transformPromiseWith(backpressureChangePromise.promise, () => {
- const writable = stream[_writable];
- const state = writable[_state];
- if (state === "erroring") {
- throw writable[_storedError];
- }
- assert(state === "writable");
- return transformStreamDefaultControllerPerformTransform(
- controller,
- chunk,
- );
- });
- }
- return transformStreamDefaultControllerPerformTransform(controller, chunk);
- }
-
- /**
- * @param {TransformStream} stream
- * @returns {Promise<void>}
- */
- function transformStreamDefaultSourcePullAlgorithm(stream) {
- assert(stream[_backpressure] === true);
- assert(stream[_backpressureChangePromise] !== undefined);
- transformStreamSetBackpressure(stream, false);
- return stream[_backpressureChangePromise].promise;
- }
-
- /**
- * @param {TransformStream} stream
- * @param {any=} e
- */
- function transformStreamError(stream, e) {
- readableStreamDefaultControllerError(
- /** @type {ReadableStreamDefaultController} */ (stream[_readable][
- _controller
- ]),
- e,
- );
- transformStreamErrorWritableAndUnblockWrite(stream, e);
- }
-
- /**
- * @param {TransformStream} stream
- * @param {any=} e
- */
- function transformStreamErrorWritableAndUnblockWrite(stream, e) {
- transformStreamDefaultControllerClearAlgorithms(stream[_controller]);
- writableStreamDefaultControllerErrorIfNeeded(
- stream[_writable][_controller],
- e,
- );
- if (stream[_backpressure] === true) {
- transformStreamSetBackpressure(stream, false);
- }
- }
-
- /**
- * @param {TransformStream} stream
- * @param {boolean} backpressure
- */
- function transformStreamSetBackpressure(stream, backpressure) {
- assert(stream[_backpressure] !== backpressure);
- if (stream[_backpressureChangePromise] !== undefined) {
- stream[_backpressureChangePromise].resolve(undefined);
- }
- stream[_backpressureChangePromise] = new Deferred();
- stream[_backpressure] = backpressure;
- }
-
- /**
- * @param {WritableStream} stream
- * @param {any=} reason
- * @returns {Promise<void>}
- */
- function writableStreamAbort(stream, reason) {
- const state = stream[_state];
- if (state === "closed" || state === "errored") {
- return resolvePromiseWith(undefined);
- }
- if (stream[_pendingAbortRequest] !== undefined) {
- return stream[_pendingAbortRequest].deferred.promise;
- }
- assert(state === "writable" || state === "erroring");
- let wasAlreadyErroring = false;
- if (state === "erroring") {
- wasAlreadyErroring = true;
- reason = undefined;
- }
- /** Deferred<void> */
- const deferred = new Deferred();
- stream[_pendingAbortRequest] = {
- deferred,
- reason,
- wasAlreadyErroring,
- };
- if (wasAlreadyErroring === false) {
- writableStreamStartErroring(stream, reason);
- }
- return deferred.promise;
- }
-
- /**
- * @param {WritableStream} stream
- * @returns {Promise<void>}
- */
- function writableStreamAddWriteRequest(stream) {
- assert(isWritableStreamLocked(stream) === true);
- assert(stream[_state] === "writable");
- /** @type {Deferred<void>} */
- const deferred = new Deferred();
- ArrayPrototypePush(stream[_writeRequests], deferred);
- return deferred.promise;
- }
-
- /**
- * @param {WritableStream} stream
- * @returns {Promise<void>}
- */
- function writableStreamClose(stream) {
- const state = stream[_state];
- if (state === "closed" || state === "errored") {
- return PromiseReject(
- new TypeError("Writable stream is closed or errored."),
- );
- }
- assert(state === "writable" || state === "erroring");
- assert(writableStreamCloseQueuedOrInFlight(stream) === false);
- /** @type {Deferred<void>} */
- const deferred = new Deferred();
- stream[_closeRequest] = deferred;
- const writer = stream[_writer];
- if (
- writer !== undefined && stream[_backpressure] === true &&
- state === "writable"
- ) {
- writer[_readyPromise].resolve(undefined);
- }
- writableStreamDefaultControllerClose(stream[_controller]);
- return deferred.promise;
- }
-
- /**
- * @param {WritableStream} stream
- * @returns {boolean}
- */
- function writableStreamCloseQueuedOrInFlight(stream) {
- if (
- stream[_closeRequest] === undefined &&
- stream[_inFlightCloseRequest] === undefined
- ) {
- return false;
- }
- return true;
- }
-
- /**
- * @param {WritableStream} stream
- * @param {any=} error
- */
- function writableStreamDealWithRejection(stream, error) {
- const state = stream[_state];
- if (state === "writable") {
- writableStreamStartErroring(stream, error);
- return;
- }
- assert(state === "erroring");
- writableStreamFinishErroring(stream);
- }
-
- /**
- * @template W
- * @param {WritableStreamDefaultController<W>} controller
- */
- function writableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
- const stream = controller[_stream];
- if (controller[_started] === false) {
- return;
- }
- if (stream[_inFlightWriteRequest] !== undefined) {
- return;
- }
- const state = stream[_state];
- assert(state !== "closed" && state !== "errored");
- if (state === "erroring") {
- writableStreamFinishErroring(stream);
- return;
- }
- if (controller[_queue].length === 0) {
- return;
- }
- const value = peekQueueValue(controller);
- if (value === _close) {
- writableStreamDefaultControllerProcessClose(controller);
- } else {
- writableStreamDefaultControllerProcessWrite(controller, value);
- }
- }
-
- function writableStreamDefaultControllerClearAlgorithms(controller) {
- controller[_writeAlgorithm] = undefined;
- controller[_closeAlgorithm] = undefined;
- controller[_abortAlgorithm] = undefined;
- controller[_strategySizeAlgorithm] = undefined;
- }
-
- /** @param {WritableStreamDefaultController} controller */
- function writableStreamDefaultControllerClose(controller) {
- enqueueValueWithSize(controller, _close, 0);
- writableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }
-
- /**
- * @param {WritableStreamDefaultController} controller
- * @param {any} error
- */
- function writableStreamDefaultControllerError(controller, error) {
- const stream = controller[_stream];
- assert(stream[_state] === "writable");
- writableStreamDefaultControllerClearAlgorithms(controller);
- writableStreamStartErroring(stream, error);
- }
-
- /**
- * @param {WritableStreamDefaultController} controller
- * @param {any} error
- */
- function writableStreamDefaultControllerErrorIfNeeded(controller, error) {
- if (controller[_stream][_state] === "writable") {
- writableStreamDefaultControllerError(controller, error);
- }
- }
-
- /**
- * @param {WritableStreamDefaultController} controller
- * @returns {boolean}
- */
- function writableStreamDefaultControllerGetBackpressure(controller) {
- const desiredSize = writableStreamDefaultControllerGetDesiredSize(
- controller,
- );
- return desiredSize <= 0;
- }
-
- /**
- * @template W
- * @param {WritableStreamDefaultController<W>} controller
- * @param {W} chunk
- * @returns {number}
- */
- function writableStreamDefaultControllerGetChunkSize(controller, chunk) {
- let value;
- try {
- value = controller[_strategySizeAlgorithm](chunk);
- } catch (e) {
- writableStreamDefaultControllerErrorIfNeeded(controller, e);
- return 1;
- }
- return value;
- }
-
- /**
- * @param {WritableStreamDefaultController} controller
- * @returns {number}
- */
- function writableStreamDefaultControllerGetDesiredSize(controller) {
- return controller[_strategyHWM] - controller[_queueTotalSize];
- }
-
- /** @param {WritableStreamDefaultController} controller */
- function writableStreamDefaultControllerProcessClose(controller) {
- const stream = controller[_stream];
- writableStreamMarkCloseRequestInFlight(stream);
- dequeueValue(controller);
- assert(controller[_queue].length === 0);
- const sinkClosePromise = controller[_closeAlgorithm]();
- writableStreamDefaultControllerClearAlgorithms(controller);
- uponPromise(sinkClosePromise, () => {
- writableStreamFinishInFlightClose(stream);
- }, (reason) => {
- writableStreamFinishInFlightCloseWithError(stream, reason);
- });
- }
-
- /**
- * @template W
- * @param {WritableStreamDefaultController<W>} controller
- * @param {W} chunk
- */
- function writableStreamDefaultControllerProcessWrite(controller, chunk) {
- const stream = controller[_stream];
- writableStreamMarkFirstWriteRequestInFlight(stream);
- const sinkWritePromise = controller[_writeAlgorithm](chunk, controller);
- uponPromise(sinkWritePromise, () => {
- writableStreamFinishInFlightWrite(stream);
- const state = stream[_state];
- assert(state === "writable" || state === "erroring");
- dequeueValue(controller);
- if (
- writableStreamCloseQueuedOrInFlight(stream) === false &&
- state === "writable"
- ) {
- const backpressure = writableStreamDefaultControllerGetBackpressure(
- controller,
- );
- writableStreamUpdateBackpressure(stream, backpressure);
- }
- writableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }, (reason) => {
- if (stream[_state] === "writable") {
- writableStreamDefaultControllerClearAlgorithms(controller);
- }
- writableStreamFinishInFlightWriteWithError(stream, reason);
- });
- }
-
- /**
- * @template W
- * @param {WritableStreamDefaultController<W>} controller
- * @param {W} chunk
- * @param {number} chunkSize
- */
- function writableStreamDefaultControllerWrite(controller, chunk, chunkSize) {
- try {
- enqueueValueWithSize(controller, chunk, chunkSize);
- } catch (e) {
- writableStreamDefaultControllerErrorIfNeeded(controller, e);
- return;
- }
- const stream = controller[_stream];
- if (
- writableStreamCloseQueuedOrInFlight(stream) === false &&
- stream[_state] === "writable"
- ) {
- const backpressure = writableStreamDefaultControllerGetBackpressure(
- controller,
- );
- writableStreamUpdateBackpressure(stream, backpressure);
- }
- writableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }
-
- /**
- * @param {WritableStreamDefaultWriter} writer
- * @param {any=} reason
- * @returns {Promise<void>}
- */
- function writableStreamDefaultWriterAbort(writer, reason) {
- const stream = writer[_stream];
- assert(stream !== undefined);
- return writableStreamAbort(stream, reason);
- }
-
- /**
- * @param {WritableStreamDefaultWriter} writer
- * @returns {Promise<void>}
- */
- function writableStreamDefaultWriterClose(writer) {
- const stream = writer[_stream];
- assert(stream !== undefined);
- return writableStreamClose(stream);
- }
-
- /**
- * @param {WritableStreamDefaultWriter} writer
- * @returns {Promise<void>}
- */
- function writableStreamDefaultWriterCloseWithErrorPropagation(writer) {
- const stream = writer[_stream];
- assert(stream !== undefined);
- const state = stream[_state];
- if (
- writableStreamCloseQueuedOrInFlight(stream) === true || state === "closed"
- ) {
- return resolvePromiseWith(undefined);
- }
- if (state === "errored") {
- return PromiseReject(stream[_storedError]);
- }
- assert(state === "writable" || state === "erroring");
- return writableStreamDefaultWriterClose(writer);
- }
-
- /**
- * @param {WritableStreamDefaultWriter} writer
- * @param {any=} error
- */
- function writableStreamDefaultWriterEnsureClosedPromiseRejected(
- writer,
- error,
- ) {
- if (writer[_closedPromise].state === "pending") {
- writer[_closedPromise].reject(error);
- } else {
- writer[_closedPromise] = new Deferred();
- writer[_closedPromise].reject(error);
- }
- setPromiseIsHandledToTrue(writer[_closedPromise].promise);
- }
-
- /**
- * @param {WritableStreamDefaultWriter} writer
- * @param {any=} error
- */
- function writableStreamDefaultWriterEnsureReadyPromiseRejected(
- writer,
- error,
- ) {
- if (writer[_readyPromise].state === "pending") {
- writer[_readyPromise].reject(error);
- } else {
- writer[_readyPromise] = new Deferred();
- writer[_readyPromise].reject(error);
- }
- setPromiseIsHandledToTrue(writer[_readyPromise].promise);
- }
-
- /**
- * @param {WritableStreamDefaultWriter} writer
- * @returns {number | null}
- */
- function writableStreamDefaultWriterGetDesiredSize(writer) {
- const stream = writer[_stream];
- const state = stream[_state];
- if (state === "errored" || state === "erroring") {
- return null;
- }
- if (state === "closed") {
- return 0;
- }
- return writableStreamDefaultControllerGetDesiredSize(stream[_controller]);
- }
-
- /** @param {WritableStreamDefaultWriter} writer */
- function writableStreamDefaultWriterRelease(writer) {
- const stream = writer[_stream];
- assert(stream !== undefined);
- assert(stream[_writer] === writer);
- const releasedError = new TypeError(
- "The writer has already been released.",
- );
- writableStreamDefaultWriterEnsureReadyPromiseRejected(
- writer,
- releasedError,
- );
- writableStreamDefaultWriterEnsureClosedPromiseRejected(
- writer,
- releasedError,
- );
- stream[_writer] = undefined;
- writer[_stream] = undefined;
- }
-
- /**
- * @template W
- * @param {WritableStreamDefaultWriter<W>} writer
- * @param {W} chunk
- * @returns {Promise<void>}
- */
- function writableStreamDefaultWriterWrite(writer, chunk) {
- const stream = writer[_stream];
- assert(stream !== undefined);
- const controller = stream[_controller];
- const chunkSize = writableStreamDefaultControllerGetChunkSize(
- controller,
- chunk,
- );
- if (stream !== writer[_stream]) {
- return PromiseReject(new TypeError("Writer's stream is unexpected."));
- }
- const state = stream[_state];
- if (state === "errored") {
- return PromiseReject(stream[_storedError]);
- }
- if (
- writableStreamCloseQueuedOrInFlight(stream) === true || state === "closed"
- ) {
- return PromiseReject(
- new TypeError("The stream is closing or is closed."),
- );
- }
- if (state === "erroring") {
- return PromiseReject(stream[_storedError]);
- }
- assert(state === "writable");
- const promise = writableStreamAddWriteRequest(stream);
- writableStreamDefaultControllerWrite(controller, chunk, chunkSize);
- return promise;
- }
-
- /** @param {WritableStream} stream */
- function writableStreamFinishErroring(stream) {
- assert(stream[_state] === "erroring");
- assert(writableStreamHasOperationMarkedInFlight(stream) === false);
- stream[_state] = "errored";
- stream[_controller][_errorSteps]();
- const storedError = stream[_storedError];
- for (const writeRequest of stream[_writeRequests]) {
- writeRequest.reject(storedError);
- }
- stream[_writeRequests] = [];
- if (stream[_pendingAbortRequest] === undefined) {
- writableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- return;
- }
- const abortRequest = stream[_pendingAbortRequest];
- stream[_pendingAbortRequest] = undefined;
- if (abortRequest.wasAlreadyErroring === true) {
- abortRequest.deferred.reject(storedError);
- writableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- return;
- }
- const promise = stream[_controller][_abortSteps](abortRequest.reason);
- uponPromise(promise, () => {
- abortRequest.deferred.resolve(undefined);
- writableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- }, (reason) => {
- abortRequest.deferred.reject(reason);
- writableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- });
- }
-
- /** @param {WritableStream} stream */
- function writableStreamFinishInFlightClose(stream) {
- assert(stream[_inFlightCloseRequest] !== undefined);
- stream[_inFlightCloseRequest].resolve(undefined);
- stream[_inFlightCloseRequest] = undefined;
- const state = stream[_state];
- assert(state === "writable" || state === "erroring");
- if (state === "erroring") {
- stream[_storedError] = undefined;
- if (stream[_pendingAbortRequest] !== undefined) {
- stream[_pendingAbortRequest].deferred.resolve(undefined);
- stream[_pendingAbortRequest] = undefined;
- }
- }
- stream[_state] = "closed";
- const writer = stream[_writer];
- if (writer !== undefined) {
- writer[_closedPromise].resolve(undefined);
- }
- assert(stream[_pendingAbortRequest] === undefined);
- assert(stream[_storedError] === undefined);
- }
-
- /**
- * @param {WritableStream} stream
- * @param {any=} error
- */
- function writableStreamFinishInFlightCloseWithError(stream, error) {
- assert(stream[_inFlightCloseRequest] !== undefined);
- stream[_inFlightCloseRequest].reject(error);
- stream[_inFlightCloseRequest] = undefined;
- assert(stream[_state] === "writable" || stream[_state] === "erroring");
- if (stream[_pendingAbortRequest] !== undefined) {
- stream[_pendingAbortRequest].deferred.reject(error);
- stream[_pendingAbortRequest] = undefined;
- }
- writableStreamDealWithRejection(stream, error);
- }
-
- /** @param {WritableStream} stream */
- function writableStreamFinishInFlightWrite(stream) {
- assert(stream[_inFlightWriteRequest] !== undefined);
- stream[_inFlightWriteRequest].resolve(undefined);
- stream[_inFlightWriteRequest] = undefined;
- }
-
- /**
- * @param {WritableStream} stream
- * @param {any=} error
- */
- function writableStreamFinishInFlightWriteWithError(stream, error) {
- assert(stream[_inFlightWriteRequest] !== undefined);
- stream[_inFlightWriteRequest].reject(error);
- stream[_inFlightWriteRequest] = undefined;
- assert(stream[_state] === "writable" || stream[_state] === "erroring");
- writableStreamDealWithRejection(stream, error);
- }
-
- /**
- * @param {WritableStream} stream
- * @returns {boolean}
- */
- function writableStreamHasOperationMarkedInFlight(stream) {
- if (
- stream[_inFlightWriteRequest] === undefined &&
- stream[_inFlightCloseRequest] === undefined
- ) {
- return false;
- }
- return true;
- }
-
- /** @param {WritableStream} stream */
- function writableStreamMarkCloseRequestInFlight(stream) {
- assert(stream[_inFlightCloseRequest] === undefined);
- assert(stream[_closeRequest] !== undefined);
- stream[_inFlightCloseRequest] = stream[_closeRequest];
- stream[_closeRequest] = undefined;
- }
-
- /**
- * @template W
- * @param {WritableStream<W>} stream
- * */
- function writableStreamMarkFirstWriteRequestInFlight(stream) {
- assert(stream[_inFlightWriteRequest] === undefined);
- assert(stream[_writeRequests].length);
- const writeRequest = stream[_writeRequests].shift();
- stream[_inFlightWriteRequest] = writeRequest;
- }
-
- /** @param {WritableStream} stream */
- function writableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
- assert(stream[_state] === "errored");
- if (stream[_closeRequest] !== undefined) {
- assert(stream[_inFlightCloseRequest] === undefined);
- stream[_closeRequest].reject(stream[_storedError]);
- stream[_closeRequest] = undefined;
- }
- const writer = stream[_writer];
- if (writer !== undefined) {
- writer[_closedPromise].reject(stream[_storedError]);
- setPromiseIsHandledToTrue(writer[_closedPromise].promise);
- }
- }
-
- /**
- * @param {WritableStream} stream
- * @param {any=} reason
- */
- function writableStreamStartErroring(stream, reason) {
- assert(stream[_storedError] === undefined);
- assert(stream[_state] === "writable");
- const controller = stream[_controller];
- assert(controller !== undefined);
- stream[_state] = "erroring";
- stream[_storedError] = reason;
- const writer = stream[_writer];
- if (writer !== undefined) {
- writableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
- }
- if (
- writableStreamHasOperationMarkedInFlight(stream) === false &&
- controller[_started] === true
- ) {
- writableStreamFinishErroring(stream);
- }
- }
-
- /**
- * @param {WritableStream} stream
- * @param {boolean} backpressure
- */
- function writableStreamUpdateBackpressure(stream, backpressure) {
- assert(stream[_state] === "writable");
- assert(writableStreamCloseQueuedOrInFlight(stream) === false);
- const writer = stream[_writer];
- if (writer !== undefined && backpressure !== stream[_backpressure]) {
- if (backpressure === true) {
- writer[_readyPromise] = new Deferred();
- } else {
- assert(backpressure === false);
- writer[_readyPromise].resolve(undefined);
- }
- }
- stream[_backpressure] = backpressure;
- }
-
- /**
- * @template T
- * @param {T} value
- * @param {boolean} done
- * @returns {IteratorResult<T>}
- */
- function createIteratorResult(value, done) {
- const result = ObjectCreate(null);
- ObjectDefineProperties(result, {
- value: { value, writable: true, enumerable: true, configurable: true },
- done: {
- value: done,
- writable: true,
- enumerable: true,
- configurable: true,
- },
- });
- return result;
- }
-
- /** @type {AsyncIterator<unknown, unknown>} */
- const asyncIteratorPrototype = ObjectGetPrototypeOf(
- ObjectGetPrototypeOf(async function* () {}).prototype,
- );
-
- /** @type {AsyncIterator<unknown>} */
- const readableStreamAsyncIteratorPrototype = ObjectSetPrototypeOf({
- /** @returns {Promise<IteratorResult<unknown>>} */
- next() {
- /** @type {ReadableStreamDefaultReader} */
- const reader = this[_reader];
- if (reader[_stream] === undefined) {
- return PromiseReject(
- new TypeError(
- "Cannot get the next iteration result once the reader has been released.",
- ),
- );
- }
- /** @type {Deferred<IteratorResult<any>>} */
- const promise = new Deferred();
- /** @type {ReadRequest} */
- const readRequest = {
- chunkSteps(chunk) {
- promise.resolve(createIteratorResult(chunk, false));
- },
- closeSteps() {
- readableStreamReaderGenericRelease(reader);
- promise.resolve(createIteratorResult(undefined, true));
- },
- errorSteps(e) {
- readableStreamReaderGenericRelease(reader);
- promise.reject(e);
- },
- };
- readableStreamDefaultReaderRead(reader, readRequest);
- return promise.promise;
- },
- /**
- * @param {unknown} arg
- * @returns {Promise<IteratorResult<unknown>>}
- */
- async return(arg) {
- /** @type {ReadableStreamDefaultReader} */
- const reader = this[_reader];
- if (reader[_stream] === undefined) {
- return createIteratorResult(undefined, true);
- }
- assert(reader[_readRequests].length === 0);
- if (this[_preventCancel] === false) {
- const result = readableStreamReaderGenericCancel(reader, arg);
- readableStreamReaderGenericRelease(reader);
- await result;
- return createIteratorResult(arg, true);
- }
- readableStreamReaderGenericRelease(reader);
- return createIteratorResult(undefined, true);
- },
- }, asyncIteratorPrototype);
-
- class ByteLengthQueuingStrategy {
- /** @param {{ highWaterMark: number }} init */
- constructor(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] = 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 WeakMapPrototypeGet(byteSizeFunctionWeakMap, this[_globalObject]);
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof ByteLengthQueuingStrategy,
- keys: [
- "highWaterMark",
- "size",
- ],
- }));
- }
-
- get [SymbolToStringTag]() {
- return "ByteLengthQueuingStrategy";
- }
- }
-
- webidl.configurePrototype(ByteLengthQueuingStrategy);
-
- /** @type {WeakMap<typeof globalThis, (chunk: ArrayBufferView) => number>} */
- const byteSizeFunctionWeakMap = new WeakMap();
-
- function initializeByteLengthSizeFunction(globalObject) {
- if (WeakMapPrototypeHas(byteSizeFunctionWeakMap, globalObject)) {
- return;
- }
- const size = (chunk) => chunk.byteLength;
- WeakMapPrototypeSet(byteSizeFunctionWeakMap, globalObject, size);
- }
-
- class CountQueuingStrategy {
- /** @param {{ highWaterMark: number }} init */
- constructor(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] = 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 WeakMapPrototypeGet(countSizeFunctionWeakMap, this[_globalObject]);
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof CountQueuingStrategy,
- keys: [
- "highWaterMark",
- "size",
- ],
- }));
- }
-
- get [SymbolToStringTag]() {
- return "CountQueuingStrategy";
- }
- }
-
- webidl.configurePrototype(CountQueuingStrategy);
-
- /** @type {WeakMap<typeof globalThis, () => 1>} */
- const countSizeFunctionWeakMap = new WeakMap();
-
- /** @param {typeof globalThis} globalObject */
- function initializeCountSizeFunction(globalObject) {
- if (WeakMapPrototypeHas(countSizeFunctionWeakMap, globalObject)) {
- return;
- }
- const size = () => 1;
- WeakMapPrototypeSet(countSizeFunctionWeakMap, globalObject, size);
- }
-
- /** @template R */
- class ReadableStream {
- /** @type {ReadableStreamDefaultController | ReadableByteStreamController} */
- [_controller];
- /** @type {boolean} */
- [_detached];
- /** @type {boolean} */
- [_disturbed];
- /** @type {ReadableStreamDefaultReader | undefined} */
- [_reader];
- /** @type {"readable" | "closed" | "errored"} */
- [_state];
- /** @type {any} */
- [_storedError];
-
- /**
- * @param {UnderlyingSource<R>=} underlyingSource
- * @param {QueuingStrategy<R>=} strategy
- */
- 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(
- `${prefix}: When underlying source is "bytes", strategy.size must be undefined.`,
- );
- }
- const highWaterMark = extractHighWaterMark(strategy, 0);
- setUpReadableByteStreamControllerFromUnderlyingSource(
- // @ts-ignore cannot easily assert this is ReadableStream<ArrayBuffer>
- this,
- underlyingSource,
- underlyingSourceDict,
- highWaterMark,
- );
- } else {
- assert(!("type" in underlyingSourceDict));
- const sizeAlgorithm = extractSizeAlgorithm(strategy);
- const highWaterMark = extractHighWaterMark(strategy, 1);
- setUpReadableStreamDefaultControllerFromUnderlyingSource(
- this,
- underlyingSource,
- underlyingSourceDict,
- highWaterMark,
- sizeAlgorithm,
- );
- }
- }
-
- /** @returns {boolean} */
- get locked() {
- webidl.assertBranded(this, ReadableStream);
- return isReadableStreamLocked(this);
- }
-
- /**
- * @param {any=} reason
- * @returns {Promise<void>}
- */
- cancel(reason = undefined) {
- try {
- webidl.assertBranded(this, ReadableStream);
- if (reason !== undefined) {
- reason = webidl.converters.any(reason);
- }
- } catch (err) {
- return PromiseReject(err);
- }
- if (isReadableStreamLocked(this)) {
- return PromiseReject(
- new TypeError("Cannot cancel a locked ReadableStream."),
- );
- }
- return readableStreamCancel(this, reason);
- }
-
- /**
- * @deprecated TODO(@kitsonk): Remove in Deno 1.8
- * @param {ReadableStreamIteratorOptions=} options
- * @returns {AsyncIterableIterator<R>}
- */
- getIterator(options = {}) {
- return this[SymbolAsyncIterator](options);
- }
-
- /**
- * @param {ReadableStreamGetReaderOptions=} options
- * @returns {ReadableStreamDefaultReader<R>}
- */
- getReader(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);
- }
- // 3. Return ? AcquireReadableStreamBYOBReader(this).
- throw new RangeError(`${prefix}: Unsupported mode '${mode}'`);
- }
-
- /**
- * @template T
- * @param {{ readable: ReadableStream<T>, writable: WritableStream<R> }} transform
- * @param {PipeOptions=} options
- * @returns {ReadableStream<T>}
- */
- 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 (isWritableStreamLocked(writable)) {
- throw new TypeError("Target WritableStream is already locked.");
- }
- const promise = readableStreamPipeTo(
- this,
- writable,
- preventClose,
- preventAbort,
- preventCancel,
- signal,
- );
- setPromiseIsHandledToTrue(promise);
- return readable;
- }
-
- /**
- * @param {WritableStream<R>} destination
- * @param {PipeOptions=} options
- * @returns {Promise<void>}
- */
- 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 PromiseReject(err);
- }
- const { preventClose, preventAbort, preventCancel, signal } = options;
- if (isReadableStreamLocked(this)) {
- return PromiseReject(
- new TypeError("ReadableStream is already locked."),
- );
- }
- if (isWritableStreamLocked(destination)) {
- return PromiseReject(
- new TypeError("destination WritableStream is already locked."),
- );
- }
- return readableStreamPipeTo(
- this,
- destination,
- preventClose,
- preventAbort,
- preventCancel,
- signal,
- );
- }
-
- /** @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>}
- */
- 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 = ObjectCreate(readableStreamAsyncIteratorPrototype);
- const reader = acquireReadableStreamDefaultReader(this);
- iterator[_reader] = reader;
- iterator[_preventCancel] = options.preventCancel;
- return iterator;
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return `${this.constructor.name} ${inspect({ locked: this.locked })}`;
- }
-
- get [SymbolToStringTag]() {
- return "ReadableStream";
- }
- }
-
- // TODO(lucacasonato): should be moved to webidl crate
- ReadableStream.prototype[SymbolAsyncIterator] =
- ReadableStream.prototype.values;
- ObjectDefineProperty(ReadableStream.prototype, SymbolAsyncIterator, {
- writable: true,
- enumerable: false,
- configurable: true,
- });
-
- webidl.configurePrototype(ReadableStream);
-
- function errorReadableStream(stream, e) {
- readableStreamDefaultControllerError(stream[_controller], e);
- }
-
- /** @template R */
- class ReadableStreamDefaultReader {
- /** @type {Deferred<void>} */
- [_closedPromise];
- /** @type {ReadableStream<R> | undefined} */
- [_stream];
- /** @type {ReadRequest[]} */
- [_readRequests];
-
- /** @param {ReadableStream<R>} stream */
- constructor(stream) {
- 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 PromiseReject(err);
- }
- if (this[_stream] === undefined) {
- return PromiseReject(
- new TypeError("Reader has no associated stream."),
- );
- }
- /** @type {Deferred<ReadableStreamReadResult<R>>} */
- const promise = new Deferred();
- /** @type {ReadRequest<R>} */
- const readRequest = {
- chunkSteps(chunk) {
- promise.resolve({ value: chunk, done: false });
- },
- closeSteps() {
- promise.resolve({ value: undefined, done: true });
- },
- errorSteps(e) {
- promise.reject(e);
- },
- };
- readableStreamDefaultReaderRead(this, readRequest);
- return promise.promise;
- }
-
- /** @returns {void} */
- releaseLock() {
- webidl.assertBranded(this, ReadableStreamDefaultReader);
- if (this[_stream] === undefined) {
- return;
- }
- if (this[_readRequests].length) {
- throw new TypeError(
- "There are pending read requests, so the reader cannot be release.",
- );
- }
- readableStreamReaderGenericRelease(this);
- }
-
- get closed() {
- try {
- webidl.assertBranded(this, ReadableStreamDefaultReader);
- } catch (err) {
- return PromiseReject(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 PromiseReject(err);
- }
-
- if (this[_stream] === undefined) {
- return PromiseReject(
- new TypeError("Reader has no associated stream."),
- );
- }
- return readableStreamReaderGenericCancel(this, reason);
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return `${this.constructor.name} ${inspect({ closed: this.closed })}`;
- }
-
- get [SymbolToStringTag]() {
- return "ReadableStreamDefaultReader";
- }
- }
-
- webidl.configurePrototype(ReadableStreamDefaultReader);
-
- class ReadableByteStreamController {
- /** @type {number | undefined} */
- [_autoAllocateChunkSize];
- /** @type {null} */
- [_byobRequest];
- /** @type {(reason: any) => Promise<void>} */
- [_cancelAlgorithm];
- /** @type {boolean} */
- [_closeRequested];
- /** @type {boolean} */
- [_pullAgain];
- /** @type {(controller: this) => Promise<void>} */
- [_pullAlgorithm];
- /** @type {boolean} */
- [_pulling];
- /** @type {ReadableByteStreamQueueEntry[]} */
- [_queue];
- /** @type {number} */
- [_queueTotalSize];
- /** @type {boolean} */
- [_started];
- /** @type {number} */
- [_strategyHWM];
- /** @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.");
- }
- if (this[_stream][_state] !== "readable") {
- throw new TypeError(
- "ReadableByteStreamController's stream is not in a readable state.",
- );
- }
- readableByteStreamControllerClose(this);
- }
-
- /**
- * @param {ArrayBufferView} chunk
- * @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 webidl.makeException(TypeError, "length must be non-zero", {
- prefix,
- context: arg1,
- });
- }
- if (chunk.buffer.byteLength === 0) {
- throw webidl.makeException(
- TypeError,
- "buffer length must be non-zero",
- { prefix, context: arg1 },
- );
- }
- if (this[_closeRequested] === true) {
- throw new TypeError(
- "Cannot enqueue chunk after a close has been requested.",
- );
- }
- if (this[_stream][_state] !== "readable") {
- throw new TypeError(
- "Cannot enqueue chunk when underlying stream is not readable.",
- );
- }
- return readableByteStreamControllerEnqueue(this, chunk);
- }
-
- /**
- * @param {any=} e
- * @returns {void}
- */
- error(e = undefined) {
- webidl.assertBranded(this, ReadableByteStreamController);
- if (e !== undefined) {
- e = webidl.converters.any(e);
- }
- readableByteStreamControllerError(this, e);
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof ReadableByteStreamController,
- keys: ["desiredSize"],
- }));
- }
-
- get [SymbolToStringTag]() {
- return "ReadableByteStreamController";
- }
-
- /**
- * @param {any} reason
- * @returns {Promise<void>}
- */
- [_cancelSteps](reason) {
- // 4.7.4. CancelStep 1. If this.[[pendingPullIntos]] is not empty,
- resetQueue(this);
- const result = this[_cancelAlgorithm](reason);
- readableByteStreamControllerClearAlgorithms(this);
- return result;
- }
-
- /**
- * @param {ReadRequest<ArrayBuffer>} readRequest
- * @returns {void}
- */
- [_pullSteps](readRequest) {
- /** @type {ReadableStream<ArrayBuffer>} */
- const stream = this[_stream];
- assert(readableStreamHasDefaultReader(stream));
- if (this[_queueTotalSize] > 0) {
- assert(readableStreamGetNumReadRequests(stream) === 0);
- const entry = ArrayPrototypeShift(this[_queue]);
- this[_queueTotalSize] -= entry.byteLength;
- readableByteStreamControllerHandleQueueDrain(this);
- const view = new Uint8Array(
- entry.buffer,
- entry.byteOffset,
- entry.byteLength,
- );
- readRequest.chunkSteps(view);
- return;
- }
- // 4. Let autoAllocateChunkSize be this.[[autoAllocateChunkSize]].
- // 5. If autoAllocateChunkSize is not undefined,
- readableStreamAddReadRequest(stream, readRequest);
- readableByteStreamControllerCallPullIfNeeded(this);
- }
- }
-
- webidl.configurePrototype(ReadableByteStreamController);
-
- /** @template R */
- class ReadableStreamDefaultController {
- /** @type {(reason: any) => Promise<void>} */
- [_cancelAlgorithm];
- /** @type {boolean} */
- [_closeRequested];
- /** @type {boolean} */
- [_pullAgain];
- /** @type {(controller: this) => Promise<void>} */
- [_pullAlgorithm];
- /** @type {boolean} */
- [_pulling];
- /** @type {Array<ValueWithSize<R>>} */
- [_queue];
- /** @type {number} */
- [_queueTotalSize];
- /** @type {boolean} */
- [_started];
- /** @type {number} */
- [_strategyHWM];
- /** @type {(chunk: R) => number} */
- [_strategySizeAlgorithm];
- /** @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.");
- }
- readableStreamDefaultControllerClose(this);
- }
-
- /**
- * @param {R} chunk
- * @returns {void}
- */
- 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.");
- }
- readableStreamDefaultControllerEnqueue(this, chunk);
- }
-
- /**
- * @param {any=} e
- * @returns {void}
- */
- error(e = undefined) {
- webidl.assertBranded(this, ReadableStreamDefaultController);
- if (e !== undefined) {
- e = webidl.converters.any(e);
- }
- readableStreamDefaultControllerError(this, e);
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof ReadableStreamDefaultController,
- keys: ["desiredSize"],
- }));
- }
-
- get [SymbolToStringTag]() {
- return "ReadableStreamDefaultController";
- }
-
- /**
- * @param {any} reason
- * @returns {Promise<void>}
- */
- [_cancelSteps](reason) {
- resetQueue(this);
- const result = this[_cancelAlgorithm](reason);
- readableStreamDefaultControllerClearAlgorithms(this);
- return result;
- }
-
- /**
- * @param {ReadRequest<R>} readRequest
- * @returns {void}
- */
- [_pullSteps](readRequest) {
- const stream = this[_stream];
- if (this[_queue].length) {
- const chunk = dequeueValue(this);
- if (this[_closeRequested] && this[_queue].length === 0) {
- readableStreamDefaultControllerClearAlgorithms(this);
- readableStreamClose(stream);
- } else {
- readableStreamDefaultControllerCallPullIfNeeded(this);
- }
- readRequest.chunkSteps(chunk);
- } else {
- readableStreamAddReadRequest(stream, readRequest);
- readableStreamDefaultControllerCallPullIfNeeded(this);
- }
- }
- }
-
- webidl.configurePrototype(ReadableStreamDefaultController);
-
- /**
- * @template I
- * @template O
- */
- class TransformStream {
- /** @type {boolean} */
- [_backpressure];
- /** @type {Deferred<void>} */
- [_backpressureChangePromise];
- /** @type {TransformStreamDefaultController<O>} */
- [_controller];
- /** @type {boolean} */
- [_detached];
- /** @type {ReadableStream<O>} */
- [_readable];
- /** @type {WritableStream<I>} */
- [_writable];
-
- /**
- *
- * @param {Transformer<I, O>} transformer
- * @param {QueuingStrategy<I>} writableStrategy
- * @param {QueuingStrategy<O>} readableStrategy
- */
- constructor(
- transformer = undefined,
- writableStrategy = {},
- readableStrategy = {},
- ) {
- const prefix = "Failed to construct 'TransformStream'";
- if (transformer !== undefined) {
- transformer = webidl.converters.object(transformer, {
- prefix,
- context: "Argument 1",
- });
- }
- 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);
- const writableHighWaterMark = extractHighWaterMark(writableStrategy, 1);
- const writableSizeAlgorithm = extractSizeAlgorithm(writableStrategy);
- /** @type {Deferred<void>} */
- const startPromise = new Deferred();
- initializeTransformStream(
- this,
- startPromise,
- writableHighWaterMark,
- writableSizeAlgorithm,
- readableHighWaterMark,
- readableSizeAlgorithm,
- );
- setUpTransformStreamDefaultControllerFromTransformer(
- this,
- transformer,
- transformerDict,
- );
- if (transformerDict.start) {
- startPromise.resolve(
- webidl.invokeCallbackFunction(
- transformerDict.start,
- [this[_controller]],
- transformer,
- webidl.converters.any,
- {
- prefix:
- "Failed to call 'start' on 'TransformStreamDefaultController'",
- },
- ),
- );
- } else {
- startPromise.resolve(undefined);
- }
- }
-
- /** @returns {ReadableStream<O>} */
- get readable() {
- webidl.assertBranded(this, TransformStream);
- return this[_readable];
- }
-
- /** @returns {WritableStream<I>} */
- get writable() {
- webidl.assertBranded(this, TransformStream);
- return this[_writable];
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return `${this.constructor.name} ${
- inspect({ readable: this.readable, writable: this.writable })
- }`;
- }
-
- get [SymbolToStringTag]() {
- return "TransformStream";
- }
- }
-
- webidl.configurePrototype(TransformStream);
-
- /** @template O */
- class TransformStreamDefaultController {
- /** @type {(controller: this) => Promise<void>} */
- [_flushAlgorithm];
- /** @type {TransformStream<O>} */
- [_stream];
- /** @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),
- );
- }
-
- /**
- * @param {O} chunk
- * @returns {void}
- */
- enqueue(chunk = undefined) {
- webidl.assertBranded(this, TransformStreamDefaultController);
- if (chunk !== undefined) {
- chunk = webidl.converters.any(chunk);
- }
- transformStreamDefaultControllerEnqueue(this, chunk);
- }
-
- /**
- * @param {any=} reason
- * @returns {void}
- */
- 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);
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof TransformStreamDefaultController,
- keys: ["desiredSize"],
- }));
- }
-
- get [SymbolToStringTag]() {
- return "TransformStreamDefaultController";
- }
- }
-
- webidl.configurePrototype(TransformStreamDefaultController);
-
- /** @template W */
- class WritableStream {
- /** @type {boolean} */
- [_backpressure];
- /** @type {Deferred<void> | undefined} */
- [_closeRequest];
- /** @type {WritableStreamDefaultController<W>} */
- [_controller];
- /** @type {boolean} */
- [_detached];
- /** @type {Deferred<void> | undefined} */
- [_inFlightWriteRequest];
- /** @type {Deferred<void> | undefined} */
- [_inFlightCloseRequest];
- /** @type {PendingAbortRequest | undefined} */
- [_pendingAbortRequest];
- /** @type {"writable" | "closed" | "erroring" | "errored"} */
- [_state];
- /** @type {any} */
- [_storedError];
- /** @type {WritableStreamDefaultWriter<W>} */
- [_writer];
- /** @type {Deferred<void>[]} */
- [_writeRequests];
-
- /**
- * @param {UnderlyingSink<W>=} underlyingSink
- * @param {QueuingStrategy<W>=} strategy
- */
- 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(
- `${prefix}: WritableStream does not support 'type' in the underlying sink.`,
- );
- }
- initializeWritableStream(this);
- const sizeAlgorithm = extractSizeAlgorithm(strategy);
- const highWaterMark = extractHighWaterMark(strategy, 1);
- setUpWritableStreamDefaultControllerFromUnderlyingSink(
- this,
- underlyingSink,
- underlyingSinkDict,
- highWaterMark,
- sizeAlgorithm,
- );
- }
-
- /** @returns {boolean} */
- get locked() {
- webidl.assertBranded(this, WritableStream);
- return isWritableStreamLocked(this);
- }
-
- /**
- * @param {any=} reason
- * @returns {Promise<void>}
- */
- abort(reason = undefined) {
- try {
- webidl.assertBranded(this, WritableStream);
- } catch (err) {
- return PromiseReject(err);
- }
- if (reason !== undefined) {
- reason = webidl.converters.any(reason);
- }
- if (isWritableStreamLocked(this)) {
- return PromiseReject(
- new TypeError(
- "The writable stream is locked, therefore cannot be aborted.",
- ),
- );
- }
- return writableStreamAbort(this, reason);
- }
-
- /** @returns {Promise<void>} */
- close() {
- try {
- webidl.assertBranded(this, WritableStream);
- } catch (err) {
- return PromiseReject(err);
- }
- if (isWritableStreamLocked(this)) {
- return PromiseReject(
- new TypeError(
- "The writable stream is locked, therefore cannot be closed.",
- ),
- );
- }
- if (writableStreamCloseQueuedOrInFlight(this) === true) {
- return PromiseReject(
- new TypeError("The writable stream is already closing."),
- );
- }
- return writableStreamClose(this);
- }
-
- /** @returns {WritableStreamDefaultWriter<W>} */
- getWriter() {
- webidl.assertBranded(this, WritableStream);
- return acquireWritableStreamDefaultWriter(this);
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return `${this.constructor.name} ${inspect({ locked: this.locked })}`;
- }
-
- get [SymbolToStringTag]() {
- return "WritableStream";
- }
- }
-
- webidl.configurePrototype(WritableStream);
-
- /** @template W */
- class WritableStreamDefaultWriter {
- /** @type {Deferred<void>} */
- [_closedPromise];
-
- /** @type {Deferred<void>} */
- [_readyPromise];
-
- /** @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 PromiseReject(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.",
- );
- }
- return writableStreamDefaultWriterGetDesiredSize(this);
- }
-
- /** @returns {Promise<void>} */
- get ready() {
- try {
- webidl.assertBranded(this, WritableStreamDefaultWriter);
- } catch (err) {
- return PromiseReject(err);
- }
- return this[_readyPromise].promise;
- }
-
- /**
- * @param {any} reason
- * @returns {Promise<void>}
- */
- abort(reason = undefined) {
- try {
- webidl.assertBranded(this, WritableStreamDefaultWriter);
- } catch (err) {
- return PromiseReject(err);
- }
- if (reason !== undefined) {
- reason = webidl.converters.any(reason);
- }
- if (this[_stream] === undefined) {
- return PromiseReject(
- new TypeError("A writable stream is not associated with the writer."),
- );
- }
- return writableStreamDefaultWriterAbort(this, reason);
- }
-
- /** @returns {Promise<void>} */
- close() {
- try {
- webidl.assertBranded(this, WritableStreamDefaultWriter);
- } catch (err) {
- return PromiseReject(err);
- }
- const stream = this[_stream];
- if (stream === undefined) {
- return PromiseReject(
- new TypeError("A writable stream is not associated with the writer."),
- );
- }
- if (writableStreamCloseQueuedOrInFlight(stream) === true) {
- return PromiseReject(
- new TypeError("The associated stream is already closing."),
- );
- }
- return writableStreamDefaultWriterClose(this);
- }
-
- /** @returns {void} */
- releaseLock() {
- webidl.assertBranded(this, WritableStreamDefaultWriter);
- const stream = this[_stream];
- if (stream === undefined) {
- return;
- }
- assert(stream[_writer] !== undefined);
- writableStreamDefaultWriterRelease(this);
- }
-
- /**
- * @param {W} chunk
- * @returns {Promise<void>}
- */
- write(chunk = undefined) {
- try {
- webidl.assertBranded(this, WritableStreamDefaultWriter);
- if (chunk !== undefined) {
- chunk = webidl.converters.any(chunk);
- }
- } catch (err) {
- return PromiseReject(err);
- }
- if (this[_stream] === undefined) {
- return PromiseReject(
- new TypeError("A writable stream is not associate with the writer."),
- );
- }
- return writableStreamDefaultWriterWrite(this, chunk);
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof WritableStreamDefaultWriter,
- keys: [
- "closed",
- "desiredSize",
- "ready",
- ],
- }));
- }
-
- get [SymbolToStringTag]() {
- return "WritableStreamDefaultWriter";
- }
- }
-
- webidl.configurePrototype(WritableStreamDefaultWriter);
-
- /** @template W */
- class WritableStreamDefaultController {
- /** @type {(reason?: any) => Promise<void>} */
- [_abortAlgorithm];
- /** @type {() => Promise<void>} */
- [_closeAlgorithm];
- /** @type {ValueWithSize<W | _close>[]} */
- [_queue];
- /** @type {number} */
- [_queueTotalSize];
- /** @type {boolean} */
- [_started];
- /** @type {number} */
- [_strategyHWM];
- /** @type {(chunk: W) => number} */
- [_strategySizeAlgorithm];
- /** @type {WritableStream<W>} */
- [_stream];
- /** @type {(chunk: W, controller: this) => Promise<void>} */
- [_writeAlgorithm];
-
- constructor() {
- webidl.illegalConstructor();
- }
-
- /**
- * @param {any=} e
- * @returns {void}
- */
- error(e = undefined) {
- webidl.assertBranded(this, WritableStreamDefaultController);
- if (e !== undefined) {
- e = webidl.converters.any(e);
- }
- const state = this[_stream][_state];
- if (state !== "writable") {
- return;
- }
- writableStreamDefaultControllerError(this, e);
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof WritableStreamDefaultController,
- keys: [],
- }));
- }
-
- get [SymbolToStringTag]() {
- return "WritableStreamDefaultController";
- }
-
- /**
- * @param {any=} reason
- * @returns {Promise<void>}
- */
- [_abortSteps](reason) {
- const result = this[_abortAlgorithm](reason);
- writableStreamDefaultControllerClearAlgorithms(this);
- return result;
- }
-
- [_errorSteps]() {
- resetQueue(this);
- }
- }
-
- webidl.configurePrototype(WritableStreamDefaultController);
-
- /**
- * @param {ReadableStream} stream
- */
- function createProxy(stream) {
- return stream.pipeThrough(new TransformStream());
- }
-
- 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,
- errorReadableStream,
- createProxy,
- writableStreamClose,
- Deferred,
- // Exposed in global runtime scope
- ByteLengthQueuingStrategy,
- CountQueuingStrategy,
- ReadableStream,
- ReadableStreamDefaultReader,
- TransformStream,
- WritableStream,
- WritableStreamDefaultWriter,
- WritableStreamDefaultController,
- ReadableByteStreamController,
- ReadableStreamDefaultController,
- TransformStreamDefaultController,
- };
-})(this);
diff --git a/extensions/web/06_streams_types.d.ts b/extensions/web/06_streams_types.d.ts
deleted file mode 100644
index 61621c003..000000000
--- a/extensions/web/06_streams_types.d.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// ** Internal Interfaces **
-
-interface PendingAbortRequest {
- deferred: Deferred<void>;
- // deno-lint-ignore no-explicit-any
- reason: any;
- wasAlreadyErroring: boolean;
-}
-
-// deno-lint-ignore no-explicit-any
-interface ReadRequest<R = any> {
- chunkSteps: (chunk: R) => void;
- closeSteps: () => void;
- // deno-lint-ignore no-explicit-any
- errorSteps: (error: any) => void;
-}
-
-interface ReadableByteStreamQueueEntry {
- buffer: ArrayBufferLike;
- byteOffset: number;
- byteLength: number;
-}
-
-interface ReadableStreamGetReaderOptions {
- mode?: "byob";
-}
-
-interface ReadableStreamIteratorOptions {
- preventCancel?: boolean;
-}
-
-interface ValueWithSize<T> {
- value: T;
- size: number;
-}
-
-interface VoidFunction {
- (): void;
-}
-
-interface ReadableStreamGenericReader<T> {
- readonly closed: Promise<void>;
- // deno-lint-ignore no-explicit-any
- cancel(reason?: any): Promise<void>;
-}
-
-// ** Ambient Definitions and Interfaces not provided by fetch **
-
-declare function queueMicrotask(callback: VoidFunction): void;
-
-declare namespace Deno {
- function inspect(value: unknown, options?: Record<string, unknown>): string;
-}
diff --git a/extensions/web/08_text_encoding.js b/extensions/web/08_text_encoding.js
deleted file mode 100644
index 9be4aa753..000000000
--- a/extensions/web/08_text_encoding.js
+++ /dev/null
@@ -1,420 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../../core/internal.d.ts" />
-/// <reference path="../webidl/internal.d.ts" />
-/// <reference path="../fetch/lib.deno_fetch.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-/// <reference lib="esnext" />
-
-"use strict";
-
-((window) => {
- const core = Deno.core;
- const webidl = window.__bootstrap.webidl;
- const {
- ArrayBufferIsView,
- PromiseReject,
- PromiseResolve,
- StringPrototypeCharCodeAt,
- StringPrototypeSlice,
- SymbolToStringTag,
- TypedArrayPrototypeSubarray,
- TypedArrayPrototypeSlice,
- Uint8Array,
- } = window.__bootstrap.primordials;
-
- class TextDecoder {
- /** @type {string} */
- #encoding;
- /** @type {boolean} */
- #fatal;
- /** @type {boolean} */
- #ignoreBOM;
-
- /** @type {number | null} */
- #rid = null;
-
- /**
- *
- * @param {string} label
- * @param {TextDecoderOptions} options
- */
- constructor(label = "utf-8", options = {}) {
- const prefix = "Failed to construct 'TextDecoder'";
- label = webidl.converters.DOMString(label, {
- prefix,
- context: "Argument 1",
- });
- options = webidl.converters.TextDecoderOptions(options, {
- prefix,
- context: "Argument 2",
- });
- const encoding = core.opSync("op_encoding_normalize_label", label);
- this.#encoding = encoding;
- this.#fatal = options.fatal;
- this.#ignoreBOM = options.ignoreBOM;
- this[webidl.brand] = webidl.brand;
- }
-
- /** @returns {string} */
- get encoding() {
- webidl.assertBranded(this, TextDecoder);
- return this.#encoding;
- }
-
- /** @returns {boolean} */
- get fatal() {
- webidl.assertBranded(this, TextDecoder);
- return this.#fatal;
- }
-
- /** @returns {boolean} */
- get ignoreBOM() {
- webidl.assertBranded(this, TextDecoder);
- return this.#ignoreBOM;
- }
-
- /**
- * @param {BufferSource} [input]
- * @param {TextDecodeOptions} options
- */
- decode(input = new Uint8Array(), options = {}) {
- webidl.assertBranded(this, TextDecoder);
- const prefix = "Failed to execute 'decode' on 'TextDecoder'";
- if (input !== undefined) {
- input = webidl.converters.BufferSource(input, {
- prefix,
- context: "Argument 1",
- allowShared: true,
- });
- }
- options = webidl.converters.TextDecodeOptions(options, {
- prefix,
- context: "Argument 2",
- });
-
- // TODO(lucacasonato): add fast path for non-streaming decoder & decode
-
- if (this.#rid === null) {
- this.#rid = core.opSync("op_encoding_new_decoder", {
- label: this.#encoding,
- fatal: this.#fatal,
- ignoreBom: this.#ignoreBOM,
- });
- }
-
- try {
- if (ArrayBufferIsView(input)) {
- input = new Uint8Array(
- input.buffer,
- input.byteOffset,
- input.byteLength,
- );
- } else {
- input = new Uint8Array(input);
- }
- return core.opSync("op_encoding_decode", new Uint8Array(input), {
- rid: this.#rid,
- stream: options.stream,
- });
- } finally {
- if (!options.stream) {
- core.close(this.#rid);
- this.#rid = null;
- }
- }
- }
-
- get [SymbolToStringTag]() {
- return "TextDecoder";
- }
- }
-
- webidl.configurePrototype(TextDecoder);
-
- class TextEncoder {
- constructor() {
- this[webidl.brand] = webidl.brand;
- }
-
- /** @returns {string} */
- get encoding() {
- webidl.assertBranded(this, TextEncoder);
- return "utf-8";
- }
-
- /**
- * @param {string} input
- * @returns {Uint8Array}
- */
- encode(input = "") {
- webidl.assertBranded(this, TextEncoder);
- const prefix = "Failed to execute 'encode' on 'TextEncoder'";
- // The WebIDL type of `input` is `USVString`, but `core.encode` already
- // converts lone surrogates to the replacement character.
- input = webidl.converters.DOMString(input, {
- prefix,
- context: "Argument 1",
- });
- return core.encode(input);
- }
-
- /**
- * @param {string} source
- * @param {Uint8Array} destination
- * @returns {TextEncoderEncodeIntoResult}
- */
- encodeInto(source, destination) {
- webidl.assertBranded(this, TextEncoder);
- const prefix = "Failed to execute 'encodeInto' on 'TextEncoder'";
- // The WebIDL type of `source` is `USVString`, but the ops bindings
- // already convert lone surrogates to the replacement character.
- source = webidl.converters.DOMString(source, {
- prefix,
- context: "Argument 1",
- });
- destination = webidl.converters.Uint8Array(destination, {
- prefix,
- context: "Argument 2",
- allowShared: true,
- });
- return core.opSync("op_encoding_encode_into", source, destination);
- }
-
- get [SymbolToStringTag]() {
- return "TextEncoder";
- }
- }
-
- webidl.configurePrototype(TextEncoder);
-
- class TextDecoderStream {
- /** @type {TextDecoder} */
- #decoder;
- /** @type {TransformStream<BufferSource, string>} */
- #transform;
-
- /**
- *
- * @param {string} label
- * @param {TextDecoderOptions} options
- */
- constructor(label = "utf-8", options = {}) {
- const prefix = "Failed to construct 'TextDecoderStream'";
- label = webidl.converters.DOMString(label, {
- prefix,
- context: "Argument 1",
- });
- options = webidl.converters.TextDecoderOptions(options, {
- prefix,
- context: "Argument 2",
- });
- this.#decoder = new TextDecoder(label, options);
- this.#transform = new TransformStream({
- // The transform and flush functions need access to TextDecoderStream's
- // `this`, so they are defined as functions rather than methods.
- transform: (chunk, controller) => {
- try {
- chunk = webidl.converters.BufferSource(chunk, {
- allowShared: true,
- });
- const decoded = this.#decoder.decode(chunk, { stream: true });
- if (decoded) {
- controller.enqueue(decoded);
- }
- return PromiseResolve();
- } catch (err) {
- return PromiseReject(err);
- }
- },
- flush: (controller) => {
- try {
- const final = this.#decoder.decode();
- if (final) {
- controller.enqueue(final);
- }
- return PromiseResolve();
- } catch (err) {
- return PromiseReject(err);
- }
- },
- });
- this[webidl.brand] = webidl.brand;
- }
-
- /** @returns {string} */
- get encoding() {
- webidl.assertBranded(this, TextDecoderStream);
- return this.#decoder.encoding;
- }
-
- /** @returns {boolean} */
- get fatal() {
- webidl.assertBranded(this, TextDecoderStream);
- return this.#decoder.fatal;
- }
-
- /** @returns {boolean} */
- get ignoreBOM() {
- webidl.assertBranded(this, TextDecoderStream);
- return this.#decoder.ignoreBOM;
- }
-
- /** @returns {ReadableStream<string>} */
- get readable() {
- webidl.assertBranded(this, TextDecoderStream);
- return this.#transform.readable;
- }
-
- /** @returns {WritableStream<BufferSource>} */
- get writable() {
- webidl.assertBranded(this, TextDecoderStream);
- return this.#transform.writable;
- }
-
- get [SymbolToStringTag]() {
- return "TextDecoderStream";
- }
- }
-
- webidl.configurePrototype(TextDecoderStream);
-
- class TextEncoderStream {
- /** @type {string | null} */
- #pendingHighSurrogate = null;
- /** @type {TransformStream<string, Uint8Array>} */
- #transform;
-
- constructor() {
- this.#transform = new TransformStream({
- // The transform and flush functions need access to TextEncoderStream's
- // `this`, so they are defined as functions rather than methods.
- transform: (chunk, controller) => {
- try {
- chunk = webidl.converters.DOMString(chunk);
- if (this.#pendingHighSurrogate !== null) {
- chunk = this.#pendingHighSurrogate + chunk;
- }
- const lastCodeUnit = StringPrototypeCharCodeAt(
- chunk,
- chunk.length - 1,
- );
- if (0xD800 <= lastCodeUnit && lastCodeUnit <= 0xDBFF) {
- this.#pendingHighSurrogate = StringPrototypeSlice(chunk, -1);
- chunk = StringPrototypeSlice(chunk, 0, -1);
- } else {
- this.#pendingHighSurrogate = null;
- }
- if (chunk) {
- controller.enqueue(core.encode(chunk));
- }
- return PromiseResolve();
- } catch (err) {
- return PromiseReject(err);
- }
- },
- flush: (controller) => {
- try {
- if (this.#pendingHighSurrogate !== null) {
- controller.enqueue(new Uint8Array([0xEF, 0xBF, 0xBD]));
- }
- return PromiseResolve();
- } catch (err) {
- return PromiseReject(err);
- }
- },
- });
- this[webidl.brand] = webidl.brand;
- }
-
- /** @returns {string} */
- get encoding() {
- webidl.assertBranded(this, TextEncoderStream);
- return "utf-8";
- }
-
- /** @returns {ReadableStream<Uint8Array>} */
- get readable() {
- webidl.assertBranded(this, TextEncoderStream);
- return this.#transform.readable;
- }
-
- /** @returns {WritableStream<string>} */
- get writable() {
- webidl.assertBranded(this, TextEncoderStream);
- return this.#transform.writable;
- }
-
- get [SymbolToStringTag]() {
- return "TextEncoderStream";
- }
- }
-
- webidl.configurePrototype(TextEncoderStream);
-
- webidl.converters.TextDecoderOptions = webidl.createDictionaryConverter(
- "TextDecoderOptions",
- [
- {
- key: "fatal",
- converter: webidl.converters.boolean,
- defaultValue: false,
- },
- {
- key: "ignoreBOM",
- converter: webidl.converters.boolean,
- defaultValue: false,
- },
- ],
- );
- webidl.converters.TextDecodeOptions = webidl.createDictionaryConverter(
- "TextDecodeOptions",
- [
- {
- key: "stream",
- converter: webidl.converters.boolean,
- defaultValue: false,
- },
- ],
- );
-
- /**
- * @param {Uint8Array} bytes
- */
- function decode(bytes, encoding) {
- const BOMEncoding = BOMSniff(bytes);
- let start = 0;
- if (BOMEncoding !== null) {
- encoding = BOMEncoding;
- if (BOMEncoding === "UTF-8") start = 3;
- else start = 2;
- }
- return new TextDecoder(encoding).decode(
- TypedArrayPrototypeSlice(bytes, start),
- );
- }
-
- /**
- * @param {Uint8Array} bytes
- */
- function BOMSniff(bytes) {
- const BOM = TypedArrayPrototypeSubarray(bytes, 0, 3);
- if (BOM[0] === 0xEF && BOM[1] === 0xBB && BOM[2] === 0xBF) {
- return "UTF-8";
- }
- if (BOM[0] === 0xFE && BOM[1] === 0xFF) return "UTF-16BE";
- if (BOM[0] === 0xFF && BOM[1] === 0xFE) return "UTF-16LE";
- return null;
- }
-
- window.__bootstrap.encoding = {
- TextEncoder,
- TextDecoder,
- TextEncoderStream,
- TextDecoderStream,
- decode,
- };
-})(this);
diff --git a/extensions/web/09_file.js b/extensions/web/09_file.js
deleted file mode 100644
index 516e80adf..000000000
--- a/extensions/web/09_file.js
+++ /dev/null
@@ -1,569 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference no-default-lib="true" />
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../../core/internal.d.ts" />
-/// <reference path="../webidl/internal.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-/// <reference path="./internal.d.ts" />
-/// <reference lib="esnext" />
-"use strict";
-
-((window) => {
- const core = window.Deno.core;
- const webidl = window.__bootstrap.webidl;
- const {
- ArrayBuffer,
- ArrayBufferPrototypeSlice,
- ArrayBufferIsView,
- ArrayPrototypePush,
- Date,
- DatePrototypeGetTime,
- MathMax,
- MathMin,
- RegExpPrototypeTest,
- StringPrototypeCharAt,
- StringPrototypeToLowerCase,
- StringPrototypeSlice,
- Symbol,
- SymbolFor,
- TypedArrayPrototypeSet,
- SymbolToStringTag,
- TypeError,
- Uint8Array,
- } = window.__bootstrap.primordials;
- const consoleInternal = window.__bootstrap.console;
-
- // TODO(lucacasonato): this needs to not be hardcoded and instead depend on
- // host os.
- const isWindows = false;
-
- /**
- * @param {string} input
- * @param {number} position
- * @returns {{result: string, position: number}}
- */
- function collectCodepointsNotCRLF(input, position) {
- // See https://w3c.github.io/FileAPI/#convert-line-endings-to-native and
- // https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
- const start = position;
- for (
- let c = StringPrototypeCharAt(input, position);
- position < input.length && !(c === "\r" || c === "\n");
- c = StringPrototypeCharAt(input, ++position)
- );
- return { result: StringPrototypeSlice(input, start, position), position };
- }
-
- /**
- * @param {string} s
- * @returns {string}
- */
- function convertLineEndingsToNative(s) {
- const nativeLineEnding = isWindows ? "\r\n" : "\n";
-
- let { result, position } = collectCodepointsNotCRLF(s, 0);
-
- while (position < s.length) {
- const codePoint = StringPrototypeCharAt(s, position);
- if (codePoint === "\r") {
- result += nativeLineEnding;
- position++;
- if (
- position < s.length && StringPrototypeCharAt(s, position) === "\n"
- ) {
- position++;
- }
- } else if (codePoint === "\n") {
- position++;
- result += nativeLineEnding;
- }
- const { result: token, position: newPosition } = collectCodepointsNotCRLF(
- s,
- position,
- );
- position = newPosition;
- result += token;
- }
-
- return result;
- }
-
- /** @param {(BlobReference | Blob)[]} parts */
- async function* toIterator(parts) {
- for (const part of parts) {
- yield* part.stream();
- }
- }
-
- /** @typedef {BufferSource | Blob | string} BlobPart */
-
- /**
- * @param {BlobPart[]} parts
- * @param {string} endings
- * @returns {{ parts: (BlobReference|Blob)[], size: number }}
- */
- function processBlobParts(parts, endings) {
- /** @type {(BlobReference|Blob)[]} */
- const processedParts = [];
- let size = 0;
- for (const element of parts) {
- if (element instanceof ArrayBuffer) {
- const chunk = new Uint8Array(ArrayBufferPrototypeSlice(element, 0));
- ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
- size += element.byteLength;
- } else if (ArrayBufferIsView(element)) {
- const chunk = new Uint8Array(
- element.buffer,
- element.byteOffset,
- element.byteLength,
- );
- size += element.byteLength;
- ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
- } else if (element instanceof Blob) {
- ArrayPrototypePush(processedParts, element);
- size += element.size;
- } else if (typeof element === "string") {
- const chunk = core.encode(
- endings == "native" ? convertLineEndingsToNative(element) : element,
- );
- size += chunk.byteLength;
- ArrayPrototypePush(processedParts, BlobReference.fromUint8Array(chunk));
- } else {
- throw new TypeError("Unreachable code (invalid element type)");
- }
- }
- return { parts: processedParts, size };
- }
-
- /**
- * @param {string} str
- * @returns {string}
- */
- function normalizeType(str) {
- let normalizedType = str;
- if (!RegExpPrototypeTest(/^[\x20-\x7E]*$/, str)) {
- normalizedType = "";
- }
- return StringPrototypeToLowerCase(normalizedType);
- }
-
- /**
- * Get all Parts as a flat array containing all references
- * @param {Blob} blob
- * @param {string[]} bag
- * @returns {string[]}
- */
- function getParts(blob, bag = []) {
- for (const part of blob[_parts]) {
- if (part instanceof Blob) {
- getParts(part, bag);
- } else {
- ArrayPrototypePush(bag, part._id);
- }
- }
- return bag;
- }
-
- const _size = Symbol("Size");
- const _parts = Symbol("Parts");
-
- class Blob {
- #type = "";
- [_size] = 0;
- [_parts];
-
- /**
- * @param {BlobPart[]} blobParts
- * @param {BlobPropertyBag} options
- */
- constructor(blobParts = [], options = {}) {
- const prefix = "Failed to construct 'Blob'";
- blobParts = webidl.converters["sequence<BlobPart>"](blobParts, {
- context: "Argument 1",
- prefix,
- });
- options = webidl.converters["BlobPropertyBag"](options, {
- context: "Argument 2",
- prefix,
- });
-
- this[webidl.brand] = webidl.brand;
-
- const { parts, size } = processBlobParts(
- blobParts,
- options.endings,
- );
-
- this[_parts] = parts;
- this[_size] = size;
- this.#type = normalizeType(options.type);
- }
-
- /** @returns {number} */
- get size() {
- webidl.assertBranded(this, Blob);
- return this[_size];
- }
-
- /** @returns {string} */
- get type() {
- webidl.assertBranded(this, Blob);
- return this.#type;
- }
-
- /**
- * @param {number} [start]
- * @param {number} [end]
- * @param {string} [contentType]
- * @returns {Blob}
- */
- slice(start, end, contentType) {
- webidl.assertBranded(this, Blob);
- const prefix = "Failed to execute 'slice' on 'Blob'";
- if (start !== undefined) {
- start = webidl.converters["long long"](start, {
- clamp: true,
- context: "Argument 1",
- prefix,
- });
- }
- if (end !== undefined) {
- end = webidl.converters["long long"](end, {
- clamp: true,
- context: "Argument 2",
- prefix,
- });
- }
- if (contentType !== undefined) {
- contentType = webidl.converters["DOMString"](contentType, {
- context: "Argument 3",
- prefix,
- });
- }
-
- // deno-lint-ignore no-this-alias
- const O = this;
- /** @type {number} */
- let relativeStart;
- if (start === undefined) {
- relativeStart = 0;
- } else {
- if (start < 0) {
- relativeStart = MathMax(O.size + start, 0);
- } else {
- relativeStart = MathMin(start, O.size);
- }
- }
- /** @type {number} */
- let relativeEnd;
- if (end === undefined) {
- relativeEnd = O.size;
- } else {
- if (end < 0) {
- relativeEnd = MathMax(O.size + end, 0);
- } else {
- relativeEnd = MathMin(end, O.size);
- }
- }
-
- const span = MathMax(relativeEnd - relativeStart, 0);
- const blobParts = [];
- let added = 0;
-
- for (const part of this[_parts]) {
- // don't add the overflow to new blobParts
- if (added >= span) {
- // Could maybe be possible to remove variable `added`
- // and only use relativeEnd?
- break;
- }
- const size = part.size;
- if (relativeStart && size <= relativeStart) {
- // Skip the beginning and change the relative
- // start & end position as we skip the unwanted parts
- relativeStart -= size;
- relativeEnd -= size;
- } else {
- const chunk = part.slice(
- relativeStart,
- MathMin(part.size, relativeEnd),
- );
- added += chunk.size;
- relativeEnd -= part.size;
- ArrayPrototypePush(blobParts, chunk);
- relativeStart = 0; // All next sequential parts should start at 0
- }
- }
-
- /** @type {string} */
- let relativeContentType;
- if (contentType === undefined) {
- relativeContentType = "";
- } else {
- relativeContentType = normalizeType(contentType);
- }
-
- const blob = new Blob([], { type: relativeContentType });
- blob[_parts] = blobParts;
- blob[_size] = span;
- return blob;
- }
-
- /**
- * @returns {ReadableStream<Uint8Array>}
- */
- stream() {
- webidl.assertBranded(this, Blob);
- const partIterator = toIterator(this[_parts]);
- const stream = new ReadableStream({
- type: "bytes",
- /** @param {ReadableByteStreamController} controller */
- async pull(controller) {
- while (true) {
- const { value, done } = await partIterator.next();
- if (done) return controller.close();
- if (value.byteLength > 0) {
- return controller.enqueue(value);
- }
- }
- },
- });
- return stream;
- }
-
- /**
- * @returns {Promise<string>}
- */
- async text() {
- webidl.assertBranded(this, Blob);
- const buffer = await this.arrayBuffer();
- return core.decode(new Uint8Array(buffer));
- }
-
- /**
- * @returns {Promise<ArrayBuffer>}
- */
- async arrayBuffer() {
- webidl.assertBranded(this, Blob);
- const stream = this.stream();
- const bytes = new Uint8Array(this.size);
- let offset = 0;
- for await (const chunk of stream) {
- TypedArrayPrototypeSet(bytes, chunk, offset);
- offset += chunk.byteLength;
- }
- return bytes.buffer;
- }
-
- get [SymbolToStringTag]() {
- return "Blob";
- }
-
- [SymbolFor("Deno.customInspect")](inspect) {
- return inspect(consoleInternal.createFilteredInspectProxy({
- object: this,
- evaluate: this instanceof Blob,
- keys: [
- "size",
- "type",
- ],
- }));
- }
- }
-
- webidl.configurePrototype(Blob);
-
- webidl.converters["Blob"] = webidl.createInterfaceConverter("Blob", Blob);
- webidl.converters["BlobPart"] = (V, opts) => {
- // Union for ((ArrayBuffer or ArrayBufferView) or Blob or USVString)
- if (typeof V == "object") {
- if (V instanceof Blob) {
- return webidl.converters["Blob"](V, opts);
- }
- if (V instanceof ArrayBuffer || V instanceof SharedArrayBuffer) {
- return webidl.converters["ArrayBuffer"](V, opts);
- }
- if (ArrayBufferIsView(V)) {
- return webidl.converters["ArrayBufferView"](V, opts);
- }
- }
- return webidl.converters["USVString"](V, opts);
- };
- webidl.converters["sequence<BlobPart>"] = webidl.createSequenceConverter(
- webidl.converters["BlobPart"],
- );
- webidl.converters["EndingType"] = webidl.createEnumConverter("EndingType", [
- "transparent",
- "native",
- ]);
- const blobPropertyBagDictionary = [
- {
- key: "type",
- converter: webidl.converters["DOMString"],
- defaultValue: "",
- },
- {
- key: "endings",
- converter: webidl.converters["EndingType"],
- defaultValue: "transparent",
- },
- ];
- webidl.converters["BlobPropertyBag"] = webidl.createDictionaryConverter(
- "BlobPropertyBag",
- blobPropertyBagDictionary,
- );
-
- const _Name = Symbol("[[Name]]");
- const _LastModified = Symbol("[[LastModified]]");
-
- class File extends Blob {
- /** @type {string} */
- [_Name];
- /** @type {number} */
- [_LastModified];
-
- /**
- * @param {BlobPart[]} fileBits
- * @param {string} fileName
- * @param {FilePropertyBag} options
- */
- constructor(fileBits, fileName, options = {}) {
- const prefix = "Failed to construct 'File'";
- webidl.requiredArguments(arguments.length, 2, { prefix });
-
- fileBits = webidl.converters["sequence<BlobPart>"](fileBits, {
- context: "Argument 1",
- prefix,
- });
- fileName = webidl.converters["USVString"](fileName, {
- context: "Argument 2",
- prefix,
- });
- options = webidl.converters["FilePropertyBag"](options, {
- context: "Argument 3",
- prefix,
- });
-
- super(fileBits, options);
-
- /** @type {string} */
- this[_Name] = fileName;
- if (options.lastModified === undefined) {
- /** @type {number} */
- this[_LastModified] = DatePrototypeGetTime(new Date());
- } else {
- /** @type {number} */
- this[_LastModified] = options.lastModified;
- }
- }
-
- /** @returns {string} */
- get name() {
- webidl.assertBranded(this, File);
- return this[_Name];
- }
-
- /** @returns {number} */
- get lastModified() {
- webidl.assertBranded(this, File);
- return this[_LastModified];
- }
-
- get [SymbolToStringTag]() {
- return "File";
- }
- }
-
- webidl.configurePrototype(File);
-
- webidl.converters["FilePropertyBag"] = webidl.createDictionaryConverter(
- "FilePropertyBag",
- blobPropertyBagDictionary,
- [
- {
- key: "lastModified",
- converter: webidl.converters["long long"],
- },
- ],
- );
-
- // A finalization registry to deallocate a blob part when its JS reference is
- // garbage collected.
- const registry = new FinalizationRegistry((uuid) => {
- core.opSync("op_blob_remove_part", uuid);
- });
-
- // TODO(lucacasonato): get a better stream from Rust in BlobReference#stream
-
- /**
- * An opaque reference to a blob part in Rust. This could be backed by a file,
- * in memory storage, or something else.
- */
- class BlobReference {
- /**
- * Don't use directly. Use `BlobReference.fromUint8Array`.
- * @param {string} id
- * @param {number} size
- */
- constructor(id, size) {
- this._id = id;
- this.size = size;
- registry.register(this, id);
- }
-
- /**
- * Create a new blob part from a Uint8Array.
- *
- * @param {Uint8Array} data
- * @returns {BlobReference}
- */
- static fromUint8Array(data) {
- const id = core.opSync("op_blob_create_part", data);
- return new BlobReference(id, data.byteLength);
- }
-
- /**
- * Create a new BlobReference by slicing this BlobReference. This is a copy
- * free operation - the sliced reference will still reference the original
- * underlying bytes.
- *
- * @param {number} start
- * @param {number} end
- * @returns {BlobReference}
- */
- slice(start, end) {
- const size = end - start;
- const id = core.opSync("op_blob_slice_part", this._id, {
- start,
- len: size,
- });
- return new BlobReference(id, size);
- }
-
- /**
- * Read the entire contents of the reference blob.
- * @returns {AsyncGenerator<Uint8Array>}
- */
- async *stream() {
- yield core.opAsync("op_blob_read_part", this._id);
-
- // let position = 0;
- // const end = this.size;
- // while (position !== end) {
- // const size = MathMin(end - position, 65536);
- // const chunk = this.slice(position, position + size);
- // position += chunk.size;
- // yield core.opAsync("op_blob_read_part", chunk._id);
- // }
- }
- }
-
- window.__bootstrap.file = {
- getParts,
- Blob,
- File,
- };
-})(this);
diff --git a/extensions/web/10_filereader.js b/extensions/web/10_filereader.js
deleted file mode 100644
index 13fe6af2d..000000000
--- a/extensions/web/10_filereader.js
+++ /dev/null
@@ -1,461 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference no-default-lib="true" />
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../../core/internal.d.ts" />
-/// <reference path="../webidl/internal.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-/// <reference path="./internal.d.ts" />
-/// <reference lib="esnext" />
-
-"use strict";
-
-((window) => {
- const webidl = window.__bootstrap.webidl;
- const { forgivingBase64Encode } = window.__bootstrap.infra;
- const { decode, TextDecoder } = window.__bootstrap.encoding;
- const { parseMimeType } = window.__bootstrap.mimesniff;
- const { DOMException } = window.__bootstrap.domException;
- const {
- ArrayPrototypeJoin,
- ArrayPrototypeMap,
- ArrayPrototypePush,
- ArrayPrototypeReduce,
- FunctionPrototypeCall,
- Map,
- MapPrototypeGet,
- MapPrototypeSet,
- ObjectDefineProperty,
- queueMicrotask,
- StringFromCodePoint,
- Symbol,
- SymbolToStringTag,
- TypedArrayPrototypeSet,
- TypeError,
- Uint8Array,
- } = window.__bootstrap.primordials;
-
- const state = Symbol("[[state]]");
- const result = Symbol("[[result]]");
- const error = Symbol("[[error]]");
- const aborted = Symbol("[[aborted]]");
-
- class FileReader extends EventTarget {
- get [SymbolToStringTag]() {
- return "FileReader";
- }
-
- /** @type {"empty" | "loading" | "done"} */
- [state] = "empty";
- /** @type {null | string | ArrayBuffer} */
- [result] = null;
- /** @type {null | DOMException} */
- [error] = null;
- /** @type {null | {aborted: boolean}} */
- [aborted] = null;
-
- /**
- * @param {Blob} blob
- * @param {{kind: "ArrayBuffer" | "Text" | "DataUrl" | "BinaryString", encoding?: string}} readtype
- */
- #readOperation(blob, readtype) {
- // 1. If fr’s state is "loading", throw an InvalidStateError DOMException.
- if (this[state] === "loading") {
- throw new DOMException(
- "Invalid FileReader state.",
- "InvalidStateError",
- );
- }
- // 2. Set fr’s state to "loading".
- this[state] = "loading";
- // 3. Set fr’s result to null.
- this[result] = null;
- // 4. Set fr’s error to null.
- this[error] = null;
-
- // We set this[aborted] to a new object, and keep track of it in a
- // separate variable, so if a new read operation starts while there are
- // remaining tasks from a previous aborted operation, the new operation
- // will run while the tasks from the previous one are still aborted.
- const abortedState = this[aborted] = { aborted: false };
-
- // 5. Let stream be the result of calling get stream on blob.
- const stream /*: ReadableStream<ArrayBufferView>*/ = blob.stream();
-
- // 6. Let reader be the result of getting a reader from stream.
- const reader = stream.getReader();
-
- // 7. Let bytes be an empty byte sequence.
- /** @type {Uint8Array[]} */
- const chunks = [];
-
- // 8. Let chunkPromise be the result of reading a chunk from stream with reader.
- let chunkPromise = reader.read();
-
- // 9. Let isFirstChunk be true.
- let isFirstChunk = true;
-
- // 10 in parallel while true
- (async () => {
- while (!abortedState.aborted) {
- // 1. Wait for chunkPromise to be fulfilled or rejected.
- try {
- const chunk = await chunkPromise;
- if (abortedState.aborted) return;
-
- // 2. If chunkPromise is fulfilled, and isFirstChunk is true, queue a task to fire a progress event called loadstart at fr.
- if (isFirstChunk) {
- // TODO(lucacasonato): this is wrong, should be HTML "queue a task"
- queueMicrotask(() => {
- if (abortedState.aborted) return;
- // fire a progress event for loadstart
- const ev = new ProgressEvent("loadstart", {});
- this.dispatchEvent(ev);
- });
- }
- // 3. Set isFirstChunk to false.
- isFirstChunk = false;
-
- // 4. If chunkPromise is fulfilled with an object whose done property is false
- // and whose value property is a Uint8Array object, run these steps:
- if (!chunk.done && chunk.value instanceof Uint8Array) {
- ArrayPrototypePush(chunks, chunk.value);
-
- // TODO(bartlomieju): (only) If roughly 50ms have passed since last progress
- {
- const size = ArrayPrototypeReduce(
- chunks,
- (p, i) => p + i.byteLength,
- 0,
- );
- const ev = new ProgressEvent("progress", {
- loaded: size,
- });
- // TODO(lucacasonato): this is wrong, should be HTML "queue a task"
- queueMicrotask(() => {
- if (abortedState.aborted) return;
- this.dispatchEvent(ev);
- });
- }
-
- chunkPromise = reader.read();
- } // 5 Otherwise, if chunkPromise is fulfilled with an object whose done property is true, queue a task to run the following steps and abort this algorithm:
- else if (chunk.done === true) {
- // TODO(lucacasonato): this is wrong, should be HTML "queue a task"
- queueMicrotask(() => {
- if (abortedState.aborted) return;
- // 1. Set fr’s state to "done".
- this[state] = "done";
- // 2. Let result be the result of package data given bytes, type, blob’s type, and encodingName.
- const size = ArrayPrototypeReduce(
- chunks,
- (p, i) => p + i.byteLength,
- 0,
- );
- const bytes = new Uint8Array(size);
- let offs = 0;
- for (const chunk of chunks) {
- TypedArrayPrototypeSet(bytes, chunk, offs);
- offs += chunk.byteLength;
- }
- switch (readtype.kind) {
- case "ArrayBuffer": {
- this[result] = bytes.buffer;
- break;
- }
- case "BinaryString":
- this[result] = ArrayPrototypeJoin(
- ArrayPrototypeMap(
- [...new Uint8Array(bytes.buffer)],
- (v) => StringFromCodePoint(v),
- ),
- "",
- );
- break;
- case "Text": {
- let decoder = undefined;
- if (readtype.encoding) {
- try {
- decoder = new TextDecoder(readtype.encoding);
- } catch {
- // don't care about the error
- }
- }
- if (decoder === undefined) {
- const mimeType = parseMimeType(blob.type);
- if (mimeType) {
- const charset = MapPrototypeGet(
- mimeType.parameters,
- "charset",
- );
- if (charset) {
- try {
- decoder = new TextDecoder(charset);
- } catch {
- // don't care about the error
- }
- }
- }
- }
- if (decoder === undefined) {
- decoder = new TextDecoder();
- }
- this[result] = decode(bytes, decoder.encoding);
- break;
- }
- case "DataUrl": {
- const mediaType = blob.type || "application/octet-stream";
- this[result] = `data:${mediaType};base64,${
- forgivingBase64Encode(bytes)
- }`;
- break;
- }
- }
- // 4.2 Fire a progress event called load at the fr.
- {
- const ev = new ProgressEvent("load", {
- lengthComputable: true,
- loaded: size,
- total: size,
- });
- this.dispatchEvent(ev);
- }
-
- // 5. If fr’s state is not "loading", fire a progress event called loadend at the fr.
- //Note: Event handler for the load or error events could have started another load, if that happens the loadend event for this load is not fired.
- if (this[state] !== "loading") {
- const ev = new ProgressEvent("loadend", {
- lengthComputable: true,
- loaded: size,
- total: size,
- });
- this.dispatchEvent(ev);
- }
- });
- break;
- }
- } catch (err) {
- // TODO(lucacasonato): this is wrong, should be HTML "queue a task"
- queueMicrotask(() => {
- if (abortedState.aborted) return;
-
- // chunkPromise rejected
- this[state] = "done";
- this[error] = err;
-
- {
- const ev = new ProgressEvent("error", {});
- this.dispatchEvent(ev);
- }
-
- //If fr’s state is not "loading", fire a progress event called loadend at fr.
- //Note: Event handler for the error event could have started another load, if that happens the loadend event for this load is not fired.
- if (this[state] !== "loading") {
- const ev = new ProgressEvent("loadend", {});
- this.dispatchEvent(ev);
- }
- });
- break;
- }
- }
- })();
- }
-
- constructor() {
- super();
- this[webidl.brand] = webidl.brand;
- }
-
- /** @returns {number} */
- get readyState() {
- webidl.assertBranded(this, FileReader);
- switch (this[state]) {
- case "empty":
- return FileReader.EMPTY;
- case "loading":
- return FileReader.LOADING;
- case "done":
- return FileReader.DONE;
- default:
- throw new TypeError("Invalid state");
- }
- }
-
- get result() {
- webidl.assertBranded(this, FileReader);
- return this[result];
- }
-
- get error() {
- webidl.assertBranded(this, FileReader);
- return this[error];
- }
-
- abort() {
- webidl.assertBranded(this, FileReader);
- // If context object's state is "empty" or if context object's state is "done" set context object's result to null and terminate this algorithm.
- if (
- this[state] === "empty" ||
- this[state] === "done"
- ) {
- this[result] = null;
- return;
- }
- // If context object's state is "loading" set context object's state to "done" and set context object's result to null.
- if (this[state] === "loading") {
- this[state] = "done";
- this[result] = null;
- }
- // If there are any tasks from the context object on the file reading task source in an affiliated task queue, then remove those tasks from that task queue.
- // Terminate the algorithm for the read method being processed.
- if (this[aborted] !== null) {
- this[aborted].aborted = true;
- }
-
- // Fire a progress event called abort at the context object.
- const ev = new ProgressEvent("abort", {});
- this.dispatchEvent(ev);
-
- // If context object's state is not "loading", fire a progress event called loadend at the context object.
- if (this[state] !== "loading") {
- const ev = new ProgressEvent("loadend", {});
- this.dispatchEvent(ev);
- }
- }
-
- /** @param {Blob} blob */
- readAsArrayBuffer(blob) {
- webidl.assertBranded(this, FileReader);
- const prefix = "Failed to execute 'readAsArrayBuffer' on 'FileReader'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- this.#readOperation(blob, { kind: "ArrayBuffer" });
- }
-
- /** @param {Blob} blob */
- readAsBinaryString(blob) {
- webidl.assertBranded(this, FileReader);
- const prefix = "Failed to execute 'readAsBinaryString' on 'FileReader'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- // alias for readAsArrayBuffer
- this.#readOperation(blob, { kind: "BinaryString" });
- }
-
- /** @param {Blob} blob */
- readAsDataURL(blob) {
- webidl.assertBranded(this, FileReader);
- const prefix = "Failed to execute 'readAsBinaryString' on 'FileReader'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- // alias for readAsArrayBuffer
- this.#readOperation(blob, { kind: "DataUrl" });
- }
-
- /**
- * @param {Blob} blob
- * @param {string} [encoding]
- */
- readAsText(blob, encoding) {
- webidl.assertBranded(this, FileReader);
- const prefix = "Failed to execute 'readAsBinaryString' on 'FileReader'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- if (encoding !== undefined) {
- encoding = webidl.converters["DOMString"](encoding, {
- prefix,
- context: "Argument 2",
- });
- }
- // alias for readAsArrayBuffer
- this.#readOperation(blob, { kind: "Text", encoding });
- }
- }
-
- webidl.configurePrototype(FileReader);
-
- ObjectDefineProperty(FileReader, "EMPTY", {
- writable: false,
- enumerable: true,
- configurable: false,
- value: 0,
- });
- ObjectDefineProperty(FileReader, "LOADING", {
- writable: false,
- enumerable: true,
- configurable: false,
- value: 1,
- });
- ObjectDefineProperty(FileReader, "DONE", {
- writable: false,
- enumerable: true,
- configurable: false,
- value: 2,
- });
- ObjectDefineProperty(FileReader.prototype, "EMPTY", {
- writable: false,
- enumerable: true,
- configurable: false,
- value: 0,
- });
- ObjectDefineProperty(FileReader.prototype, "LOADING", {
- writable: false,
- enumerable: true,
- configurable: false,
- value: 1,
- });
- ObjectDefineProperty(FileReader.prototype, "DONE", {
- writable: false,
- enumerable: true,
- configurable: false,
- value: 2,
- });
-
- const handlerSymbol = Symbol("eventHandlers");
-
- function makeWrappedHandler(handler) {
- function wrappedHandler(...args) {
- if (typeof wrappedHandler.handler !== "function") {
- return;
- }
- return FunctionPrototypeCall(wrappedHandler.handler, this, ...args);
- }
- wrappedHandler.handler = handler;
- return wrappedHandler;
- }
- // TODO(benjamingr) reuse when we can reuse code between web crates
- function defineEventHandler(emitter, name) {
- // HTML specification section 8.1.5.1
- ObjectDefineProperty(emitter, `on${name}`, {
- get() {
- const maybeMap = this[handlerSymbol];
- if (!maybeMap) return null;
-
- return MapPrototypeGet(maybeMap, name)?.handler ?? null;
- },
- set(value) {
- if (!this[handlerSymbol]) {
- this[handlerSymbol] = new Map();
- }
- let handlerWrapper = MapPrototypeGet(this[handlerSymbol], name);
- if (handlerWrapper) {
- handlerWrapper.handler = value;
- } else {
- handlerWrapper = makeWrappedHandler(value);
- this.addEventListener(name, handlerWrapper);
- }
- MapPrototypeSet(this[handlerSymbol], name, handlerWrapper);
- },
- configurable: true,
- enumerable: true,
- });
- }
- defineEventHandler(FileReader.prototype, "error");
- defineEventHandler(FileReader.prototype, "loadstart");
- defineEventHandler(FileReader.prototype, "load");
- defineEventHandler(FileReader.prototype, "loadend");
- defineEventHandler(FileReader.prototype, "progress");
- defineEventHandler(FileReader.prototype, "abort");
-
- window.__bootstrap.fileReader = {
- FileReader,
- };
-})(this);
diff --git a/extensions/web/11_blob_url.js b/extensions/web/11_blob_url.js
deleted file mode 100644
index fa0ea041c..000000000
--- a/extensions/web/11_blob_url.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference no-default-lib="true" />
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../webidl/internal.d.ts" />
-/// <reference path="../web/internal.d.ts" />
-/// <reference path="../web/lib.deno_web.d.ts" />
-/// <reference path="../url/internal.d.ts" />
-/// <reference path="../url/lib.deno_url.d.ts" />
-/// <reference path="./internal.d.ts" />
-/// <reference lib="esnext" />
-"use strict";
-
-((window) => {
- const core = Deno.core;
- const webidl = window.__bootstrap.webidl;
- const { getParts } = window.__bootstrap.file;
- const { URL } = window.__bootstrap.url;
-
- /**
- * @param {Blob} blob
- * @returns {string}
- */
- function createObjectURL(blob) {
- const prefix = "Failed to execute 'createObjectURL' on 'URL'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- blob = webidl.converters["Blob"](blob, {
- context: "Argument 1",
- prefix,
- });
-
- const url = core.opSync(
- "op_blob_create_object_url",
- blob.type,
- getParts(blob),
- );
-
- return url;
- }
-
- /**
- * @param {string} url
- * @returns {void}
- */
- function revokeObjectURL(url) {
- const prefix = "Failed to execute 'revokeObjectURL' on 'URL'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- url = webidl.converters["DOMString"](url, {
- context: "Argument 1",
- prefix,
- });
-
- core.opSync("op_blob_revoke_object_url", url);
- }
-
- URL.createObjectURL = createObjectURL;
- URL.revokeObjectURL = revokeObjectURL;
-})(globalThis);
diff --git a/extensions/web/12_location.js b/extensions/web/12_location.js
deleted file mode 100644
index 40dd545fe..000000000
--- a/extensions/web/12_location.js
+++ /dev/null
@@ -1,409 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-"use strict";
-
-/// <reference path="../../core/internal.d.ts" />
-
-((window) => {
- const { URL } = window.__bootstrap.url;
- const { DOMException } = window.__bootstrap.domException;
- const {
- Error,
- ObjectDefineProperties,
- ReferenceError,
- Symbol,
- SymbolFor,
- SymbolToStringTag,
- TypeError,
- WeakMap,
- WeakMapPrototypeGet,
- WeakMapPrototypeSet,
- } = window.__bootstrap.primordials;
-
- const locationConstructorKey = Symbol("locationConstuctorKey");
-
- // The differences between the definitions of `Location` and `WorkerLocation`
- // are because of the `LegacyUnforgeable` attribute only specified upon
- // `Location`'s properties. See:
- // - https://html.spec.whatwg.org/multipage/history.html#the-location-interface
- // - https://heycam.github.io/webidl/#LegacyUnforgeable
- class Location {
- constructor(href = null, key = null) {
- if (key != locationConstructorKey) {
- throw new TypeError("Illegal constructor.");
- }
- const url = new URL(href);
- url.username = "";
- url.password = "";
- ObjectDefineProperties(this, {
- hash: {
- get() {
- return url.hash;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.hash".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- host: {
- get() {
- return url.host;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.host".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- hostname: {
- get() {
- return url.hostname;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.hostname".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- href: {
- get() {
- return url.href;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.href".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- origin: {
- get() {
- return url.origin;
- },
- enumerable: true,
- },
- pathname: {
- get() {
- return url.pathname;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.pathname".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- port: {
- get() {
- return url.port;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.port".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- protocol: {
- get() {
- return url.protocol;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.protocol".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- search: {
- get() {
- return url.search;
- },
- set() {
- throw new DOMException(
- `Cannot set "location.search".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- ancestorOrigins: {
- get() {
- // TODO(nayeemrmn): Replace with a `DOMStringList` instance.
- return {
- length: 0,
- item: () => null,
- contains: () => false,
- };
- },
- enumerable: true,
- },
- assign: {
- value: function assign() {
- throw new DOMException(
- `Cannot call "location.assign()".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- reload: {
- value: function reload() {
- throw new DOMException(
- `Cannot call "location.reload()".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- replace: {
- value: function replace() {
- throw new DOMException(
- `Cannot call "location.replace()".`,
- "NotSupportedError",
- );
- },
- enumerable: true,
- },
- toString: {
- value: function toString() {
- return url.href;
- },
- enumerable: true,
- },
- [SymbolFor("Deno.privateCustomInspect")]: {
- value: function (inspect) {
- const object = {
- hash: this.hash,
- host: this.host,
- hostname: this.hostname,
- href: this.href,
- origin: this.origin,
- pathname: this.pathname,
- port: this.port,
- protocol: this.protocol,
- search: this.search,
- };
- return `${this.constructor.name} ${inspect(object)}`;
- },
- },
- });
- }
- }
-
- ObjectDefineProperties(Location.prototype, {
- [SymbolToStringTag]: {
- value: "Location",
- configurable: true,
- },
- });
-
- const workerLocationUrls = new WeakMap();
-
- class WorkerLocation {
- constructor(href = null, key = null) {
- if (key != locationConstructorKey) {
- throw new TypeError("Illegal constructor.");
- }
- const url = new URL(href);
- url.username = "";
- url.password = "";
- WeakMapPrototypeSet(workerLocationUrls, this, url);
- }
- }
-
- ObjectDefineProperties(WorkerLocation.prototype, {
- hash: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.hash;
- },
- configurable: true,
- enumerable: true,
- },
- host: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.host;
- },
- configurable: true,
- enumerable: true,
- },
- hostname: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.hostname;
- },
- configurable: true,
- enumerable: true,
- },
- href: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.href;
- },
- configurable: true,
- enumerable: true,
- },
- origin: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.origin;
- },
- configurable: true,
- enumerable: true,
- },
- pathname: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.pathname;
- },
- configurable: true,
- enumerable: true,
- },
- port: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.port;
- },
- configurable: true,
- enumerable: true,
- },
- protocol: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.protocol;
- },
- configurable: true,
- enumerable: true,
- },
- search: {
- get() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.search;
- },
- configurable: true,
- enumerable: true,
- },
- toString: {
- value: function toString() {
- const url = WeakMapPrototypeGet(workerLocationUrls, this);
- if (url == null) {
- throw new TypeError("Illegal invocation.");
- }
- return url.href;
- },
- configurable: true,
- enumerable: true,
- writable: true,
- },
- [SymbolToStringTag]: {
- value: "WorkerLocation",
- configurable: true,
- },
- [SymbolFor("Deno.privateCustomInspect")]: {
- value: function (inspect) {
- const object = {
- hash: this.hash,
- host: this.host,
- hostname: this.hostname,
- href: this.href,
- origin: this.origin,
- pathname: this.pathname,
- port: this.port,
- protocol: this.protocol,
- search: this.search,
- };
- return `${this.constructor.name} ${inspect(object)}`;
- },
- },
- });
-
- let location = null;
- let workerLocation = null;
-
- function setLocationHref(href) {
- location = new Location(href, locationConstructorKey);
- workerLocation = new WorkerLocation(href, locationConstructorKey);
- }
-
- window.__bootstrap.location = {
- locationConstructorDescriptor: {
- value: Location,
- configurable: true,
- writable: true,
- },
- workerLocationConstructorDescriptor: {
- value: WorkerLocation,
- configurable: true,
- writable: true,
- },
- locationDescriptor: {
- get() {
- if (location == null) {
- throw new ReferenceError(
- `Access to "location", run again with --location <href>.`,
- );
- }
- return location;
- },
- set() {
- throw new DOMException(`Cannot set "location".`, "NotSupportedError");
- },
- enumerable: true,
- },
- workerLocationDescriptor: {
- get() {
- if (workerLocation == null) {
- throw new Error(
- `Assertion: "globalThis.location" must be defined in a worker.`,
- );
- }
- return workerLocation;
- },
- configurable: true,
- enumerable: true,
- },
- setLocationHref,
- getLocationHref() {
- return location?.href;
- },
- };
-})(this);
diff --git a/extensions/web/13_message_port.js b/extensions/web/13_message_port.js
deleted file mode 100644
index d5014fdb9..000000000
--- a/extensions/web/13_message_port.js
+++ /dev/null
@@ -1,286 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// @ts-check
-/// <reference path="../../core/lib.deno_core.d.ts" />
-/// <reference path="../webidl/internal.d.ts" />
-/// <reference path="./internal.d.ts" />
-/// <reference path="./lib.deno_web.d.ts" />
-
-"use strict";
-
-((window) => {
- const core = window.Deno.core;
- const webidl = window.__bootstrap.webidl;
- const { setEventTargetData } = window.__bootstrap.eventTarget;
- const { defineEventHandler } = window.__bootstrap.event;
- const { DOMException } = window.__bootstrap.domException;
- const {
- ObjectSetPrototypeOf,
- Symbol,
- SymbolFor,
- SymbolToStringTag,
- TypeError,
- } = window.__bootstrap.primordials;
-
- class MessageChannel {
- /** @type {MessagePort} */
- #port1;
- /** @type {MessagePort} */
- #port2;
-
- constructor() {
- this[webidl.brand] = webidl.brand;
- const [port1Id, port2Id] = opCreateEntangledMessagePort();
- const port1 = createMessagePort(port1Id);
- const port2 = createMessagePort(port2Id);
- this.#port1 = port1;
- this.#port2 = port2;
- }
-
- get port1() {
- webidl.assertBranded(this, MessageChannel);
- return this.#port1;
- }
-
- get port2() {
- webidl.assertBranded(this, MessageChannel);
- return this.#port2;
- }
-
- [SymbolFor("Deno.inspect")](inspect) {
- return `MessageChannel ${
- inspect({ port1: this.port1, port2: this.port2 })
- }`;
- }
-
- get [SymbolToStringTag]() {
- return "MessageChannel";
- }
- }
-
- webidl.configurePrototype(MessageChannel);
-
- const _id = Symbol("id");
- const _enabled = Symbol("enabled");
-
- /**
- * @param {number} id
- * @returns {MessagePort}
- */
- function createMessagePort(id) {
- const port = core.createHostObject();
- ObjectSetPrototypeOf(port, MessagePort.prototype);
- port[webidl.brand] = webidl.brand;
- setEventTargetData(port);
- port[_id] = id;
- return port;
- }
-
- class MessagePort extends EventTarget {
- /** @type {number | null} */
- [_id] = null;
- /** @type {boolean} */
- [_enabled] = false;
-
- constructor() {
- super();
- webidl.illegalConstructor();
- }
-
- /**
- * @param {any} message
- * @param {object[] | StructuredSerializeOptions} transferOrOptions
- */
- postMessage(message, transferOrOptions = {}) {
- webidl.assertBranded(this, MessagePort);
- const prefix = "Failed to execute 'postMessage' on 'MessagePort'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- message = webidl.converters.any(message);
- let options;
- if (
- webidl.type(transferOrOptions) === "Object" &&
- transferOrOptions !== undefined &&
- transferOrOptions[Symbol.iterator] !== undefined
- ) {
- const transfer = webidl.converters["sequence<object>"](
- transferOrOptions,
- { prefix, context: "Argument 2" },
- );
- options = { transfer };
- } else {
- options = webidl.converters.StructuredSerializeOptions(
- transferOrOptions,
- {
- prefix,
- context: "Argument 2",
- },
- );
- }
- const { transfer } = options;
- if (transfer.includes(this)) {
- throw new DOMException("Can not tranfer self", "DataCloneError");
- }
- const data = serializeJsMessageData(message, transfer);
- if (this[_id] === null) return;
- core.opSync("op_message_port_post_message", this[_id], data);
- }
-
- start() {
- webidl.assertBranded(this, MessagePort);
- if (this[_enabled]) return;
- (async () => {
- this[_enabled] = true;
- while (true) {
- if (this[_id] === null) break;
- const data = await core.opAsync(
- "op_message_port_recv_message",
- this[_id],
- );
- if (data === null) break;
- let message, transfer;
- try {
- const v = deserializeJsMessageData(data);
- message = v[0];
- transfer = v[1];
- } catch (err) {
- const event = new MessageEvent("messageerror", { data: err });
- this.dispatchEvent(event);
- return;
- }
- const event = new MessageEvent("message", {
- data: message,
- ports: transfer,
- });
- this.dispatchEvent(event);
- }
- this[_enabled] = false;
- })();
- }
-
- close() {
- webidl.assertBranded(this, MessagePort);
- if (this[_id] !== null) {
- core.close(this[_id]);
- this[_id] = null;
- }
- }
-
- get [SymbolToStringTag]() {
- return "MessagePort";
- }
- }
-
- defineEventHandler(MessagePort.prototype, "message", function (self) {
- self.start();
- });
- defineEventHandler(MessagePort.prototype, "messageerror");
-
- webidl.configurePrototype(MessagePort);
-
- /**
- * @returns {[number, number]}
- */
- function opCreateEntangledMessagePort() {
- return core.opSync("op_message_port_create_entangled");
- }
-
- /**
- * @param {globalThis.__bootstrap.messagePort.MessageData} messageData
- * @returns {[any, object[]]}
- */
- function deserializeJsMessageData(messageData) {
- /** @type {object[]} */
- const transferables = [];
-
- for (const transferable of messageData.transferables) {
- switch (transferable.kind) {
- case "messagePort": {
- const port = createMessagePort(transferable.data);
- transferables.push(port);
- break;
- }
- default:
- throw new TypeError("Unreachable");
- }
- }
-
- const data = core.deserialize(messageData.data, {
- hostObjects: transferables,
- });
-
- return [data, transferables];
- }
-
- /**
- * @param {any} data
- * @param {object[]} tranferables
- * @returns {globalThis.__bootstrap.messagePort.MessageData}
- */
- function serializeJsMessageData(data, tranferables) {
- let serializedData;
- try {
- serializedData = core.serialize(data, { hostObjects: tranferables });
- } catch (err) {
- throw new DOMException(err.message, "DataCloneError");
- }
-
- /** @type {globalThis.__bootstrap.messagePort.Transferable[]} */
- const serializedTransferables = [];
-
- for (const transferable of tranferables) {
- if (transferable instanceof MessagePort) {
- webidl.assertBranded(transferable, MessagePort);
- const id = transferable[_id];
- if (id === null) {
- throw new DOMException(
- "Can not transfer disentangled message port",
- "DataCloneError",
- );
- }
- transferable[_id] = null;
- serializedTransferables.push({ kind: "messagePort", data: id });
- } else {
- throw new DOMException("Value not transferable", "DataCloneError");
- }
- }
-
- return {
- data: serializedData,
- transferables: serializedTransferables,
- };
- }
-
- webidl.converters.StructuredSerializeOptions = webidl
- .createDictionaryConverter(
- "StructuredSerializeOptions",
- [
- {
- key: "transfer",
- converter: webidl.converters["sequence<object>"],
- get defaultValue() {
- return [];
- },
- },
- ],
- );
-
- function structuredClone(value, options) {
- const prefix = "Failed to execute 'structuredClone'";
- webidl.requiredArguments(arguments.length, 1, { prefix });
- options = webidl.converters.StructuredSerializeOptions(options, {
- prefix,
- context: "Argument 2",
- });
- const messageData = serializeJsMessageData(value, options.transfer);
- const [data] = deserializeJsMessageData(messageData);
- return data;
- }
-
- window.__bootstrap.messagePort = {
- MessageChannel,
- MessagePort,
- deserializeJsMessageData,
- serializeJsMessageData,
- structuredClone,
- };
-})(globalThis);
diff --git a/extensions/web/Cargo.toml b/extensions/web/Cargo.toml
deleted file mode 100644
index 6160ef89f..000000000
--- a/extensions/web/Cargo.toml
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-[package]
-name = "deno_web"
-version = "0.45.0"
-authors = ["the Deno authors"]
-edition = "2018"
-license = "MIT"
-readme = "README.md"
-repository = "https://github.com/denoland/deno"
-description = "Collection of Web APIs"
-
-[lib]
-path = "lib.rs"
-
-[dependencies]
-async-trait = "0.1.50"
-base64 = "0.13.0"
-deno_core = { version = "0.96.0", path = "../../core" }
-encoding_rs = "0.8.28"
-serde = "1.0"
-tokio = { version = "1.8.1", features = ["full"] }
-uuid = { version = "0.8.2", features = ["v4", "serde"] }
-
-[dev-dependencies]
-futures = "0.3.15"
diff --git a/extensions/web/README.md b/extensions/web/README.md
deleted file mode 100644
index d847ae52e..000000000
--- a/extensions/web/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# deno web
-
-Op crate that implements Event, TextEncoder, TextDecoder and File API
-(https://w3c.github.io/FileAPI).
-
-Testing for text encoding is done via WPT in cli/.
diff --git a/extensions/web/blob.rs b/extensions/web/blob.rs
deleted file mode 100644
index 0f27553c7..000000000
--- a/extensions/web/blob.rs
+++ /dev/null
@@ -1,265 +0,0 @@
-use async_trait::async_trait;
-use deno_core::error::type_error;
-use deno_core::parking_lot::Mutex;
-use deno_core::url::Url;
-use deno_core::ZeroCopyBuf;
-use serde::Deserialize;
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::fmt::Debug;
-use std::rc::Rc;
-use std::sync::Arc;
-
-use deno_core::error::AnyError;
-use uuid::Uuid;
-
-use crate::Location;
-
-pub type PartMap = HashMap<Uuid, Arc<Box<dyn BlobPart + Send + Sync>>>;
-
-#[derive(Clone, Default, Debug)]
-pub struct BlobStore {
- parts: Arc<Mutex<PartMap>>,
- object_urls: Arc<Mutex<HashMap<Url, Arc<Blob>>>>,
-}
-
-impl BlobStore {
- pub fn insert_part(&self, part: Box<dyn BlobPart + Send + Sync>) -> Uuid {
- let id = Uuid::new_v4();
- let mut parts = self.parts.lock();
- parts.insert(id, Arc::new(part));
- id
- }
-
- pub fn get_part(
- &self,
- id: &Uuid,
- ) -> Option<Arc<Box<dyn BlobPart + Send + Sync>>> {
- let parts = self.parts.lock();
- let part = parts.get(id);
- part.cloned()
- }
-
- pub fn remove_part(
- &self,
- id: &Uuid,
- ) -> Option<Arc<Box<dyn BlobPart + Send + Sync>>> {
- let mut parts = self.parts.lock();
- parts.remove(id)
- }
-
- pub fn get_object_url(
- &self,
- mut url: Url,
- ) -> Result<Option<Arc<Blob>>, AnyError> {
- let blob_store = self.object_urls.lock();
- url.set_fragment(None);
- Ok(blob_store.get(&url).cloned())
- }
-
- pub fn insert_object_url(
- &self,
- blob: Blob,
- maybe_location: Option<Url>,
- ) -> Url {
- let origin = if let Some(location) = maybe_location {
- location.origin().ascii_serialization()
- } else {
- "null".to_string()
- };
- let id = Uuid::new_v4();
- let url = Url::parse(&format!("blob:{}/{}", origin, id)).unwrap();
-
- let mut blob_store = self.object_urls.lock();
- blob_store.insert(url.clone(), Arc::new(blob));
-
- url
- }
-
- pub fn remove_object_url(&self, url: &Url) {
- let mut blob_store = self.object_urls.lock();
- blob_store.remove(url);
- }
-}
-
-#[derive(Debug)]
-pub struct Blob {
- pub media_type: String,
-
- pub parts: Vec<Arc<Box<dyn BlobPart + Send + Sync>>>,
-}
-
-impl Blob {
- // TODO(lucacsonato): this should be a stream!
- pub async fn read_all(&self) -> Result<Vec<u8>, AnyError> {
- let size = self.size();
- let mut bytes = Vec::with_capacity(size);
-
- for part in &self.parts {
- let chunk = part.read().await?;
- bytes.extend_from_slice(chunk);
- }
-
- assert_eq!(bytes.len(), size);
-
- Ok(bytes)
- }
-
- fn size(&self) -> usize {
- let mut total = 0;
- for part in &self.parts {
- total += part.size()
- }
- total
- }
-}
-
-#[async_trait]
-pub trait BlobPart: Debug {
- // TODO(lucacsonato): this should be a stream!
- async fn read(&self) -> Result<&[u8], AnyError>;
- fn size(&self) -> usize;
-}
-
-#[derive(Debug)]
-pub struct InMemoryBlobPart(Vec<u8>);
-
-impl From<Vec<u8>> for InMemoryBlobPart {
- fn from(vec: Vec<u8>) -> Self {
- Self(vec)
- }
-}
-
-#[async_trait]
-impl BlobPart for InMemoryBlobPart {
- async fn read(&self) -> Result<&[u8], AnyError> {
- Ok(&self.0)
- }
-
- fn size(&self) -> usize {
- self.0.len()
- }
-}
-
-#[derive(Debug)]
-pub struct SlicedBlobPart {
- part: Arc<Box<dyn BlobPart + Send + Sync>>,
- start: usize,
- len: usize,
-}
-
-#[async_trait]
-impl BlobPart for SlicedBlobPart {
- async fn read(&self) -> Result<&[u8], AnyError> {
- let original = self.part.read().await?;
- Ok(&original[self.start..self.start + self.len])
- }
-
- fn size(&self) -> usize {
- self.len
- }
-}
-
-pub fn op_blob_create_part(
- state: &mut deno_core::OpState,
- data: ZeroCopyBuf,
- _: (),
-) -> Result<Uuid, AnyError> {
- let blob_store = state.borrow::<BlobStore>();
- let part = InMemoryBlobPart(data.to_vec());
- let id = blob_store.insert_part(Box::new(part));
- Ok(id)
-}
-
-#[derive(Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SliceOptions {
- start: usize,
- len: usize,
-}
-
-pub fn op_blob_slice_part(
- state: &mut deno_core::OpState,
- id: Uuid,
- options: SliceOptions,
-) -> Result<Uuid, AnyError> {
- let blob_store = state.borrow::<BlobStore>();
- let part = blob_store
- .get_part(&id)
- .ok_or_else(|| type_error("Blob part not found"))?;
-
- let SliceOptions { start, len } = options;
-
- let size = part.size();
- if start + len > size {
- return Err(type_error(
- "start + len can not be larger than blob part size",
- ));
- }
-
- let sliced_part = SlicedBlobPart { part, start, len };
- let id = blob_store.insert_part(Box::new(sliced_part));
-
- Ok(id)
-}
-
-pub async fn op_blob_read_part(
- state: Rc<RefCell<deno_core::OpState>>,
- id: Uuid,
- _: (),
-) -> Result<ZeroCopyBuf, AnyError> {
- let part = {
- let state = state.borrow();
- let blob_store = state.borrow::<BlobStore>();
- blob_store.get_part(&id)
- }
- .ok_or_else(|| type_error("Blob part not found"))?;
- let buf = part.read().await?;
- Ok(ZeroCopyBuf::from(buf.to_vec()))
-}
-
-pub fn op_blob_remove_part(
- state: &mut deno_core::OpState,
- id: Uuid,
- _: (),
-) -> Result<(), AnyError> {
- let blob_store = state.borrow::<BlobStore>();
- blob_store.remove_part(&id);
- Ok(())
-}
-
-pub fn op_blob_create_object_url(
- state: &mut deno_core::OpState,
- media_type: String,
- part_ids: Vec<Uuid>,
-) -> Result<String, AnyError> {
- let mut parts = Vec::with_capacity(part_ids.len());
- let blob_store = state.borrow::<BlobStore>();
- for part_id in part_ids {
- let part = blob_store
- .get_part(&part_id)
- .ok_or_else(|| type_error("Blob part not found"))?;
- parts.push(part);
- }
-
- let blob = Blob { media_type, parts };
-
- let maybe_location = state.try_borrow::<Location>();
- let blob_store = state.borrow::<BlobStore>();
-
- let url = blob_store
- .insert_object_url(blob, maybe_location.map(|location| location.0.clone()));
-
- Ok(url.to_string())
-}
-
-pub fn op_blob_revoke_object_url(
- state: &mut deno_core::OpState,
- url: String,
- _: (),
-) -> Result<(), AnyError> {
- let url = Url::parse(&url)?;
- let blob_store = state.borrow::<BlobStore>();
- blob_store.remove_object_url(&url);
- Ok(())
-}
diff --git a/extensions/web/internal.d.ts b/extensions/web/internal.d.ts
deleted file mode 100644
index 3a2a0c1be..000000000
--- a/extensions/web/internal.d.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-/// <reference no-default-lib="true" />
-/// <reference lib="esnext" />
-
-declare namespace globalThis {
- declare namespace __bootstrap {
- declare var infra: {
- collectSequenceOfCodepoints(
- input: string,
- position: number,
- condition: (char: string) => boolean,
- ): {
- result: string;
- position: number;
- };
- ASCII_DIGIT: string[];
- ASCII_UPPER_ALPHA: string[];
- ASCII_LOWER_ALPHA: string[];
- ASCII_ALPHA: string[];
- ASCII_ALPHANUMERIC: string[];
- HTTP_TAB_OR_SPACE: string[];
- HTTP_WHITESPACE: string[];
- HTTP_TOKEN_CODE_POINT: string[];
- HTTP_TOKEN_CODE_POINT_RE: RegExp;
- HTTP_QUOTED_STRING_TOKEN_POINT: string[];
- HTTP_QUOTED_STRING_TOKEN_POINT_RE: RegExp;
- HTTP_TAB_OR_SPACE_PREFIX_RE: RegExp;
- HTTP_TAB_OR_SPACE_SUFFIX_RE: RegExp;
- HTTP_WHITESPACE_PREFIX_RE: RegExp;
- HTTP_WHITESPACE_SUFFIX_RE: RegExp;
- regexMatcher(chars: string[]): string;
- byteUpperCase(s: string): string;
- byteLowerCase(s: string): string;
- collectHttpQuotedString(
- input: string,
- position: number,
- extractValue: boolean,
- ): {
- result: string;
- position: number;
- };
- forgivingBase64Encode(data: Uint8Array): string;
- forgivingBase64Decode(data: string): Uint8Array;
- };
-
- declare var domException: {
- DOMException: typeof DOMException;
- };
-
- declare namespace mimesniff {
- declare interface MimeType {
- type: string;
- subtype: string;
- parameters: Map<string, string>;
- }
- declare function parseMimeType(input: string): MimeType | null;
- declare function essence(mimeType: MimeType): string;
- declare function serializeMimeType(mimeType: MimeType): string;
- }
-
- declare var eventTarget: {
- EventTarget: typeof EventTarget;
- };
-
- declare var location: {
- getLocationHref(): string | undefined;
- };
-
- declare var base64: {
- atob(data: string): string;
- btoa(data: string): string;
- };
-
- declare var file: {
- getParts(blob: Blob): string[];
- Blob: typeof Blob;
- File: typeof File;
- };
-
- declare var streams: {
- ReadableStream: typeof ReadableStream;
- isReadableStreamDisturbed(stream: ReadableStream): boolean;
- createProxy<T>(stream: ReadableStream<T>): ReadableStream<T>;
- };
-
- declare namespace messagePort {
- declare type Transferable = {
- kind: "messagePort";
- data: number;
- };
- declare interface MessageData {
- data: Uint8Array;
- transferables: Transferable[];
- }
- }
- }
-}
diff --git a/extensions/web/lib.deno_web.d.ts b/extensions/web/lib.deno_web.d.ts
deleted file mode 100644
index 3f110353f..000000000
--- a/extensions/web/lib.deno_web.d.ts
+++ /dev/null
@@ -1,752 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-// deno-lint-ignore-file no-explicit-any
-
-/// <reference no-default-lib="true" />
-/// <reference lib="esnext" />
-
-declare class DOMException extends Error {
- constructor(message?: string, name?: string);
- readonly name: string;
- readonly message: string;
- readonly code: number;
-}
-
-interface EventInit {
- bubbles?: boolean;
- cancelable?: boolean;
- composed?: boolean;
-}
-
-/** An event which takes place in the DOM. */
-declare class Event {
- constructor(type: string, eventInitDict?: EventInit);
- /** Returns true or false depending on how event was initialized. True if
- * event goes through its target's ancestors in reverse tree order, and
- * false otherwise. */
- readonly bubbles: boolean;
- cancelBubble: boolean;
- /** Returns true or false depending on how event was initialized. Its return
- * value does not always carry meaning, but true can indicate that part of the
- * operation during which event was dispatched, can be canceled by invoking
- * the preventDefault() method. */
- readonly cancelable: boolean;
- /** Returns true or false depending on how event was initialized. True if
- * event invokes listeners past a ShadowRoot node that is the root of its
- * target, and false otherwise. */
- readonly composed: boolean;
- /** Returns the object whose event listener's callback is currently being
- * invoked. */
- readonly currentTarget: EventTarget | null;
- /** Returns true if preventDefault() was invoked successfully to indicate
- * cancellation, and false otherwise. */
- readonly defaultPrevented: boolean;
- /** Returns the event's phase, which is one of NONE, CAPTURING_PHASE,
- * AT_TARGET, and BUBBLING_PHASE. */
- readonly eventPhase: number;
- /** Returns true if event was dispatched by the user agent, and false
- * otherwise. */
- readonly isTrusted: boolean;
- /** Returns the object to which event is dispatched (its target). */
- readonly target: EventTarget | null;
- /** Returns the event's timestamp as the number of milliseconds measured
- * relative to the time origin. */
- readonly timeStamp: number;
- /** Returns the type of event, e.g. "click", "hashchange", or "submit". */
- readonly type: string;
- /** Returns the invocation target objects of event's path (objects on which
- * listeners will be invoked), except for any nodes in shadow trees of which
- * the shadow root's mode is "closed" that are not reachable from event's
- * currentTarget. */
- composedPath(): EventTarget[];
- /** If invoked when the cancelable attribute value is true, and while
- * executing a listener for the event with passive set to false, signals to
- * the operation that caused event to be dispatched that it needs to be
- * canceled. */
- preventDefault(): void;
- /** Invoking this method prevents event from reaching any registered event
- * listeners after the current one finishes running and, when dispatched in a
- * tree, also prevents event from reaching any other objects. */
- stopImmediatePropagation(): void;
- /** When dispatched in a tree, invoking this method prevents event from
- * reaching any objects other than the current object. */
- stopPropagation(): void;
- readonly AT_TARGET: number;
- readonly BUBBLING_PHASE: number;
- readonly CAPTURING_PHASE: number;
- readonly NONE: number;
- static readonly AT_TARGET: number;
- static readonly BUBBLING_PHASE: number;
- static readonly CAPTURING_PHASE: number;
- static readonly NONE: number;
-}
-
-/**
- * EventTarget is a DOM interface implemented by objects that can receive events
- * and may have listeners for them.
- */
-declare class EventTarget {
- /** Appends an event listener for events whose type attribute value is type.
- * The callback argument sets the callback that will be invoked when the event
- * is dispatched.
- *
- * The options argument sets listener-specific options. For compatibility this
- * can be a boolean, in which case the method behaves exactly as if the value
- * was specified as options's capture.
- *
- * When set to true, options's capture prevents callback from being invoked
- * when the event's eventPhase attribute value is BUBBLING_PHASE. When false
- * (or not present), callback will not be invoked when event's eventPhase
- * attribute value is CAPTURING_PHASE. Either way, callback will be invoked if
- * event's eventPhase attribute value is AT_TARGET.
- *
- * When set to true, options's passive indicates that the callback will not
- * cancel the event by invoking preventDefault(). This is used to enable
- * performance optimizations described in § 2.8 Observing event listeners.
- *
- * When set to true, options's once indicates that the callback will only be
- * invoked once after which the event listener will be removed.
- *
- * The event listener is appended to target's event listener list and is not
- * appended if it has the same type, callback, and capture. */
- addEventListener(
- type: string,
- listener: EventListenerOrEventListenerObject | null,
- options?: boolean | AddEventListenerOptions,
- ): void;
- /** Dispatches a synthetic event event to target and returns true if either
- * event's cancelable attribute value is false or its preventDefault() method
- * was not invoked, and false otherwise. */
- dispatchEvent(event: Event): boolean;
- /** Removes the event listener in target's event listener list with the same
- * type, callback, and options. */
- removeEventListener(
- type: string,
- callback: EventListenerOrEventListenerObject | null,
- options?: EventListenerOptions | boolean,
- ): void;
-}
-
-interface EventListener {
- (evt: Event): void | Promise<void>;
-}
-
-interface EventListenerObject {
- handleEvent(evt: Event): void | Promise<void>;
-}
-
-declare type EventListenerOrEventListenerObject =
- | EventListener
- | EventListenerObject;
-
-interface AddEventListenerOptions extends EventListenerOptions {
- once?: boolean;
- passive?: boolean;
-}
-
-interface EventListenerOptions {
- capture?: boolean;
-}
-
-interface ProgressEventInit extends EventInit {
- lengthComputable?: boolean;
- loaded?: number;
- total?: number;
-}
-
-/** Events measuring progress of an underlying process, like an HTTP request
- * (for an XMLHttpRequest, or the loading of the underlying resource of an
- * <img>, <audio>, <video>, <style> or <link>). */
-declare class ProgressEvent<T extends EventTarget = EventTarget> extends Event {
- constructor(type: string, eventInitDict?: ProgressEventInit);
- readonly lengthComputable: boolean;
- readonly loaded: number;
- readonly target: T | null;
- readonly total: number;
-}
-
-/** Decodes a string of data which has been encoded using base-64 encoding.
- *
- * console.log(atob("aGVsbG8gd29ybGQ=")); // outputs 'hello world'
- */
-declare function atob(s: string): string;
-
-/** Creates a base-64 ASCII encoded string from the input string.
- *
- * console.log(btoa("hello world")); // outputs "aGVsbG8gd29ybGQ="
- */
-declare function btoa(s: string): string;
-
-declare interface TextDecoderOptions {
- fatal?: boolean;
- ignoreBOM?: boolean;
-}
-
-declare interface TextDecodeOptions {
- stream?: boolean;
-}
-
-declare class TextDecoder {
- constructor(label?: string, options?: TextDecoderOptions);
-
- /** Returns encoding's name, lowercased. */
- readonly encoding: string;
- /** Returns `true` if error mode is "fatal", and `false` otherwise. */
- readonly fatal: boolean;
- /** Returns `true` if ignore BOM flag is set, and `false` otherwise. */
- readonly ignoreBOM = false;
-
- /** Returns the result of running encoding's decoder. */
- decode(input?: BufferSource, options?: TextDecodeOptions): string;
-}
-
-declare interface TextEncoderEncodeIntoResult {
- read: number;
- written: number;
-}
-
-declare class TextEncoder {
- /** Returns "utf-8". */
- readonly encoding: "utf-8";
- /** Returns the result of running UTF-8's encoder. */
- encode(input?: string): Uint8Array;
- encodeInto(input: string, dest: Uint8Array): TextEncoderEncodeIntoResult;
-}
-
-declare class TextDecoderStream {
- /** Returns encoding's name, lowercased. */
- readonly encoding: string;
- /** Returns `true` if error mode is "fatal", and `false` otherwise. */
- readonly fatal: boolean;
- /** Returns `true` if ignore BOM flag is set, and `false` otherwise. */
- readonly ignoreBOM = false;
- constructor(label?: string, options?: TextDecoderOptions);
- readonly readable: ReadableStream<string>;
- readonly writable: WritableStream<BufferSource>;
- readonly [Symbol.toStringTag]: string;
-}
-
-declare class TextEncoderStream {
- /** Returns "utf-8". */
- readonly encoding: "utf-8";
- readonly readable: ReadableStream<Uint8Array>;
- readonly writable: WritableStream<string>;
- readonly [Symbol.toStringTag]: string;
-}
-
-/** A controller object that allows you to abort one or more DOM requests as and
- * when desired. */
-declare class AbortController {
- /** Returns the AbortSignal object associated with this object. */
- readonly signal: AbortSignal;
- /** Invoking this method will set this object's AbortSignal's aborted flag and
- * signal to any observers that the associated activity is to be aborted. */
- abort(): void;
-}
-
-interface AbortSignalEventMap {
- abort: Event;
-}
-
-/** A signal object that allows you to communicate with a DOM request (such as a
- * Fetch) and abort it if required via an AbortController object. */
-interface AbortSignal extends EventTarget {
- /** Returns true if this AbortSignal's AbortController has signaled to abort,
- * and false otherwise. */
- readonly aborted: boolean;
- onabort: ((this: AbortSignal, ev: Event) => any) | null;
- addEventListener<K extends keyof AbortSignalEventMap>(
- type: K,
- listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any,
- options?: boolean | AddEventListenerOptions,
- ): void;
- addEventListener(
- type: string,
- listener: EventListenerOrEventListenerObject,
- options?: boolean | AddEventListenerOptions,
- ): void;
- removeEventListener<K extends keyof AbortSignalEventMap>(
- type: K,
- listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any,
- options?: boolean | EventListenerOptions,
- ): void;
- removeEventListener(
- type: string,
- listener: EventListenerOrEventListenerObject,
- options?: boolean | EventListenerOptions,
- ): void;
-}
-
-declare var AbortSignal: {
- prototype: AbortSignal;
- new (): AbortSignal;
-};
-
-interface FileReaderEventMap {
- "abort": ProgressEvent<FileReader>;
- "error": ProgressEvent<FileReader>;
- "load": ProgressEvent<FileReader>;
- "loadend": ProgressEvent<FileReader>;
- "loadstart": ProgressEvent<FileReader>;
- "progress": ProgressEvent<FileReader>;
-}
-
-/** Lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read. */
-interface FileReader extends EventTarget {
- readonly error: DOMException | null;
- onabort: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
- onerror: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
- onload: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
- onloadend: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
- onloadstart:
- | ((this: FileReader, ev: ProgressEvent<FileReader>) => any)
- | null;
- onprogress: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
- readonly readyState: number;
- readonly result: string | ArrayBuffer | null;
- abort(): void;
- readAsArrayBuffer(blob: Blob): void;
- readAsBinaryString(blob: Blob): void;
- readAsDataURL(blob: Blob): void;
- readAsText(blob: Blob, encoding?: string): void;
- readonly DONE: number;
- readonly EMPTY: number;
- readonly LOADING: number;
- addEventListener<K extends keyof FileReaderEventMap>(
- type: K,
- listener: (this: FileReader, ev: FileReaderEventMap[K]) => any,
- options?: boolean | AddEventListenerOptions,
- ): void;
- addEventListener(
- type: string,
- listener: EventListenerOrEventListenerObject,
- options?: boolean | AddEventListenerOptions,
- ): void;
- removeEventListener<K extends keyof FileReaderEventMap>(
- type: K,
- listener: (this: FileReader, ev: FileReaderEventMap[K]) => any,
- options?: boolean | EventListenerOptions,
- ): void;
- removeEventListener(
- type: string,
- listener: EventListenerOrEventListenerObject,
- options?: boolean | EventListenerOptions,
- ): void;
-}
-
-declare var FileReader: {
- prototype: FileReader;
- new (): FileReader;
- readonly DONE: number;
- readonly EMPTY: number;
- readonly LOADING: number;
-};
-
-type BlobPart = BufferSource | Blob | string;
-
-interface BlobPropertyBag {
- type?: string;
- endings?: "transparent" | "native";
-}
-
-/** A file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user's system. */
-declare class Blob {
- constructor(blobParts?: BlobPart[], options?: BlobPropertyBag);
-
- readonly size: number;
- readonly type: string;
- arrayBuffer(): Promise<ArrayBuffer>;
- slice(start?: number, end?: number, contentType?: string): Blob;
- stream(): ReadableStream<Uint8Array>;
- text(): Promise<string>;
-}
-
-interface FilePropertyBag extends BlobPropertyBag {
- lastModified?: number;
-}
-
-/** Provides information about files and allows JavaScript in a web page to
- * access their content. */
-declare class File extends Blob {
- constructor(
- fileBits: BlobPart[],
- fileName: string,
- options?: FilePropertyBag,
- );
-
- readonly lastModified: number;
- readonly name: string;
-}
-
-interface ReadableStreamReadDoneResult<T> {
- done: true;
- value?: T;
-}
-
-interface ReadableStreamReadValueResult<T> {
- done: false;
- value: T;
-}
-
-type ReadableStreamReadResult<T> =
- | ReadableStreamReadValueResult<T>
- | ReadableStreamReadDoneResult<T>;
-
-interface ReadableStreamDefaultReader<R = any> {
- readonly closed: Promise<void>;
- cancel(reason?: any): Promise<void>;
- read(): Promise<ReadableStreamReadResult<R>>;
- releaseLock(): void;
-}
-
-declare var ReadableStreamDefaultReader: {
- prototype: ReadableStreamDefaultReader;
- new <R>(stream: ReadableStream<R>): ReadableStreamDefaultReader<R>;
-};
-
-interface ReadableStreamReader<R = any> {
- cancel(): Promise<void>;
- read(): Promise<ReadableStreamReadResult<R>>;
- releaseLock(): void;
-}
-
-declare var ReadableStreamReader: {
- prototype: ReadableStreamReader;
- new (): ReadableStreamReader;
-};
-
-interface ReadableByteStreamControllerCallback {
- (controller: ReadableByteStreamController): void | PromiseLike<void>;
-}
-
-interface UnderlyingByteSource {
- autoAllocateChunkSize?: number;
- cancel?: ReadableStreamErrorCallback;
- pull?: ReadableByteStreamControllerCallback;
- start?: ReadableByteStreamControllerCallback;
- type: "bytes";
-}
-
-interface UnderlyingSink<W = any> {
- abort?: WritableStreamErrorCallback;
- close?: WritableStreamDefaultControllerCloseCallback;
- start?: WritableStreamDefaultControllerStartCallback;
- type?: undefined;
- write?: WritableStreamDefaultControllerWriteCallback<W>;
-}
-
-interface UnderlyingSource<R = any> {
- cancel?: ReadableStreamErrorCallback;
- pull?: ReadableStreamDefaultControllerCallback<R>;
- start?: ReadableStreamDefaultControllerCallback<R>;
- type?: undefined;
-}
-
-interface ReadableStreamErrorCallback {
- (reason: any): void | PromiseLike<void>;
-}
-
-interface ReadableStreamDefaultControllerCallback<R> {
- (controller: ReadableStreamDefaultController<R>): void | PromiseLike<void>;
-}
-
-interface ReadableStreamDefaultController<R = any> {
- readonly desiredSize: number | null;
- close(): void;
- enqueue(chunk: R): void;
- error(error?: any): void;
-}
-
-declare var ReadableStreamDefaultController: {
- prototype: ReadableStreamDefaultController;
- new (): ReadableStreamDefaultController;
-};
-
-interface ReadableByteStreamController {
- readonly byobRequest: undefined;
- readonly desiredSize: number | null;
- close(): void;
- enqueue(chunk: ArrayBufferView): void;
- error(error?: any): void;
-}
-
-declare var ReadableByteStreamController: {
- prototype: ReadableByteStreamController;
- new (): ReadableByteStreamController;
-};
-
-interface PipeOptions {
- preventAbort?: boolean;
- preventCancel?: boolean;
- preventClose?: boolean;
- signal?: AbortSignal;
-}
-
-interface QueuingStrategySizeCallback<T = any> {
- (chunk: T): number;
-}
-
-interface QueuingStrategy<T = any> {
- highWaterMark?: number;
- size?: QueuingStrategySizeCallback<T>;
-}
-
-/** This Streams API interface provides a built-in byte length queuing strategy
- * that can be used when constructing streams. */
-declare class CountQueuingStrategy implements QueuingStrategy {
- constructor(options: { highWaterMark: number });
- highWaterMark: number;
- size(chunk: any): 1;
-}
-
-declare class ByteLengthQueuingStrategy
- implements QueuingStrategy<ArrayBufferView> {
- constructor(options: { highWaterMark: number });
- highWaterMark: number;
- size(chunk: ArrayBufferView): number;
-}
-
-/** This Streams API interface represents a readable stream of byte data. The
- * Fetch API offers a concrete instance of a ReadableStream through the body
- * property of a Response object. */
-interface ReadableStream<R = any> {
- readonly locked: boolean;
- cancel(reason?: any): Promise<void>;
- /**
- * @deprecated This is no longer part of the Streams standard and the async
- * iterable should be obtained by just using the stream as an
- * async iterator.
- */
- getIterator(options?: { preventCancel?: boolean }): AsyncIterableIterator<R>;
- getReader(): ReadableStreamDefaultReader<R>;
- pipeThrough<T>(
- { writable, readable }: {
- writable: WritableStream<R>;
- readable: ReadableStream<T>;
- },
- options?: PipeOptions,
- ): ReadableStream<T>;
- pipeTo(dest: WritableStream<R>, options?: PipeOptions): Promise<void>;
- tee(): [ReadableStream<R>, ReadableStream<R>];
- [Symbol.asyncIterator](options?: {
- preventCancel?: boolean;
- }): AsyncIterableIterator<R>;
-}
-
-declare var ReadableStream: {
- prototype: ReadableStream;
- new (
- underlyingSource: UnderlyingByteSource,
- strategy?: { highWaterMark?: number; size?: undefined },
- ): ReadableStream<Uint8Array>;
- new <R = any>(
- underlyingSource?: UnderlyingSource<R>,
- strategy?: QueuingStrategy<R>,
- ): ReadableStream<R>;
-};
-
-interface WritableStreamDefaultControllerCloseCallback {
- (): void | PromiseLike<void>;
-}
-
-interface WritableStreamDefaultControllerStartCallback {
- (controller: WritableStreamDefaultController): void | PromiseLike<void>;
-}
-
-interface WritableStreamDefaultControllerWriteCallback<W> {
- (chunk: W, controller: WritableStreamDefaultController):
- | void
- | PromiseLike<
- void
- >;
-}
-
-interface WritableStreamErrorCallback {
- (reason: any): void | PromiseLike<void>;
-}
-
-/** This Streams API interface provides a standard abstraction for writing
- * streaming data to a destination, known as a sink. This object comes with
- * built-in backpressure and queuing. */
-interface WritableStream<W = any> {
- readonly locked: boolean;
- abort(reason?: any): Promise<void>;
- getWriter(): WritableStreamDefaultWriter<W>;
-}
-
-declare var WritableStream: {
- prototype: WritableStream;
- new <W = any>(
- underlyingSink?: UnderlyingSink<W>,
- strategy?: QueuingStrategy<W>,
- ): WritableStream<W>;
-};
-
-/** This Streams API interface represents a controller allowing control of a
- * WritableStream's state. When constructing a WritableStream, the underlying
- * sink is given a corresponding WritableStreamDefaultController instance to
- * manipulate. */
-interface WritableStreamDefaultController {
- error(error?: any): void;
-}
-
-/** This Streams API interface is the object returned by
- * WritableStream.getWriter() and once created locks the < writer to the
- * WritableStream ensuring that no other streams can write to the underlying
- * sink. */
-interface WritableStreamDefaultWriter<W = any> {
- readonly closed: Promise<void>;
- readonly desiredSize: number | null;
- readonly ready: Promise<void>;
- abort(reason?: any): Promise<void>;
- close(): Promise<void>;
- releaseLock(): void;
- write(chunk: W): Promise<void>;
-}
-
-declare var WritableStreamDefaultWriter: {
- prototype: WritableStreamDefaultWriter;
- new (): WritableStreamDefaultWriter;
-};
-
-interface TransformStream<I = any, O = any> {
- readonly readable: ReadableStream<O>;
- readonly writable: WritableStream<I>;
-}
-
-declare var TransformStream: {
- prototype: TransformStream;
- new <I = any, O = any>(
- transformer?: Transformer<I, O>,
- writableStrategy?: QueuingStrategy<I>,
- readableStrategy?: QueuingStrategy<O>,
- ): TransformStream<I, O>;
-};
-
-interface TransformStreamDefaultController<O = any> {
- readonly desiredSize: number | null;
- enqueue(chunk: O): void;
- error(reason?: any): void;
- terminate(): void;
-}
-
-interface Transformer<I = any, O = any> {
- flush?: TransformStreamDefaultControllerCallback<O>;
- readableType?: undefined;
- start?: TransformStreamDefaultControllerCallback<O>;
- transform?: TransformStreamDefaultControllerTransformCallback<I, O>;
- writableType?: undefined;
-}
-
-interface TransformStreamDefaultControllerCallback<O> {
- (controller: TransformStreamDefaultController<O>): void | PromiseLike<void>;
-}
-
-interface TransformStreamDefaultControllerTransformCallback<I, O> {
- (
- chunk: I,
- controller: TransformStreamDefaultController<O>,
- ): void | PromiseLike<void>;
-}
-
-interface MessageEventInit<T = any> extends EventInit {
- data?: T;
- origin?: string;
- lastEventId?: string;
-}
-
-declare class MessageEvent<T = any> extends Event {
- /**
- * Returns the data of the message.
- */
- readonly data: T;
- /**
- * Returns the last event ID string, for server-sent events.
- */
- readonly lastEventId: string;
- /**
- * Returns transfered ports.
- */
- readonly ports: ReadonlyArray<MessagePort>;
- constructor(type: string, eventInitDict?: MessageEventInit);
-}
-
-type Transferable = ArrayBuffer | MessagePort;
-
-/**
- * @deprecated
- *
- * This type has been renamed to StructuredSerializeOptions. Use that type for
- * new code.
- */
-type PostMessageOptions = StructuredSerializeOptions;
-
-interface StructuredSerializeOptions {
- transfer?: Transferable[];
-}
-
-/** The MessageChannel interface of the Channel Messaging API allows us to
- * create a new message channel and send data through it via its two MessagePort
- * properties. */
-declare class MessageChannel {
- constructor();
- readonly port1: MessagePort;
- readonly port2: MessagePort;
-}
-
-interface MessagePortEventMap {
- "message": MessageEvent;
- "messageerror": MessageEvent;
-}
-
-/** The MessagePort interface of the Channel Messaging API represents one of the
- * two ports of a MessageChannel, allowing messages to be sent from one port and
- * listening out for them arriving at the other. */
-declare class MessagePort extends EventTarget {
- onmessage: ((this: MessagePort, ev: MessageEvent) => any) | null;
- onmessageerror: ((this: MessagePort, ev: MessageEvent) => any) | null;
- /**
- * Disconnects the port, so that it is no longer active.
- */
- close(): void;
- /**
- * Posts a message through the channel. Objects listed in transfer are
- * transferred, not just cloned, meaning that they are no longer usable on the
- * sending side.
- *
- * Throws a "DataCloneError" DOMException if transfer contains duplicate
- * objects or port, or if message could not be cloned.
- */
- postMessage(message: any, transfer: Transferable[]): void;
- postMessage(message: any, options?: StructuredSerializeOptions): void;
- /**
- * Begins dispatching messages received on the port. This is implictly called
- * when assiging a value to `this.onmessage`.
- */
- start(): void;
- addEventListener<K extends keyof MessagePortEventMap>(
- type: K,
- listener: (this: MessagePort, ev: MessagePortEventMap[K]) => any,
- options?: boolean | AddEventListenerOptions,
- ): void;
- addEventListener(
- type: string,
- listener: EventListenerOrEventListenerObject,
- options?: boolean | AddEventListenerOptions,
- ): void;
- removeEventListener<K extends keyof MessagePortEventMap>(
- type: K,
- listener: (this: MessagePort, ev: MessagePortEventMap[K]) => any,
- options?: boolean | EventListenerOptions,
- ): void;
- removeEventListener(
- type: string,
- listener: EventListenerOrEventListenerObject,
- options?: boolean | EventListenerOptions,
- ): void;
-}
-
-declare function structuredClone(
- value: any,
- options?: StructuredSerializeOptions,
-): any;
diff --git a/extensions/web/lib.rs b/extensions/web/lib.rs
deleted file mode 100644
index 634004ac9..000000000
--- a/extensions/web/lib.rs
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-
-mod blob;
-mod message_port;
-
-use deno_core::error::bad_resource_id;
-use deno_core::error::range_error;
-use deno_core::error::type_error;
-use deno_core::error::AnyError;
-use deno_core::include_js_files;
-use deno_core::op_async;
-use deno_core::op_sync;
-use deno_core::url::Url;
-use deno_core::Extension;
-use deno_core::OpState;
-use deno_core::Resource;
-use deno_core::ResourceId;
-use deno_core::ZeroCopyBuf;
-use encoding_rs::CoderResult;
-use encoding_rs::Decoder;
-use encoding_rs::DecoderResult;
-use encoding_rs::Encoding;
-use serde::Deserialize;
-use serde::Serialize;
-use std::borrow::Cow;
-use std::cell::RefCell;
-use std::fmt;
-use std::path::PathBuf;
-use std::usize;
-
-use crate::blob::op_blob_create_object_url;
-use crate::blob::op_blob_create_part;
-use crate::blob::op_blob_read_part;
-use crate::blob::op_blob_remove_part;
-use crate::blob::op_blob_revoke_object_url;
-use crate::blob::op_blob_slice_part;
-pub use crate::blob::Blob;
-pub use crate::blob::BlobPart;
-pub use crate::blob::BlobStore;
-pub use crate::blob::InMemoryBlobPart;
-
-pub use crate::message_port::create_entangled_message_port;
-use crate::message_port::op_message_port_create_entangled;
-use crate::message_port::op_message_port_post_message;
-use crate::message_port::op_message_port_recv_message;
-pub use crate::message_port::JsMessageData;
-pub use crate::message_port::MessagePort;
-
-/// Load and execute the javascript code.
-pub fn init(blob_store: BlobStore, maybe_location: Option<Url>) -> Extension {
- Extension::builder()
- .js(include_js_files!(
- prefix "deno:extensions/web",
- "00_infra.js",
- "01_dom_exception.js",
- "01_mimesniff.js",
- "02_event.js",
- "02_structured_clone.js",
- "03_abort_signal.js",
- "04_global_interfaces.js",
- "05_base64.js",
- "06_streams.js",
- "08_text_encoding.js",
- "09_file.js",
- "10_filereader.js",
- "11_blob_url.js",
- "12_location.js",
- "13_message_port.js",
- ))
- .ops(vec![
- ("op_base64_decode", op_sync(op_base64_decode)),
- ("op_base64_encode", op_sync(op_base64_encode)),
- (
- "op_encoding_normalize_label",
- op_sync(op_encoding_normalize_label),
- ),
- ("op_encoding_new_decoder", op_sync(op_encoding_new_decoder)),
- ("op_encoding_decode", op_sync(op_encoding_decode)),
- ("op_encoding_encode_into", op_sync(op_encoding_encode_into)),
- ("op_blob_create_part", op_sync(op_blob_create_part)),
- ("op_blob_slice_part", op_sync(op_blob_slice_part)),
- ("op_blob_read_part", op_async(op_blob_read_part)),
- ("op_blob_remove_part", op_sync(op_blob_remove_part)),
- (
- "op_blob_create_object_url",
- op_sync(op_blob_create_object_url),
- ),
- (
- "op_blob_revoke_object_url",
- op_sync(op_blob_revoke_object_url),
- ),
- (
- "op_message_port_create_entangled",
- op_sync(op_message_port_create_entangled),
- ),
- (
- "op_message_port_post_message",
- op_sync(op_message_port_post_message),
- ),
- (
- "op_message_port_recv_message",
- op_async(op_message_port_recv_message),
- ),
- ])
- .state(move |state| {
- state.put(blob_store.clone());
- if let Some(location) = maybe_location.clone() {
- state.put(Location(location));
- }
- Ok(())
- })
- .build()
-}
-
-fn op_base64_decode(
- _state: &mut OpState,
- input: String,
- _: (),
-) -> Result<ZeroCopyBuf, AnyError> {
- let mut input: &str = &input.replace(|c| char::is_ascii_whitespace(&c), "");
- // "If the length of input divides by 4 leaving no remainder, then:
- // if input ends with one or two U+003D EQUALS SIGN (=) characters,
- // remove them from input."
- if input.len() % 4 == 0 {
- if input.ends_with("==") {
- input = &input[..input.len() - 2]
- } else if input.ends_with('=') {
- input = &input[..input.len() - 1]
- }
- }
-
- // "If the length of input divides by 4 leaving a remainder of 1,
- // throw an InvalidCharacterError exception and abort these steps."
- if input.len() % 4 == 1 {
- return Err(
- DomExceptionInvalidCharacterError::new("Failed to decode base64.").into(),
- );
- }
-
- if input
- .chars()
- .any(|c| c != '+' && c != '/' && !c.is_alphanumeric())
- {
- return Err(
- DomExceptionInvalidCharacterError::new(
- "Failed to decode base64: invalid character",
- )
- .into(),
- );
- }
-
- let cfg = base64::Config::new(base64::CharacterSet::Standard, true)
- .decode_allow_trailing_bits(true);
- let out = base64::decode_config(&input, cfg).map_err(|err| {
- DomExceptionInvalidCharacterError::new(&format!(
- "Failed to decode base64: {:?}",
- err
- ))
- })?;
- Ok(ZeroCopyBuf::from(out))
-}
-
-fn op_base64_encode(
- _state: &mut OpState,
- s: ZeroCopyBuf,
- _: (),
-) -> Result<String, AnyError> {
- let cfg = base64::Config::new(base64::CharacterSet::Standard, true)
- .decode_allow_trailing_bits(true);
- let out = base64::encode_config(&s, cfg);
- Ok(out)
-}
-
-#[derive(Deserialize)]
-#[serde(rename_all = "camelCase")]
-struct DecoderOptions {
- label: String,
- ignore_bom: bool,
- fatal: bool,
-}
-
-fn op_encoding_normalize_label(
- _state: &mut OpState,
- label: String,
- _: (),
-) -> Result<String, AnyError> {
- let encoding = Encoding::for_label_no_replacement(label.as_bytes())
- .ok_or_else(|| {
- range_error(format!(
- "The encoding label provided ('{}') is invalid.",
- label
- ))
- })?;
- Ok(encoding.name().to_lowercase())
-}
-
-fn op_encoding_new_decoder(
- state: &mut OpState,
- options: DecoderOptions,
- _: (),
-) -> Result<ResourceId, AnyError> {
- let DecoderOptions {
- label,
- fatal,
- ignore_bom,
- } = options;
-
- let encoding = Encoding::for_label(label.as_bytes()).ok_or_else(|| {
- range_error(format!(
- "The encoding label provided ('{}') is invalid.",
- label
- ))
- })?;
-
- let decoder = if ignore_bom {
- encoding.new_decoder_without_bom_handling()
- } else {
- encoding.new_decoder_with_bom_removal()
- };
-
- let rid = state.resource_table.add(TextDecoderResource {
- decoder: RefCell::new(decoder),
- fatal,
- });
-
- Ok(rid)
-}
-
-#[derive(Deserialize)]
-#[serde(rename_all = "camelCase")]
-struct DecodeOptions {
- rid: ResourceId,
- stream: bool,
-}
-
-fn op_encoding_decode(
- state: &mut OpState,
- data: ZeroCopyBuf,
- options: DecodeOptions,
-) -> Result<String, AnyError> {
- let DecodeOptions { rid, stream } = options;
-
- let resource = state
- .resource_table
- .get::<TextDecoderResource>(rid)
- .ok_or_else(bad_resource_id)?;
-
- let mut decoder = resource.decoder.borrow_mut();
- let fatal = resource.fatal;
-
- let max_buffer_length = if fatal {
- decoder
- .max_utf8_buffer_length_without_replacement(data.len())
- .ok_or_else(|| range_error("Value too large to decode."))?
- } else {
- decoder
- .max_utf8_buffer_length(data.len())
- .ok_or_else(|| range_error("Value too large to decode."))?
- };
-
- let mut output = String::with_capacity(max_buffer_length);
-
- if fatal {
- let (result, _) =
- decoder.decode_to_string_without_replacement(&data, &mut output, !stream);
- match result {
- DecoderResult::InputEmpty => Ok(output),
- DecoderResult::OutputFull => {
- Err(range_error("Provided buffer too small."))
- }
- DecoderResult::Malformed(_, _) => {
- Err(type_error("The encoded data is not valid."))
- }
- }
- } else {
- let (result, _, _) = decoder.decode_to_string(&data, &mut output, !stream);
- match result {
- CoderResult::InputEmpty => Ok(output),
- CoderResult::OutputFull => Err(range_error("Provided buffer too small.")),
- }
- }
-}
-
-struct TextDecoderResource {
- decoder: RefCell<Decoder>,
- fatal: bool,
-}
-
-impl Resource for TextDecoderResource {
- fn name(&self) -> Cow<str> {
- "textDecoder".into()
- }
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct EncodeIntoResult {
- read: usize,
- written: usize,
-}
-
-fn op_encoding_encode_into(
- _state: &mut OpState,
- input: String,
- mut buffer: ZeroCopyBuf,
-) -> Result<EncodeIntoResult, AnyError> {
- // Since `input` is already UTF-8, we can simply find the last UTF-8 code
- // point boundary from input that fits in `buffer`, and copy the bytes up to
- // that point.
- let boundary = if buffer.len() >= input.len() {
- input.len()
- } else {
- let mut boundary = buffer.len();
-
- // The maximum length of a UTF-8 code point is 4 bytes.
- for _ in 0..4 {
- if input.is_char_boundary(boundary) {
- break;
- }
- debug_assert!(boundary > 0);
- boundary -= 1;
- }
-
- debug_assert!(input.is_char_boundary(boundary));
- boundary
- };
-
- buffer[..boundary].copy_from_slice(input[..boundary].as_bytes());
-
- Ok(EncodeIntoResult {
- // The `read` output parameter is measured in UTF-16 code units.
- read: input[..boundary].encode_utf16().count(),
- written: boundary,
- })
-}
-
-pub fn get_declaration() -> PathBuf {
- PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_web.d.ts")
-}
-
-#[derive(Debug)]
-pub struct DomExceptionQuotaExceededError {
- pub msg: String,
-}
-
-impl DomExceptionQuotaExceededError {
- pub fn new(msg: &str) -> Self {
- DomExceptionQuotaExceededError {
- msg: msg.to_string(),
- }
- }
-}
-
-#[derive(Debug)]
-pub struct DomExceptionInvalidCharacterError {
- pub msg: String,
-}
-
-impl DomExceptionInvalidCharacterError {
- pub fn new(msg: &str) -> Self {
- DomExceptionInvalidCharacterError {
- msg: msg.to_string(),
- }
- }
-}
-
-impl fmt::Display for DomExceptionQuotaExceededError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.pad(&self.msg)
- }
-}
-impl fmt::Display for DomExceptionInvalidCharacterError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.pad(&self.msg)
- }
-}
-
-impl std::error::Error for DomExceptionQuotaExceededError {}
-
-impl std::error::Error for DomExceptionInvalidCharacterError {}
-
-pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
- e.downcast_ref::<DomExceptionQuotaExceededError>()
- .map(|_| "DOMExceptionQuotaExceededError")
- .or_else(|| {
- e.downcast_ref::<DomExceptionInvalidCharacterError>()
- .map(|_| "DOMExceptionInvalidCharacterError")
- })
-}
-pub struct Location(pub Url);
diff --git a/extensions/web/message_port.rs b/extensions/web/message_port.rs
deleted file mode 100644
index f73d0486a..000000000
--- a/extensions/web/message_port.rs
+++ /dev/null
@@ -1,217 +0,0 @@
-use std::borrow::Cow;
-use std::cell::RefCell;
-use std::rc::Rc;
-
-use deno_core::error::bad_resource_id;
-use deno_core::error::type_error;
-use deno_core::error::AnyError;
-use deno_core::ZeroCopyBuf;
-use deno_core::{CancelFuture, Resource};
-use deno_core::{CancelHandle, OpState};
-use deno_core::{RcRef, ResourceId};
-use serde::Deserialize;
-use serde::Serialize;
-use tokio::sync::mpsc::unbounded_channel;
-use tokio::sync::mpsc::UnboundedReceiver;
-use tokio::sync::mpsc::UnboundedSender;
-
-enum Transferable {
- MessagePort(MessagePort),
-}
-
-type MessagePortMessage = (Vec<u8>, Vec<Transferable>);
-
-pub struct MessagePort {
- rx: RefCell<UnboundedReceiver<MessagePortMessage>>,
- tx: RefCell<Option<UnboundedSender<MessagePortMessage>>>,
-}
-
-impl MessagePort {
- pub fn send(
- &self,
- state: &mut OpState,
- data: JsMessageData,
- ) -> Result<(), AnyError> {
- let transferables =
- deserialize_js_transferables(state, data.transferables)?;
-
- // Swallow the failed to send error. It means the channel was disentangled,
- // but not cleaned up.
- if let Some(tx) = &*self.tx.borrow() {
- tx.send((data.data.to_vec(), transferables)).ok();
- }
-
- Ok(())
- }
-
- pub async fn recv(
- &self,
- state: Rc<RefCell<OpState>>,
- ) -> Result<Option<JsMessageData>, AnyError> {
- let mut rx = self
- .rx
- .try_borrow_mut()
- .map_err(|_| type_error("Port receiver is already borrowed"))?;
- if let Some((data, transferables)) = rx.recv().await {
- let js_transferables =
- serialize_transferables(&mut state.borrow_mut(), transferables);
- return Ok(Some(JsMessageData {
- data: ZeroCopyBuf::from(data),
- transferables: js_transferables,
- }));
- }
- Ok(None)
- }
-
- /// This forcefully disconnects the message port from its paired port. This
- /// will wake up the `.recv` on the paired port, which will return `Ok(None)`.
- pub fn disentangle(&self) {
- let mut tx = self.tx.borrow_mut();
- tx.take();
- }
-}
-
-pub fn create_entangled_message_port() -> (MessagePort, MessagePort) {
- let (port1_tx, port2_rx) = unbounded_channel::<MessagePortMessage>();
- let (port2_tx, port1_rx) = unbounded_channel::<MessagePortMessage>();
-
- let port1 = MessagePort {
- rx: RefCell::new(port1_rx),
- tx: RefCell::new(Some(port1_tx)),
- };
-
- let port2 = MessagePort {
- rx: RefCell::new(port2_rx),
- tx: RefCell::new(Some(port2_tx)),
- };
-
- (port1, port2)
-}
-
-pub struct MessagePortResource {
- port: MessagePort,
- cancel: CancelHandle,
-}
-
-impl Resource for MessagePortResource {
- fn name(&self) -> Cow<str> {
- "messagePort".into()
- }
-
- fn close(self: Rc<Self>) {
- self.cancel.cancel();
- }
-}
-
-pub fn op_message_port_create_entangled(
- state: &mut OpState,
- _: (),
- _: (),
-) -> Result<(ResourceId, ResourceId), AnyError> {
- let (port1, port2) = create_entangled_message_port();
-
- let port1_id = state.resource_table.add(MessagePortResource {
- port: port1,
- cancel: CancelHandle::new(),
- });
-
- let port2_id = state.resource_table.add(MessagePortResource {
- port: port2,
- cancel: CancelHandle::new(),
- });
-
- Ok((port1_id, port2_id))
-}
-
-#[derive(Deserialize, Serialize)]
-#[serde(tag = "kind", content = "data", rename_all = "camelCase")]
-pub enum JsTransferable {
- #[serde(rename_all = "camelCase")]
- MessagePort(ResourceId),
-}
-
-fn deserialize_js_transferables(
- state: &mut OpState,
- js_transferables: Vec<JsTransferable>,
-) -> Result<Vec<Transferable>, AnyError> {
- let mut transferables = Vec::with_capacity(js_transferables.len());
- for js_transferable in js_transferables {
- match js_transferable {
- JsTransferable::MessagePort(id) => {
- let resource = state
- .resource_table
- .take::<MessagePortResource>(id)
- .ok_or_else(|| type_error("Invalid message port transfer"))?;
- resource.cancel.cancel();
- let resource = Rc::try_unwrap(resource)
- .map_err(|_| type_error("Message port is not ready for transfer"))?;
- transferables.push(Transferable::MessagePort(resource.port));
- }
- }
- }
- Ok(transferables)
-}
-
-fn serialize_transferables(
- state: &mut OpState,
- transferables: Vec<Transferable>,
-) -> Vec<JsTransferable> {
- let mut js_transferables = Vec::with_capacity(transferables.len());
- for transferable in transferables {
- match transferable {
- Transferable::MessagePort(port) => {
- let rid = state.resource_table.add(MessagePortResource {
- port,
- cancel: CancelHandle::new(),
- });
- js_transferables.push(JsTransferable::MessagePort(rid));
- }
- }
- }
- js_transferables
-}
-
-#[derive(Deserialize, Serialize)]
-pub struct JsMessageData {
- data: ZeroCopyBuf,
- transferables: Vec<JsTransferable>,
-}
-
-pub fn op_message_port_post_message(
- state: &mut OpState,
- rid: ResourceId,
- data: JsMessageData,
-) -> Result<(), AnyError> {
- for js_transferable in &data.transferables {
- match js_transferable {
- JsTransferable::MessagePort(id) => {
- if *id == rid {
- return Err(type_error("Can not transfer self message port"));
- }
- }
- }
- }
-
- let resource = state
- .resource_table
- .get::<MessagePortResource>(rid)
- .ok_or_else(bad_resource_id)?;
-
- resource.port.send(state, data)
-}
-
-pub async fn op_message_port_recv_message(
- state: Rc<RefCell<OpState>>,
- rid: ResourceId,
- _: (),
-) -> Result<Option<JsMessageData>, AnyError> {
- let resource = {
- let state = state.borrow();
- match state.resource_table.get::<MessagePortResource>(rid) {
- Some(resource) => resource,
- None => return Ok(None),
- }
- };
- let cancel = RcRef::map(resource.clone(), |r| &r.cancel);
- resource.port.recv(state).or_cancel(cancel).await?
-}