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: https://github.com/nodejs/node/issues/17277
PR-URL: https://github.com/nodejs/node/pull/17281
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
Ben Noordhuis 2017-11-24 01:50:28 +01:00
parent 6c47033024
commit 597b3d1941
10 changed files with 40 additions and 7 deletions

View File

@ -3,6 +3,7 @@ lib/internal/v8_prof_polyfill.js
lib/punycode.js
test/addons/??_*
test/fixtures
test/message/esm_display_syntax_error.mjs
tools/eslint
tools/icu
tools/remark-*

View File

@ -23,6 +23,7 @@
const NativeModule = require('native_module');
const util = require('util');
const { decorateErrorStack } = require('internal/util');
const internalModule = require('internal/module');
const { getURLFromFilePath } = require('internal/url');
const vm = require('vm');
@ -474,6 +475,7 @@ Module._load = function(request, parent, isMain) {
await ESMLoader.import(getURLFromFilePath(request).pathname);
})()
.catch((e) => {
decorateErrorStack(e);
console.error(e);
process.exit(1);
});

View File

@ -103,9 +103,17 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
False(isolate), // is opaque (?)
False(isolate), // is WASM
True(isolate)); // is ES6 module
TryCatch try_catch(isolate);
ScriptCompiler::Source source(source_text, origin);
if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module))
if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) {
CHECK(try_catch.HasCaught());
CHECK(!try_catch.Message().IsEmpty());
CHECK(!try_catch.Exception().IsEmpty());
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
ErrorHandlingMode::MODULE_ERROR);
try_catch.ReThrow();
return;
}
}
Local<Object> that = args.This();

View File

@ -269,7 +269,7 @@ constexpr size_t arraysize(const T(&)[N]) { return N; }
bool IsExceptionDecorated(Environment* env, v8::Local<v8::Value> er);
enum ErrorHandlingMode { FATAL_ERROR, CONTEXTIFY_ERROR };
enum ErrorHandlingMode { CONTEXTIFY_ERROR, FATAL_ERROR, MODULE_ERROR };
void AppendExceptionLine(Environment* env,
v8::Local<v8::Value> er,
v8::Local<v8::Message> message,

View File

@ -0,0 +1,2 @@
'use strict';
await async () => 0;

View File

@ -0,0 +1,3 @@
// Flags: --experimental-modules
'use strict';
await async () => 0;

View File

@ -0,0 +1,7 @@
(node:*) ExperimentalWarning: The ESM module loader is experimental.
file:///*/test/message/esm_display_syntax_error.mjs:3
await async () => 0;
^^^^^
SyntaxError: Unexpected reserved word
at loaders.set (internal/loader/ModuleRequest.js:*:*)
at <anonymous>

View File

@ -0,0 +1,3 @@
// Flags: --experimental-modules
import '../common';
import '../fixtures/es-module-loaders/syntax-error';

View File

@ -0,0 +1,7 @@
(node:*) ExperimentalWarning: The ESM module loader is experimental.
file:///*/test/fixtures/es-module-loaders/syntax-error.mjs:2
await async () => 0;
^^^^^
SyntaxError: Unexpected reserved word
at loaders.set (internal/loader/ModuleRequest.js:*:*)
at <anonymous>

View File

@ -114,18 +114,18 @@ class MessageTestConfiguration(test.TestConfiguration):
def Ls(self, path):
if isdir(path):
return [f[:-3] for f in os.listdir(path) if f.endswith('.js')]
return [f for f in os.listdir(path)
if f.endswith('.js') or f.endswith('.mjs')]
else:
return []
return []
def ListTests(self, current_path, path, arch, mode):
all_tests = [current_path + [t] for t in self.Ls(self.root)]
result = []
for test in all_tests:
if self.Contains(path, test):
file_prefix = join(self.root, reduce(join, test[1:], ""))
file_path = file_prefix + ".js"
output_path = file_prefix + ".out"
file_path = join(self.root, reduce(join, test[1:], ''))
output_path = file_path[:file_path.rfind('.')] + '.out'
if not exists(output_path):
raise Exception("Could not find %s" % output_path)
result.append(MessageTestCase(test, file_path, output_path,