Skip to content
This repository was archived by the owner on Apr 16, 2020. It is now read-only.

Commit 9ef172b

Browse files
guybedfordnodejs-ci
authored andcommitted
esm: unify type mismatch errors
1 parent 1de1db7 commit 9ef172b

File tree

5 files changed

+46
-37
lines changed

5 files changed

+46
-37
lines changed

doc/api/esm.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,22 +254,25 @@ PACKAGE_MAIN_RESOLVE(_packageURL_, _pjson_)
254254
> 1. Assert: _url_ corresponds to an existing file.
255255
> 1. If _isMain_ is **true** and the `--type` flag is _"module"_, then
256256
> 1. If _url_ ends with _".cjs"_, then
257-
> 1. Throw a _Format Mismatch_ error.
257+
> 1. Throw a _Type Mismatch_ error.
258258
> 1. Return _"module"_.
259259
> 1. Let _pjson_ be the result of **READ_PACKAGE_BOUNDARY**(_url_).
260260
> 1. If _pjson_ is **null** and _isMain_ is **true**, then
261+
> 1. If _url_ ends in _".mjs"_, then
262+
> 1. Return _"module"_.
261263
> 1. Return _"commonjs"_.
262264
> 1. If _pjson.type_ exists and is _"module"_, then
263265
> 1. If _url_ ends in _".cjs"_, then
264-
> 1. Throw a _Format Mismatch_ error.
266+
> 1. Throw a _Type Mismatch_ error.
265267
> 1. If _url_ does not end in _".js"_ or _".mjs"_, then
266268
> 1. Throw an _Unsupported File Extension_ error.
267269
> 1. Return _"module"_.
268270
> 1. Otherwise,
269271
> 1. If _url_ ends in _".mjs"_, then
270272
> 1. Return _"module"_.
271-
> 1. Otherwise,
272-
> 1. Return _"commonjs"_.
273+
> 1. If _url_ does not end in _".js"_, then
274+
> 1. Throw an _Unsupported File Extension_ error.
275+
> 1. Return _"commonjs"_.
273276
274277
READ_PACKAGE_BOUNDARY(_url_)
275278
> 1. Let _boundaryURL_ be _url_.

lib/internal/errors.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -956,15 +956,21 @@ E('ERR_TRANSFORM_ALREADY_TRANSFORMING',
956956
E('ERR_TRANSFORM_WITH_LENGTH_0',
957957
'Calling transform done when writableState.length != 0', Error);
958958
E('ERR_TTY_INIT_FAILED', 'TTY initialization failed', SystemError);
959-
E('ERR_TYPE_MISMATCH', (flagValue, extension, scopeType) => {
960-
if (flagValue === 'module')
961-
flagValue = 'module or -m';
962-
if (extension) // Mismatch between --type and file extension
963-
return `${extension} is not supported for --type=${flagValue}`;
964-
else // Mismatch between --type and package.json "type" field
965-
return `Cannot use --type=${flagValue} because nearest parent ` +
966-
`package.json includes "type": "${scopeType}"${(scopeType === 'commonjs') ?
967-
' (or lacks the "type" field)' : ''}`;
959+
E('ERR_TYPE_MISMATCH', (filename, moduleType, scopeConflict, extConflict) => {
960+
const typeValue = moduleType ? 'module' : 'commonjs';
961+
// --type mismatches file extension
962+
if (!scopeConflict && extConflict)
963+
return `--type=${typeValue + (typeValue === 'module' ? ' / -m' : '')}` +
964+
` flag conflicts with the file extension loading ${filename}`;
965+
// --type mismatches package.json "type"
966+
else if (scopeConflict && !extConflict)
967+
return `--type=${typeValue + (typeValue === 'module' ? ' / ` -m' : '')}` +
968+
' flag conflicts with the package.json "type": "' +
969+
(moduleType ? 'commonjs' : 'module') + `" loading ${filename}`;
970+
// package.json "type" mismatches file extension
971+
else if (extConflict && scopeConflict)
972+
return `"type": "${typeValue}" in package.json conflicts with the file ` +
973+
`extension loading ${filename}`;
968974
}, TypeError);
969975
E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET',
970976
'`process.setupUncaughtExceptionCapture()` was called while a capture ' +

lib/internal/modules/cjs/loader.js

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ const { compileFunction } = internalBinding('contextify');
5151

5252
const {
5353
ERR_INVALID_ARG_VALUE,
54-
ERR_REQUIRE_ESM,
55-
ERR_TYPE_MISMATCH
54+
ERR_REQUIRE_ESM
5655
} = require('internal/errors').codes;
5756
const { validateString } = require('internal/validators');
5857

@@ -861,28 +860,9 @@ Module.runMain = function() {
861860
// Load the main module--the command line argument.
862861
if (experimentalModules) {
863862
if (asyncESM === undefined) lazyLoadESM();
864-
865-
// Check for mismatch between --type and file extension,
866-
// and between --type and package.json.
867-
const ext = path.extname(process.argv[1]);
868-
const fileURL = pathToFileURL(process.argv[1]);
869-
const resolve = require('internal/modules/esm/default_resolve');
870-
const { format } = resolve(fileURL.toString());
871-
const isModule = format === 'module';
872-
if ((isModule && asyncESM.typeFlag === 'commonjs') ||
873-
(!isModule && asyncESM.typeFlag === 'module')) {
874-
if (ext === '.js') {
875-
// Conflict between package scope type and --type
876-
throw new ERR_TYPE_MISMATCH(asyncESM.typeFlag, undefined, format);
877-
} else {
878-
// Conflict between explicit extension (.mjs, .cjs) and --type
879-
throw new ERR_TYPE_MISMATCH(asyncESM.typeFlag, ext, undefined);
880-
}
881-
}
882-
883863
if (asyncESM.typeFlag !== 'commonjs') {
884864
asyncESM.loaderPromise.then((loader) => {
885-
return loader.import(fileURL.pathname);
865+
return loader.import(pathToFileURL(process.argv[1]).pathname);
886866
})
887867
.catch((e) => {
888868
internalBinding('util').triggerFatalException(e);

lib/internal/modules/esm/default_resolve.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ const { getOptionValue } = require('internal/options');
88
const preserveSymlinks = getOptionValue('--preserve-symlinks');
99
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
1010
const { ERR_INVALID_PACKAGE_CONFIG,
11+
ERR_TYPE_MISMATCH,
1112
ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
1213
const { resolve: moduleWrapResolve } = internalBinding('module_wrap');
1314
const { pathToFileURL, fileURLToPath, URL } = require('internal/url');
15+
const asyncESM = require('internal/process/esm_loader');
1416

1517
const realpathCache = new Map();
1618
// TOOD(@guybedford): Shared cache with C++
@@ -68,9 +70,14 @@ function getPackageBoundaryConfig(url, parentURL) {
6870

6971
function getModuleFormat(url, isMain, parentURL) {
7072
const pcfg = getPackageBoundaryConfig(url, parentURL);
73+
7174
const legacy = !pcfg || pcfg.type !== 'module';
7275

7376
const ext = extname(url.pathname);
77+
78+
if (!legacy && ext === '.cjs')
79+
throw new ERR_TYPE_MISMATCH(true, true, fileURLToPath(url));
80+
7481
let format = (legacy ? legacyExtensionFormatMap : extensionFormatMap)[ext];
7582

7683
if (!format) {
@@ -80,6 +87,19 @@ function getModuleFormat(url, isMain, parentURL) {
8087
throw new ERR_UNKNOWN_FILE_EXTENSION(fileURLToPath(url),
8188
fileURLToPath(parentURL));
8289
}
90+
91+
// Check for mismatch between --type and file extension,
92+
// and between --type and package.json.
93+
if (isMain && format !== 'module' && asyncESM.typeFlag === 'module') {
94+
// Conflict between package scope type and --type
95+
if (ext === '.js') {
96+
throw new ERR_TYPE_MISMATCH(fileURLToPath(url), true, true, false);
97+
// Conflict between explicit extension (.mjs, .cjs) and --type
98+
} else {
99+
throw new ERR_TYPE_MISMATCH(fileURLToPath(url), true, false, true);
100+
}
101+
}
102+
83103
return format;
84104
}
85105

test/es-module/test-esm-type-flag-errors.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ expect('', packageTypeCommonJsMain, 'package-type-commonjs');
2020
expect('', packageWithoutTypeMain, 'package-without-type');
2121

2222
// Check that running with conflicting --type flags throws errors
23-
expect('--type=commonjs', mjsFile, 'ERR_TYPE_MISMATCH', true);
23+
expect('--type=commonjs', mjsFile, 'ERR_REQUIRE_ESM', true);
2424
expect('--type=module', cjsFile, 'ERR_TYPE_MISMATCH', true);
2525
expect('-m', cjsFile, 'ERR_TYPE_MISMATCH', true);
2626
expect('--type=commonjs', packageTypeModuleMain,
27-
'ERR_TYPE_MISMATCH', true);
27+
'SyntaxError', true);
2828
expect('--type=module', packageTypeCommonJsMain,
2929
'ERR_TYPE_MISMATCH', true);
3030
expect('-m', packageTypeCommonJsMain,

0 commit comments

Comments
 (0)