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

Commit 4d841b3

Browse files
committed
esm: --type=auto should throw syntax errors directly
1 parent a227deb commit 4d841b3

File tree

9 files changed

+31
-9
lines changed

9 files changed

+31
-9
lines changed

lib/internal/errors.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,8 @@ E('ERR_INVALID_SYNC_FORK_INPUT',
816816
E('ERR_INVALID_THIS', 'Value of "this" must be of type %s', TypeError);
817817
E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple', TypeError);
818818
E('ERR_INVALID_TYPE_FLAG',
819-
'Type flag must be one of "auto", "commonjs", or "module". Received --type=%s',
819+
'Type flag must be one of "auto", "commonjs", or "module". ' +
820+
'Received --type=%s',
820821
TypeError);
821822
E('ERR_INVALID_URI', 'URI malformed', URIError);
822823
E('ERR_INVALID_URL', 'Invalid URL: %s', TypeError);

lib/internal/main/check_syntax.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ function checkSyntax(source, filename) {
5858
if (filename === '[stdin]' || filename === '[eval]') {
5959
const { typeFlag } = require('internal/process/esm_loader');
6060
isModule = typeFlag === 'module' || (typeFlag === 'auto' &&
61-
require('internal/modules/esm/detect_type')(source) === 'module');
61+
require('internal/modules/esm/detect_type')(source, filename) ===
62+
'module');
6263
} else {
6364
const resolve = require('internal/modules/esm/default_resolve');
6465
const { format } = resolve(pathToFileURL(filename).toString());

lib/internal/main/eval_stdin.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ readStdin((code) => {
2121
process._eval = code;
2222
if (typeFlag === 'module' ||
2323
(typeFlag === 'auto' &&
24-
require('internal/modules/esm/detect_type')(code) === 'module'))
24+
require('internal/modules/esm/detect_type')(code, '[stdin]') === 'module'))
2525
evalModule(process._eval);
2626
else
2727
evalScript('[stdin]', process._eval, process._breakFirstLine);

lib/internal/main/eval_string.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ addBuiltinLibsToObject(global);
1616
markBootstrapComplete();
1717
if (typeFlag === 'module' ||
1818
(typeFlag === 'auto' &&
19-
require('internal/modules/esm/detect_type')(source) === 'module'))
19+
require('internal/modules/esm/detect_type')(source, '[eval]') === 'module'))
2020
evalModule(source);
2121
else
2222
evalScript('[eval]', source, process._breakFirstLine);

lib/internal/modules/esm/default_resolve.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,9 @@ function getModuleFormat(url, isMain, parentURL) {
102102

103103
// --type=auto detects an ESM .js file within a CommonJS scope.
104104
if (isMain && format === 'commonjs' && asyncESM.typeFlag === 'auto') {
105-
const source = readFileSync(fileURLToPath(url), 'utf8');
106-
format = require('internal/modules/esm/detect_type')(source);
105+
const filename = fileURLToPath(url);
106+
const source = readFileSync(filename, 'utf8');
107+
format = require('internal/modules/esm/detect_type')(source, filename);
107108
}
108109

109110
return format;

lib/internal/modules/esm/detect_type.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
'use strict';
22

33
const acorn = require('internal/deps/acorn/acorn/dist/acorn');
4+
const {
5+
stripShebang, stripBOM
6+
} = require('internal/modules/cjs/helpers');
47

58
// Detect the module type of a file: CommonJS or ES module.
69
// An ES module, for the purposes of this algorithm, is defined as any
@@ -9,7 +12,9 @@ const acorn = require('internal/deps/acorn/acorn/dist/acorn');
912
// full parse; we can detect import or export statements just from the tokens.
1013
// Also as of this writing, Acorn doesn't support import() expressions as they
1114
// are only Stage 3; yet Node already supports them.
12-
function detectType(source) {
15+
function detectType(source, filename) {
16+
source = stripShebang(source);
17+
source = stripBOM(source);
1318
try {
1419
let prevToken, prevPrevToken;
1520
for (const { type: token } of acorn.tokenizer(source)) {
@@ -30,7 +35,10 @@ function detectType(source) {
3035
prevToken = token;
3136
}
3237
} catch {
33-
return 'commonjs';
38+
// If the tokenizer threw, there's a syntax error.
39+
// Compile the script, this will throw with an informative error.
40+
const vm = require('vm');
41+
new vm.Script(source, { displayErrors: true, filename });
3442
}
3543
return 'commonjs';
3644
}

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ expect('cjs-with-string-containing-import.js', version);
1919
expect('print-version.js', version);
2020
expect('ambiguous-with-import-expression.js', version);
2121

22-
function expect(file, want) {
22+
expect('syntax-error-1.js', 'SyntaxError', true);
23+
expect('syntax-error-2.js', 'SyntaxError', true);
24+
25+
function expect(file, want, wantsError = false) {
2326
const argv = [
2427
require.resolve(`../fixtures/es-modules/type-auto-scope/${file}`)
2528
];
@@ -32,6 +35,11 @@ function expect(file, want) {
3235
};
3336
exec(process.execPath, argv, opts,
3437
common.mustCall((err, stdout, stderr) => {
38+
if (wantsError) {
39+
stdout = stderr;
40+
} else {
41+
assert.ifError(err);
42+
}
3543
if (stdout.includes(want)) return;
3644
assert.fail(
3745
`For ${file}, failed to find ${want} in: <\n${stdout}\n>`);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const str = 'import
2+
var foo = 3;

0 commit comments

Comments
 (0)