diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2023-02-07 20:22:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-07 20:22:46 +0100 |
commit | b4aa1530970f7b9cc4e6f2f27e077852c4e178d3 (patch) | |
tree | 3d008912affe8550692183bd2697a386db5e3c79 /ext/fetch/20_headers.js | |
parent | 65500f36e870b4ada3996b06aa287e30177d21a3 (diff) |
refactor: Use ES modules for internal runtime code (#17648)
This PR refactors all internal js files (except core) to be written as
ES modules.
`__bootstrap`has been mostly replaced with static imports in form in
`internal:[path to file from repo root]`.
To specify if files are ESM, an `esm` method has been added to
`Extension`, similar to the `js` method.
A new ModuleLoader called `InternalModuleLoader` has been added to
enable the loading of internal specifiers, which is used in all
situations except when a snapshot is only loaded, and not a new one is
created from it.
---------
Co-authored-by: Bartek IwaĆczuk <biwanczuk@gmail.com>
Diffstat (limited to 'ext/fetch/20_headers.js')
-rw-r--r-- | ext/fetch/20_headers.js | 808 |
1 files changed, 403 insertions, 405 deletions
diff --git a/ext/fetch/20_headers.js b/ext/fetch/20_headers.js index 54e635522..9790bb69f 100644 --- a/ext/fetch/20_headers.js +++ b/ext/fetch/20_headers.js @@ -8,472 +8,470 @@ /// <reference path="../web/06_streams_types.d.ts" /> /// <reference path="./lib.deno_fetch.d.ts" /> /// <reference lib="esnext" /> -"use strict"; - -((window) => { - const webidl = window.__bootstrap.webidl; - const { - HTTP_TAB_OR_SPACE_PREFIX_RE, - HTTP_TAB_OR_SPACE_SUFFIX_RE, - HTTP_TOKEN_CODE_POINT_RE, - byteLowerCase, - collectSequenceOfCodepoints, - collectHttpQuotedString, - httpTrim, - } = window.__bootstrap.infra; - const { - ArrayIsArray, - ArrayPrototypeMap, - ArrayPrototypePush, - ArrayPrototypeSort, - ArrayPrototypeJoin, - ArrayPrototypeSplice, - ArrayPrototypeFilter, - ObjectPrototypeHasOwnProperty, - ObjectEntries, - RegExpPrototypeTest, - SafeArrayIterator, - Symbol, - SymbolFor, - SymbolIterator, - StringPrototypeReplaceAll, - TypeError, - } = window.__bootstrap.primordials; - - const _headerList = Symbol("header list"); - const _iterableHeaders = Symbol("iterable headers"); - const _guard = Symbol("guard"); - - /** - * @typedef Header - * @type {[string, string]} - */ - /** - * @typedef HeaderList - * @type {Header[]} - */ +import * as webidl from "internal:ext/webidl/00_webidl.js"; +import { + byteLowerCase, + collectHttpQuotedString, + collectSequenceOfCodepoints, + HTTP_TAB_OR_SPACE_PREFIX_RE, + HTTP_TAB_OR_SPACE_SUFFIX_RE, + HTTP_TOKEN_CODE_POINT_RE, + httpTrim, +} from "internal:ext/web/00_infra.js"; +const primordials = globalThis.__bootstrap.primordials; +const { + ArrayIsArray, + ArrayPrototypeMap, + ArrayPrototypePush, + ArrayPrototypeSort, + ArrayPrototypeJoin, + ArrayPrototypeSplice, + ArrayPrototypeFilter, + ObjectPrototypeHasOwnProperty, + ObjectEntries, + RegExpPrototypeTest, + SafeArrayIterator, + Symbol, + SymbolFor, + SymbolIterator, + StringPrototypeReplaceAll, + TypeError, +} = primordials; + +const _headerList = Symbol("header list"); +const _iterableHeaders = Symbol("iterable headers"); +const _guard = Symbol("guard"); + +/** + * @typedef Header + * @type {[string, string]} + */ + +/** + * @typedef HeaderList + * @type {Header[]} + */ + +/** + * @param {string} potentialValue + * @returns {string} + */ +function normalizeHeaderValue(potentialValue) { + return httpTrim(potentialValue); +} + +/** + * @param {Headers} headers + * @param {HeadersInit} object + */ +function fillHeaders(headers, object) { + if (ArrayIsArray(object)) { + for (let i = 0; i < object.length; ++i) { + const header = object[i]; + if (header.length !== 2) { + throw new TypeError( + `Invalid header. Length must be 2, but is ${header.length}`, + ); + } + appendHeader(headers, header[0], header[1]); + } + } else { + for (const key in object) { + if (!ObjectPrototypeHasOwnProperty(object, key)) { + continue; + } + appendHeader(headers, key, object[key]); + } + } +} + +// Regex matching illegal chars in a header value +// deno-lint-ignore no-control-regex +const ILLEGAL_VALUE_CHARS = /[\x00\x0A\x0D]/; + +/** + * https://fetch.spec.whatwg.org/#concept-headers-append + * @param {Headers} headers + * @param {string} name + * @param {string} value + */ +function appendHeader(headers, name, value) { + // 1. + value = normalizeHeaderValue(value); + + // 2. + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { + throw new TypeError("Header name is not valid."); + } + if (RegExpPrototypeTest(ILLEGAL_VALUE_CHARS, value)) { + throw new TypeError("Header value is not valid."); + } - /** - * @param {string} potentialValue - * @returns {string} - */ - function normalizeHeaderValue(potentialValue) { - return httpTrim(potentialValue); + // 3. + if (headers[_guard] == "immutable") { + throw new TypeError("Headers are immutable."); } - /** - * @param {Headers} headers - * @param {HeadersInit} object - */ - function fillHeaders(headers, object) { - if (ArrayIsArray(object)) { - for (let i = 0; i < object.length; ++i) { - const header = object[i]; - if (header.length !== 2) { - throw new TypeError( - `Invalid header. Length must be 2, but is ${header.length}`, - ); + // 7. + const list = headers[_headerList]; + const lowercaseName = byteLowerCase(name); + for (let i = 0; i < list.length; i++) { + if (byteLowerCase(list[i][0]) === lowercaseName) { + name = list[i][0]; + break; + } + } + ArrayPrototypePush(list, [name, value]); +} + +/** + * https://fetch.spec.whatwg.org/#concept-header-list-get + * @param {HeaderList} list + * @param {string} name + */ +function getHeader(list, name) { + const lowercaseName = byteLowerCase(name); + const entries = ArrayPrototypeMap( + ArrayPrototypeFilter( + list, + (entry) => byteLowerCase(entry[0]) === lowercaseName, + ), + (entry) => entry[1], + ); + if (entries.length === 0) { + return null; + } else { + return ArrayPrototypeJoin(entries, "\x2C\x20"); + } +} + +/** + * https://fetch.spec.whatwg.org/#concept-header-list-get-decode-split + * @param {HeaderList} list + * @param {string} name + * @returns {string[] | null} + */ +function getDecodeSplitHeader(list, name) { + const initialValue = getHeader(list, name); + if (initialValue === null) return null; + const input = initialValue; + let position = 0; + const values = []; + let value = ""; + while (position < initialValue.length) { + // 7.1. collect up to " or , + const res = collectSequenceOfCodepoints( + initialValue, + position, + (c) => c !== "\u0022" && c !== "\u002C", + ); + value += res.result; + position = res.position; + + if (position < initialValue.length) { + if (input[position] === "\u0022") { + const res = collectHttpQuotedString(input, position, false); + value += res.result; + position = res.position; + if (position < initialValue.length) { + continue; } - appendHeader(headers, header[0], header[1]); + } else { + if (input[position] !== "\u002C") throw new TypeError("Unreachable"); + position += 1; } - } else { - for (const key in object) { - if (!ObjectPrototypeHasOwnProperty(object, key)) { - continue; + } + + value = StringPrototypeReplaceAll(value, HTTP_TAB_OR_SPACE_PREFIX_RE, ""); + value = StringPrototypeReplaceAll(value, HTTP_TAB_OR_SPACE_SUFFIX_RE, ""); + + ArrayPrototypePush(values, value); + value = ""; + } + return values; +} + +class Headers { + /** @type {HeaderList} */ + [_headerList] = []; + /** @type {"immutable" | "request" | "request-no-cors" | "response" | "none"} */ + [_guard]; + + get [_iterableHeaders]() { + const list = this[_headerList]; + + // The order of steps are not similar to the ones suggested by the + // spec but produce the same result. + const headers = {}; + const cookies = []; + for (let i = 0; i < list.length; ++i) { + const entry = list[i]; + const name = byteLowerCase(entry[0]); + const value = entry[1]; + if (value === null) throw new TypeError("Unreachable"); + // The following if statement is not spec compliant. + // `set-cookie` is the only header that can not be concatenated, + // 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") { + 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 + // list to combine multiple values with same header name. It + // instead gradually combines them as they are found. + let header = headers[name]; + if (header && header.length > 0) { + header += "\x2C\x20" + value; + } else { + header = value; } - appendHeader(headers, key, object[key]); + headers[name] = header; } } + + return ArrayPrototypeSort( + [ + ...new SafeArrayIterator(ObjectEntries(headers)), + ...new SafeArrayIterator(cookies), + ], + (a, b) => { + const akey = a[0]; + const bkey = b[0]; + if (akey > bkey) return 1; + if (akey < bkey) return -1; + return 0; + }, + ); } - // Regex matching illegal chars in a header value - // deno-lint-ignore no-control-regex - const ILLEGAL_VALUE_CHARS = /[\x00\x0A\x0D]/; + /** @param {HeadersInit} [init] */ + constructor(init = undefined) { + const prefix = "Failed to construct 'Headers'"; + if (init !== undefined) { + init = webidl.converters["HeadersInit"](init, { + prefix, + context: "Argument 1", + }); + } + + this[webidl.brand] = webidl.brand; + this[_guard] = "none"; + if (init !== undefined) { + fillHeaders(this, init); + } + } /** - * https://fetch.spec.whatwg.org/#concept-headers-append - * @param {Headers} headers * @param {string} name * @param {string} value */ - function appendHeader(headers, name, value) { - // 1. - value = normalizeHeaderValue(value); + append(name, value) { + webidl.assertBranded(this, HeadersPrototype); + const prefix = "Failed to execute 'append' on 'Headers'"; + webidl.requiredArguments(arguments.length, 2, { prefix }); + name = webidl.converters["ByteString"](name, { + prefix, + context: "Argument 1", + }); + value = webidl.converters["ByteString"](value, { + prefix, + context: "Argument 2", + }); + appendHeader(this, name, value); + } + + /** + * @param {string} name + */ + delete(name) { + const prefix = "Failed to execute 'delete' on 'Headers'"; + webidl.requiredArguments(arguments.length, 1, { prefix }); + name = webidl.converters["ByteString"](name, { + prefix, + context: "Argument 1", + }); - // 2. if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { throw new TypeError("Header name is not valid."); } - if (RegExpPrototypeTest(ILLEGAL_VALUE_CHARS, value)) { - throw new TypeError("Header value is not valid."); - } - - // 3. - if (headers[_guard] == "immutable") { + if (this[_guard] == "immutable") { throw new TypeError("Headers are immutable."); } - // 7. - const list = headers[_headerList]; + const list = this[_headerList]; const lowercaseName = byteLowerCase(name); for (let i = 0; i < list.length; i++) { if (byteLowerCase(list[i][0]) === lowercaseName) { - name = list[i][0]; - break; + ArrayPrototypeSplice(list, i, 1); + i--; } } - ArrayPrototypePush(list, [name, value]); } /** - * https://fetch.spec.whatwg.org/#concept-header-list-get - * @param {HeaderList} list * @param {string} name */ - function getHeader(list, name) { - const lowercaseName = byteLowerCase(name); - const entries = ArrayPrototypeMap( - ArrayPrototypeFilter( - list, - (entry) => byteLowerCase(entry[0]) === lowercaseName, - ), - (entry) => entry[1], - ); - if (entries.length === 0) { - return null; - } else { - return ArrayPrototypeJoin(entries, "\x2C\x20"); + get(name) { + const prefix = "Failed to execute 'get' on 'Headers'"; + webidl.requiredArguments(arguments.length, 1, { prefix }); + name = webidl.converters["ByteString"](name, { + prefix, + context: "Argument 1", + }); + + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { + throw new TypeError("Header name is not valid."); } + + const list = this[_headerList]; + return getHeader(list, name); } /** - * https://fetch.spec.whatwg.org/#concept-header-list-get-decode-split - * @param {HeaderList} list * @param {string} name - * @returns {string[] | null} */ - function getDecodeSplitHeader(list, name) { - const initialValue = getHeader(list, name); - if (initialValue === null) return null; - const input = initialValue; - let position = 0; - const values = []; - let value = ""; - while (position < initialValue.length) { - // 7.1. collect up to " or , - const res = collectSequenceOfCodepoints( - initialValue, - position, - (c) => c !== "\u0022" && c !== "\u002C", - ); - value += res.result; - position = res.position; - - if (position < initialValue.length) { - if (input[position] === "\u0022") { - const res = collectHttpQuotedString(input, position, false); - value += res.result; - position = res.position; - if (position < initialValue.length) { - continue; - } - } else { - if (input[position] !== "\u002C") throw new TypeError("Unreachable"); - position += 1; - } - } - - value = StringPrototypeReplaceAll(value, HTTP_TAB_OR_SPACE_PREFIX_RE, ""); - value = StringPrototypeReplaceAll(value, HTTP_TAB_OR_SPACE_SUFFIX_RE, ""); + has(name) { + const prefix = "Failed to execute 'has' on 'Headers'"; + webidl.requiredArguments(arguments.length, 1, { prefix }); + name = webidl.converters["ByteString"](name, { + prefix, + context: "Argument 1", + }); - ArrayPrototypePush(values, value); - value = ""; + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { + throw new TypeError("Header name is not valid."); } - return values; - } - class Headers { - /** @type {HeaderList} */ - [_headerList] = []; - /** @type {"immutable" | "request" | "request-no-cors" | "response" | "none"} */ - [_guard]; - - get [_iterableHeaders]() { - const list = this[_headerList]; - - // The order of steps are not similar to the ones suggested by the - // spec but produce the same result. - const headers = {}; - const cookies = []; - for (let i = 0; i < list.length; ++i) { - const entry = list[i]; - const name = byteLowerCase(entry[0]); - const value = entry[1]; - if (value === null) throw new TypeError("Unreachable"); - // The following if statement is not spec compliant. - // `set-cookie` is the only header that can not be concatenated, - // 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") { - 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 - // list to combine multiple values with same header name. It - // instead gradually combines them as they are found. - let header = headers[name]; - if (header && header.length > 0) { - header += "\x2C\x20" + value; - } else { - header = value; - } - headers[name] = header; - } + const list = this[_headerList]; + const lowercaseName = byteLowerCase(name); + for (let i = 0; i < list.length; i++) { + if (byteLowerCase(list[i][0]) === lowercaseName) { + return true; } - - return ArrayPrototypeSort( - [ - ...new SafeArrayIterator(ObjectEntries(headers)), - ...new SafeArrayIterator(cookies), - ], - (a, b) => { - const akey = a[0]; - const bkey = b[0]; - if (akey > bkey) return 1; - if (akey < bkey) return -1; - return 0; - }, - ); } + return false; + } - /** @param {HeadersInit} [init] */ - constructor(init = undefined) { - const prefix = "Failed to construct 'Headers'"; - if (init !== undefined) { - init = webidl.converters["HeadersInit"](init, { - prefix, - context: "Argument 1", - }); - } + /** + * @param {string} name + * @param {string} value + */ + set(name, value) { + webidl.assertBranded(this, HeadersPrototype); + const prefix = "Failed to execute 'set' on 'Headers'"; + webidl.requiredArguments(arguments.length, 2, { prefix }); + name = webidl.converters["ByteString"](name, { + prefix, + context: "Argument 1", + }); + value = webidl.converters["ByteString"](value, { + prefix, + context: "Argument 2", + }); - this[webidl.brand] = webidl.brand; - this[_guard] = "none"; - if (init !== undefined) { - fillHeaders(this, init); - } - } + value = normalizeHeaderValue(value); - /** - * @param {string} name - * @param {string} value - */ - append(name, value) { - webidl.assertBranded(this, HeadersPrototype); - const prefix = "Failed to execute 'append' on 'Headers'"; - webidl.requiredArguments(arguments.length, 2, { prefix }); - name = webidl.converters["ByteString"](name, { - prefix, - context: "Argument 1", - }); - value = webidl.converters["ByteString"](value, { - prefix, - context: "Argument 2", - }); - appendHeader(this, name, value); + // 2. + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { + throw new TypeError("Header name is not valid."); } - - /** - * @param {string} name - */ - delete(name) { - const prefix = "Failed to execute 'delete' on 'Headers'"; - webidl.requiredArguments(arguments.length, 1, { prefix }); - name = webidl.converters["ByteString"](name, { - prefix, - context: "Argument 1", - }); - - if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { - throw new TypeError("Header name is not valid."); - } - if (this[_guard] == "immutable") { - throw new TypeError("Headers are immutable."); - } - - const list = this[_headerList]; - const lowercaseName = byteLowerCase(name); - for (let i = 0; i < list.length; i++) { - if (byteLowerCase(list[i][0]) === lowercaseName) { - ArrayPrototypeSplice(list, i, 1); - i--; - } - } + if (RegExpPrototypeTest(ILLEGAL_VALUE_CHARS, value)) { + throw new TypeError("Header value is not valid."); } - /** - * @param {string} name - */ - get(name) { - const prefix = "Failed to execute 'get' on 'Headers'"; - webidl.requiredArguments(arguments.length, 1, { prefix }); - name = webidl.converters["ByteString"](name, { - prefix, - context: "Argument 1", - }); - - if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { - throw new TypeError("Header name is not valid."); - } - - const list = this[_headerList]; - return getHeader(list, name); + if (this[_guard] == "immutable") { + throw new TypeError("Headers are immutable."); } - /** - * @param {string} name - */ - has(name) { - const prefix = "Failed to execute 'has' on 'Headers'"; - webidl.requiredArguments(arguments.length, 1, { prefix }); - name = webidl.converters["ByteString"](name, { - prefix, - context: "Argument 1", - }); - - if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { - throw new TypeError("Header name is not valid."); - } - - const list = this[_headerList]; - const lowercaseName = byteLowerCase(name); - for (let i = 0; i < list.length; i++) { - if (byteLowerCase(list[i][0]) === lowercaseName) { - return true; + const list = this[_headerList]; + const lowercaseName = byteLowerCase(name); + let added = false; + for (let i = 0; i < list.length; i++) { + if (byteLowerCase(list[i][0]) === lowercaseName) { + if (!added) { + list[i][1] = value; + added = true; + } else { + ArrayPrototypeSplice(list, i, 1); + i--; } } - return false; } - - /** - * @param {string} name - * @param {string} value - */ - set(name, value) { - webidl.assertBranded(this, HeadersPrototype); - const prefix = "Failed to execute 'set' on 'Headers'"; - webidl.requiredArguments(arguments.length, 2, { prefix }); - name = webidl.converters["ByteString"](name, { - prefix, - context: "Argument 1", - }); - value = webidl.converters["ByteString"](value, { - prefix, - context: "Argument 2", - }); - - value = normalizeHeaderValue(value); - - // 2. - if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name)) { - throw new TypeError("Header name is not valid."); - } - if (RegExpPrototypeTest(ILLEGAL_VALUE_CHARS, value)) { - throw new TypeError("Header value is not valid."); - } - - if (this[_guard] == "immutable") { - throw new TypeError("Headers are immutable."); - } - - const list = this[_headerList]; - const lowercaseName = byteLowerCase(name); - let added = false; - for (let i = 0; i < list.length; i++) { - if (byteLowerCase(list[i][0]) === lowercaseName) { - if (!added) { - list[i][1] = value; - added = true; - } else { - ArrayPrototypeSplice(list, i, 1); - i--; - } - } - } - if (!added) { - ArrayPrototypePush(list, [name, value]); - } + if (!added) { + ArrayPrototypePush(list, [name, value]); } + } - [SymbolFor("Deno.privateCustomInspect")](inspect) { - const headers = {}; - // deno-lint-ignore prefer-primordials - for (const header of this) { - headers[header[0]] = header[1]; - } - return `Headers ${inspect(headers)}`; + [SymbolFor("Deno.privateCustomInspect")](inspect) { + const headers = {}; + // deno-lint-ignore prefer-primordials + for (const header of this) { + headers[header[0]] = header[1]; } + return `Headers ${inspect(headers)}`; } +} - webidl.mixinPairIterable("Headers", Headers, _iterableHeaders, 0, 1); +webidl.mixinPairIterable("Headers", Headers, _iterableHeaders, 0, 1); - webidl.configurePrototype(Headers); - const HeadersPrototype = Headers.prototype; +webidl.configurePrototype(Headers); +const HeadersPrototype = Headers.prototype; - webidl.converters["HeadersInit"] = (V, opts) => { - // Union for (sequence<sequence<ByteString>> or record<ByteString, ByteString>) - if (webidl.type(V) === "Object" && V !== null) { - if (V[SymbolIterator] !== undefined) { - return webidl.converters["sequence<sequence<ByteString>>"](V, opts); - } - return webidl.converters["record<ByteString, ByteString>"](V, opts); +webidl.converters["HeadersInit"] = (V, opts) => { + // Union for (sequence<sequence<ByteString>> or record<ByteString, ByteString>) + if (webidl.type(V) === "Object" && V !== null) { + if (V[SymbolIterator] !== undefined) { + return webidl.converters["sequence<sequence<ByteString>>"](V, opts); } - throw webidl.makeException( - TypeError, - "The provided value is not of type '(sequence<sequence<ByteString>> or record<ByteString, ByteString>)'", - opts, - ); - }; - webidl.converters["Headers"] = webidl.createInterfaceConverter( - "Headers", - Headers.prototype, - ); - - /** - * @param {HeaderList} list - * @param {"immutable" | "request" | "request-no-cors" | "response" | "none"} guard - * @returns {Headers} - */ - function headersFromHeaderList(list, guard) { - const headers = webidl.createBranded(Headers); - headers[_headerList] = list; - headers[_guard] = guard; - return headers; + return webidl.converters["record<ByteString, ByteString>"](V, opts); } - - /** - * @param {Headers} - * @returns {HeaderList} - */ - function headerListFromHeaders(headers) { - return headers[_headerList]; - } - - /** - * @param {Headers} - * @returns {"immutable" | "request" | "request-no-cors" | "response" | "none"} - */ - function guardFromHeaders(headers) { - return headers[_guard]; - } - - window.__bootstrap.headers = { - headersFromHeaderList, - headerListFromHeaders, - getDecodeSplitHeader, - guardFromHeaders, - fillHeaders, - getHeader, - Headers, - }; -})(this); + throw webidl.makeException( + TypeError, + "The provided value is not of type '(sequence<sequence<ByteString>> or record<ByteString, ByteString>)'", + opts, + ); +}; +webidl.converters["Headers"] = webidl.createInterfaceConverter( + "Headers", + Headers.prototype, +); + +/** + * @param {HeaderList} list + * @param {"immutable" | "request" | "request-no-cors" | "response" | "none"} guard + * @returns {Headers} + */ +function headersFromHeaderList(list, guard) { + const headers = webidl.createBranded(Headers); + headers[_headerList] = list; + headers[_guard] = guard; + return headers; +} + +/** + * @param {Headers} headers + * @returns {HeaderList} + */ +function headerListFromHeaders(headers) { + return headers[_headerList]; +} + +/** + * @param {Headers} headers + * @returns {"immutable" | "request" | "request-no-cors" | "response" | "none"} + */ +function guardFromHeaders(headers) { + return headers[_guard]; +} + +export { + fillHeaders, + getDecodeSplitHeader, + getHeader, + guardFromHeaders, + headerListFromHeaders, + Headers, + headersFromHeaderList, +}; |