@@ -74,24 +74,14 @@ function evalModuleEntryPoint(source, print) {
74
74
}
75
75
76
76
function evalScript ( name , body , breakFirstLine , print , shouldLoadESM = false ) {
77
- const CJSModule = require ( 'internal/modules/cjs/loader' ) . Module ;
78
-
79
- const cwd = tryGetCwd ( ) ;
80
77
const origModule = globalThis . module ; // Set e.g. when called from the REPL.
81
-
82
- const module = new CJSModule ( name ) ;
83
- module . filename = path . join ( cwd , name ) ;
84
- module . paths = CJSModule . _nodeModulePaths ( cwd ) ;
85
-
78
+ const module = createModule ( name ) ;
86
79
const baseUrl = pathToFileURL ( module . filename ) . href ;
87
80
88
- if ( getOptionValue ( '--experimental-detect-module' ) &&
89
- getOptionValue ( '--input-type' ) === '' &&
90
- containsModuleSyntax ( body , name , null , 'no CJS variables' ) ) {
91
- if ( getOptionValue ( '--experimental-strip-types' ) ) {
92
- return evalTypeScriptModuleEntryPoint ( body , print ) ;
93
- }
94
- return evalModuleEntryPoint ( body , print ) ;
81
+ if ( shouldUseModuleEntryPoint ( name , body ) ) {
82
+ return getOptionValue ( '--experimental-strip-types' ) ?
83
+ evalTypeScriptModuleEntryPoint ( body , print ) :
84
+ evalModuleEntryPoint ( body , print ) ;
95
85
}
96
86
97
87
const runScript = ( ) => {
@@ -106,23 +96,8 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) {
106
96
globalThis . __filename = name ;
107
97
RegExpPrototypeExec ( / ^ / , '' ) ; // Necessary to reset RegExp statics before user code runs.
108
98
const result = module . _compile ( script , `${ name } -wrapper` ) ( ( ) => {
109
- const hostDefinedOptionId = Symbol ( name ) ;
110
- async function importModuleDynamically ( specifier , _ , importAttributes ) {
111
- const cascadedLoader = require ( 'internal/modules/esm/loader' ) . getOrInitializeCascadedLoader ( ) ;
112
- return cascadedLoader . import ( specifier , baseUrl , importAttributes ) ;
113
- }
114
- const script = makeContextifyScript (
115
- body , // code
116
- name , // filename,
117
- 0 , // lineOffset
118
- 0 , // columnOffset,
119
- undefined , // cachedData
120
- false , // produceCachedData
121
- undefined , // parsingContext
122
- hostDefinedOptionId , // hostDefinedOptionId
123
- importModuleDynamically , // importModuleDynamically
124
- ) ;
125
- return runScriptInThisContext ( script , true , ! ! breakFirstLine ) ;
99
+ const compiledScript = compileScript ( name , body , baseUrl ) ;
100
+ return runScriptInThisContext ( compiledScript , true , ! ! breakFirstLine ) ;
126
101
} ) ;
127
102
if ( print ) {
128
103
const { log } = require ( 'internal/console/global' ) ;
@@ -284,16 +259,33 @@ function decorateCJSErrorWithTSMessage(originalStack, newMessage) {
284
259
* @returns {void }
285
260
*/
286
261
function evalTypeScript ( name , source , breakFirstLine , print , shouldLoadESM = false ) {
262
+ const origModule = globalThis . module ; // Set e.g. when called from the REPL.
263
+ const module = createModule ( name ) ;
264
+ const baseUrl = pathToFileURL ( module . filename ) . href ;
265
+
266
+ if ( shouldUseModuleEntryPoint ( name , source ) ) {
267
+ return evalTypeScriptModuleEntryPoint ( source , print ) ;
268
+ }
269
+
270
+ let compiledScript ;
271
+ // This variable can be modified if the source code is stripped.
272
+ let sourceToRun = source ;
287
273
try {
288
- evalScript ( name , source , breakFirstLine , print , shouldLoadESM ) ;
274
+ compiledScript = compileScript ( name , source , baseUrl ) ;
289
275
} catch ( originalError ) {
290
276
// If it's not a SyntaxError, rethrow it.
291
277
if ( ! isError ( originalError ) || originalError . name !== 'SyntaxError' ) {
292
278
throw originalError ;
293
279
}
294
280
try {
295
- const strippedSource = stripTypeScriptModuleTypes ( source , name , false ) ;
296
- evalScript ( name , strippedSource , breakFirstLine , print , shouldLoadESM ) ;
281
+ sourceToRun = stripTypeScriptModuleTypes ( source , name , false ) ;
282
+ // Retry the CJS/ESM syntax detection after stripping the types.
283
+ if ( shouldUseModuleEntryPoint ( name , sourceToRun ) ) {
284
+ return evalTypeScriptModuleEntryPoint ( source , print ) ;
285
+ }
286
+ // If the ContextifiedScript was successfully created, execute it.
287
+ // outside the try-catch block to avoid catching runtime errors.
288
+ compiledScript = compileScript ( name , sourceToRun , baseUrl ) ;
297
289
// Emit the experimental warning after the code was successfully evaluated.
298
290
emitExperimentalWarning ( 'Type Stripping' ) ;
299
291
} catch ( tsError ) {
@@ -308,6 +300,20 @@ function evalTypeScript(name, source, breakFirstLine, print, shouldLoadESM = fal
308
300
throw originalError ;
309
301
}
310
302
}
303
+
304
+ if ( shouldLoadESM ) {
305
+ return require ( 'internal/modules/run_main' ) . runEntryPointWithESMLoader (
306
+ ( ) => runScriptInContext ( name ,
307
+ sourceToRun ,
308
+ breakFirstLine ,
309
+ print ,
310
+ module ,
311
+ baseUrl ,
312
+ compiledScript ,
313
+ origModule ) ) ;
314
+ }
315
+
316
+ runScriptInContext ( name , sourceToRun , breakFirstLine , print , module , baseUrl , compiledScript , origModule ) ;
311
317
}
312
318
313
319
/**
@@ -393,6 +399,97 @@ function parseAndEvalCommonjsTypeScript(name, source, breakFirstLine, print, sho
393
399
evalScript ( name , strippedSource , breakFirstLine , print , shouldLoadESM ) ;
394
400
}
395
401
402
+ /**
403
+ *
404
+ * @param {string } name - The filename of the script.
405
+ * @param {string } body - The code of the script.
406
+ * @param {string } baseUrl Path of the parent importing the module.
407
+ * @returns {ContextifyScript } The created contextify script.
408
+ */
409
+ function compileScript ( name , body , baseUrl ) {
410
+ const hostDefinedOptionId = Symbol ( name ) ;
411
+ async function importModuleDynamically ( specifier , _ , importAttributes ) {
412
+ const cascadedLoader = require ( 'internal/modules/esm/loader' ) . getOrInitializeCascadedLoader ( ) ;
413
+ return cascadedLoader . import ( specifier , baseUrl , importAttributes ) ;
414
+ }
415
+ return makeContextifyScript (
416
+ body , // code
417
+ name , // filename,
418
+ 0 , // lineOffset
419
+ 0 , // columnOffset,
420
+ undefined , // cachedData
421
+ false , // produceCachedData
422
+ undefined , // parsingContext
423
+ hostDefinedOptionId , // hostDefinedOptionId
424
+ importModuleDynamically , // importModuleDynamically
425
+ ) ;
426
+ }
427
+
428
+ /**
429
+ * @param {string } name - The filename of the script.
430
+ * @param {string } body - The code of the script.
431
+ * @returns {boolean } Whether the module entry point should be evaluated as a module.
432
+ */
433
+ function shouldUseModuleEntryPoint ( name , body ) {
434
+ return getOptionValue ( '--experimental-detect-module' ) &&
435
+ getOptionValue ( '--input-type' ) === '' &&
436
+ containsModuleSyntax ( body , name , null , 'no CJS variables' ) ;
437
+ }
438
+
439
+ /**
440
+ *
441
+ * @param {string } name - The filename of the script.
442
+ * @returns {import('internal/modules/esm/loader').CJSModule } The created module.
443
+ */
444
+ function createModule ( name ) {
445
+ const CJSModule = require ( 'internal/modules/cjs/loader' ) . Module ;
446
+ const cwd = tryGetCwd ( ) ;
447
+ const module = new CJSModule ( name ) ;
448
+ module . filename = path . join ( cwd , name ) ;
449
+ module . paths = CJSModule . _nodeModulePaths ( cwd ) ;
450
+ return module ;
451
+ }
452
+
453
+ /**
454
+ *
455
+ * @param {string } name - The filename of the script.
456
+ * @param {string } body - The code of the script.
457
+ * @param {boolean } breakFirstLine Whether to break on the first line
458
+ * @param {boolean } print If the result should be printed
459
+ * @param {import('internal/modules/esm/loader').CJSModule } module The module
460
+ * @param {string } baseUrl Path of the parent importing the module.
461
+ * @param {object } compiledScript The compiled script.
462
+ * @param {any } origModule The original module.
463
+ * @returns {void }
464
+ */
465
+ function runScriptInContext ( name , body , breakFirstLine , print , module , baseUrl , compiledScript , origModule ) {
466
+ // Create wrapper for cache entry
467
+ const script = `
468
+ globalThis.module = module;
469
+ globalThis.exports = exports;
470
+ globalThis.__dirname = __dirname;
471
+ globalThis.require = require;
472
+ return (main) => main();
473
+ ` ;
474
+ globalThis . __filename = name ;
475
+ RegExpPrototypeExec ( / ^ / , '' ) ; // Necessary to reset RegExp statics before user code runs.
476
+ const result = module . _compile ( script , `${ name } -wrapper` ) ( ( ) => {
477
+ // If the script was already compiled, use it.
478
+ return runScriptInThisContext (
479
+ compiledScript ,
480
+ true , ! ! breakFirstLine ) ;
481
+ } ) ;
482
+ if ( print ) {
483
+ const { log } = require ( 'internal/console/global' ) ;
484
+
485
+ process . on ( 'exit' , ( ) => {
486
+ log ( result ) ;
487
+ } ) ;
488
+ }
489
+ if ( origModule !== undefined )
490
+ globalThis . module = origModule ;
491
+ }
492
+
396
493
module . exports = {
397
494
parseAndEvalCommonjsTypeScript,
398
495
parseAndEvalModuleTypeScript,
0 commit comments