All files / lib/internal/modules/esm assert.js

100% Statements 110/110
100% Branches 14/14
100% Functions 2/2
100% Lines 110/110

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 139x 1061x 1061x 1061x 1061x 1061x 1061x 13x 13x 13x 1061x 1061x 1019x 1019x 1019x 1009x 1009x 10x 1061x 1061x 21x 21x 1061x 1061x 8x 8x 8x 6x 6x 6x 6x 1061x 1061x 139x 139x 139x 139x 139x 139x 12x 12x 12x 12x 12x 12x 6x 6x 5x 5x 5x 12x 139x 139x 139x 139x 139x 139x  
'use strict';
 
const {
  ArrayPrototypeFilter,
  ArrayPrototypeIncludes,
  ObjectCreate,
  ObjectValues,
  ObjectPrototypeHasOwnProperty,
} = primordials;
const { validateString } = require('internal/validators');
 
const {
  ERR_IMPORT_ASSERTION_TYPE_FAILED,
  ERR_IMPORT_ASSERTION_TYPE_MISSING,
  ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED,
} = require('internal/errors').codes;
 
// The HTML spec has an implied default type of `'javascript'`.
const kImplicitAssertType = 'javascript';
 
/**
 * Define a map of module formats to import assertion types (the value of
 * `type` in `assert { type: 'json' }`).
 * @type {Map<string, string>}
 */
const formatTypeMap = {
  '__proto__': null,
  'builtin': kImplicitAssertType,
  'commonjs': kImplicitAssertType,
  'json': 'json',
  'module': kImplicitAssertType,
  'wasm': kImplicitAssertType, // It's unclear whether the HTML spec will require an assertion type 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' assert { type: 'javascript' }` throws.
 * @type {Array<string, string>}
 */
const supportedAssertionTypes = ArrayPrototypeFilter(
  ObjectValues(formatTypeMap),
  (type) => type !== kImplicitAssertType);
 
 
/**
 * Test a module's import assertions.
 * @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>} importAssertions Validations for the
 *                                                  module import.
 * @returns {true}
 * @throws {TypeError} If the format and assertion type are incompatible.
 */
function validateAssertions(url, format,
                            importAssertions = ObjectCreate(null)) {
  const validType = formatTypeMap[format];
 
  switch (validType) {
    case undefined:
      // Ignore assertions for module formats we don't recognize, to allow new
      // formats in the future.
      return true;
 
    case kImplicitAssertType:
      // This format doesn't allow an import assertion type, so the property
      // must not be set on the import assertions object.
      if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) {
        return true;
      }
      return handleInvalidType(url, importAssertions.type);
 
    case importAssertions.type:
      // The asserted type is the valid type for this format.
      return true;
 
    default:
      // There is an expected type for this format, but the value of
      // `importAssertions.type` might not have been it.
      if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) {
        // `type` wasn't specified at all.
        throw new ERR_IMPORT_ASSERTION_TYPE_MISSING(url, validType);
      }
      handleInvalidType(url, importAssertions.type);
  }
}
 
/**
 * Throw the correct error depending on what's wrong with the type assertion.
 * @param {string} url The resolved URL for the module to be imported
 * @param {string} type The value of the import assertion `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 (!ArrayPrototypeIncludes(supportedAssertionTypes, type)) {
    throw new ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED(type);
  }
 
  // `type` was the wrong value for this format.
  throw new ERR_IMPORT_ASSERTION_TYPE_FAILED(url, type);
}
 
 
module.exports = {
  kImplicitAssertType,
  validateAssertions,
};