mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
4a54a80aa3
`String.prototype.substr` is deprecated, and using it will raise an error when using ESLint 9+. Co-authored-by: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <targos@protonmail.com> PR-URL: https://github.com/nodejs/node/pull/53070 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Tierney Cyren <hello@bnb.im> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
140 lines
4.5 KiB
JavaScript
140 lines
4.5 KiB
JavaScript
import { mustCall } from '../common/index.mjs';
|
|
import { ok, deepStrictEqual, strictEqual } from 'assert';
|
|
|
|
import importer from '../fixtures/es-modules/pkgimports/importer.js';
|
|
import { requireFixture } from '../fixtures/pkgexports.mjs';
|
|
|
|
const { requireImport, importImport } = importer;
|
|
|
|
[requireImport, importImport].forEach((loadFixture) => {
|
|
const isRequire = loadFixture === requireImport;
|
|
|
|
const internalImports = new Map([
|
|
// Base case
|
|
['#test', { default: 'test' }],
|
|
// import / require conditions
|
|
['#branch', { default: isRequire ? 'requirebranch' : 'importbranch' }],
|
|
// Subpath imports
|
|
['#subpath/x.js', { default: 'xsubpath' }],
|
|
// External imports
|
|
['#external', { default: 'asdf' }],
|
|
// External subpath imports
|
|
['#external/subpath/asdf.js', { default: 'asdf' }],
|
|
// Trailing pattern imports
|
|
['#subpath/asdf.asdf', { default: 'test' }],
|
|
// Leading slash
|
|
['#subpath//asdf.asdf', { default: 'test' }],
|
|
// Double slash
|
|
['#subpath/as//df.asdf', { default: 'test' }],
|
|
]);
|
|
|
|
for (const [validSpecifier, expected] of internalImports) {
|
|
if (validSpecifier === null) continue;
|
|
|
|
loadFixture(validSpecifier)
|
|
.then(mustCall((actual) => {
|
|
deepStrictEqual({ ...actual }, expected);
|
|
}));
|
|
}
|
|
|
|
const invalidImportTargets = new Set([
|
|
// Target steps below the package base
|
|
['#belowbase', '#belowbase'],
|
|
// Target is a URL
|
|
['#url', '#url'],
|
|
]);
|
|
|
|
for (const [specifier, subpath] of invalidImportTargets) {
|
|
loadFixture(specifier).catch(mustCall((err) => {
|
|
strictEqual(err.code, 'ERR_INVALID_PACKAGE_TARGET');
|
|
assertStartsWith(err.message, 'Invalid "imports"');
|
|
assertIncludes(err.message, subpath);
|
|
assertNotIncludes(err.message, 'targets must start with');
|
|
}));
|
|
}
|
|
|
|
const invalidImportSpecifiers = new Map([
|
|
// Backtracking below the package base
|
|
['#subpath/sub/../../../belowbase', 'request is not a valid match in pattern'],
|
|
// Percent-encoded slash errors
|
|
['#external/subpath/x%2Fy', 'must not include encoded "/" or "\\"'],
|
|
['#external/subpath/x%5Cy', 'must not include encoded "/" or "\\"'],
|
|
// Target must have a name
|
|
['#', '#'],
|
|
// Initial slash target must have a leading name
|
|
['#/initialslash', '#/initialslash'],
|
|
// Percent-encoded target paths
|
|
['#encodedslash', 'must not include encoded "/" or "\\"'],
|
|
['#encodedbackslash', 'must not include encoded "/" or "\\"'],
|
|
]);
|
|
|
|
for (const [specifier, expected] of invalidImportSpecifiers) {
|
|
loadFixture(specifier).catch(mustCall((err) => {
|
|
strictEqual(err.code, 'ERR_INVALID_MODULE_SPECIFIER');
|
|
assertStartsWith(err.message, 'Invalid module');
|
|
assertIncludes(err.message, expected);
|
|
}));
|
|
}
|
|
|
|
const undefinedImports = new Set([
|
|
// EOL subpaths
|
|
'#external/invalidsubpath/x',
|
|
// Missing import
|
|
'#missing',
|
|
// Explicit null import
|
|
'#null',
|
|
'#subpath/null',
|
|
// No condition match import
|
|
'#nullcondition',
|
|
// Null subpath shadowing
|
|
'#subpath/nullshadow/x',
|
|
// Null pattern
|
|
'#subpath/internal/test',
|
|
'#subpath/internal//test',
|
|
]);
|
|
|
|
for (const specifier of undefinedImports) {
|
|
loadFixture(specifier).catch(mustCall((err) => {
|
|
strictEqual(err.code, 'ERR_PACKAGE_IMPORT_NOT_DEFINED');
|
|
assertStartsWith(err.message, 'Package import ');
|
|
assertIncludes(err.message, specifier);
|
|
}));
|
|
}
|
|
|
|
// Handle not found for the defined imports target not existing
|
|
const nonDefinedImports = new Set([
|
|
'#notfound',
|
|
'#subpath//null',
|
|
'#subpath/////null',
|
|
'#subpath//internal/test',
|
|
'#subpath//internal//test',
|
|
'#subpath/////internal/////test',
|
|
]);
|
|
for (const specifier of nonDefinedImports) {
|
|
loadFixture(specifier).catch(mustCall((err) => {
|
|
strictEqual(err.code,
|
|
isRequire ? 'MODULE_NOT_FOUND' : 'ERR_MODULE_NOT_FOUND');
|
|
}));
|
|
}
|
|
});
|
|
|
|
// CJS resolver must still support #package packages in node_modules
|
|
requireFixture('#cjs').then(mustCall((actual) => {
|
|
strictEqual(actual.default, 'cjs backcompat');
|
|
}));
|
|
|
|
function assertStartsWith(actual, expected) {
|
|
const start = actual.toString().slice(0, expected.length);
|
|
strictEqual(start, expected);
|
|
}
|
|
|
|
function assertIncludes(actual, expected) {
|
|
ok(actual.toString().indexOf(expected) !== -1,
|
|
`${JSON.stringify(actual)} includes ${JSON.stringify(expected)}`);
|
|
}
|
|
|
|
function assertNotIncludes(actual, expected) {
|
|
ok(actual.toString().indexOf(expected) === -1,
|
|
`${JSON.stringify(actual)} doesn't include ${JSON.stringify(expected)}`);
|
|
}
|