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/web/01_mimesniff.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/web/01_mimesniff.js')
-rw-r--r-- | ext/web/01_mimesniff.js | 420 |
1 files changed, 206 insertions, 214 deletions
diff --git a/ext/web/01_mimesniff.js b/ext/web/01_mimesniff.js index 2d67d5f95..17d954eb4 100644 --- a/ext/web/01_mimesniff.js +++ b/ext/web/01_mimesniff.js @@ -6,255 +6,247 @@ /// <reference path="../web/internal.d.ts" /> /// <reference path="../web/lib.deno_web.d.ts" /> -"use strict"; - -((window) => { - const { - ArrayPrototypeIncludes, - Map, - MapPrototypeGet, - MapPrototypeHas, - MapPrototypeSet, - RegExpPrototypeTest, - SafeMapIterator, - StringPrototypeReplaceAll, - StringPrototypeToLowerCase, - } = window.__bootstrap.primordials; - const { - collectSequenceOfCodepoints, - HTTP_WHITESPACE, - HTTP_WHITESPACE_PREFIX_RE, - HTTP_WHITESPACE_SUFFIX_RE, - HTTP_QUOTED_STRING_TOKEN_POINT_RE, - HTTP_TOKEN_CODE_POINT_RE, - collectHttpQuotedString, - } = window.__bootstrap.infra; +const primordials = globalThis.__bootstrap.primordials; +const { + ArrayPrototypeIncludes, + Map, + MapPrototypeGet, + MapPrototypeHas, + MapPrototypeSet, + RegExpPrototypeTest, + SafeMapIterator, + StringPrototypeReplaceAll, + StringPrototypeToLowerCase, +} = primordials; +import { + collectHttpQuotedString, + collectSequenceOfCodepoints, + HTTP_QUOTED_STRING_TOKEN_POINT_RE, + HTTP_TOKEN_CODE_POINT_RE, + HTTP_WHITESPACE, + HTTP_WHITESPACE_PREFIX_RE, + HTTP_WHITESPACE_SUFFIX_RE, +} from "internal:ext/web/00_infra.js"; + +/** + * @typedef MimeType + * @property {string} type + * @property {string} subtype + * @property {Map<string,string>} parameters + */ + +/** + * @param {string} input + * @returns {MimeType | null} + */ +function parseMimeType(input) { + // 1. + input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_PREFIX_RE, ""); + input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_SUFFIX_RE, ""); + + // 2. + let position = 0; + const endOfInput = input.length; + + // 3. + const res1 = collectSequenceOfCodepoints( + input, + position, + (c) => c != "\u002F", + ); + const type = res1.result; + position = res1.position; + + // 4. + if (type === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, type)) { + return null; + } - /** - * @typedef MimeType - * @property {string} type - * @property {string} subtype - * @property {Map<string,string>} parameters - */ + // 5. + if (position >= endOfInput) return null; + + // 6. + position++; + + // 7. + const res2 = collectSequenceOfCodepoints( + input, + position, + (c) => c != "\u003B", + ); + let subtype = res2.result; + position = res2.position; + + // 8. + subtype = StringPrototypeReplaceAll(subtype, HTTP_WHITESPACE_SUFFIX_RE, ""); + + // 9. + if ( + subtype === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, subtype) + ) { + return null; + } - /** - * @param {string} input - * @returns {MimeType | null} - */ - function parseMimeType(input) { - // 1. - input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_PREFIX_RE, ""); - input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_SUFFIX_RE, ""); + // 10. + const mimeType = { + type: StringPrototypeToLowerCase(type), + subtype: StringPrototypeToLowerCase(subtype), + /** @type {Map<string, string>} */ + parameters: new Map(), + }; - // 2. - let position = 0; - const endOfInput = input.length; + // 11. + while (position < endOfInput) { + // 11.1. + position++; - // 3. + // 11.2. const res1 = collectSequenceOfCodepoints( input, position, - (c) => c != "\u002F", + (c) => ArrayPrototypeIncludes(HTTP_WHITESPACE, c), ); - const type = res1.result; position = res1.position; - // 4. - if (type === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, type)) { - return null; - } - - // 5. - if (position >= endOfInput) return null; - - // 6. - position++; - - // 7. + // 11.3. const res2 = collectSequenceOfCodepoints( input, position, - (c) => c != "\u003B", + (c) => c !== "\u003B" && c !== "\u003D", ); - let subtype = res2.result; + let parameterName = res2.result; position = res2.position; - // 8. - subtype = StringPrototypeReplaceAll(subtype, HTTP_WHITESPACE_SUFFIX_RE, ""); + // 11.4. + parameterName = StringPrototypeToLowerCase(parameterName); - // 9. - if ( - subtype === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, subtype) - ) { - return null; + // 11.5. + if (position < endOfInput) { + if (input[position] == "\u003B") continue; + position++; } - // 10. - const mimeType = { - type: StringPrototypeToLowerCase(type), - subtype: StringPrototypeToLowerCase(subtype), - /** @type {Map<string, string>} */ - parameters: new Map(), - }; + // 11.6. + if (position >= endOfInput) break; - // 11. - while (position < endOfInput) { - // 11.1. - position++; + // 11.7. + let parameterValue = null; - // 11.2. - const res1 = collectSequenceOfCodepoints( - input, - position, - (c) => ArrayPrototypeIncludes(HTTP_WHITESPACE, c), - ); - position = res1.position; + // 11.8. + if (input[position] === "\u0022") { + // 11.8.1. + const res = collectHttpQuotedString(input, position, true); + parameterValue = res.result; + position = res.position; - // 11.3. - const res2 = collectSequenceOfCodepoints( + // 11.8.2. + position++; + } else { // 11.9. + // 11.9.1. + const res = collectSequenceOfCodepoints( input, position, - (c) => c !== "\u003B" && c !== "\u003D", + (c) => c !== "\u003B", + ); + parameterValue = res.result; + position = res.position; + + // 11.9.2. + parameterValue = StringPrototypeReplaceAll( + parameterValue, + HTTP_WHITESPACE_SUFFIX_RE, + "", ); - let parameterName = res2.result; - position = res2.position; - - // 11.4. - parameterName = StringPrototypeToLowerCase(parameterName); - - // 11.5. - if (position < endOfInput) { - if (input[position] == "\u003B") continue; - position++; - } - - // 11.6. - if (position >= endOfInput) break; - - // 11.7. - let parameterValue = null; - - // 11.8. - if (input[position] === "\u0022") { - // 11.8.1. - const res = collectHttpQuotedString(input, position, true); - parameterValue = res.result; - position = res.position; - - // 11.8.2. - position++; - } else { // 11.9. - // 11.9.1. - const res = collectSequenceOfCodepoints( - input, - position, - (c) => c !== "\u003B", - ); - parameterValue = res.result; - position = res.position; - - // 11.9.2. - parameterValue = StringPrototypeReplaceAll( - parameterValue, - HTTP_WHITESPACE_SUFFIX_RE, - "", - ); - - // 11.9.3. - if (parameterValue === "") continue; - } - // 11.10. - if ( - parameterName !== "" && - RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, parameterName) && - RegExpPrototypeTest( - HTTP_QUOTED_STRING_TOKEN_POINT_RE, - parameterValue, - ) && - !MapPrototypeHas(mimeType.parameters, parameterName) - ) { - MapPrototypeSet(mimeType.parameters, parameterName, parameterValue); - } + // 11.9.3. + if (parameterValue === "") continue; } - // 12. - return mimeType; - } - - /** - * @param {MimeType} mimeType - * @returns {string} - */ - function essence(mimeType) { - return `${mimeType.type}/${mimeType.subtype}`; + // 11.10. + if ( + parameterName !== "" && + RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, parameterName) && + RegExpPrototypeTest( + HTTP_QUOTED_STRING_TOKEN_POINT_RE, + parameterValue, + ) && + !MapPrototypeHas(mimeType.parameters, parameterName) + ) { + MapPrototypeSet(mimeType.parameters, parameterName, parameterValue); + } } - /** - * @param {MimeType} mimeType - * @returns {string} - */ - function serializeMimeType(mimeType) { - let serialization = essence(mimeType); - for (const param of new SafeMapIterator(mimeType.parameters)) { - serialization += `;${param[0]}=`; - let value = param[1]; - if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, value)) { - value = StringPrototypeReplaceAll(value, "\\", "\\\\"); - value = StringPrototypeReplaceAll(value, '"', '\\"'); - value = `"${value}"`; - } - serialization += value; + // 12. + return mimeType; +} + +/** + * @param {MimeType} mimeType + * @returns {string} + */ +function essence(mimeType) { + return `${mimeType.type}/${mimeType.subtype}`; +} + +/** + * @param {MimeType} mimeType + * @returns {string} + */ +function serializeMimeType(mimeType) { + let serialization = essence(mimeType); + for (const param of new SafeMapIterator(mimeType.parameters)) { + serialization += `;${param[0]}=`; + let value = param[1]; + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, value)) { + value = StringPrototypeReplaceAll(value, "\\", "\\\\"); + value = StringPrototypeReplaceAll(value, '"', '\\"'); + value = `"${value}"`; } - return serialization; + serialization += value; } - - /** - * 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 (let i = 0; i < headerValues.length; ++i) { - const value = headerValues[i]; - const temporaryMimeType = parseMimeType(value); + return serialization; +} + +/** + * 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 (let i = 0; i < headerValues.length; ++i) { + const value = headerValues[i]; + 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 ( - temporaryMimeType === null || - essence(temporaryMimeType) == "*/*" + !MapPrototypeHas(mimeType.parameters, "charset") && + charset !== null ) { - 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); - } + MapPrototypeSet(mimeType.parameters, "charset", charset); } } - return mimeType; } + return mimeType; +} - window.__bootstrap.mimesniff = { - parseMimeType, - essence, - serializeMimeType, - extractMimeType, - }; -})(this); +export { essence, extractMimeType, parseMimeType, serializeMimeType }; |