UNPKG

nstdlib-nightly

Version:

Node.js standard library converted to runtime-agnostic ES modules.

114 lines (99 loc) 3.88 kB
// Source: https://github.com/nodejs/node/blob/65eff1eb/lib/internal/modules/esm/assert.js import { validateString } from "nstdlib/lib/internal/validators"; import { codes as __codes__ } from "nstdlib/lib/internal/errors"; const { ERR_IMPORT_ATTRIBUTE_TYPE_INCOMPATIBLE, ERR_IMPORT_ATTRIBUTE_MISSING, ERR_IMPORT_ATTRIBUTE_UNSUPPORTED, } = __codes__; // The HTML spec has an implied default type of `'javascript'`. const kImplicitTypeAttribute = "javascript"; /** * Define a map of module formats to import attributes types (the value of * `type` in `with { type: 'json' }`). * @type {Map<string, string>} */ const formatTypeMap = { __proto__: null, builtin: kImplicitTypeAttribute, commonjs: kImplicitTypeAttribute, json: "json", module: kImplicitTypeAttribute, wasm: kImplicitTypeAttribute, // It's unclear whether the HTML spec will require an type attribute or not for Wasm; see https://github.com/WebAssembly/esm-integration/issues/42 }; /** * The HTML spec disallows the default type to be explicitly specified * (for now); so `import './file.js'` is okay but * `import './file.js' with { type: 'javascript' }` throws. * @type {Array<string, string>} */ const supportedTypeAttributes = Array.prototype.filter.call( Object.values(formatTypeMap), (type) => type !== kImplicitTypeAttribute, ); /** * Test a module's import attributes. * @param {string} url The URL of the imported module, for error reporting. * @param {string} format One of Node's supported translators * @param {Record<string, string>} importAttributes Validations for the * module import. * @returns {true} * @throws {TypeError} If the format and type attribute are incompatible. */ function validateAttributes( url, format, importAttributes = { __proto__: null }, ) { const keys = Object.keys(importAttributes); for (let i = 0; i < keys.length; i++) { if (keys[i] !== "type") { throw new ERR_IMPORT_ATTRIBUTE_UNSUPPORTED( keys[i], importAttributes[keys[i]], ); } } const validType = formatTypeMap[format]; switch (validType) { case undefined: // Ignore attributes for module formats we don't recognize, to allow new // formats in the future. return true; case kImplicitTypeAttribute: // This format doesn't allow an import type attribute, so the property // must not be set on the import attributes object. if (!Object.prototype.hasOwnProperty.call(importAttributes, "type")) { return true; } return handleInvalidType(url, importAttributes.type); case importAttributes.type: // The type attribute is the valid type for this format. return true; default: // There is an expected type for this format, but the value of // `importAttributes.type` might not have been it. if (!Object.prototype.hasOwnProperty.call(importAttributes, "type")) { // `type` wasn't specified at all. throw new ERR_IMPORT_ATTRIBUTE_MISSING(url, "type", validType); } return handleInvalidType(url, importAttributes.type); } } /** * Throw the correct error depending on what's wrong with the type attribute. * @param {string} url The resolved URL for the module to be imported * @param {string} type The value of the import attributes' `type` property */ function handleInvalidType(url, type) { // `type` might have not been a string. validateString(type, "type"); // `type` might not have been one of the types we understand. if (!Array.prototype.includes.call(supportedTypeAttributes, type)) { throw new ERR_IMPORT_ATTRIBUTE_UNSUPPORTED("type", type); } // `type` was the wrong value for this format. throw new ERR_IMPORT_ATTRIBUTE_TYPE_INCOMPATIBLE(url, type); } export { kImplicitTypeAttribute }; export { validateAttributes };