diff --git a/ext/fetch/23_request.js b/ext/fetch/23_request.js index 1ffdd2a60d..9672287df3 100644 --- a/ext/fetch/23_request.js +++ b/ext/fetch/23_request.js @@ -18,7 +18,7 @@ const { guardFromHeaders } = window.__bootstrap.headers; const { mixinBody, extractBody } = window.__bootstrap.fetchBody; const { getLocationHref } = window.__bootstrap.location; - const mimesniff = window.__bootstrap.mimesniff; + const { extractMimeType } = window.__bootstrap.mimesniff; const { blobFromObjectUrl } = window.__bootstrap.file; const { headersFromHeaderList, @@ -32,9 +32,6 @@ ArrayPrototypeMap, ArrayPrototypeSlice, ArrayPrototypeSplice, - MapPrototypeHas, - MapPrototypeGet, - MapPrototypeSet, ObjectKeys, ObjectPrototypeIsPrototypeOf, RegExpPrototypeTest, @@ -174,41 +171,11 @@ /** @type {AbortSignal} */ [_signal]; get [_mimeType]() { - let charset = null; - let essence = null; - let mimeType = null; const values = getDecodeSplitHeader( headerListFromHeaders(this[_headers]), "Content-Type", ); - if (values === null) return null; - for (const value of values) { - const temporaryMimeType = mimesniff.parseMimeType(value); - if ( - temporaryMimeType === null || - mimesniff.essence(temporaryMimeType) == "*/*" - ) { - continue; - } - mimeType = temporaryMimeType; - if (mimesniff.essence(mimeType) !== essence) { - charset = null; - const newCharset = MapPrototypeGet(mimeType.parameters, "charset"); - if (newCharset !== undefined) { - charset = newCharset; - } - essence = mimesniff.essence(mimeType); - } else { - if ( - MapPrototypeHas(mimeType.parameters, "charset") === null && - charset !== null - ) { - MapPrototypeSet(mimeType.parameters, "charset", charset); - } - } - } - if (mimeType === null) return null; - return mimeType; + return extractMimeType(values); } get [_body]() { return this[_request].body; diff --git a/ext/fetch/23_response.js b/ext/fetch/23_response.js index 03f8c276b9..f1f6fe1dda 100644 --- a/ext/fetch/23_response.js +++ b/ext/fetch/23_response.js @@ -18,7 +18,7 @@ const { HTTP_TAB_OR_SPACE, regexMatcher } = window.__bootstrap.infra; const { extractBody, mixinBody } = window.__bootstrap.fetchBody; const { getLocationHref } = window.__bootstrap.location; - const mimesniff = window.__bootstrap.mimesniff; + const { extractMimeType } = window.__bootstrap.mimesniff; const { URL } = window.__bootstrap.url; const { getDecodeSplitHeader, @@ -30,9 +30,6 @@ const { ArrayPrototypeMap, ArrayPrototypePush, - MapPrototypeHas, - MapPrototypeGet, - MapPrototypeSet, ObjectPrototypeIsPrototypeOf, RangeError, RegExp, @@ -162,41 +159,11 @@ class Response { get [_mimeType]() { - let charset = null; - let essence = null; - let mimeType = null; const values = getDecodeSplitHeader( headerListFromHeaders(this[_headers]), "Content-Type", ); - if (values === null) return null; - for (const value of values) { - const temporaryMimeType = mimesniff.parseMimeType(value); - if ( - temporaryMimeType === null || - mimesniff.essence(temporaryMimeType) == "*/*" - ) { - continue; - } - mimeType = temporaryMimeType; - if (mimesniff.essence(mimeType) !== essence) { - charset = null; - const newCharset = MapPrototypeGet(mimeType.parameters, "charset"); - if (newCharset !== undefined) { - charset = newCharset; - } - essence = mimesniff.essence(mimeType); - } else { - if ( - MapPrototypeHas(mimeType.parameters, "charset") === null && - charset !== null - ) { - MapPrototypeSet(mimeType.parameters, "charset", charset); - } - } - } - if (mimeType === null) return null; - return mimeType; + return extractMimeType(values); } get [_body]() { return this[_response].body; diff --git a/ext/web/01_mimesniff.js b/ext/web/01_mimesniff.js index c6ac7c66c3..d2c784d6eb 100644 --- a/ext/web/01_mimesniff.js +++ b/ext/web/01_mimesniff.js @@ -12,6 +12,7 @@ const { ArrayPrototypeIncludes, Map, + MapPrototypeGet, MapPrototypeHas, MapPrototypeSet, RegExpPrototypeTest, @@ -207,5 +208,51 @@ return serialization; } - window.__bootstrap.mimesniff = { parseMimeType, essence, serializeMimeType }; + /** + * Part of the Fetch spec's "extract a MIME type" algorithm + * (https://fetch.spec.whatwg.org/#concept-header-extract-mime-type). + * @param {string[] | null} headerValues The result of getting, decoding and + * splitting the "Content-Type" header. + * @returns {MimeType | null} + */ + function extractMimeType(headerValues) { + if (headerValues === null) return null; + + let charset = null; + let essence_ = null; + let mimeType = null; + for (const value of headerValues) { + const temporaryMimeType = parseMimeType(value); + if ( + temporaryMimeType === null || + essence(temporaryMimeType) == "*/*" + ) { + continue; + } + mimeType = temporaryMimeType; + if (essence(mimeType) !== essence_) { + charset = null; + const newCharset = MapPrototypeGet(mimeType.parameters, "charset"); + if (newCharset !== undefined) { + charset = newCharset; + } + essence_ = essence(mimeType); + } else { + if ( + !MapPrototypeHas(mimeType.parameters, "charset") && + charset !== null + ) { + MapPrototypeSet(mimeType.parameters, "charset", charset); + } + } + } + return mimeType; + } + + window.__bootstrap.mimesniff = { + parseMimeType, + essence, + serializeMimeType, + extractMimeType, + }; })(this); diff --git a/ext/web/internal.d.ts b/ext/web/internal.d.ts index 41d4c9b325..8e580495b1 100644 --- a/ext/web/internal.d.ts +++ b/ext/web/internal.d.ts @@ -60,6 +60,9 @@ declare namespace globalThis { declare function parseMimeType(input: string): MimeType | null; declare function essence(mimeType: MimeType): string; declare function serializeMimeType(mimeType: MimeType): string; + declare function extractMimeType( + headerValues: string[] | null, + ): MimeType | null; } declare var eventTarget: {