diff options
author | Satya Rohith <me@satyarohith.com> | 2021-07-06 15:02:59 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-06 11:32:59 +0200 |
commit | ab6b0cefd36f4a2530267c03683e1db1a1b81838 (patch) | |
tree | b625b0bc87148830e266e640a29142402a9b934c | |
parent | e8258e0210c4690a1fbbcefe0e6a859da8efc19b (diff) |
refactor: use primordials in extensions/fetch (#11266)
-rw-r--r-- | extensions/fetch/01_fetch_util.js | 1 | ||||
-rw-r--r-- | extensions/fetch/20_headers.js | 102 | ||||
-rw-r--r-- | extensions/fetch/21_formdata.js | 116 | ||||
-rw-r--r-- | extensions/fetch/22_body.js | 36 | ||||
-rw-r--r-- | extensions/fetch/23_request.js | 41 | ||||
-rw-r--r-- | extensions/fetch/23_response.js | 35 | ||||
-rw-r--r-- | extensions/fetch/26_fetch.js | 110 |
7 files changed, 307 insertions, 134 deletions
diff --git a/extensions/fetch/01_fetch_util.js b/extensions/fetch/01_fetch_util.js index ff76421a1..9cf19588b 100644 --- a/extensions/fetch/01_fetch_util.js +++ b/extensions/fetch/01_fetch_util.js @@ -2,6 +2,7 @@ "use strict"; ((window) => { + const { TypeError } = window.__bootstrap.primordials; function requiredArguments( name, length, diff --git a/extensions/fetch/20_headers.js b/extensions/fetch/20_headers.js index 59f81a8ff..91154d958 100644 --- a/extensions/fetch/20_headers.js +++ b/extensions/fetch/20_headers.js @@ -22,6 +22,25 @@ collectSequenceOfCodepoints, collectHttpQuotedString, } = window.__bootstrap.infra; + const { + ArrayIsArray, + ArrayPrototypeMap, + ArrayPrototypePush, + ArrayPrototypeSort, + ArrayPrototypeJoin, + ArrayPrototypeSplice, + ArrayPrototypeFilter, + ObjectKeys, + ObjectEntries, + RegExpPrototypeTest, + Symbol, + SymbolFor, + SymbolIterator, + SymbolToStringTag, + StringPrototypeReplaceAll, + StringPrototypeIncludes, + TypeError, + } = window.__bootstrap.primordials; const _headerList = Symbol("header list"); const _iterableHeaders = Symbol("iterable headers"); @@ -42,8 +61,16 @@ * @returns {string} */ function normalizeHeaderValue(potentialValue) { - potentialValue = potentialValue.replaceAll(HTTP_WHITESPACE_PREFIX_RE, ""); - potentialValue = potentialValue.replaceAll(HTTP_WHITESPACE_SUFFIX_RE, ""); + potentialValue = StringPrototypeReplaceAll( + potentialValue, + HTTP_WHITESPACE_PREFIX_RE, + "", + ); + potentialValue = StringPrototypeReplaceAll( + potentialValue, + HTTP_WHITESPACE_SUFFIX_RE, + "", + ); return potentialValue; } @@ -52,7 +79,7 @@ * @param {HeadersInit} object */ function fillHeaders(headers, object) { - if (Array.isArray(object)) { + if (ArrayIsArray(object)) { for (const header of object) { if (header.length !== 2) { throw new TypeError( @@ -62,7 +89,7 @@ appendHeader(headers, header[0], header[1]); } } else { - for (const key of Object.keys(object)) { + for (const key of ObjectKeys(object)) { appendHeader(headers, key, object[key]); } } @@ -79,11 +106,13 @@ value = normalizeHeaderValue(value); // 2. - if (!HTTP_TOKEN_CODE_POINT_RE.test(name)) { + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { throw new TypeError("Header name is not valid."); } if ( - value.includes("\x00") || value.includes("\x0A") || value.includes("\x0D") + StringPrototypeIncludes(value, "\x00") || + StringPrototypeIncludes(value, "\x0A") || + StringPrototypeIncludes(value, "\x0D") ) { throw new TypeError("Header value is not valid."); } @@ -96,7 +125,7 @@ // 7. const list = headers[_headerList]; name = byteLowerCase(name); - list.push([name, value]); + ArrayPrototypePush(list, [name, value]); } /** @@ -106,13 +135,14 @@ */ function getHeader(list, name) { const lowercaseName = byteLowerCase(name); - const entries = list - .filter((entry) => entry[0] === lowercaseName) - .map((entry) => entry[1]); + const entries = ArrayPrototypeMap( + ArrayPrototypeFilter(list, (entry) => entry[0] === lowercaseName), + (entry) => entry[1], + ); if (entries.length === 0) { return null; } else { - return entries.join("\x2C\x20"); + return ArrayPrototypeJoin(entries, "\x2C\x20"); } } @@ -153,10 +183,10 @@ } } - value = value.replaceAll(HTTP_TAB_OR_SPACE_PREFIX_RE, ""); - value = value.replaceAll(HTTP_TAB_OR_SPACE_SUFFIX_RE, ""); + value = StringPrototypeReplaceAll(value, HTTP_TAB_OR_SPACE_PREFIX_RE, ""); + value = StringPrototypeReplaceAll(value, HTTP_TAB_OR_SPACE_SUFFIX_RE, ""); - values.push(value); + ArrayPrototypePush(values, value); value = ""; } return values; @@ -184,7 +214,7 @@ // so must be given to the user as multiple headers. // The else block of the if statement is spec compliant again. if (name === "set-cookie") { - cookies.push([name, value]); + ArrayPrototypePush(cookies, [name, value]); } else { // The following code has the same behaviour as getHeader() // at the end of loop. But it avoids looping through the entire @@ -200,13 +230,16 @@ } } - return [...Object.entries(headers), ...cookies].sort((a, b) => { - const akey = a[0]; - const bkey = b[0]; - if (akey > bkey) return 1; - if (akey < bkey) return -1; - return 0; - }); + return ArrayPrototypeSort( + [...ObjectEntries(headers), ...cookies], + (a, b) => { + const akey = a[0]; + const bkey = b[0]; + if (akey > bkey) return 1; + if (akey < bkey) return -1; + return 0; + }, + ); } /** @param {HeadersInit} [init] */ @@ -256,7 +289,7 @@ context: "Argument 1", }); - if (!HTTP_TOKEN_CODE_POINT_RE.test(name)) { + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { throw new TypeError("Header name is not valid."); } if (this[_guard] == "immutable") { @@ -267,7 +300,7 @@ name = byteLowerCase(name); for (let i = 0; i < list.length; i++) { if (list[i][0] === name) { - list.splice(i, 1); + ArrayPrototypeSplice(list, i, 1); i--; } } @@ -284,7 +317,7 @@ context: "Argument 1", }); - if (!HTTP_TOKEN_CODE_POINT_RE.test(name)) { + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { throw new TypeError("Header name is not valid."); } @@ -303,7 +336,7 @@ context: "Argument 1", }); - if (!HTTP_TOKEN_CODE_POINT_RE.test(name)) { + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { throw new TypeError("Header name is not valid."); } @@ -337,12 +370,13 @@ value = normalizeHeaderValue(value); // 2. - if (!HTTP_TOKEN_CODE_POINT_RE.test(name)) { + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { throw new TypeError("Header name is not valid."); } if ( - value.includes("\x00") || value.includes("\x0A") || - value.includes("\x0D") + StringPrototypeIncludes(value, "\x00") || + StringPrototypeIncludes(value, "\x0A") || + StringPrototypeIncludes(value, "\x0D") ) { throw new TypeError("Header value is not valid."); } @@ -360,17 +394,17 @@ list[i][1] = value; added = true; } else { - list.splice(i, 1); + ArrayPrototypeSplice(list, i, 1); i--; } } } if (!added) { - list.push([name, value]); + ArrayPrototypePush(list, [name, value]); } } - [Symbol.for("Deno.privateCustomInspect")](inspect) { + [SymbolFor("Deno.privateCustomInspect")](inspect) { const headers = {}; for (const header of this) { headers[header[0]] = header[1]; @@ -378,7 +412,7 @@ return `Headers ${inspect(headers)}`; } - get [Symbol.toStringTag]() { + get [SymbolToStringTag]() { return "Headers"; } } @@ -390,7 +424,7 @@ webidl.converters["HeadersInit"] = (V, opts) => { // Union for (sequence<sequence<ByteString>> or record<ByteString, ByteString>) if (webidl.type(V) === "Object" && V !== null) { - if (V[Symbol.iterator] !== undefined) { + if (V[SymbolIterator] !== undefined) { return webidl.converters["sequence<sequence<ByteString>>"](V, opts); } return webidl.converters["record<ByteString, ByteString>"](V, opts); diff --git a/extensions/fetch/21_formdata.js b/extensions/fetch/21_formdata.js index f0033a332..25ed32c2d 100644 --- a/extensions/fetch/21_formdata.js +++ b/extensions/fetch/21_formdata.js @@ -14,6 +14,31 @@ const core = window.Deno.core; const webidl = globalThis.__bootstrap.webidl; const { Blob, File } = globalThis.__bootstrap.file; + const { + ArrayPrototypeMap, + ArrayPrototypePush, + ArrayPrototypeSlice, + ArrayPrototypeSplice, + ArrayPrototypeFilter, + ArrayPrototypeForEach, + Map, + MapPrototypeGet, + MapPrototypeSet, + MathRandom, + Symbol, + SymbolToStringTag, + StringFromCharCode, + StringPrototypeTrim, + StringPrototypeSlice, + StringPrototypeSplit, + StringPrototypeReplace, + StringPrototypeIndexOf, + StringPrototypePadStart, + StringPrototypeCodePointAt, + StringPrototypeReplaceAll, + TypeError, + TypedArrayPrototypeSubarray, + } = window.__bootstrap.primordials; const entryList = Symbol("entry list"); @@ -47,7 +72,7 @@ */ class FormData { - get [Symbol.toStringTag]() { + get [SymbolToStringTag]() { return "FormData"; } @@ -97,7 +122,7 @@ const entry = createEntry(name, valueOrBlobValue, filename); - this[entryList].push(entry); + ArrayPrototypePush(this[entryList], entry); } /** @@ -117,7 +142,7 @@ const list = this[entryList]; for (let i = 0; i < list.length; i++) { if (list[i].name === name) { - list.splice(i, 1); + ArrayPrototypeSplice(list, i, 1); i--; } } @@ -159,7 +184,7 @@ const returnList = []; for (const entry of this[entryList]) { - if (entry.name === name) returnList.push(entry.value); + if (entry.name === name) ArrayPrototypePush(returnList, entry.value); } return returnList; } @@ -227,13 +252,13 @@ list[i] = entry; added = true; } else { - list.splice(i, 1); + ArrayPrototypeSplice(list, i, 1); i--; } } } if (!added) { - list.push(entry); + ArrayPrototypePush(list, entry); } } } @@ -243,29 +268,46 @@ webidl.configurePrototype(FormData); const escape = (str, isFilename) => - (isFilename ? str : str.replace(/\r?\n|\r/g, "\r\n")) - .replace(/\n/g, "%0A") - .replace(/\r/g, "%0D") - .replace(/"/g, "%22"); + StringPrototypeReplace( + StringPrototypeReplace( + StringPrototypeReplace( + (isFilename ? str : StringPrototypeReplace(str, /\r?\n|\r/g, "\r\n")), + /\n/g, + "%0A", + ), + /\r/g, + "%0D", + ), + /"/g, + "%22", + ); /** * convert FormData to a Blob synchronous without reading all of the files * @param {globalThis.FormData} formData */ function formDataToBlob(formData) { - const boundary = `${Math.random()}${Math.random()}` - .replaceAll(".", "").slice(-28).padStart(32, "-"); + const boundary = StringPrototypePadStart( + StringPrototypeSlice( + StringPrototypeReplaceAll(`${MathRandom()}${MathRandom()}`, ".", ""), + -28, + ), + 32, + "-", + ); const chunks = []; const prefix = `--${boundary}\r\nContent-Disposition: form-data; name="`; for (const [name, value] of formData) { if (typeof value === "string") { - chunks.push( + ArrayPrototypePush( + chunks, prefix + escape(name) + '"' + CRLF + CRLF + - value.replace(/\r(?!\n)|(?<!\r)\n/g, CRLF) + CRLF, + StringPrototypeReplace(value, /\r(?!\n)|(?<!\r)\n/g, CRLF) + CRLF, ); } else { - chunks.push( + ArrayPrototypePush( + chunks, prefix + escape(name) + `"; filename="${escape(value.name, true)}"` + CRLF + `Content-Type: ${value.type || "application/octet-stream"}\r\n\r\n`, @@ -275,7 +317,7 @@ } } - chunks.push(`--${boundary}--`); + ArrayPrototypePush(chunks, `--${boundary}--`); return new Blob(chunks, { type: "multipart/form-data; boundary=" + boundary, @@ -290,19 +332,26 @@ /** @type {Map<string, string>} */ const params = new Map(); // Forced to do so for some Map constructor param mismatch - value - .split(";") - .slice(1) - .map((s) => s.trim().split("=")) - .filter((arr) => arr.length > 1) - .map(([k, v]) => [k, v.replace(/^"([^"]*)"$/, "$1")]) - .forEach(([k, v]) => params.set(k, v)); + ArrayPrototypeForEach( + ArrayPrototypeMap( + ArrayPrototypeFilter( + ArrayPrototypeMap( + ArrayPrototypeSlice(StringPrototypeSplit(value, ";"), 1), + (s) => StringPrototypeSplit(StringPrototypeTrim(s), "="), + ), + (arr) => arr.length > 1, + ), + ([k, v]) => [k, StringPrototypeReplace(v, /^"([^"]*)"$/, "$1")], + ), + ([k, v]) => MapPrototypeSet(params, k, v), + ); + return params; } const CRLF = "\r\n"; - const LF = CRLF.codePointAt(1); - const CR = CRLF.codePointAt(0); + const LF = StringPrototypeCodePointAt(CRLF, 1); + const CR = StringPrototypeCodePointAt(CRLF, 0); class MultipartParser { /** @@ -325,14 +374,14 @@ */ #parseHeaders(headersText) { const headers = new Headers(); - const rawHeaders = headersText.split("\r\n"); + const rawHeaders = StringPrototypeSplit(headersText, "\r\n"); for (const rawHeader of rawHeaders) { - const sepIndex = rawHeader.indexOf(":"); + const sepIndex = StringPrototypeIndexOf(rawHeader, ":"); if (sepIndex < 0) { continue; // Skip this header } - const key = rawHeader.slice(0, sepIndex); - const value = rawHeader.slice(sepIndex + 1); + const key = StringPrototypeSlice(rawHeader, 0, sepIndex); + const value = StringPrototypeSlice(rawHeader, sepIndex + 1); headers.set(key, value); } @@ -364,7 +413,7 @@ const isNewLine = byte === LF && prevByte === CR; if (state === 1 || state === 2 || state == 3) { - headerText += String.fromCharCode(byte); + headerText += StringFromCharCode(byte); } if (state === 0 && isNewLine) { state = 1; @@ -390,13 +439,14 @@ if (boundaryIndex >= this.boundary.length) { const { headers, disposition } = this.#parseHeaders(headerText); - const content = this.body.subarray( + const content = TypedArrayPrototypeSubarray( + this.body, fileStart, i - boundaryIndex - 1, ); // https://fetch.spec.whatwg.org/#ref-for-dom-body-formdata - const filename = disposition.get("filename"); - const name = disposition.get("name"); + const filename = MapPrototypeGet(disposition, "filename"); + const name = MapPrototypeGet(disposition, "name"); state = 5; // Reset diff --git a/extensions/fetch/22_body.js b/extensions/fetch/22_body.js index c683ca14f..2a1a91159 100644 --- a/extensions/fetch/22_body.js +++ b/extensions/fetch/22_body.js @@ -21,6 +21,18 @@ const mimesniff = globalThis.__bootstrap.mimesniff; const { isReadableStreamDisturbed, errorReadableStream, createProxy } = globalThis.__bootstrap.streams; + const { + ArrayBufferIsView, + ArrayPrototypePush, + ArrayPrototypeMap, + JSONParse, + ObjectDefineProperties, + PromiseResolve, + TypedArrayPrototypeSet, + TypedArrayPrototypeSlice, + TypeError, + Uint8Array, + } = window.__bootstrap.primordials; class InnerBody { /** @type {ReadableStream<Uint8Array> | { body: Uint8Array, consumed: boolean }} */ @@ -92,13 +104,13 @@ while (true) { const { value: chunk, done } = await reader.read(); if (done) break; - chunks.push(chunk); + ArrayPrototypePush(chunks, chunk); totalLength += chunk.byteLength; } const finalBuffer = new Uint8Array(totalLength); let i = 0; for (const chunk of chunks) { - finalBuffer.set(chunk, i); + TypedArrayPrototypeSet(finalBuffer, chunk, i); i += chunk.byteLength; } return finalBuffer; @@ -165,7 +177,7 @@ if (object[bodySymbol] !== null) { return object[bodySymbol].consume(); } - return Promise.resolve(new Uint8Array()); + return PromiseResolve(new Uint8Array()); } /** @type {PropertyDescriptorMap} */ @@ -255,7 +267,7 @@ enumerable: true, }, }; - return Object.defineProperties(prototype.prototype, mixin); + return ObjectDefineProperties(prototype.prototype, mixin); } /** @@ -287,7 +299,10 @@ } else if (essence === "application/x-www-form-urlencoded") { const entries = parseUrlEncoded(bytes); return formDataFromEntries( - entries.map((x) => ({ name: x[0], value: x[1] })), + ArrayPrototypeMap( + entries, + (x) => ({ name: x[0], value: x[1] }), + ), ); } } @@ -296,7 +311,7 @@ throw new TypeError("Missing content type"); } case "JSON": - return JSON.parse(core.decode(bytes)); + return JSONParse(core.decode(bytes)); case "text": return core.decode(bytes); } @@ -319,15 +334,15 @@ if (object.type.length !== 0) { contentType = object.type; } - } else if (ArrayBuffer.isView(object) || object instanceof ArrayBuffer) { - const u8 = ArrayBuffer.isView(object) + } else if (ArrayBufferIsView(object) || object instanceof ArrayBuffer) { + const u8 = ArrayBufferIsView(object) ? new Uint8Array( object.buffer, object.byteOffset, object.byteLength, ) : new Uint8Array(object); - const copy = u8.slice(0, u8.byteLength); + const copy = TypedArrayPrototypeSlice(u8, 0, u8.byteLength); source = copy; } else if (object instanceof FormData) { const res = formDataToBlob(object); @@ -336,6 +351,7 @@ length = res.size; contentType = res.type; } else if (object instanceof URLSearchParams) { + // TODO(@satyarohith): not sure what primordial here. source = core.encode(object.toString()); contentType = "application/x-www-form-urlencoded;charset=UTF-8"; } else if (typeof object === "string") { @@ -374,7 +390,7 @@ if (V instanceof ArrayBuffer || V instanceof SharedArrayBuffer) { return webidl.converters["ArrayBuffer"](V, opts); } - if (ArrayBuffer.isView(V)) { + if (ArrayBufferIsView(V)) { return webidl.converters["ArrayBufferView"](V, opts); } } diff --git a/extensions/fetch/23_request.js b/extensions/fetch/23_request.js index 93d13e8d8..829f7e6dc 100644 --- a/extensions/fetch/23_request.js +++ b/extensions/fetch/23_request.js @@ -26,6 +26,20 @@ } = window.__bootstrap.headers; const { HttpClient } = window.__bootstrap.fetch; const abortSignal = window.__bootstrap.abortSignal; + const { + ArrayPrototypeMap, + ArrayPrototypeSlice, + ArrayPrototypeSplice, + MapPrototypeHas, + MapPrototypeGet, + MapPrototypeSet, + ObjectKeys, + RegExpPrototypeTest, + Symbol, + SymbolFor, + SymbolToStringTag, + TypeError, + } = window.__bootstrap.primordials; const _request = Symbol("request"); const _headers = Symbol("headers"); @@ -81,7 +95,9 @@ * @returns {InnerRequest} */ function cloneInnerRequest(request) { - const headerList = [...request.headerList.map((x) => [x[0], x[1]])]; + const headerList = [ + ...ArrayPrototypeMap(request.headerList, (x) => [x[0], x[1]]), + ]; let body = null; if (request.body !== null) { body = request.body.clone(); @@ -129,7 +145,7 @@ } // Regular path - if (!HTTP_TOKEN_CODE_POINT_RE.test(m)) { + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, m)) { throw new TypeError("Method is not valid."); } const upperCase = byteUpperCase(m); @@ -166,14 +182,17 @@ mimeType = temporaryMimeType; if (mimesniff.essence(mimeType) !== essence) { charset = null; - const newCharset = mimeType.parameters.get("charset"); + const newCharset = MapPrototypeGet(mimeType.parameters, "charset"); if (newCharset !== undefined) { charset = newCharset; } essence = mimesniff.essence(mimeType); } else { - if (mimeType.parameters.has("charset") === null && charset !== null) { - mimeType.parameters.set("charset", charset); + if ( + MapPrototypeHas(mimeType.parameters, "charset") === null && + charset !== null + ) { + MapPrototypeSet(mimeType.parameters, "charset", charset); } } } @@ -267,15 +286,17 @@ this[_headers] = headersFromHeaderList(request.headerList, "request"); // 32. - if (Object.keys(init).length > 0) { - let headers = headerListFromHeaders(this[_headers]).slice( + if (ObjectKeys(init).length > 0) { + let headers = ArrayPrototypeSlice( + headerListFromHeaders(this[_headers]), 0, headerListFromHeaders(this[_headers]).length, ); if (init.headers !== undefined) { headers = init.headers; } - headerListFromHeaders(this[_headers]).splice( + ArrayPrototypeSplice( + headerListFromHeaders(this[_headers]), 0, headerListFromHeaders(this[_headers]).length, ); @@ -367,11 +388,11 @@ ); } - get [Symbol.toStringTag]() { + get [SymbolToStringTag]() { return "Request"; } - [Symbol.for("Deno.customInspect")](inspect) { + [SymbolFor("Deno.customInspect")](inspect) { const inner = { bodyUsed: this.bodyUsed, headers: this.headers, diff --git a/extensions/fetch/23_response.js b/extensions/fetch/23_response.js index 5d22b2457..32a9b466c 100644 --- a/extensions/fetch/23_response.js +++ b/extensions/fetch/23_response.js @@ -25,6 +25,20 @@ guardFromHeaders, fillHeaders, } = window.__bootstrap.headers; + const { + ArrayPrototypeMap, + ArrayPrototypePush, + MapPrototypeHas, + MapPrototypeGet, + MapPrototypeSet, + RangeError, + RegExp, + RegExpPrototypeTest, + Symbol, + SymbolFor, + SymbolToStringTag, + TypeError, + } = window.__bootstrap.primordials; const VCHAR = ["\x21-\x7E"]; const OBS_TEXT = ["\x80-\xFF"]; @@ -75,7 +89,9 @@ */ function cloneInnerResponse(response) { const urlList = [...response.urlList]; - const headerList = [...response.headerList.map((x) => [x[0], x[1]])]; + const headerList = [ + ...ArrayPrototypeMap(response.headerList, (x) => [x[0], x[1]]), + ]; let body = null; if (response.body !== null) { body = response.body.clone(); @@ -162,14 +178,17 @@ mimeType = temporaryMimeType; if (mimesniff.essence(mimeType) !== essence) { charset = null; - const newCharset = mimeType.parameters.get("charset"); + const newCharset = MapPrototypeGet(mimeType.parameters, "charset"); if (newCharset !== undefined) { charset = newCharset; } essence = mimesniff.essence(mimeType); } else { - if (mimeType.parameters.has("charset") === null && charset !== null) { - mimeType.parameters.set("charset", charset); + if ( + MapPrototypeHas(mimeType.parameters, "charset") === null && + charset !== null + ) { + MapPrototypeSet(mimeType.parameters, "charset", charset); } } } @@ -218,7 +237,7 @@ } const inner = newInnerResponse(status); inner.type = "default"; - inner.headerList.push(["location", parsedURL.href]); + ArrayPrototypePush(inner.headerList, ["location", parsedURL.href]); const response = webidl.createBranded(Response); response[_response] = inner; response[_headers] = headersFromHeaderList( @@ -249,7 +268,7 @@ ); } - if (!REASON_PHRASE_RE.test(init.statusText)) { + if (!RegExpPrototypeTest(REASON_PHRASE_RE, init.statusText)) { throw new TypeError("Status text is not valid."); } @@ -353,11 +372,11 @@ return second; } - get [Symbol.toStringTag]() { + get [SymbolToStringTag]() { return "Response"; } - [Symbol.for("Deno.customInspect")](inspect) { + [SymbolFor("Deno.customInspect")](inspect) { const inner = { body: this.body, bodyUsed: this.bodyUsed, diff --git a/extensions/fetch/26_fetch.js b/extensions/fetch/26_fetch.js index a33187344..a0256b2bd 100644 --- a/extensions/fetch/26_fetch.js +++ b/extensions/fetch/26_fetch.js @@ -27,6 +27,19 @@ } = window.__bootstrap.fetch; const abortSignal = window.__bootstrap.abortSignal; const { DOMException } = window.__bootstrap.domException; + const { + ArrayPrototypePush, + ArrayPrototypeSplice, + ArrayPrototypeFilter, + ArrayPrototypeIncludes, + Promise, + PromisePrototypeThen, + PromisePrototypeCatch, + StringPrototypeToLowerCase, + TypedArrayPrototypeSubarray, + TypeError, + Uint8Array, + } = window.__bootstrap.primordials; const REQUEST_BODY_HEADER_NAMES = [ "content-encoding", @@ -104,7 +117,7 @@ ); if (read > 0) { // We read some data. Enqueue it onto the stream. - controller.enqueue(chunk.subarray(0, read)); + controller.enqueue(TypedArrayPrototypeSubarray(chunk, 0, read)); } else { // We have reached the end of the body, so we close the stream. controller.close(); @@ -201,20 +214,26 @@ const reader = reqBody.getReader(); (async () => { while (true) { - const { value, done } = await reader.read().catch((err) => { - if (terminator.aborted) return { done: true, value: undefined }; - throw err; - }); + const { value, done } = await PromisePrototypeCatch( + reader.read(), + (err) => { + if (terminator.aborted) return { done: true, value: undefined }; + throw err; + }, + ); if (done) break; if (!(value instanceof Uint8Array)) { await reader.cancel("value not a Uint8Array"); break; } try { - await opFetchRequestWrite(requestBodyRid, value).catch((err) => { - if (terminator.aborted) return; - throw err; - }); + await PromisePrototypeCatch( + opFetchRequestWrite(requestBodyRid, value), + (err) => { + if (terminator.aborted) return; + throw err; + }, + ); if (terminator.aborted) break; } catch (err) { await reader.cancel(err); @@ -231,7 +250,7 @@ let resp; try { - resp = await opFetchSend(requestRid).catch((err) => { + resp = await PromisePrototypeCatch(opFetchSend(requestRid), (err) => { if (terminator.aborted) return; throw err; }); @@ -300,7 +319,8 @@ * @returns {Promise<InnerResponse>} */ function httpRedirectFetch(request, response, terminator) { - const locationHeaders = response.headerList.filter( + const locationHeaders = ArrayPrototypeFilter( + response.headerList, (entry) => entry[0] === "location", ); if (locationHeaders.length === 0) { @@ -339,8 +359,13 @@ request.method = "GET"; request.body = null; for (let i = 0; i < request.headerList.length; i++) { - if (REQUEST_BODY_HEADER_NAMES.includes(request.headerList[i][0])) { - request.headerList.splice(i, 1); + if ( + ArrayPrototypeIncludes( + REQUEST_BODY_HEADER_NAMES, + request.headerList[i][0], + ) + ) { + ArrayPrototypeSplice(request.headerList, i, 1); i--; } } @@ -349,7 +374,7 @@ const res = extractBody(request.body.source); request.body = res.body; } - request.urlList.push(locationURL.href); + ArrayPrototypePush(request.urlList, locationURL.href); return mainFetch(request, true, terminator); } @@ -393,35 +418,41 @@ requestObject.signal[abortSignal.add](onabort); if (!requestObject.headers.has("accept")) { - request.headerList.push(["accept", "*/*"]); + ArrayPrototypePush(request.headerList, ["accept", "*/*"]); } // 12. - mainFetch(request, false, requestObject.signal).then((response) => { - // 12.1. - if (locallyAborted) return; - // 12.2. - if (response.aborted) { - reject(request, responseObject); - requestObject.signal[abortSignal.remove](onabort); - return; - } - // 12.3. - if (response.type === "error") { - const err = new TypeError( - "Fetch failed: " + (response.error ?? "unknown error"), - ); + PromisePrototypeCatch( + PromisePrototypeThen( + mainFetch(request, false, requestObject.signal), + (response) => { + // 12.1. + if (locallyAborted) return; + // 12.2. + if (response.aborted) { + reject(request, responseObject); + requestObject.signal[abortSignal.remove](onabort); + return; + } + // 12.3. + if (response.type === "error") { + const err = new TypeError( + "Fetch failed: " + (response.error ?? "unknown error"), + ); + reject(err); + requestObject.signal[abortSignal.remove](onabort); + return; + } + responseObject = fromInnerResponse(response, "immutable"); + resolve(responseObject); + requestObject.signal[abortSignal.remove](onabort); + }, + ), + (err) => { reject(err); requestObject.signal[abortSignal.remove](onabort); - return; - } - responseObject = fromInnerResponse(response, "immutable"); - resolve(responseObject); - requestObject.signal[abortSignal.remove](onabort); - }).catch((err) => { - reject(err); - requestObject.signal[abortSignal.remove](onabort); - }); + }, + ); }); return p; } @@ -461,7 +492,8 @@ // https://github.com/WebAssembly/spec/issues/1138. The WPT tests // expect the raw value of the Content-Type attribute lowercased. if ( - res.headers.get("Content-Type")?.toLowerCase() !== "application/wasm" + StringPrototypeToLowerCase(res.headers.get("Content-Type")) !== + "application/wasm" ) { throw new TypeError("Invalid WebAssembly content type."); } |