7
7
} = primordials ;
8
8
9
9
const {
10
+ ERR_INVALID_ARG_VALUE ,
10
11
ERR_INVALID_RETURN_PROPERTY ,
11
12
ERR_INVALID_RETURN_PROPERTY_VALUE ,
12
13
ERR_INVALID_RETURN_VALUE ,
@@ -47,6 +48,14 @@ class Loader {
47
48
// Map of already-loaded CJS modules to use
48
49
this . cjsCache = new SafeMap ( ) ;
49
50
51
+ // This hook is called before the first root module is imported. It's a
52
+ // function that returns a piece of code that runs as a sloppy-mode script.
53
+ // The script may evaluate to a function that can be called with a
54
+ // `getBuiltin` helper that can be used to retrieve builtins.
55
+ // If the hook returns `null` instead of a source string, it opts out of
56
+ // running any preload code.
57
+ // The preload code runs as soon as the hook module has finished evaluating.
58
+ this . _getGlobalPreloadCode = null ;
50
59
// The resolver has the signature
51
60
// (specifier : string, parentURL : string, defaultResolve)
52
61
// -> Promise<{ url : string }>
@@ -168,7 +177,16 @@ class Loader {
168
177
return module . getNamespace ( ) ;
169
178
}
170
179
171
- hook ( { resolve, dynamicInstantiate, getFormat, getSource, transformSource } ) {
180
+ hook ( hooks ) {
181
+ const {
182
+ resolve,
183
+ dynamicInstantiate,
184
+ getFormat,
185
+ getSource,
186
+ transformSource,
187
+ getGlobalPreloadCode,
188
+ } = hooks ;
189
+
172
190
// Use .bind() to avoid giving access to the Loader instance when called.
173
191
if ( resolve !== undefined )
174
192
this . _resolve = FunctionPrototypeBind ( resolve , null ) ;
@@ -185,6 +203,37 @@ class Loader {
185
203
if ( transformSource !== undefined ) {
186
204
this . _transformSource = FunctionPrototypeBind ( transformSource , null ) ;
187
205
}
206
+ if ( getGlobalPreloadCode !== undefined ) {
207
+ this . _getGlobalPreloadCode =
208
+ FunctionPrototypeBind ( getGlobalPreloadCode , null ) ;
209
+ }
210
+ }
211
+
212
+ runGlobalPreloadCode ( ) {
213
+ if ( ! this . _getGlobalPreloadCode ) {
214
+ return ;
215
+ }
216
+ const preloadCode = this . _getGlobalPreloadCode ( ) ;
217
+ if ( preloadCode === null ) {
218
+ return ;
219
+ }
220
+
221
+ if ( typeof preloadCode !== 'string' ) {
222
+ throw new ERR_INVALID_RETURN_VALUE (
223
+ 'string' , 'loader getGlobalPreloadCode' , preloadCode ) ;
224
+ }
225
+ const { compileFunction } = require ( 'vm' ) ;
226
+ const preloadInit = compileFunction ( preloadCode , [ 'getBuiltin' ] , {
227
+ filename : '<preload>' ,
228
+ } ) ;
229
+ const { NativeModule } = require ( 'internal/bootstrap/loaders' ) ;
230
+
231
+ preloadInit . call ( globalThis , ( builtinName ) => {
232
+ if ( NativeModule . canBeRequiredByUsers ( builtinName ) ) {
233
+ return require ( builtinName ) ;
234
+ }
235
+ throw new ERR_INVALID_ARG_VALUE ( 'builtinName' , builtinName ) ;
236
+ } ) ;
188
237
}
189
238
190
239
async getModuleJob ( specifier , parentURL ) {
0 commit comments