Skip to content

Commit b719b77

Browse files
bnoordhuisMylesBorins
authored andcommitted
module: print better message on esm syntax error
Include the offending line in the output and underline the bad token. Before this commit, it printed "SyntaxError: Unexpected reserved word" without indicating where the syntax error is. Now it prints the line and underlines the offending token, like it does for syntax errors in CJS scripts. Minor changes are made to the test runner in order to support `*.mjs` files in test/message. Fixes: #17277 PR-URL: #17281 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Evan Lucas <[email protected]> Reviewed-By: Michaël Zasso <[email protected]>
1 parent 742a456 commit b719b77

10 files changed

+40
-7
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ lib/internal/v8_prof_polyfill.js
22
lib/punycode.js
33
test/addons/??_*
44
test/fixtures
5+
test/message/esm_display_syntax_error.mjs
56
tools/eslint
67
tools/icu
78
tools/remark-*

lib/module.js

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
const NativeModule = require('native_module');
2525
const util = require('util');
26+
const { decorateErrorStack } = require('internal/util');
2627
const internalModule = require('internal/module');
2728
const { getURLFromFilePath } = require('internal/url');
2829
const vm = require('vm');
@@ -471,6 +472,7 @@ Module._load = function(request, parent, isMain) {
471472
await ESMLoader.import(getURLFromFilePath(request).pathname);
472473
})()
473474
.catch((e) => {
475+
decorateErrorStack(e);
474476
console.error(e);
475477
process.exit(1);
476478
});

src/module_wrap.cc

+9-1
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,17 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
103103
False(isolate), // is opaque (?)
104104
False(isolate), // is WASM
105105
True(isolate)); // is ES6 module
106+
TryCatch try_catch(isolate);
106107
ScriptCompiler::Source source(source_text, origin);
107-
if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module))
108+
if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) {
109+
CHECK(try_catch.HasCaught());
110+
CHECK(!try_catch.Message().IsEmpty());
111+
CHECK(!try_catch.Exception().IsEmpty());
112+
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
113+
ErrorHandlingMode::MODULE_ERROR);
114+
try_catch.ReThrow();
108115
return;
116+
}
109117
}
110118

111119
Local<Object> that = args.This();

src/node_internals.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ constexpr size_t arraysize(const T(&)[N]) { return N; }
262262

263263
bool IsExceptionDecorated(Environment* env, v8::Local<v8::Value> er);
264264

265-
enum ErrorHandlingMode { FATAL_ERROR, CONTEXTIFY_ERROR };
265+
enum ErrorHandlingMode { CONTEXTIFY_ERROR, FATAL_ERROR, MODULE_ERROR };
266266
void AppendExceptionLine(Environment* env,
267267
v8::Local<v8::Value> er,
268268
v8::Local<v8::Message> message,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
'use strict';
2+
await async () => 0;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Flags: --experimental-modules
2+
'use strict';
3+
await async () => 0;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(node:*) ExperimentalWarning: The ESM module loader is experimental.
2+
file:///*/test/message/esm_display_syntax_error.mjs:3
3+
await async () => 0;
4+
^^^^^
5+
SyntaxError: Unexpected reserved word
6+
at loaders.set (internal/loader/ModuleRequest.js:*:*)
7+
at <anonymous>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Flags: --experimental-modules
2+
import '../common';
3+
import '../fixtures/es-module-loaders/syntax-error';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(node:*) ExperimentalWarning: The ESM module loader is experimental.
2+
file:///*/test/fixtures/es-module-loaders/syntax-error.mjs:2
3+
await async () => 0;
4+
^^^^^
5+
SyntaxError: Unexpected reserved word
6+
at loaders.set (internal/loader/ModuleRequest.js:*:*)
7+
at <anonymous>

test/message/testcfg.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,18 @@ def __init__(self, context, root):
114114

115115
def Ls(self, path):
116116
if isdir(path):
117-
return [f[:-3] for f in os.listdir(path) if f.endswith('.js')]
117+
return [f for f in os.listdir(path)
118+
if f.endswith('.js') or f.endswith('.mjs')]
118119
else:
119-
return []
120+
return []
120121

121122
def ListTests(self, current_path, path, arch, mode):
122123
all_tests = [current_path + [t] for t in self.Ls(self.root)]
123124
result = []
124125
for test in all_tests:
125126
if self.Contains(path, test):
126-
file_prefix = join(self.root, reduce(join, test[1:], ""))
127-
file_path = file_prefix + ".js"
128-
output_path = file_prefix + ".out"
127+
file_path = join(self.root, reduce(join, test[1:], ''))
128+
output_path = file_path[:file_path.rfind('.')] + '.out'
129129
if not exists(output_path):
130130
raise Exception("Could not find %s" % output_path)
131131
result.append(MessageTestCase(test, file_path, output_path,

0 commit comments

Comments
 (0)