• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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