11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayPrototypeFilter,
51cb0ef41Sopenharmony_ci  ArrayPrototypeIncludes,
61cb0ef41Sopenharmony_ci  ObjectKeys,
71cb0ef41Sopenharmony_ci  ObjectValues,
81cb0ef41Sopenharmony_ci  ObjectPrototypeHasOwnProperty,
91cb0ef41Sopenharmony_ci} = primordials;
101cb0ef41Sopenharmony_ciconst { validateString } = require('internal/validators');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst {
131cb0ef41Sopenharmony_ci  ERR_IMPORT_ASSERTION_TYPE_FAILED,
141cb0ef41Sopenharmony_ci  ERR_IMPORT_ASSERTION_TYPE_MISSING,
151cb0ef41Sopenharmony_ci  ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED,
161cb0ef41Sopenharmony_ci  ERR_IMPORT_ATTRIBUTE_UNSUPPORTED,
171cb0ef41Sopenharmony_ci} = require('internal/errors').codes;
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci// The HTML spec has an implied default type of `'javascript'`.
201cb0ef41Sopenharmony_ciconst kImplicitAssertType = 'javascript';
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci/**
231cb0ef41Sopenharmony_ci * Define a map of module formats to import attributes types (the value of
241cb0ef41Sopenharmony_ci * `type` in `with { type: 'json' }`).
251cb0ef41Sopenharmony_ci * @type {Map<string, string>}
261cb0ef41Sopenharmony_ci */
271cb0ef41Sopenharmony_ciconst formatTypeMap = {
281cb0ef41Sopenharmony_ci  '__proto__': null,
291cb0ef41Sopenharmony_ci  'builtin': kImplicitAssertType,
301cb0ef41Sopenharmony_ci  'commonjs': kImplicitAssertType,
311cb0ef41Sopenharmony_ci  'json': 'json',
321cb0ef41Sopenharmony_ci  'module': kImplicitAssertType,
331cb0ef41Sopenharmony_ci  'wasm': kImplicitAssertType, // It's unclear whether the HTML spec will require an attribute type or not for Wasm; see https://github.com/WebAssembly/esm-integration/issues/42
341cb0ef41Sopenharmony_ci};
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci/**
371cb0ef41Sopenharmony_ci * The HTML spec disallows the default type to be explicitly specified
381cb0ef41Sopenharmony_ci * (for now); so `import './file.js'` is okay but
391cb0ef41Sopenharmony_ci * `import './file.js' with { type: 'javascript' }` throws.
401cb0ef41Sopenharmony_ci * @type {Array<string, string>}
411cb0ef41Sopenharmony_ci */
421cb0ef41Sopenharmony_ciconst supportedAssertionTypes = ArrayPrototypeFilter(
431cb0ef41Sopenharmony_ci  ObjectValues(formatTypeMap),
441cb0ef41Sopenharmony_ci  (type) => type !== kImplicitAssertType);
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci/**
481cb0ef41Sopenharmony_ci * Test a module's import attributes.
491cb0ef41Sopenharmony_ci * @param {string} url The URL of the imported module, for error reporting.
501cb0ef41Sopenharmony_ci * @param {string} format One of Node's supported translators
511cb0ef41Sopenharmony_ci * @param {Record<string, string>} importAttributes Validations for the
521cb0ef41Sopenharmony_ci *                                                  module import.
531cb0ef41Sopenharmony_ci * @returns {true}
541cb0ef41Sopenharmony_ci * @throws {TypeError} If the format and assertion type are incompatible.
551cb0ef41Sopenharmony_ci */
561cb0ef41Sopenharmony_cifunction validateAttributes(url, format,
571cb0ef41Sopenharmony_ci                            importAttributes = { __proto__: null }) {
581cb0ef41Sopenharmony_ci  const keys = ObjectKeys(importAttributes);
591cb0ef41Sopenharmony_ci  for (let i = 0; i < keys.length; i++) {
601cb0ef41Sopenharmony_ci    if (keys[i] !== 'type') {
611cb0ef41Sopenharmony_ci      throw new ERR_IMPORT_ATTRIBUTE_UNSUPPORTED(keys[i], importAttributes[keys[i]]);
621cb0ef41Sopenharmony_ci    }
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci  const validType = formatTypeMap[format];
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  switch (validType) {
671cb0ef41Sopenharmony_ci    case undefined:
681cb0ef41Sopenharmony_ci      // Ignore attributes for module formats we don't recognize, to allow new
691cb0ef41Sopenharmony_ci      // formats in the future.
701cb0ef41Sopenharmony_ci      return true;
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci    case kImplicitAssertType:
731cb0ef41Sopenharmony_ci      // This format doesn't allow an import assertion type, so the property
741cb0ef41Sopenharmony_ci      // must not be set on the import attributes object.
751cb0ef41Sopenharmony_ci      if (!ObjectPrototypeHasOwnProperty(importAttributes, 'type')) {
761cb0ef41Sopenharmony_ci        return true;
771cb0ef41Sopenharmony_ci      }
781cb0ef41Sopenharmony_ci      return handleInvalidType(url, importAttributes.type);
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci    case importAttributes.type:
811cb0ef41Sopenharmony_ci      // The asserted type is the valid type for this format.
821cb0ef41Sopenharmony_ci      return true;
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci    default:
851cb0ef41Sopenharmony_ci      // There is an expected type for this format, but the value of
861cb0ef41Sopenharmony_ci      // `importAttributes.type` might not have been it.
871cb0ef41Sopenharmony_ci      if (!ObjectPrototypeHasOwnProperty(importAttributes, 'type')) {
881cb0ef41Sopenharmony_ci        // `type` wasn't specified at all.
891cb0ef41Sopenharmony_ci        throw new ERR_IMPORT_ASSERTION_TYPE_MISSING(url, validType);
901cb0ef41Sopenharmony_ci      }
911cb0ef41Sopenharmony_ci      return handleInvalidType(url, importAttributes.type);
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci/**
961cb0ef41Sopenharmony_ci * Throw the correct error depending on what's wrong with the type assertion.
971cb0ef41Sopenharmony_ci * @param {string} url The resolved URL for the module to be imported
981cb0ef41Sopenharmony_ci * @param {string} type The value of the import assertion `type` property
991cb0ef41Sopenharmony_ci */
1001cb0ef41Sopenharmony_cifunction handleInvalidType(url, type) {
1011cb0ef41Sopenharmony_ci  // `type` might have not been a string.
1021cb0ef41Sopenharmony_ci  validateString(type, 'type');
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  // `type` might not have been one of the types we understand.
1051cb0ef41Sopenharmony_ci  if (!ArrayPrototypeIncludes(supportedAssertionTypes, type)) {
1061cb0ef41Sopenharmony_ci    throw new ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED(type);
1071cb0ef41Sopenharmony_ci  }
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  // `type` was the wrong value for this format.
1101cb0ef41Sopenharmony_ci  throw new ERR_IMPORT_ASSERTION_TYPE_FAILED(url, type);
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_cimodule.exports = {
1151cb0ef41Sopenharmony_ci  kImplicitAssertType,
1161cb0ef41Sopenharmony_ci  validateAttributes,
1171cb0ef41Sopenharmony_ci};
118