1import { mustCall } from '../common/index.mjs'; 2import { ok, deepStrictEqual, strictEqual } from 'assert'; 3 4import importer from '../fixtures/es-modules/pkgimports/importer.js'; 5import { requireFixture } from '../fixtures/pkgexports.mjs'; 6 7const { requireImport, importImport } = importer; 8 9[requireImport, importImport].forEach((loadFixture) => { 10 const isRequire = loadFixture === requireImport; 11 12 const internalImports = new Map([ 13 // Base case 14 ['#test', { default: 'test' }], 15 // import / require conditions 16 ['#branch', { default: isRequire ? 'requirebranch' : 'importbranch' }], 17 // Subpath imports 18 ['#subpath/x.js', { default: 'xsubpath' }], 19 // External imports 20 ['#external', { default: 'asdf' }], 21 // External subpath imports 22 ['#external/subpath/asdf.js', { default: 'asdf' }], 23 // Trailing pattern imports 24 ['#subpath/asdf.asdf', { default: 'test' }], 25 ]); 26 27 for (const [validSpecifier, expected] of internalImports) { 28 if (validSpecifier === null) continue; 29 30 loadFixture(validSpecifier) 31 .then(mustCall((actual) => { 32 deepStrictEqual({ ...actual }, expected); 33 })); 34 } 35 36 const invalidImportTargets = new Set([ 37 // External subpath import without trailing slash 38 ['#external/invalidsubpath/x', '#external/invalidsubpath/'], 39 // Target steps below the package base 40 ['#belowbase', '#belowbase'], 41 // Target is a URL 42 ['#url', '#url'], 43 ]); 44 45 for (const [specifier, subpath] of invalidImportTargets) { 46 loadFixture(specifier).catch(mustCall((err) => { 47 strictEqual(err.code, 'ERR_INVALID_PACKAGE_TARGET'); 48 assertStartsWith(err.message, 'Invalid "imports"'); 49 assertIncludes(err.message, subpath); 50 assertNotIncludes(err.message, 'targets must start with'); 51 })); 52 } 53 54 const invalidImportSpecifiers = new Map([ 55 // Backtracking below the package base 56 ['#subpath/sub/../../../belowbase', 'request is not a valid subpath'], 57 // Percent-encoded slash errors 58 ['#external/subpath/x%2Fy', 'must not include encoded "/" or "\\"'], 59 ['#external/subpath/x%5Cy', 'must not include encoded "/" or "\\"'], 60 // Target must have a name 61 ['#', '#'], 62 // Initial slash target must have a leading name 63 ['#/initialslash', '#/initialslash'], 64 // Percent-encoded target paths 65 ['#encodedslash', 'must not include encoded "/" or "\\"'], 66 ['#encodedbackslash', 'must not include encoded "/" or "\\"'], 67 ]); 68 69 for (const [specifier, expected] of invalidImportSpecifiers) { 70 loadFixture(specifier).catch(mustCall((err) => { 71 strictEqual(err.code, 'ERR_INVALID_MODULE_SPECIFIER'); 72 assertStartsWith(err.message, 'Invalid module'); 73 assertIncludes(err.message, expected); 74 })); 75 } 76 77 const undefinedImports = new Set([ 78 // Missing import 79 '#missing', 80 // Explicit null import 81 '#null', 82 // No condition match import 83 '#nullcondition', 84 // Null subpath shadowing 85 '#subpath/nullshadow/x', 86 ]); 87 88 for (const specifier of undefinedImports) { 89 loadFixture(specifier).catch(mustCall((err) => { 90 strictEqual(err.code, 'ERR_PACKAGE_IMPORT_NOT_DEFINED'); 91 assertStartsWith(err.message, 'Package import '); 92 assertIncludes(err.message, specifier); 93 })); 94 } 95 96 // Handle not found for the defined imports target not existing 97 loadFixture('#notfound').catch(mustCall((err) => { 98 strictEqual(err.code, 99 isRequire ? 'MODULE_NOT_FOUND' : 'ERR_MODULE_NOT_FOUND'); 100 })); 101}); 102 103// CJS resolver must still support #package packages in node_modules 104requireFixture('#cjs').then(mustCall((actual) => { 105 strictEqual(actual.default, 'cjs backcompat'); 106})); 107 108function assertStartsWith(actual, expected) { 109 const start = actual.toString().substr(0, expected.length); 110 strictEqual(start, expected); 111} 112 113function assertIncludes(actual, expected) { 114 ok(actual.toString().indexOf(expected) !== -1, 115 `${JSON.stringify(actual)} includes ${JSON.stringify(expected)}`); 116} 117 118function assertNotIncludes(actual, expected) { 119 ok(actual.toString().indexOf(expected) === -1, 120 `${JSON.stringify(actual)} doesn't include ${JSON.stringify(expected)}`); 121} 122