diff options
Diffstat (limited to 'op_crates/fetch/20_headers.js')
-rw-r--r-- | op_crates/fetch/20_headers.js | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/op_crates/fetch/20_headers.js b/op_crates/fetch/20_headers.js index ce46e5dee..3c6fc0b26 100644 --- a/op_crates/fetch/20_headers.js +++ b/op_crates/fetch/20_headers.js @@ -14,10 +14,14 @@ ((window) => { const webidl = window.__bootstrap.webidl; const { + HTTP_TAB_OR_SPACE_PREFIX_RE, + HTTP_TAB_OR_SPACE_SUFFIX_RE, HTTP_WHITESPACE_PREFIX_RE, HTTP_WHITESPACE_SUFFIX_RE, HTTP_TOKEN_CODE_POINT_RE, byteLowerCase, + collectSequenceOfCodepoints, + collectHttpQuotedString, } = window.__bootstrap.infra; const _headerList = Symbol("header list"); @@ -35,7 +39,7 @@ */ /** - * @typedef {string} potentialValue + * @param {string} potentialValue * @returns {string} */ function normalizeHeaderValue(potentialValue) { @@ -103,6 +107,7 @@ } /** + * https://fetch.spec.whatwg.org/#concept-header-list-get * @param {HeaderList} list * @param {string} name */ @@ -118,10 +123,56 @@ } } + /** + * 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 = value.replaceAll(HTTP_TAB_OR_SPACE_PREFIX_RE, ""); + value = value.replaceAll(HTTP_TAB_OR_SPACE_SUFFIX_RE, ""); + + values.push(value); + value = ""; + } + return values; + } + class Headers { /** @type {HeaderList} */ [_headerList] = []; - /** @type {"immutable"| "request"| "request-no-cors"| "response" | "none"} */ + /** @type {"immutable" | "request" | "request-no-cors" | "response" | "none"} */ [_guard]; get [_iterableHeaders]() { @@ -359,7 +410,40 @@ Headers, ); + /** + * @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} + * @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 = { Headers, + headersFromHeaderList, + headerListFromHeaders, + fillHeaders, + getDecodeSplitHeader, + guardFromHeaders, }; })(this); |