• 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    // Leading slash
26    ['#subpath//asdf.asdf', { default: 'test' }],
27    // Double slash
28    ['#subpath/as//df.asdf', { default: 'test' }],
29  ]);
30
31  for (const [validSpecifier, expected] of internalImports) {
32    if (validSpecifier === null) continue;
33
34    loadFixture(validSpecifier)
35      .then(mustCall((actual) => {
36        deepStrictEqual({ ...actual }, expected);
37      }));
38  }
39
40  const invalidImportTargets = new Set([
41    // Target steps below the package base
42    ['#belowbase', '#belowbase'],
43    // Target is a URL
44    ['#url', '#url'],
45  ]);
46
47  for (const [specifier, subpath] of invalidImportTargets) {
48    loadFixture(specifier).catch(mustCall((err) => {
49      strictEqual(err.code, 'ERR_INVALID_PACKAGE_TARGET');
50      assertStartsWith(err.message, 'Invalid "imports"');
51      assertIncludes(err.message, subpath);
52      assertNotIncludes(err.message, 'targets must start with');
53    }));
54  }
55
56  const invalidImportSpecifiers = new Map([
57    // Backtracking below the package base
58    ['#subpath/sub/../../../belowbase', 'request is not a valid match in pattern'],
59    // Percent-encoded slash errors
60    ['#external/subpath/x%2Fy', 'must not include encoded "/" or "\\"'],
61    ['#external/subpath/x%5Cy', 'must not include encoded "/" or "\\"'],
62    // Target must have a name
63    ['#', '#'],
64    // Initial slash target must have a leading name
65    ['#/initialslash', '#/initialslash'],
66    // Percent-encoded target paths
67    ['#encodedslash', 'must not include encoded "/" or "\\"'],
68    ['#encodedbackslash', 'must not include encoded "/" or "\\"'],
69  ]);
70
71  for (const [specifier, expected] of invalidImportSpecifiers) {
72    loadFixture(specifier).catch(mustCall((err) => {
73      strictEqual(err.code, 'ERR_INVALID_MODULE_SPECIFIER');
74      assertStartsWith(err.message, 'Invalid module');
75      assertIncludes(err.message, expected);
76    }));
77  }
78
79  const undefinedImports = new Set([
80    // EOL subpaths
81    '#external/invalidsubpath/x',
82    // Missing import
83    '#missing',
84    // Explicit null import
85    '#null',
86    '#subpath/null',
87    // No condition match import
88    '#nullcondition',
89    // Null subpath shadowing
90    '#subpath/nullshadow/x',
91    // Null pattern
92    '#subpath/internal/test',
93    '#subpath/internal//test',
94  ]);
95
96  for (const specifier of undefinedImports) {
97    loadFixture(specifier).catch(mustCall((err) => {
98      strictEqual(err.code, 'ERR_PACKAGE_IMPORT_NOT_DEFINED');
99      assertStartsWith(err.message, 'Package import ');
100      assertIncludes(err.message, specifier);
101    }));
102  }
103
104  // Handle not found for the defined imports target not existing
105  const nonDefinedImports = new Set([
106    '#notfound',
107    '#subpath//null',
108    '#subpath/////null',
109    '#subpath//internal/test',
110    '#subpath//internal//test',
111    '#subpath/////internal/////test',
112  ]);
113  for (const specifier of nonDefinedImports) {
114    loadFixture(specifier).catch(mustCall((err) => {
115      strictEqual(err.code,
116                  isRequire ? 'MODULE_NOT_FOUND' : 'ERR_MODULE_NOT_FOUND');
117    }));
118  }
119});
120
121// CJS resolver must still support #package packages in node_modules
122requireFixture('#cjs').then(mustCall((actual) => {
123  strictEqual(actual.default, 'cjs backcompat');
124}));
125
126function assertStartsWith(actual, expected) {
127  const start = actual.toString().substr(0, expected.length);
128  strictEqual(start, expected);
129}
130
131function assertIncludes(actual, expected) {
132  ok(actual.toString().indexOf(expected) !== -1,
133     `${JSON.stringify(actual)} includes ${JSON.stringify(expected)}`);
134}
135
136function assertNotIncludes(actual, expected) {
137  ok(actual.toString().indexOf(expected) === -1,
138     `${JSON.stringify(actual)} doesn't include ${JSON.stringify(expected)}`);
139}
140