Skip to content

Commit d1f4e62

Browse files
committed
Include the filename in the error when an ES module has syntax errors
* Fixes #168
1 parent 555e69a commit d1f4e62

File tree

7 files changed

+54
-2
lines changed

7 files changed

+54
-2
lines changed

lib/loader.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@ function Loader(options) {
88

99
Loader.prototype.load = function(path) {
1010
if (path.endsWith('.mjs')) {
11-
return this.import_(path);
11+
return this.import_(path).catch(function(e) {
12+
if (e.message.indexOf(path) !== -1 || e.stack.indexOf(path) !== -1) {
13+
return Promise.reject(e);
14+
} else {
15+
// When an ES module has a syntax error, the resulting exception does not
16+
// include the filename. Add it. We lose the stack trace in the process,
17+
// but the stack trace is usually not useful since it contains only frames
18+
// from the Node module loader.
19+
const updatedError = new Error(`While loading ${path}: ${e.constructor.name}: ${e.message}`);
20+
return Promise.reject(updatedError);
21+
}
22+
});
1223
} else {
1324
return new Promise(resolve => {
1425
this.require_(path);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"spec_dir": ".",
3+
"spec_files": [
4+
"throws_on_load.mjs"
5+
],
6+
"helpers": []
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
throw new Error("nope");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"spec_dir": ".",
3+
"spec_files": [
4+
"syntax_error.mjs"
5+
],
6+
"helpers": []
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
function(

spec/integration_spec.js

+14
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,26 @@ describe('Integration', function () {
2727
expect(output).toMatch(/at .*throws_on_load.js/);
2828
});
2929

30+
it('handles load-time exceptions from ESM specs properly', async function () {
31+
const {exitCode, output} = await runJasmine('spec/fixtures/esm-load-exception');
32+
expect(exitCode).toEqual(1);
33+
expect(output).toContain('Error: nope');
34+
expect(output).toMatch(/at .*throws_on_load.mjs/);
35+
});
36+
3037
it('handles syntax errors in CommonJS specs properly', async function () {
3138
const {exitCode, output} = await runJasmine('spec/fixtures/cjs-syntax-error');
3239
expect(exitCode).toEqual(1);
3340
expect(output).toContain('SyntaxError');
3441
expect(output).toContain('syntax_error.js');
3542
});
43+
44+
it('handles syntax errors in ESM specs properly', async function () {
45+
const {exitCode, output} = await runJasmine('spec/fixtures/esm-syntax-error');
46+
expect(exitCode).toEqual(1);
47+
expect(output).toContain('SyntaxError');
48+
expect(output).toContain('syntax_error.mjs');
49+
});
3650
});
3751

3852
async function runJasmine(cwd) {

spec/loader_spec.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,20 @@ describe('loader', function() {
2828
await expectAsync(loaderPromise).toBeResolved();
2929
});
3030

31-
it('propagates the error when import fails', async function () {
31+
it("adds the filename to errors that don't include it", async function() {
32+
const underlyingError = new SyntaxError('some details but no filename, not even in the stack trace');
33+
const importShim = () => Promise.reject(underlyingError);
34+
const loader = new Loader({importShim});
35+
36+
await expectAsync(loader.load('foo.mjs')).toBeRejectedWithError(
37+
"While loading foo.mjs: SyntaxError: some details but no filename, not even in the stack trace"
38+
);
39+
});
40+
41+
it('propagates errors that already contain the filename without modifying them', async function () {
3242
const requireShim = jasmine.createSpy('requireShim');
3343
const underlyingError = new Error('nope');
44+
underlyingError.stack = underlyingError.stack.replace('loader_spec.js', 'foo.mjs');
3445
const importShim = jasmine.createSpy('importShim')
3546
.and.callFake(() => Promise.reject(underlyingError));
3647
const loader = new Loader({requireShim, importShim});

0 commit comments

Comments
 (0)