From a0285e2eb88f6254f6494b0ecd1878db3a3b2a58 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Wed, 11 Aug 2021 12:27:05 +0200 Subject: Rename extensions/ directory to ext/ (#11643) --- extensions/web/00_infra.js | 264 -- extensions/web/01_dom_exception.js | 171 -- extensions/web/01_mimesniff.js | 211 -- extensions/web/02_event.js | 1294 --------- extensions/web/02_structured_clone.js | 85 - extensions/web/03_abort_signal.js | 123 - extensions/web/04_global_interfaces.js | 79 - extensions/web/05_base64.js | 73 - extensions/web/06_streams.js | 4473 -------------------------------- extensions/web/06_streams_types.d.ts | 55 - extensions/web/08_text_encoding.js | 420 --- extensions/web/09_file.js | 569 ---- extensions/web/10_filereader.js | 461 ---- extensions/web/11_blob_url.js | 59 - extensions/web/12_location.js | 409 --- extensions/web/13_message_port.js | 286 -- extensions/web/Cargo.toml | 26 - extensions/web/README.md | 6 - extensions/web/blob.rs | 265 -- extensions/web/internal.d.ts | 98 - extensions/web/lib.deno_web.d.ts | 752 ------ extensions/web/lib.rs | 390 --- extensions/web/message_port.rs | 217 -- 23 files changed, 10786 deletions(-) delete mode 100644 extensions/web/00_infra.js delete mode 100644 extensions/web/01_dom_exception.js delete mode 100644 extensions/web/01_mimesniff.js delete mode 100644 extensions/web/02_event.js delete mode 100644 extensions/web/02_structured_clone.js delete mode 100644 extensions/web/03_abort_signal.js delete mode 100644 extensions/web/04_global_interfaces.js delete mode 100644 extensions/web/05_base64.js delete mode 100644 extensions/web/06_streams.js delete mode 100644 extensions/web/06_streams_types.d.ts delete mode 100644 extensions/web/08_text_encoding.js delete mode 100644 extensions/web/09_file.js delete mode 100644 extensions/web/10_filereader.js delete mode 100644 extensions/web/11_blob_url.js delete mode 100644 extensions/web/12_location.js delete mode 100644 extensions/web/13_message_port.js delete mode 100644 extensions/web/Cargo.toml delete mode 100644 extensions/web/README.md delete mode 100644 extensions/web/blob.rs delete mode 100644 extensions/web/internal.d.ts delete mode 100644 extensions/web/lib.deno_web.d.ts delete mode 100644 extensions/web/lib.rs delete mode 100644 extensions/web/message_port.rs (limited to 'extensions/web') 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 -/// -/// -/// -/// - -"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 -/// -/// -/// -/// -/// - -"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} */ - 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 -/// -/// -/// -/// - -"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} 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} */ - 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 -/// -/// -/// -/// - -"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 -/// - -((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 -/// - -((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 -/// -/// -/// -/// - -"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 -/// -/// -/// -/// -"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} */ - #promise; - /** @type {(reject?: any) => void} */ - #reject; - /** @type {(value: T | PromiseLike) => void} */ - #resolve; - /** @type {"pending" | "fulfilled"} */ - #state = "pending"; - - constructor() { - this.#promise = new Promise((resolve, reject) => { - this.#resolve = resolve; - this.#reject = reject; - }); - } - - /** @returns {Promise} */ - 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} 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} value - * @returns {Promise} - */ - 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} promise */ - function setPromiseIsHandledToTrue(promise) { - PromisePrototypeThen(promise, undefined, rethrowAssertionErrorRejection); - } - - /** - * @template T - * @template TResult1 - * @template TResult2 - * @param {Promise} promise - * @param {(value: T) => TResult1 | PromiseLike} fulfillmentHandler - * @param {(reason: any) => TResult2 | PromiseLike=} rejectionHandler - * @returns {Promise} - */ - function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { - return PromisePrototypeThen(promise, fulfillmentHandler, rejectionHandler); - } - - /** - * @template T - * @template TResult - * @param {Promise} promise - * @param {(value: T) => TResult | PromiseLike} onFulfilled - * @returns {void} - */ - function uponFulfillment(promise, onFulfilled) { - uponPromise(promise, onFulfilled); - } - - /** - * @template T - * @template TResult - * @param {Promise} promise - * @param {(value: T) => TResult | PromiseLike} onRejected - * @returns {void} - */ - function uponRejection(promise, onRejected) { - uponPromise(promise, undefined, onRejected); - } - - /** - * @template T - * @template TResult1 - * @template TResult2 - * @param {Promise} promise - * @param {(value: T) => TResult1 | PromiseLike} onFulfilled - * @param {(reason: any) => TResult2 | PromiseLike=} onRejected - * @returns {void} - */ - function uponPromise(promise, onFulfilled, onRejected) { - PromisePrototypeThen( - PromisePrototypeThen(promise, onFulfilled, onRejected), - undefined, - rethrowAssertionErrorRejection, - ); - } - - const isFakeDetached = Symbol("<>"); - - /** - * @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} stream - * @returns {ReadableStreamDefaultReader} - */ - function acquireReadableStreamDefaultReader(stream) { - return new ReadableStreamDefaultReader(stream); - } - - /** - * @template W - * @param {WritableStream} stream - * @returns {WritableStreamDefaultWriter} - */ - function acquireWritableStreamDefaultWriter(stream) { - return new WritableStreamDefaultWriter(stream); - } - - /** - * @template R - * @param {() => void} startAlgorithm - * @param {() => Promise} pullAlgorithm - * @param {(reason: any) => Promise} cancelAlgorithm - * @param {number=} highWaterMark - * @param {((chunk: R) => number)=} sizeAlgorithm - * @returns {ReadableStream} - */ - 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) => Promise} startAlgorithm - * @param {(chunk: W) => Promise} writeAlgorithm - * @param {() => Promise} closeAlgorithm - * @param {(reason: any) => Promise} abortAlgorithm - * @param {number} highWaterMark - * @param {(chunk: W) => number} sizeAlgorithm - * @returns {WritableStream} - */ - 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>, [_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>, [_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} 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} stream - * @param {Deferred} 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>, [_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} */ - 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} */ - 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} */ - 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} */ - 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} */ - 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} stream - * @param {ReadRequest} readRequest - * @returns {void} - */ - function readableStreamAddReadRequest(stream, readRequest) { - assert(isReadableStreamDefaultReader(stream[_reader])); - assert(stream[_state] === "readable"); - ArrayPrototypePush(stream[_reader][_readRequests], readRequest); - } - - /** - * @template R - * @param {ReadableStream} stream - * @param {any=} reason - * @returns {Promise} - */ - 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} */ - const sourceCancelPromise = stream[_controller][_cancelSteps](reason); - return PromisePrototypeThen(sourceCancelPromise, () => undefined); - } - - /** - * @template R - * @param {ReadableStream} stream - * @returns {void} - */ - function readableStreamClose(stream) { - assert(stream[_state] === "readable"); - stream[_state] = "closed"; - /** @type {ReadableStreamDefaultReader | undefined} */ - const reader = stream[_reader]; - if (!reader) { - return; - } - if (isReadableStreamDefaultReader(reader)) { - /** @type {Array>} */ - 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} 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} controller - * @returns {boolean} - */ - function readableStreamDefaultControllerCanCloseOrEnqueue(controller) { - const state = controller[_stream][_state]; - if (controller[_closeRequested] === false && state === "readable") { - return true; - } else { - return false; - } - } - - /** @param {ReadableStreamDefaultController} controller */ - function readableStreamDefaultControllerClearAlgorithms(controller) { - controller[_pullAlgorithm] = undefined; - controller[_cancelAlgorithm] = undefined; - controller[_strategySizeAlgorithm] = undefined; - } - - /** @param {ReadableStreamDefaultController} 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} 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} 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} 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} 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} reader - * @param {ReadRequest} 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} stream - * @param {any} e - */ - function readableStreamError(stream, e) { - assert(stream[_state] === "readable"); - stream[_state] = "errored"; - stream[_storedError] = e; - /** @type {ReadableStreamDefaultReader | undefined} */ - const reader = stream[_reader]; - if (reader === undefined) { - return; - } - /** @type {Deferred} */ - const closedPromise = reader[_closedPromise]; - closedPromise.reject(e); - setPromiseIsHandledToTrue(closedPromise.promise); - if (isReadableStreamDefaultReader(reader)) { - /** @type {Array>} */ - 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} stream - * @param {R} chunk - * @param {boolean} done - */ - function readableStreamFulfillReadRequest(stream, chunk, done) { - assert(readableStreamHasDefaultReader(stream) === true); - /** @type {ReadableStreamDefaultReader} */ - const reader = stream[_reader]; - assert(reader[_readRequests].length); - /** @type {ReadRequest} */ - 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} source - * @param {WritableStream} dest - * @param {boolean} preventClose - * @param {boolean} preventAbort - * @param {boolean} preventCancel - * @param {AbortSignal=} signal - * @returns {Promise} - */ - 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} */ - const promise = new Deferred(); - /** @type {() => void} */ - let abortAlgorithm; - if (signal) { - abortAlgorithm = () => { - const error = new DOMException("Aborted", "AbortError"); - /** @type {Array<() => Promise>} */ - 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} */ - 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} */ - function waitForWritesToFinish() { - const oldCurrentWrite = currentWrite; - return transformPromiseWith( - currentWrite, - () => - oldCurrentWrite !== currentWrite - ? waitForWritesToFinish() - : undefined, - ); - } - - /** - * @param {ReadableStream | WritableStream} stream - * @param {Promise} 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} promise - * @param {() => void} action - */ - function isOrBecomesClosed(stream, promise, action) { - if (stream[_state] === "closed") { - action(); - } else { - uponFulfillment(promise, action); - } - } - - /** - * @param {() => Promise} 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} reader - * @param {any} reason - * @returns {Promise} - */ - function readableStreamReaderGenericCancel(reader, reason) { - const stream = reader[_stream]; - assert(stream !== undefined); - return readableStreamCancel(stream, reason); - } - - /** - * @template R - * @param {ReadableStreamDefaultReader} reader - * @param {ReadableStream} 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} 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} stream - * @param {boolean} cloneForBranch2 - * @returns {[ReadableStream, ReadableStream]} - */ - 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} */ - // deno-lint-ignore prefer-const - let branch1; - /** @type {ReadableStream} */ - // deno-lint-ignore prefer-const - let branch2; - - /** @type {Deferred} */ - const cancelPromise = new Deferred(); - - function pullAlgorithm() { - if (reading === true) { - return resolvePromiseWith(undefined); - } - reading = true; - /** @type {ReadRequest} */ - const readRequest = { - chunkSteps(value) { - queueMicrotask(() => { - reading = false; - const value1 = value; - const value2 = value; - - // TODO(lucacasonato): respect clonedForBranch2. - - if (canceled1 === false) { - readableStreamDefaultControllerEnqueue( - /** @type {ReadableStreamDefaultController} */ (branch1[ - _controller - ]), - value1, - ); - } - if (canceled2 === false) { - readableStreamDefaultControllerEnqueue( - /** @type {ReadableStreamDefaultController} */ (branch2[ - _controller - ]), - value2, - ); - } - }); - }, - closeSteps() { - reading = false; - if (canceled1 === false) { - readableStreamDefaultControllerClose( - /** @type {ReadableStreamDefaultController} */ (branch1[ - _controller - ]), - ); - } - if (canceled2 === false) { - readableStreamDefaultControllerClose( - /** @type {ReadableStreamDefaultController} */ (branch2[ - _controller - ]), - ); - } - cancelPromise.resolve(undefined); - }, - errorSteps() { - reading = false; - }, - }; - readableStreamDefaultReaderRead(reader, readRequest); - return resolvePromiseWith(undefined); - } - - /** - * @param {any} reason - * @returns {Promise} - */ - 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} - */ - 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} */ (branch1[ - _controller - ]), - r, - ); - readableStreamDefaultControllerError( - /** @type {ReadableStreamDefaultController} */ (branch2[ - _controller - ]), - r, - ); - if (canceled1 === false || canceled2 === false) { - cancelPromise.resolve(undefined); - } - }); - - return [branch1, branch2]; - } - - /** - * @param {ReadableStream} stream - * @param {ReadableByteStreamController} controller - * @param {() => void} startAlgorithm - * @param {() => Promise} pullAlgorithm - * @param {(reason: any) => Promise} 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} stream - * @param {UnderlyingSource} underlyingSource - * @param {UnderlyingSource} underlyingSourceDict - * @param {number} highWaterMark - */ - function setUpReadableByteStreamControllerFromUnderlyingSource( - stream, - underlyingSource, - underlyingSourceDict, - highWaterMark, - ) { - const controller = webidl.createBranded(ReadableByteStreamController); - /** @type {() => void} */ - let startAlgorithm = () => undefined; - /** @type {() => Promise} */ - let pullAlgorithm = () => resolvePromiseWith(undefined); - /** @type {(reason: any) => Promise} */ - 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"], - { - prefix: - "Failed to call 'pullAlgorithm' on 'ReadableByteStreamController'", - returnsPromise: true, - }, - ); - } - if (underlyingSourceDict.cancel !== undefined) { - cancelAlgorithm = (reason) => - webidl.invokeCallbackFunction( - underlyingSourceDict.cancel, - [reason], - underlyingSource, - webidl.converters["Promise"], - { - 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} stream - * @param {ReadableStreamDefaultController} controller - * @param {(controller: ReadableStreamDefaultController) => void | Promise} startAlgorithm - * @param {(controller: ReadableStreamDefaultController) => Promise} pullAlgorithm - * @param {(reason: any) => Promise} 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} stream - * @param {UnderlyingSource} underlyingSource - * @param {UnderlyingSource} underlyingSourceDict - * @param {number} highWaterMark - * @param {(chunk: R) => number} sizeAlgorithm - */ - function setUpReadableStreamDefaultControllerFromUnderlyingSource( - stream, - underlyingSource, - underlyingSourceDict, - highWaterMark, - sizeAlgorithm, - ) { - const controller = webidl.createBranded(ReadableStreamDefaultController); - /** @type {() => Promise} */ - let startAlgorithm = () => undefined; - /** @type {() => Promise} */ - let pullAlgorithm = () => resolvePromiseWith(undefined); - /** @type {(reason?: any) => Promise} */ - 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"], - { - prefix: - "Failed to call 'pullAlgorithm' on 'ReadableStreamDefaultController'", - returnsPromise: true, - }, - ); - } - if (underlyingSourceDict.cancel !== undefined) { - cancelAlgorithm = (reason) => - webidl.invokeCallbackFunction( - underlyingSourceDict.cancel, - [reason], - underlyingSource, - webidl.converters["Promise"], - { - prefix: - "Failed to call 'cancelAlgorithm' on 'ReadableStreamDefaultController'", - returnsPromise: true, - }, - ); - } - setUpReadableStreamDefaultController( - stream, - controller, - startAlgorithm, - pullAlgorithm, - cancelAlgorithm, - highWaterMark, - sizeAlgorithm, - ); - } - - /** - * @template R - * @param {ReadableStreamDefaultReader} reader - * @param {ReadableStream} stream - */ - function setUpReadableStreamDefaultReader(reader, stream) { - if (isReadableStreamLocked(stream)) { - throw new TypeError("ReadableStream is locked."); - } - readableStreamReaderGenericInitialize(reader, stream); - reader[_readRequests] = []; - } - - /** - * @template O - * @param {TransformStream} stream - * @param {TransformStreamDefaultController} controller - * @param {(chunk: O, controller: TransformStreamDefaultController) => Promise} transformAlgorithm - * @param {(controller: TransformStreamDefaultController) => Promise} 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} stream - * @param {Transformer} transformer - * @param {Transformer} transformerDict - */ - function setUpTransformStreamDefaultControllerFromTransformer( - stream, - transformer, - transformerDict, - ) { - /** @type {TransformStreamDefaultController} */ - const controller = webidl.createBranded(TransformStreamDefaultController); - /** @type {(chunk: O, controller: TransformStreamDefaultController) => Promise} */ - let transformAlgorithm = (chunk) => { - try { - transformStreamDefaultControllerEnqueue(controller, chunk); - } catch (e) { - return PromiseReject(e); - } - return resolvePromiseWith(undefined); - }; - /** @type {(controller: TransformStreamDefaultController) => Promise} */ - let flushAlgorithm = () => resolvePromiseWith(undefined); - if (transformerDict.transform !== undefined) { - transformAlgorithm = (chunk, controller) => - webidl.invokeCallbackFunction( - transformerDict.transform, - [chunk, controller], - transformer, - webidl.converters["Promise"], - { - prefix: - "Failed to call 'transformAlgorithm' on 'TransformStreamDefaultController'", - returnsPromise: true, - }, - ); - } - if (transformerDict.flush !== undefined) { - flushAlgorithm = (controller) => - webidl.invokeCallbackFunction( - transformerDict.flush, - [controller], - transformer, - webidl.converters["Promise"], - { - prefix: - "Failed to call 'flushAlgorithm' on 'TransformStreamDefaultController'", - returnsPromise: true, - }, - ); - } - setUpTransformStreamDefaultController( - stream, - controller, - transformAlgorithm, - flushAlgorithm, - ); - } - - /** - * @template W - * @param {WritableStream} stream - * @param {WritableStreamDefaultController} controller - * @param {(controller: WritableStreamDefaultController) => Promise} startAlgorithm - * @param {(chunk: W, controller: WritableStreamDefaultController) => Promise} writeAlgorithm - * @param {() => Promise} closeAlgorithm - * @param {(reason?: any) => Promise} 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} stream - * @param {UnderlyingSink} underlyingSink - * @param {UnderlyingSink} underlyingSinkDict - * @param {number} highWaterMark - * @param {(chunk: W) => number} sizeAlgorithm - */ - function setUpWritableStreamDefaultControllerFromUnderlyingSink( - stream, - underlyingSink, - underlyingSinkDict, - highWaterMark, - sizeAlgorithm, - ) { - const controller = webidl.createBranded(WritableStreamDefaultController); - /** @type {(controller: WritableStreamDefaultController) => any} */ - let startAlgorithm = () => undefined; - /** @type {(chunk: W, controller: WritableStreamDefaultController) => Promise} */ - let writeAlgorithm = () => resolvePromiseWith(undefined); - let closeAlgorithm = () => resolvePromiseWith(undefined); - /** @type {(reason?: any) => Promise} */ - 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"], - { - prefix: - "Failed to call 'writeAlgorithm' on 'WritableStreamDefaultController'", - returnsPromise: true, - }, - ); - } - if (underlyingSinkDict.close !== undefined) { - closeAlgorithm = () => - webidl.invokeCallbackFunction( - underlyingSinkDict.close, - [], - underlyingSink, - webidl.converters["Promise"], - { - prefix: - "Failed to call 'closeAlgorithm' on 'WritableStreamDefaultController'", - returnsPromise: true, - }, - ); - } - if (underlyingSinkDict.abort !== undefined) { - abortAlgorithm = (reason) => - webidl.invokeCallbackFunction( - underlyingSinkDict.abort, - [reason], - underlyingSink, - webidl.converters["Promise"], - { - prefix: - "Failed to call 'abortAlgorithm' on 'WritableStreamDefaultController'", - returnsPromise: true, - }, - ); - } - setUpWritableStreamDefaultController( - stream, - controller, - startAlgorithm, - writeAlgorithm, - closeAlgorithm, - abortAlgorithm, - highWaterMark, - sizeAlgorithm, - ); - } - - /** - * @template W - * @param {WritableStreamDefaultWriter} writer - * @param {WritableStream} 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} controller - * @param {O} chunk - */ - function transformStreamDefaultControllerEnqueue(controller, chunk) { - const stream = controller[_stream]; - const readableController = stream[_readable][_controller]; - if ( - readableStreamDefaultControllerCanCloseOrEnqueue( - /** @type {ReadableStreamDefaultController} */ (readableController), - ) === false - ) { - throw new TypeError("Readable stream is unavailable."); - } - try { - readableStreamDefaultControllerEnqueue( - /** @type {ReadableStreamDefaultController} */ (readableController), - chunk, - ); - } catch (e) { - transformStreamErrorWritableAndUnblockWrite(stream, e); - throw stream[_readable][_storedError]; - } - const backpressure = readableStreamDefaultcontrollerHasBackpressure( - /** @type {ReadableStreamDefaultController} */ (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} controller - * @param {any} chunk - * @returns {Promise} - */ - 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} - */ - function transformStreamDefaultSinkAbortAlgorithm(stream, reason) { - transformStreamError(stream, reason); - return resolvePromiseWith(undefined); - } - - /** - * @template I - * @template O - * @param {TransformStream} stream - * @returns {Promise} - */ - 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} stream - * @param {I} chunk - * @returns {Promise} - */ - 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} - */ - 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} - */ - 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 */ - const deferred = new Deferred(); - stream[_pendingAbortRequest] = { - deferred, - reason, - wasAlreadyErroring, - }; - if (wasAlreadyErroring === false) { - writableStreamStartErroring(stream, reason); - } - return deferred.promise; - } - - /** - * @param {WritableStream} stream - * @returns {Promise} - */ - function writableStreamAddWriteRequest(stream) { - assert(isWritableStreamLocked(stream) === true); - assert(stream[_state] === "writable"); - /** @type {Deferred} */ - const deferred = new Deferred(); - ArrayPrototypePush(stream[_writeRequests], deferred); - return deferred.promise; - } - - /** - * @param {WritableStream} stream - * @returns {Promise} - */ - 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} */ - 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} 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} 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} 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} 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} - */ - function writableStreamDefaultWriterAbort(writer, reason) { - const stream = writer[_stream]; - assert(stream !== undefined); - return writableStreamAbort(stream, reason); - } - - /** - * @param {WritableStreamDefaultWriter} writer - * @returns {Promise} - */ - function writableStreamDefaultWriterClose(writer) { - const stream = writer[_stream]; - assert(stream !== undefined); - return writableStreamClose(stream); - } - - /** - * @param {WritableStreamDefaultWriter} writer - * @returns {Promise} - */ - 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} writer - * @param {W} chunk - * @returns {Promise} - */ - 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} 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} - */ - 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} */ - const asyncIteratorPrototype = ObjectGetPrototypeOf( - ObjectGetPrototypeOf(async function* () {}).prototype, - ); - - /** @type {AsyncIterator} */ - const readableStreamAsyncIteratorPrototype = ObjectSetPrototypeOf({ - /** @returns {Promise>} */ - 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>} */ - 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>} - */ - 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 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 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=} underlyingSource - * @param {QueuingStrategy=} 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 - 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} - */ - 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} - */ - getIterator(options = {}) { - return this[SymbolAsyncIterator](options); - } - - /** - * @param {ReadableStreamGetReaderOptions=} options - * @returns {ReadableStreamDefaultReader} - */ - 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, writable: WritableStream }} transform - * @param {PipeOptions=} options - * @returns {ReadableStream} - */ - 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} destination - * @param {PipeOptions=} options - * @returns {Promise} - */ - 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, ReadableStream]} */ - tee() { - webidl.assertBranded(this, ReadableStream); - return readableStreamTee(this, false); - } - - // TODO(lucacasonato): should be moved to webidl crate - /** - * @param {ReadableStreamIteratorOptions=} options - * @returns {AsyncIterableIterator} - */ - 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} */ - 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} */ - [_closedPromise]; - /** @type {ReadableStream | undefined} */ - [_stream]; - /** @type {ReadRequest[]} */ - [_readRequests]; - - /** @param {ReadableStream} 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>} */ - 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>} */ - const promise = new Deferred(); - /** @type {ReadRequest} */ - 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} - */ - 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} */ - [_cancelAlgorithm]; - /** @type {boolean} */ - [_closeRequested]; - /** @type {boolean} */ - [_pullAgain]; - /** @type {(controller: this) => Promise} */ - [_pullAlgorithm]; - /** @type {boolean} */ - [_pulling]; - /** @type {ReadableByteStreamQueueEntry[]} */ - [_queue]; - /** @type {number} */ - [_queueTotalSize]; - /** @type {boolean} */ - [_started]; - /** @type {number} */ - [_strategyHWM]; - /** @type {ReadableStream} */ - [_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} - */ - [_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} readRequest - * @returns {void} - */ - [_pullSteps](readRequest) { - /** @type {ReadableStream} */ - 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} */ - [_cancelAlgorithm]; - /** @type {boolean} */ - [_closeRequested]; - /** @type {boolean} */ - [_pullAgain]; - /** @type {(controller: this) => Promise} */ - [_pullAlgorithm]; - /** @type {boolean} */ - [_pulling]; - /** @type {Array>} */ - [_queue]; - /** @type {number} */ - [_queueTotalSize]; - /** @type {boolean} */ - [_started]; - /** @type {number} */ - [_strategyHWM]; - /** @type {(chunk: R) => number} */ - [_strategySizeAlgorithm]; - /** @type {ReadableStream} */ - [_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} - */ - [_cancelSteps](reason) { - resetQueue(this); - const result = this[_cancelAlgorithm](reason); - readableStreamDefaultControllerClearAlgorithms(this); - return result; - } - - /** - * @param {ReadRequest} 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} */ - [_backpressureChangePromise]; - /** @type {TransformStreamDefaultController} */ - [_controller]; - /** @type {boolean} */ - [_detached]; - /** @type {ReadableStream} */ - [_readable]; - /** @type {WritableStream} */ - [_writable]; - - /** - * - * @param {Transformer} transformer - * @param {QueuingStrategy} writableStrategy - * @param {QueuingStrategy} 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} */ - 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} */ - get readable() { - webidl.assertBranded(this, TransformStream); - return this[_readable]; - } - - /** @returns {WritableStream} */ - 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} */ - [_flushAlgorithm]; - /** @type {TransformStream} */ - [_stream]; - /** @type {(chunk: O, controller: this) => Promise} */ - [_transformAlgorithm]; - - constructor() { - webidl.illegalConstructor(); - } - - /** @returns {number | null} */ - get desiredSize() { - webidl.assertBranded(this, TransformStreamDefaultController); - const readableController = this[_stream][_readable][_controller]; - return readableStreamDefaultControllerGetDesiredSize( - /** @type {ReadableStreamDefaultController} */ (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 | undefined} */ - [_closeRequest]; - /** @type {WritableStreamDefaultController} */ - [_controller]; - /** @type {boolean} */ - [_detached]; - /** @type {Deferred | undefined} */ - [_inFlightWriteRequest]; - /** @type {Deferred | undefined} */ - [_inFlightCloseRequest]; - /** @type {PendingAbortRequest | undefined} */ - [_pendingAbortRequest]; - /** @type {"writable" | "closed" | "erroring" | "errored"} */ - [_state]; - /** @type {any} */ - [_storedError]; - /** @type {WritableStreamDefaultWriter} */ - [_writer]; - /** @type {Deferred[]} */ - [_writeRequests]; - - /** - * @param {UnderlyingSink=} underlyingSink - * @param {QueuingStrategy=} 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} - */ - 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} */ - 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} */ - 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} */ - [_closedPromise]; - - /** @type {Deferred} */ - [_readyPromise]; - - /** @type {WritableStream} */ - [_stream]; - - /** - * @param {WritableStream} 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} */ - 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} */ - get ready() { - try { - webidl.assertBranded(this, WritableStreamDefaultWriter); - } catch (err) { - return PromiseReject(err); - } - return this[_readyPromise].promise; - } - - /** - * @param {any} reason - * @returns {Promise} - */ - 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} */ - 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} - */ - 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} */ - [_abortAlgorithm]; - /** @type {() => Promise} */ - [_closeAlgorithm]; - /** @type {ValueWithSize[]} */ - [_queue]; - /** @type {number} */ - [_queueTotalSize]; - /** @type {boolean} */ - [_started]; - /** @type {number} */ - [_strategyHWM]; - /** @type {(chunk: W) => number} */ - [_strategySizeAlgorithm]; - /** @type {WritableStream} */ - [_stream]; - /** @type {(chunk: W, controller: this) => Promise} */ - [_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} - */ - [_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; - // deno-lint-ignore no-explicit-any - reason: any; - wasAlreadyErroring: boolean; -} - -// deno-lint-ignore no-explicit-any -interface ReadRequest { - 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 { - value: T; - size: number; -} - -interface VoidFunction { - (): void; -} - -interface ReadableStreamGenericReader { - readonly closed: Promise; - // deno-lint-ignore no-explicit-any - cancel(reason?: any): Promise; -} - -// ** Ambient Definitions and Interfaces not provided by fetch ** - -declare function queueMicrotask(callback: VoidFunction): void; - -declare namespace Deno { - function inspect(value: unknown, options?: Record): 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 -/// -/// -/// -/// -/// -/// -/// - -"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} */ - #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} */ - get readable() { - webidl.assertBranded(this, TextDecoderStream); - return this.#transform.readable; - } - - /** @returns {WritableStream} */ - 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} */ - #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} */ - get readable() { - webidl.assertBranded(this, TextEncoderStream); - return this.#transform.readable; - } - - /** @returns {WritableStream} */ - 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 -/// -/// -/// -/// -/// -/// -/// -/// -"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"](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} - */ - 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} - */ - async text() { - webidl.assertBranded(this, Blob); - const buffer = await this.arrayBuffer(); - return core.decode(new Uint8Array(buffer)); - } - - /** - * @returns {Promise} - */ - 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"] = 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"](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} - */ - 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 -/// -/// -/// -/// -/// -/// -/// -/// - -"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*/ = 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 -/// -/// -/// -/// -/// -/// -/// -/// -/// -"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"; - -/// - -((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 .`, - ); - } - 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 -/// -/// -/// -/// - -"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"]( - 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"], - 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>>; - -#[derive(Clone, Default, Debug)] -pub struct BlobStore { - parts: Arc>, - object_urls: Arc>>>, -} - -impl BlobStore { - pub fn insert_part(&self, part: Box) -> 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>> { - let parts = self.parts.lock(); - let part = parts.get(id); - part.cloned() - } - - pub fn remove_part( - &self, - id: &Uuid, - ) -> Option>> { - let mut parts = self.parts.lock(); - parts.remove(id) - } - - pub fn get_object_url( - &self, - mut url: Url, - ) -> Result>, 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 { - 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>>, -} - -impl Blob { - // TODO(lucacsonato): this should be a stream! - pub async fn read_all(&self) -> Result, 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); - -impl From> for InMemoryBlobPart { - fn from(vec: Vec) -> 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>, - 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 { - let blob_store = state.borrow::(); - 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 { - let blob_store = state.borrow::(); - 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>, - id: Uuid, - _: (), -) -> Result { - let part = { - let state = state.borrow(); - let blob_store = state.borrow::(); - 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::(); - blob_store.remove_part(&id); - Ok(()) -} - -pub fn op_blob_create_object_url( - state: &mut deno_core::OpState, - media_type: String, - part_ids: Vec, -) -> Result { - let mut parts = Vec::with_capacity(part_ids.len()); - let blob_store = state.borrow::(); - 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::(); - let blob_store = state.borrow::(); - - 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::(); - 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. - -/// -/// - -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; - } - 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(stream: ReadableStream): ReadableStream; - }; - - 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 - -/// -/// - -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; -} - -interface EventListenerObject { - handleEvent(evt: Event): void | Promise; -} - -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 - * ,