Skip to content

Commit a5dcc58

Browse files
joyeecheungmarco-ippolito
authored andcommitted
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. PR-URL: #58957 Backport-PR-URL: #59504Fixes: #58945 Reviewed-By: Marco Ippolito <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]> Refs: #52697
1 parent 4dd20fe commit a5dcc58

File tree

4 files changed

+45
-2
lines changed

4 files changed

+45
-2
lines changed

‎lib/internal/modules/esm/loader.js‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const{
4141
kEvaluated,
4242
kEvaluating,
4343
kInstantiated,
44+
kErrored,
4445
throwIfPromiseRejected,
4546
}=internalBinding('module_wrap');
4647
const{
@@ -350,6 +351,9 @@ class ModuleLoader{
350351
mod[kRequiredModuleSymbol]=job.module;
351352
const{ namespace }=job.runSync(parent);
352353
return{wrap: job.module,namespace: namespace||job.module.getNamespace()};
354+
}elseif(status===kErrored){
355+
// If the module was previously imported and errored, throw the error.
356+
throwjob.module.getError();
353357
}
354358
// When the cached async job have already encountered a linking
355359
// error that gets wrapped into a rejection, but is still later

‎lib/internal/modules/esm/module_job.js‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ class ModuleJob extends ModuleJobBase{
281281
assert(this.moduleinstanceofModuleWrap);
282282
letstatus=this.module.getStatus();
283283

284-
debug('ModuleJob.runSync',this.module);
284+
debug('ModuleJob.runSync()',status,this.module);
285285
// FIXME(joyeecheung): this cannot fully handle < kInstantiated. Make the linking
286286
// fully synchronous instead.
287287
if(status===kUninstantiated){
@@ -316,6 +316,7 @@ class ModuleJob extends ModuleJobBase{
316316
}
317317

318318
asyncrun(){
319+
debug('ModuleJob.run()',this.module);
319320
awaitthis.instantiate();
320321
consttimeout=-1;
321322
constbreakOnSigint=false;
@@ -392,7 +393,11 @@ class ModuleJobSync extends ModuleJobBase{
392393
asyncrun(){
393394
// This path is hit by a require'd module that is imported again.
394395
conststatus=this.module.getStatus();
395-
if(status>kInstantiated){
396+
debug('ModuleJobSync.run()',status,this.module);
397+
// If the module was previously required and errored, reject from import() again.
398+
if(status===kErrored){
399+
throwthis.module.getError();
400+
}elseif(status>kInstantiated){
396401
if(this.evaluationPromise){
397402
awaitthis.evaluationPromise;
398403
}
@@ -413,6 +418,7 @@ class ModuleJobSync extends ModuleJobBase{
413418
}
414419

415420
runSync(parent){
421+
debug('ModuleJobSync.runSync()',this.module);
416422
// TODO(joyeecheung): add the error decoration logic from the async instantiate.
417423
this.module.async=this.module.instantiateSync();
418424
// If --experimental-print-required-tla is true, proceeds to evaluation even
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+
constcommon=require('../common');
6+
constassert=require('assert');
7+
8+
(async()=>{
9+
awaitassert.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+
constcommon=require('../common');
6+
constassert=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)