Skip to content

Commit 435dc9b

Browse files
committed
review comments, rework tests
1 parent 6f7d871 commit 435dc9b

File tree

3 files changed

+65
-75
lines changed

3 files changed

+65
-75
lines changed

lib/internal/modules/esm/get_format.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const legacyExtensionFormatMap = {
3232
'.node': 'commonjs'
3333
};
3434

35+
let experimentalSpecifierResolutionWarned = false;
36+
3537
if (experimentalWasmModules)
3638
extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm';
3739

@@ -64,9 +66,12 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), {
6466
}
6567
if (!format) {
6668
if (experimentalSpecifierResolution === 'node') {
67-
process.emitWarning(
68-
'The Node.js specifier resolution in ESM is experimental.',
69-
'ExperimentalWarning');
69+
if (!experimentalSpecifierResolutionWarned) {
70+
process.emitWarning(
71+
'The Node.js specifier resolution in ESM is experimental.',
72+
'ExperimentalWarning');
73+
experimentalSpecifierResolutionWarned = true;
74+
}
7075
format = legacyExtensionFormatMap[ext];
7176
} else {
7277
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, fileURLToPath(url));
@@ -90,4 +95,5 @@ module.exports = {
9095
defaultGetFormat,
9196
extensionFormatMap,
9297
legacyExtensionFormatMap,
98+
experimentalSpecifierResolutionWarned
9399
};

lib/internal/modules/esm/resolve.js

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -469,30 +469,34 @@ function resolvePackageTargetString(
469469

470470
const composeResult = (resolved) => {
471471
let format;
472-
try {
473-
const ext = extname(resolved.pathname);
474-
if (ext === '.js') {
472+
473+
const ext = extname(resolved.pathname);
474+
if (ext === '.js') {
475+
try {
475476
format = getPackageType(resolved);
476-
} else {
477-
format = extensionFormatMap[ext];
478-
}
479-
if (!format) {
480-
if (experimentalSpecifierResolution === 'node') {
481-
process.emitWarning(
482-
'The Node.js specifier resolution in ESM is experimental.',
483-
'ExperimentalWarning');
484-
format = legacyExtensionFormatMap[ext];
477+
} catch (err) {
478+
if (err.code === 'ERR_INVALID_FILE_URL_PATH') {
479+
const invalidModuleErr = new ERR_INVALID_MODULE_SPECIFIER(
480+
resolved, 'must not include encoded "/" or "\\" characters', base);
481+
invalidModuleErr.cause = err;
482+
throw invalidModuleErr;
485483
}
484+
throw err;
486485
}
487-
} catch (err) {
488-
if (err.code === 'ERR_INVALID_FILE_URL_PATH') {
489-
const invalidModuleErr = new ERR_INVALID_MODULE_SPECIFIER(
490-
resolved, 'must not include encoded "/" or "\\" characters', base);
491-
invalidModuleErr.cause = err;
492-
throw invalidModuleErr;
486+
} else {
487+
format = extensionFormatMap[ext];
488+
}
489+
490+
if (format == null && experimentalSpecifierResolution === 'node') {
491+
if (!experimentalSpecifierResolutionWarned) {
492+
process.emitWarning(
493+
'The Node.js specifier resolution in ESM is experimental.',
494+
'ExperimentalWarning');
495+
experimentalSpecifierResolutionWarned = true;
493496
}
494-
throw err;
497+
format = legacyExtensionFormatMap[ext];
495498
}
499+
496500
return { resolved, ...(format !== 'none') && { format } };
497501
};
498502

@@ -1123,6 +1127,9 @@ module.exports = {
11231127
};
11241128

11251129
// cycle
1126-
const { defaultGetFormat,
1127-
extensionFormatMap,
1128-
legacyExtensionFormatMap } = require('internal/modules/esm/get_format');
1130+
let {
1131+
defaultGetFormat,
1132+
extensionFormatMap,
1133+
legacyExtensionFormatMap,
1134+
experimentalSpecifierResolutionWarned,
1135+
} = require('internal/modules/esm/get_format');

test/es-module/test-esm-resolve-type.js

Lines changed: 27 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -181,69 +181,49 @@ try {
181181
assert.ok(resolveResult.url.includes('my-dual-package/es/index.js'));
182182
}
183183

184-
function testDualPackageWithMjsMainScriptAndCJSType() {
184+
testDualPackageWithJsMainScriptAndModuleType();
185185

186-
// Additional test for following scenario
187-
/**
188-
* this creates following directory structure:
189-
*
190-
* ./node_modules:
191-
* |-> dual-mjs-pjson
192-
* |-> subdir
193-
* |-> index.mjs [3]
194-
* |-> package.json [2]
195-
* |-> index.js
196-
* |->package.json [1]
197-
*
198-
* [1] - main package.json of the package
199-
* - it contains:
200-
* - type: 'commonjs'
201-
* - main: 'subdir/index.js'
202-
* - conditional exports for 'require' (subdir/index.js) and
203-
* 'import' (subdir/index.mjs)
204-
* [2] - package.json add-on for the import case
205-
* - it only contains:
206-
* - type: 'commonjs'
207-
* [3] - main script for the `import` case
208-
*
209-
* in case the package is consumed as an ESM by importing it:
210-
* import * as my-package from 'dual-mjs-pjson'
211-
* it will cause the resolve method to return:
212-
* {
213-
* url: '<base_path>/node_modules/dual-mjs-pjson/subdir/index.mjs',
214-
* format: 'module'
215-
* }
216-
*
217-
* following testcase ensures that resolve works correctly in this case
218-
* returning the information as specified above. Source for 'url' value
219-
* is [1], source for 'format' value is the file extension of [3]
220-
*/
221-
const moduleName = 'dual-mjs-pjson';
186+
// TestParameters are ModuleName, mainRequireScript, mainImportScript,
187+
// mainPackageType, subdirPkgJsonType, expectedResolvedFormat
188+
[ [ 'mjs-mod-mod', 'index.js', 'index.mjs', 'module', 'module', 'module'],
189+
[ 'mjs-com-com', 'idx.js', 'idx.mjs', 'commonjs', 'commonjs', 'module'],
190+
[ 'mjs-mod-com', 'index.js', 'imp.mjs', 'module', 'commonjs', 'module'],
191+
[ 'js-com-com', 'index.js', 'imp.js', 'commonjs', 'commonjs', 'commonjs'],
192+
[ 'js-com-mod', 'index.js', 'imp.js', 'commonjs', 'module', 'module'],
193+
[ 'ts-mod-com', 'index.js', 'imp.ts', 'module', 'commonjs', undefined],
194+
].forEach((testVariant) => {
195+
const [
196+
moduleName,
197+
mainRequireScript,
198+
mainImportScript,
199+
mainPackageType,
200+
subdirPackageType,
201+
expectedResolvedFormat ] = testVariant;
222202

223203
const mDir = rel(`node_modules/${moduleName}`);
224204
const subDir = rel(`node_modules/${moduleName}/subdir`);
225205
const pkg = rel(`node_modules/${moduleName}/package.json`);
226206
const subdirPkg = rel(`node_modules/${moduleName}/subdir/package.json`);
227-
const esScript = rel(`node_modules/${moduleName}/subdir/index.mjs`);
228-
const cjsScript = rel(`node_modules/${moduleName}/subdir/index.js`);
207+
const esScript = rel(`node_modules/${moduleName}/subdir/${mainImportScript}`);
208+
const cjsScript = rel(`node_modules/${moduleName}/subdir/${mainRequireScript}`);
229209

230210
createDir(nmDir);
231211
createDir(mDir);
232212
createDir(subDir);
233213

234214
const mainPkgJsonContent = {
235-
type: 'commonjs',
236-
main: 'lib/index.js',
215+
type: mainPackageType,
216+
main: `./subdir/${mainRequireScript}`,
237217
exports: {
238218
'.': {
239-
'require': './subdir/index.js',
240-
'import': './subdir/index.mjs'
219+
'require': `./subdir/${mainRequireScript}`,
220+
'import': `./subdir/${mainImportScript}`
241221
},
242222
'./package.json': './package.json',
243223
}
244224
};
245225
const subdirPkgJsonContent = {
246-
type: 'commonjs'
226+
type: `${subdirPackageType}`
247227
};
248228

249229
fs.writeFileSync(pkg, JSON.stringify(mainPkgJsonContent));
@@ -257,12 +237,9 @@ try {
257237

258238
// test the resolve
259239
const resolveResult = resolve(`${moduleName}`);
260-
assert.strictEqual(resolveResult.format, 'module');
261-
assert.ok(resolveResult.url.includes(`${moduleName}/subdir/index.mjs`));
262-
}
263-
264-
testDualPackageWithJsMainScriptAndModuleType();
265-
testDualPackageWithMjsMainScriptAndCJSType();
240+
assert.strictEqual(resolveResult.format, expectedResolvedFormat);
241+
assert.ok(resolveResult.url.includes(`${moduleName}/subdir/${mainImportScript}`));
242+
});
266243

267244
} finally {
268245
process.chdir(previousCwd);

0 commit comments

Comments
 (0)