Skip to content

Commit 1b1b6a4

Browse files
committed
module: throw error when re-runing errored module jobs
Re-evaluating an errored ESM should lead to rejecting the rejection again - this is also the case when importing it twice. In the case of retrying with require after import, just throw the cached error. Drive-by: add some debug logs.
1 parent 8173d9d commit 1b1b6a4

File tree

4 files changed

+43
-2
lines changed

4 files changed

+43
-2
lines changed

lib/internal/modules/esm/loader.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const {
4343
kEvaluating,
4444
kEvaluationPhase,
4545
kInstantiated,
46+
kErrored,
4647
kSourcePhase,
4748
throwIfPromiseRejected,
4849
} = internalBinding('module_wrap');
@@ -402,6 +403,9 @@ class ModuleLoader {
402403
mod[kRequiredModuleSymbol] = job.module;
403404
const { namespace } = job.runSync(parent);
404405
return { wrap: job.module, namespace: namespace || job.module.getNamespace() };
406+
} else if (status === kErrored) {
407+
// If the module was previously imported and errored, throw the error.
408+
throw job.module.getError();
405409
}
406410
// When the cached async job have already encountered a linking
407411
// error that gets wrapped into a rejection, but is still later

lib/internal/modules/esm/module_job.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ class ModuleJob extends ModuleJobBase {
325325
assert(this.module instanceof ModuleWrap);
326326
let status = this.module.getStatus();
327327

328-
debug('ModuleJob.runSync', this.module);
328+
debug('ModuleJob.runSync()', status, this.module);
329329
// FIXME(joyeecheung): this cannot fully handle < kInstantiated. Make the linking
330330
// fully synchronous instead.
331331
if (status === kUninstantiated) {
@@ -360,6 +360,7 @@ class ModuleJob extends ModuleJobBase {
360360
}
361361

362362
async run(isEntryPoint = false) {
363+
debug('ModuleJob.run()', this.module);
363364
assert(this.phase === kEvaluationPhase);
364365
await this.#instantiate();
365366
if (isEntryPoint) {
@@ -465,7 +466,9 @@ class ModuleJobSync extends ModuleJobBase {
465466
assert(this.phase === kEvaluationPhase);
466467
// This path is hit by a require'd module that is imported again.
467468
const status = this.module.getStatus();
468-
if (status > kInstantiated) {
469+
if (status === kErrored) {
470+
throw this.module.getError();
471+
} else if (status > kInstantiated) {
469472
if (this.evaluationPromise) {
470473
await this.evaluationPromise;
471474
}
@@ -486,6 +489,7 @@ class ModuleJobSync extends ModuleJobBase {
486489
}
487490

488491
runSync(parent) {
492+
debug('ModuleJobSync.runSync()', this.module);
489493
assert(this.phase === kEvaluationPhase);
490494
// TODO(joyeecheung): add the error decoration logic from the async instantiate.
491495
this.module.async = this.module.instantiateSync();
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// This tests that after failing to import an ESM that rejects,
2+
// retrying with require() still throws.
3+
4+
'use strict';
5+
const common = require('../common');
6+
const assert = require('assert');
7+
8+
(async () => {
9+
await assert.rejects(import('../fixtures/es-modules/throw-error.mjs'), {
10+
message: 'test',
11+
});
12+
assert.throws(() => {
13+
require('../fixtures/es-modules/throw-error.mjs');
14+
}, {
15+
message: 'test',
16+
});
17+
})().catch(common.mustNotCall());
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This tests that after failing to require an ESM that throws,
2+
// retrying with import() still rejects.
3+
4+
'use strict';
5+
const common = require('../common');
6+
const assert = require('assert');
7+
8+
assert.throws(() => {
9+
require('../fixtures/es-modules/throw-error.mjs');
10+
}, {
11+
message: 'test',
12+
});
13+
14+
assert.rejects(import('../fixtures/es-modules/throw-error.mjs'), {
15+
message: 'test',
16+
}).catch(common.mustNotCall());

0 commit comments

Comments
 (0)