diff options
Diffstat (limited to 'ext/fetch')
-rw-r--r-- | ext/fetch/20_headers.js | 7 | ||||
-rw-r--r-- | ext/fetch/21_formdata.js | 34 | ||||
-rw-r--r-- | ext/fetch/22_body.js | 105 | ||||
-rw-r--r-- | ext/fetch/22_http_client.js | 2 | ||||
-rw-r--r-- | ext/fetch/23_request.js | 36 | ||||
-rw-r--r-- | ext/fetch/23_response.js | 26 | ||||
-rw-r--r-- | ext/fetch/26_fetch.js | 46 |
7 files changed, 176 insertions, 80 deletions
diff --git a/ext/fetch/20_headers.js b/ext/fetch/20_headers.js index b1299fb1b..94f68df42 100644 --- a/ext/fetch/20_headers.js +++ b/ext/fetch/20_headers.js @@ -263,7 +263,7 @@ * @param {string} value */ append(name, value) { - webidl.assertBranded(this, Headers); + webidl.assertBranded(this, HeadersPrototype); const prefix = "Failed to execute 'append' on 'Headers'"; webidl.requiredArguments(arguments.length, 2, { prefix }); name = webidl.converters["ByteString"](name, { @@ -354,7 +354,7 @@ * @param {string} value */ set(name, value) { - webidl.assertBranded(this, Headers); + webidl.assertBranded(this, HeadersPrototype); const prefix = "Failed to execute 'set' on 'Headers'"; webidl.requiredArguments(arguments.length, 2, { prefix }); name = webidl.converters["ByteString"](name, { @@ -411,6 +411,7 @@ webidl.mixinPairIterable("Headers", Headers, _iterableHeaders, 0, 1); webidl.configurePrototype(Headers); + const HeadersPrototype = Headers.prototype; webidl.converters["HeadersInit"] = (V, opts) => { // Union for (sequence<sequence<ByteString>> or record<ByteString, ByteString>) @@ -428,7 +429,7 @@ }; webidl.converters["Headers"] = webidl.createInterfaceConverter( "Headers", - Headers, + Headers.prototype, ); /** diff --git a/ext/fetch/21_formdata.js b/ext/fetch/21_formdata.js index cc338de72..a134fe5f7 100644 --- a/ext/fetch/21_formdata.js +++ b/ext/fetch/21_formdata.js @@ -13,7 +13,8 @@ ((window) => { const core = window.Deno.core; const webidl = globalThis.__bootstrap.webidl; - const { Blob, File } = globalThis.__bootstrap.file; + const { Blob, BlobPrototype, File, FilePrototype } = + globalThis.__bootstrap.file; const { ArrayPrototypeMap, ArrayPrototypePush, @@ -25,6 +26,7 @@ MapPrototypeGet, MapPrototypeSet, MathRandom, + ObjectPrototypeIsPrototypeOf, Symbol, StringFromCharCode, StringPrototypeTrim, @@ -48,10 +50,16 @@ * @returns {FormDataEntry} */ function createEntry(name, value, filename) { - if (value instanceof Blob && !(value instanceof File)) { + if ( + ObjectPrototypeIsPrototypeOf(BlobPrototype, value) && + !ObjectPrototypeIsPrototypeOf(FilePrototype, value) + ) { value = new File([value], "blob", { type: value.type }); } - if (value instanceof File && filename !== undefined) { + if ( + ObjectPrototypeIsPrototypeOf(FilePrototype, value) && + filename !== undefined + ) { value = new File([value], filename, { type: value.type, lastModified: value.lastModified, @@ -89,7 +97,7 @@ * @returns {void} */ append(name, valueOrBlobValue, filename) { - webidl.assertBranded(this, FormData); + webidl.assertBranded(this, FormDataPrototype); const prefix = "Failed to execute 'append' on 'FormData'"; webidl.requiredArguments(arguments.length, 2, { prefix }); @@ -97,7 +105,7 @@ prefix, context: "Argument 1", }); - if (valueOrBlobValue instanceof Blob) { + if (ObjectPrototypeIsPrototypeOf(BlobPrototype, valueOrBlobValue)) { valueOrBlobValue = webidl.converters["Blob"](valueOrBlobValue, { prefix, context: "Argument 2", @@ -125,7 +133,7 @@ * @returns {void} */ delete(name) { - webidl.assertBranded(this, FormData); + webidl.assertBranded(this, FormDataPrototype); const prefix = "Failed to execute 'name' on 'FormData'"; webidl.requiredArguments(arguments.length, 1, { prefix }); @@ -148,7 +156,7 @@ * @returns {FormDataEntryValue | null} */ get(name) { - webidl.assertBranded(this, FormData); + webidl.assertBranded(this, FormDataPrototype); const prefix = "Failed to execute 'get' on 'FormData'"; webidl.requiredArguments(arguments.length, 1, { prefix }); @@ -168,7 +176,7 @@ * @returns {FormDataEntryValue[]} */ getAll(name) { - webidl.assertBranded(this, FormData); + webidl.assertBranded(this, FormDataPrototype); const prefix = "Failed to execute 'getAll' on 'FormData'"; webidl.requiredArguments(arguments.length, 1, { prefix }); @@ -189,7 +197,7 @@ * @returns {boolean} */ has(name) { - webidl.assertBranded(this, FormData); + webidl.assertBranded(this, FormDataPrototype); const prefix = "Failed to execute 'has' on 'FormData'"; webidl.requiredArguments(arguments.length, 1, { prefix }); @@ -211,7 +219,7 @@ * @returns {void} */ set(name, valueOrBlobValue, filename) { - webidl.assertBranded(this, FormData); + webidl.assertBranded(this, FormDataPrototype); const prefix = "Failed to execute 'set' on 'FormData'"; webidl.requiredArguments(arguments.length, 2, { prefix }); @@ -219,7 +227,7 @@ prefix, context: "Argument 1", }); - if (valueOrBlobValue instanceof Blob) { + if (ObjectPrototypeIsPrototypeOf(BlobPrototype, valueOrBlobValue)) { valueOrBlobValue = webidl.converters["Blob"](valueOrBlobValue, { prefix, context: "Argument 2", @@ -261,6 +269,7 @@ webidl.mixinPairIterable("FormData", FormData, entryList, "name", "value"); webidl.configurePrototype(FormData); + const FormDataPrototype = FormData.prototype; const escape = (str, isFilename) => StringPrototypeReplace( @@ -491,10 +500,11 @@ } webidl.converters["FormData"] = webidl - .createInterfaceConverter("FormData", FormData); + .createInterfaceConverter("FormData", FormDataPrototype); globalThis.__bootstrap.formData = { FormData, + FormDataPrototype, formDataToBlob, parseFormData, formDataFromEntries, diff --git a/ext/fetch/22_body.js b/ext/fetch/22_body.js index acfd06b0f..f33097033 100644 --- a/ext/fetch/22_body.js +++ b/ext/fetch/22_body.js @@ -16,23 +16,35 @@ const core = window.Deno.core; const webidl = globalThis.__bootstrap.webidl; const { parseUrlEncoded } = globalThis.__bootstrap.url; - const { parseFormData, formDataFromEntries, formDataToBlob } = - globalThis.__bootstrap.formData; + const { URLSearchParamsPrototype } = globalThis.__bootstrap.url; + const { + parseFormData, + formDataFromEntries, + formDataToBlob, + FormDataPrototype, + } = globalThis.__bootstrap.formData; const mimesniff = globalThis.__bootstrap.mimesniff; - const { isReadableStreamDisturbed, errorReadableStream, createProxy } = - globalThis.__bootstrap.streams; + const { BlobPrototype } = globalThis.__bootstrap.file; + const { + isReadableStreamDisturbed, + errorReadableStream, + createProxy, + ReadableStreamPrototype, + } = globalThis.__bootstrap.streams; const { - ArrayBuffer, + ArrayBufferPrototype, ArrayBufferIsView, ArrayPrototypePush, ArrayPrototypeMap, JSONParse, ObjectDefineProperties, + ObjectPrototypeIsPrototypeOf, PromiseResolve, TypedArrayPrototypeSet, TypedArrayPrototypeSlice, TypeError, Uint8Array, + Uint8ArrayPrototype, } = window.__bootstrap.primordials; /** @@ -66,7 +78,12 @@ } get stream() { - if (!(this.streamOrStatic instanceof ReadableStream)) { + if ( + !ObjectPrototypeIsPrototypeOf( + ReadableStreamPrototype, + this.streamOrStatic, + ) + ) { const { body, consumed } = this.streamOrStatic; if (consumed) { this.streamOrStatic = new ReadableStream(); @@ -88,7 +105,12 @@ * @returns {boolean} */ unusable() { - if (this.streamOrStatic instanceof ReadableStream) { + if ( + ObjectPrototypeIsPrototypeOf( + ReadableStreamPrototype, + this.streamOrStatic, + ) + ) { return this.streamOrStatic.locked || isReadableStreamDisturbed(this.streamOrStatic); } @@ -99,7 +121,12 @@ * @returns {boolean} */ consumed() { - if (this.streamOrStatic instanceof ReadableStream) { + if ( + ObjectPrototypeIsPrototypeOf( + ReadableStreamPrototype, + this.streamOrStatic, + ) + ) { return isReadableStreamDisturbed(this.streamOrStatic); } return this.streamOrStatic.consumed; @@ -111,7 +138,12 @@ */ async consume() { if (this.unusable()) throw new TypeError("Body already consumed."); - if (this.streamOrStatic instanceof ReadableStream) { + if ( + ObjectPrototypeIsPrototypeOf( + ReadableStreamPrototype, + this.streamOrStatic, + ) + ) { const reader = this.stream.getReader(); /** @type {Uint8Array[]} */ const chunks = []; @@ -136,7 +168,12 @@ } cancel(error) { - if (this.streamOrStatic instanceof ReadableStream) { + if ( + ObjectPrototypeIsPrototypeOf( + ReadableStreamPrototype, + this.streamOrStatic, + ) + ) { this.streamOrStatic.cancel(error); } else { this.streamOrStatic.consumed = true; @@ -144,7 +181,12 @@ } error(error) { - if (this.streamOrStatic instanceof ReadableStream) { + if ( + ObjectPrototypeIsPrototypeOf( + ReadableStreamPrototype, + this.streamOrStatic, + ) + ) { errorReadableStream(this.streamOrStatic, error); } else { this.streamOrStatic.consumed = true; @@ -168,7 +210,12 @@ */ createProxy() { let proxyStreamOrStatic; - if (this.streamOrStatic instanceof ReadableStream) { + if ( + ObjectPrototypeIsPrototypeOf( + ReadableStreamPrototype, + this.streamOrStatic, + ) + ) { proxyStreamOrStatic = createProxy(this.streamOrStatic); } else { proxyStreamOrStatic = { ...this.streamOrStatic }; @@ -282,7 +329,7 @@ enumerable: true, }, }; - return ObjectDefineProperties(prototype.prototype, mixin); + return ObjectDefineProperties(prototype, mixin); } /** @@ -341,18 +388,21 @@ let source = null; let length = null; let contentType = null; - if (object instanceof Blob) { + if (ObjectPrototypeIsPrototypeOf(BlobPrototype, object)) { stream = object.stream(); source = object; length = object.size; if (object.type.length !== 0) { contentType = object.type; } - } else if (object instanceof Uint8Array) { + } else if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, object)) { // Fast(er) path for common case of Uint8Array const copy = TypedArrayPrototypeSlice(object, 0, object.byteLength); source = copy; - } else if (ArrayBufferIsView(object) || object instanceof ArrayBuffer) { + } else if ( + ArrayBufferIsView(object) || + ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, object) + ) { const u8 = ArrayBufferIsView(object) ? new Uint8Array( object.buffer, @@ -362,26 +412,28 @@ : new Uint8Array(object); const copy = TypedArrayPrototypeSlice(u8, 0, u8.byteLength); source = copy; - } else if (object instanceof FormData) { + } else if (ObjectPrototypeIsPrototypeOf(FormDataPrototype, object)) { const res = formDataToBlob(object); stream = res.stream(); source = res; length = res.size; contentType = res.type; - } else if (object instanceof URLSearchParams) { + } else if ( + ObjectPrototypeIsPrototypeOf(URLSearchParamsPrototype, object) + ) { // TODO(@satyarohith): not sure what primordial here. source = object.toString(); contentType = "application/x-www-form-urlencoded;charset=UTF-8"; } else if (typeof object === "string") { source = object; contentType = "text/plain;charset=UTF-8"; - } else if (object instanceof ReadableStream) { + } else if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, object)) { stream = object; if (object.locked || isReadableStreamDisturbed(object)) { throw new TypeError("ReadableStream is locked or disturbed"); } } - if (source instanceof Uint8Array) { + if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, source)) { stream = { body: source, consumed: false }; length = source.byteLength; } else if (typeof source === "string") { @@ -399,19 +451,22 @@ webidl.converters["BodyInit_DOMString"] = (V, opts) => { // Union for (ReadableStream or Blob or ArrayBufferView or ArrayBuffer or FormData or URLSearchParams or USVString) - if (V instanceof ReadableStream) { + if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, V)) { // TODO(lucacasonato): ReadableStream is not branded return V; - } else if (V instanceof Blob) { + } else if (ObjectPrototypeIsPrototypeOf(BlobPrototype, V)) { return webidl.converters["Blob"](V, opts); - } else if (V instanceof FormData) { + } else if (ObjectPrototypeIsPrototypeOf(FormDataPrototype, V)) { return webidl.converters["FormData"](V, opts); - } else if (V instanceof URLSearchParams) { + } else if (ObjectPrototypeIsPrototypeOf(URLSearchParamsPrototype, V)) { // TODO(lucacasonato): URLSearchParams is not branded return V; } if (typeof V === "object") { - if (V instanceof ArrayBuffer || V instanceof SharedArrayBuffer) { + if ( + ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V) || + ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V) + ) { return webidl.converters["ArrayBuffer"](V, opts); } if (ArrayBufferIsView(V)) { diff --git a/ext/fetch/22_http_client.js b/ext/fetch/22_http_client.js index 44159de07..15690b7d4 100644 --- a/ext/fetch/22_http_client.js +++ b/ext/fetch/22_http_client.js @@ -34,8 +34,10 @@ core.close(this.rid); } } + const HttpClientPrototype = HttpClient.prototype; window.__bootstrap.fetch ??= {}; window.__bootstrap.fetch.createHttpClient = createHttpClient; window.__bootstrap.fetch.HttpClient = HttpClient; + window.__bootstrap.fetch.HttpClientPrototype = HttpClientPrototype; })(globalThis); diff --git a/ext/fetch/23_request.js b/ext/fetch/23_request.js index 5783cac9e..5294009ff 100644 --- a/ext/fetch/23_request.js +++ b/ext/fetch/23_request.js @@ -26,7 +26,7 @@ fillHeaders, getDecodeSplitHeader, } = window.__bootstrap.headers; - const { HttpClient } = window.__bootstrap.fetch; + const { HttpClientPrototype } = window.__bootstrap.fetch; const abortSignal = window.__bootstrap.abortSignal; const { ArrayPrototypeMap, @@ -36,6 +36,7 @@ MapPrototypeGet, MapPrototypeSet, ObjectKeys, + ObjectPrototypeIsPrototypeOf, RegExpPrototypeTest, Symbol, SymbolFor, @@ -241,7 +242,9 @@ const parsedURL = new URL(input, baseURL); request = newInnerRequest("GET", parsedURL.href, [], null, true); } else { // 6. - if (!(input instanceof Request)) throw new TypeError("Unreachable"); + if (!ObjectPrototypeIsPrototypeOf(RequestPrototype, input)) { + throw new TypeError("Unreachable"); + } request = input[_request]; signal = input[_signal]; } @@ -268,7 +271,10 @@ // NOTE: non standard extension. This handles Deno.HttpClient parameter if (init.client !== undefined) { - if (init.client !== null && !(init.client instanceof HttpClient)) { + if ( + init.client !== null && + !ObjectPrototypeIsPrototypeOf(HttpClientPrototype, init.client) + ) { throw webidl.makeException( TypeError, "`client` must be a Deno.HttpClient", @@ -312,7 +318,7 @@ // 33. let inputBody = null; - if (input instanceof Request) { + if (ObjectPrototypeIsPrototypeOf(RequestPrototype, input)) { inputBody = input[_body]; } @@ -356,32 +362,32 @@ } get method() { - webidl.assertBranded(this, Request); + webidl.assertBranded(this, RequestPrototype); return this[_request].method; } get url() { - webidl.assertBranded(this, Request); + webidl.assertBranded(this, RequestPrototype); return this[_request].url(); } get headers() { - webidl.assertBranded(this, Request); + webidl.assertBranded(this, RequestPrototype); return this[_headers]; } get redirect() { - webidl.assertBranded(this, Request); + webidl.assertBranded(this, RequestPrototype); return this[_request].redirectMode; } get signal() { - webidl.assertBranded(this, Request); + webidl.assertBranded(this, RequestPrototype); return this[_signal]; } clone() { - webidl.assertBranded(this, Request); + webidl.assertBranded(this, RequestPrototype); if (this[_body] && this[_body].unusable()) { throw new TypeError("Body is unusable."); } @@ -398,7 +404,7 @@ [SymbolFor("Deno.customInspect")](inspect) { return inspect(consoleInternal.createFilteredInspectProxy({ object: this, - evaluate: this instanceof Request, + evaluate: ObjectPrototypeIsPrototypeOf(RequestPrototype, this), keys: [ "bodyUsed", "headers", @@ -410,18 +416,18 @@ } } - mixinBody(Request, _body, _mimeType); - webidl.configurePrototype(Request); + const RequestPrototype = Request.prototype; + mixinBody(RequestPrototype, _body, _mimeType); webidl.converters["Request"] = webidl.createInterfaceConverter( "Request", - Request, + RequestPrototype, ); webidl.converters["RequestInfo_DOMString"] = (V, opts) => { // Union for (Request or USVString) if (typeof V == "object") { - if (V instanceof Request) { + if (ObjectPrototypeIsPrototypeOf(RequestPrototype, V)) { return webidl.converters["Request"](V, opts); } } diff --git a/ext/fetch/23_response.js b/ext/fetch/23_response.js index e7b205418..14aadbaf2 100644 --- a/ext/fetch/23_response.js +++ b/ext/fetch/23_response.js @@ -33,6 +33,7 @@ MapPrototypeHas, MapPrototypeGet, MapPrototypeSet, + ObjectPrototypeIsPrototypeOf, RangeError, RegExp, RegExpPrototypeTest, @@ -297,7 +298,7 @@ * @returns {"basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"} */ get type() { - webidl.assertBranded(this, Response); + webidl.assertBranded(this, ResponsePrototype); return this[_response].type; } @@ -305,7 +306,7 @@ * @returns {string} */ get url() { - webidl.assertBranded(this, Response); + webidl.assertBranded(this, ResponsePrototype); const url = this[_response].url(); if (url === null) return ""; const newUrl = new URL(url); @@ -317,7 +318,7 @@ * @returns {boolean} */ get redirected() { - webidl.assertBranded(this, Response); + webidl.assertBranded(this, ResponsePrototype); return this[_response].urlList.length > 1; } @@ -325,7 +326,7 @@ * @returns {number} */ get status() { - webidl.assertBranded(this, Response); + webidl.assertBranded(this, ResponsePrototype); return this[_response].status; } @@ -333,7 +334,7 @@ * @returns {boolean} */ get ok() { - webidl.assertBranded(this, Response); + webidl.assertBranded(this, ResponsePrototype); const status = this[_response].status; return status >= 200 && status <= 299; } @@ -342,7 +343,7 @@ * @returns {string} */ get statusText() { - webidl.assertBranded(this, Response); + webidl.assertBranded(this, ResponsePrototype); return this[_response].statusMessage; } @@ -350,7 +351,7 @@ * @returns {Headers} */ get headers() { - webidl.assertBranded(this, Response); + webidl.assertBranded(this, ResponsePrototype); return this[_headers]; } @@ -358,7 +359,7 @@ * @returns {Response} */ clone() { - webidl.assertBranded(this, Response); + webidl.assertBranded(this, ResponsePrototype); if (this[_body] && this[_body].unusable()) { throw new TypeError("Body is unusable."); } @@ -375,7 +376,7 @@ [SymbolFor("Deno.customInspect")](inspect) { return inspect(consoleInternal.createFilteredInspectProxy({ object: this, - evaluate: this instanceof Response, + evaluate: ObjectPrototypeIsPrototypeOf(ResponsePrototype, this), keys: [ "body", "bodyUsed", @@ -390,13 +391,13 @@ } } - mixinBody(Response, _body, _mimeType); - webidl.configurePrototype(Response); + const ResponsePrototype = Response.prototype; + mixinBody(ResponsePrototype, _body, _mimeType); webidl.converters["Response"] = webidl.createInterfaceConverter( "Response", - Response, + ResponsePrototype, ); webidl.converters["ResponseInit"] = webidl.createDictionaryConverter( "ResponseInit", @@ -457,6 +458,7 @@ window.__bootstrap.fetch ??= {}; window.__bootstrap.fetch.Response = Response; + window.__bootstrap.fetch.ResponsePrototype = ResponsePrototype; window.__bootstrap.fetch.newInnerResponse = newInnerResponse; window.__bootstrap.fetch.toInnerResponse = toInnerResponse; window.__bootstrap.fetch.fromInnerResponse = fromInnerResponse; diff --git a/ext/fetch/26_fetch.js b/ext/fetch/26_fetch.js index c6fc9197b..0c58bbf97 100644 --- a/ext/fetch/26_fetch.js +++ b/ext/fetch/26_fetch.js @@ -15,7 +15,9 @@ const core = window.Deno.core; const webidl = window.__bootstrap.webidl; const { byteLowerCase } = window.__bootstrap.infra; - const { errorReadableStream } = window.__bootstrap.streams; + const { BlobPrototype } = window.__bootstrap.file; + const { errorReadableStream, ReadableStreamPrototype } = + window.__bootstrap.streams; const { InnerBody, extractBody } = window.__bootstrap.fetchBody; const { toInnerRequest, @@ -32,6 +34,7 @@ ArrayPrototypeSplice, ArrayPrototypeFilter, ArrayPrototypeIncludes, + ObjectPrototypeIsPrototypeOf, Promise, PromisePrototypeThen, PromisePrototypeCatch, @@ -41,6 +44,7 @@ TypedArrayPrototypeSubarray, TypeError, Uint8Array, + Uint8ArrayPrototype, WeakMap, WeakMapPrototypeDelete, WeakMapPrototypeGet, @@ -172,8 +176,16 @@ let reqBody = null; if (req.body !== null) { - if (req.body.streamOrStatic instanceof ReadableStream) { - if (req.body.length === null || req.body.source instanceof Blob) { + if ( + ObjectPrototypeIsPrototypeOf( + ReadableStreamPrototype, + req.body.streamOrStatic, + ) + ) { + if ( + req.body.length === null || + ObjectPrototypeIsPrototypeOf(BlobPrototype, req.body.source) + ) { reqBody = req.body.stream; } else { const reader = req.body.stream.getReader(); @@ -196,14 +208,19 @@ } } - const { requestRid, requestBodyRid, cancelHandleRid } = opFetch({ - method: req.method, - url: req.currentUrl(), - headers: req.headerList, - clientRid: req.clientRid, - hasBody: reqBody !== null, - bodyLength: req.body?.length, - }, reqBody instanceof Uint8Array ? reqBody : null); + const { requestRid, requestBodyRid, cancelHandleRid } = opFetch( + { + method: req.method, + url: req.currentUrl(), + headers: req.headerList, + clientRid: req.clientRid, + hasBody: reqBody !== null, + bodyLength: req.body?.length, + }, + ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, reqBody) + ? reqBody + : null, + ); function onAbort() { if (cancelHandleRid !== null) { @@ -216,7 +233,10 @@ terminator[abortSignal.add](onAbort); if (requestBodyRid !== null) { - if (reqBody === null || !(reqBody instanceof ReadableStream)) { + if ( + reqBody === null || + !ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, reqBody) + ) { throw new TypeError("Unreachable"); } const reader = reqBody.getReader(); @@ -231,7 +251,7 @@ }, ); if (done) break; - if (!(value instanceof Uint8Array)) { + if (!ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, value)) { await reader.cancel("value not a Uint8Array"); break; } |