@@ -74,24 +74,14 @@ function evalModuleEntryPoint(source, print) {
7474}
7575
7676function evalScript ( name , body , breakFirstLine , print , shouldLoadESM = false ) {
77- const CJSModule = require ( 'internal/modules/cjs/loader' ) . Module ;
78-
79- const cwd = tryGetCwd ( ) ;
8077 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 ) ;
8679 const baseUrl = pathToFileURL ( module . filename ) . href ;
8780
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 ) ;
9585 }
9686
9787 const runScript = ( ) => {
@@ -106,23 +96,8 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) {
10696 globalThis . __filename = name ;
10797 RegExpPrototypeExec ( / ^ / , '' ) ; // Necessary to reset RegExp statics before user code runs.
10898 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 ) ;
126101 } ) ;
127102 if ( print ) {
128103 const { log } = require ( 'internal/console/global' ) ;
@@ -284,16 +259,33 @@ function decorateCJSErrorWithTSMessage(originalStack, newMessage) {
284259 * @returns {void }
285260 */
286261function 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 ;
287273 try {
288- evalScript ( name , source , breakFirstLine , print , shouldLoadESM ) ;
274+ compiledScript = compileScript ( name , source , baseUrl ) ;
289275 } catch ( originalError ) {
290276 // If it's not a SyntaxError, rethrow it.
291277 if ( ! isError ( originalError ) || originalError . name !== 'SyntaxError' ) {
292278 throw originalError ;
293279 }
294280 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 ) ;
297289 // Emit the experimental warning after the code was successfully evaluated.
298290 emitExperimentalWarning ( 'Type Stripping' ) ;
299291 } catch ( tsError ) {
@@ -308,6 +300,20 @@ function evalTypeScript(name, source, breakFirstLine, print, shouldLoadESM = fal
308300 throw originalError ;
309301 }
310302 }
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 ) ;
311317}
312318
313319/**
@@ -393,6 +399,97 @@ function parseAndEvalCommonjsTypeScript(name, source, breakFirstLine, print, sho
393399 evalScript ( name , strippedSource , breakFirstLine , print , shouldLoadESM ) ;
394400}
395401
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+
396493module . exports = {
397494 parseAndEvalCommonjsTypeScript,
398495 parseAndEvalModuleTypeScript,
0 commit comments