@@ -81,8 +81,8 @@ let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {
81
81
// [2] `validate...()`s throw the wrong error
82
82
83
83
84
- class Hooks {
85
- #chains = {
84
+ function getDefaultChains ( ) {
85
+ return {
86
86
/**
87
87
* Prior to ESM loading. These are called once before any modules are started.
88
88
* @private
@@ -115,27 +115,46 @@ class Hooks {
115
115
} ,
116
116
] ,
117
117
} ;
118
+ }
119
+
120
+ class Hooks {
121
+ #chains;
118
122
119
123
// Cache URLs we've already validated to avoid repeated validation
120
- #validatedUrls = new SafeSet ( ) ;
124
+ #validatedUrls;
125
+
126
+ constructor ( chains = getDefaultChains ( ) , validatedUrls = new SafeSet ( ) ) {
127
+ this . #chains = chains ;
128
+ this . #validatedUrls = validatedUrls ;
129
+ }
121
130
122
131
/**
123
132
* Import and register custom/user-defined module loader hook(s).
124
133
* @param {string } urlOrSpecifier
125
134
* @param {string } parentURL
126
135
*/
127
136
async register ( urlOrSpecifier , parentURL ) {
128
- const moduleLoader = require ( 'internal/process/esm_loader' ) . esmLoader ;
129
-
130
- const keyedExports = await moduleLoader . import (
137
+ const esmLoader = require ( 'internal/process/esm_loader' ) . esmLoader ;
138
+ const keyedExports = await esmLoader . import (
131
139
urlOrSpecifier ,
132
140
parentURL ,
133
141
kEmptyObject ,
134
142
) ;
135
-
136
143
this . addCustomLoader ( urlOrSpecifier , keyedExports ) ;
137
144
}
138
145
146
+ allowImportMetaResolve ( ) {
147
+ return false ;
148
+ }
149
+
150
+ getChains ( ) {
151
+ return this . #chains;
152
+ }
153
+
154
+ getValidatedUrls ( ) {
155
+ return this . #validatedUrls;
156
+ }
157
+
139
158
/**
140
159
* Collect custom/user-defined module loader hook(s).
141
160
* After all hooks have been collected, the global preload hook(s) must be initialized.
@@ -221,15 +240,16 @@ class Hooks {
221
240
parentURL ,
222
241
importAssertions = { __proto__ : null } ,
223
242
) {
243
+ const chain = this . #chains. resolve ;
224
244
throwIfInvalidParentURL ( parentURL ) ;
225
245
226
- const chain = this . #chains. resolve ;
227
246
const context = {
228
247
conditions : getDefaultConditions ( ) ,
229
248
importAssertions,
230
249
parentURL,
231
250
} ;
232
251
const meta = {
252
+ hooks : this ,
233
253
chainFinished : null ,
234
254
context,
235
255
hookErrIdentifier : '' ,
@@ -346,6 +366,7 @@ class Hooks {
346
366
async load ( url , context = { } ) {
347
367
const chain = this . #chains. load ;
348
368
const meta = {
369
+ hooks : this ,
349
370
chainFinished : null ,
350
371
context,
351
372
hookErrIdentifier : '' ,
@@ -528,7 +549,17 @@ class HooksProxy {
528
549
debug ( 'wait for signal from worker' ) ;
529
550
AtomicsWait ( this . #lock, WORKER_TO_MAIN_THREAD_NOTIFICATION , 0 ) ;
530
551
const response = this . #worker. receiveMessageSync ( ) ;
531
- if ( response . message . status === 'exit' ) { return ; }
552
+ if ( response . message . status === 'exit' ) {
553
+ // TODO: I do not understand why this is necessary.
554
+ // node \
555
+ // --no-warnings --experimental-loader 'data:text/javascript,process.exit(42)'
556
+ // ./test/fixtures/empty.js
557
+ // Does not trigger `this.#worker.on('exit', process.exit);`.
558
+ // I think it is because `makeSyncRequest` keeps waiting to see another
559
+ // message and blocks the thread from ANY other activity including the exit.
560
+ process . exit ( response . message . body ) ;
561
+ return ;
562
+ }
532
563
const { preloadScripts } = this . #unwrapMessage( response ) ;
533
564
this . #executePreloadScripts( preloadScripts ) ;
534
565
}
@@ -749,7 +780,25 @@ function nextHookFactory(chain, meta, { validateArgs, validateOutput }) {
749
780
ObjectAssign ( meta . context , context ) ;
750
781
}
751
782
752
- const output = await hook ( arg0 , meta . context , nextNextHook ) ;
783
+ const esmLoader = require ( 'internal/process/esm_loader' ) . esmLoader ;
784
+
785
+ const chains = meta . hooks . getChains ( ) ;
786
+ const load = chain === chains . load ? chains . load . slice ( 0 , generatedHookIndex ) : chains . load ;
787
+ const resolve = chain === chains . resolve ? chains . resolve . slice ( 0 , generatedHookIndex ) : chains . resolve ;
788
+ let output ;
789
+ if ( load . length > 0 && resolve . length > 0 ) {
790
+ const nextChains = {
791
+ load,
792
+ resolve,
793
+ globalPreload : chains . globalPreload ,
794
+ } ;
795
+ const delegate = new Hooks ( nextChains , meta . hooks . getValidatedUrls ( ) ) ;
796
+ output = await esmLoader . withDelegate ( delegate , ( ) => {
797
+ return hook ( arg0 , meta . context , nextNextHook ) ;
798
+ } ) ;
799
+ } else {
800
+ output = await hook ( arg0 , meta . context , nextNextHook ) ;
801
+ }
753
802
754
803
validateOutput ( outputErrIdentifier , output ) ;
755
804
0 commit comments