@@ -106,7 +106,6 @@ module.exports = {
106
106
kModuleExportNames,
107
107
kModuleCircularVisited,
108
108
initializeCJS,
109
- entryPointSource : undefined , // Set below.
110
109
Module,
111
110
wrapSafe,
112
111
kIsMainSymbol,
@@ -1332,9 +1331,18 @@ function loadESMFromCJS(mod, filename) {
1332
1331
const source = getMaybeCachedSource ( mod , filename ) ;
1333
1332
const cascadedLoader = require ( 'internal/modules/esm/loader' ) . getOrInitializeCascadedLoader ( ) ;
1334
1333
const isMain = mod [ kIsMainSymbol ] ;
1335
- // TODO(joyeecheung): we may want to invent optional special handling for default exports here.
1336
- // For now, it's good enough to be identical to what `import()` returns.
1337
- mod . exports = cascadedLoader . importSyncForRequire ( mod , filename , source , isMain , mod [ kModuleParent ] ) ;
1334
+ if ( isMain ) {
1335
+ require ( 'internal/modules/run_main' ) . runEntryPointWithESMLoader ( ( cascadedLoader ) => {
1336
+ const mainURL = pathToFileURL ( filename ) . href ;
1337
+ cascadedLoader . import ( mainURL , undefined , { __proto__ : null } , true ) ;
1338
+ } ) ;
1339
+ // ESM won't be accessible via process.mainModule.
1340
+ setOwnProperty ( process , 'mainModule' , undefined ) ;
1341
+ } else {
1342
+ // TODO(joyeecheung): we may want to invent optional special handling for default exports here.
1343
+ // For now, it's good enough to be identical to what `import()` returns.
1344
+ mod . exports = cascadedLoader . importSyncForRequire ( mod , filename , source , isMain , mod [ kModuleParent ] ) ;
1345
+ }
1338
1346
}
1339
1347
1340
1348
/**
@@ -1343,8 +1351,10 @@ function loadESMFromCJS(mod, filename) {
1343
1351
* @param {string } content The content of the file being loaded
1344
1352
* @param {Module } cjsModuleInstance The CommonJS loader instance
1345
1353
* @param {object } codeCache The SEA code cache
1354
+ * @param {'commonjs'|undefined } format Intended format of the module.
1346
1355
*/
1347
- function wrapSafe ( filename , content , cjsModuleInstance , codeCache ) {
1356
+ function wrapSafe ( filename , content , cjsModuleInstance , codeCache , format ) {
1357
+ assert ( format !== 'module' ) ; // ESM should be handled in loadESMFromCJS().
1348
1358
const hostDefinedOptionId = vm_dynamic_import_default_internal ;
1349
1359
const importModuleDynamically = vm_dynamic_import_default_internal ;
1350
1360
if ( patched ) {
@@ -1374,46 +1384,33 @@ function wrapSafe(filename, content, cjsModuleInstance, codeCache) {
1374
1384
} ;
1375
1385
}
1376
1386
1377
- try {
1378
- const result = compileFunctionForCJSLoader ( content , filename ) ;
1379
-
1380
- // cachedDataRejected is only set for cache coming from SEA.
1381
- if ( codeCache &&
1382
- result . cachedDataRejected !== false &&
1383
- internalBinding ( 'sea' ) . isSea ( ) ) {
1384
- process . emitWarning ( 'Code cache data rejected.' ) ;
1385
- }
1387
+ const isMain = ! ! ( cjsModuleInstance && cjsModuleInstance [ kIsMainSymbol ] ) ;
1388
+ const shouldDetectModule = ( format !== 'commonjs' && getOptionValue ( '--experimental-detect-module' ) ) ;
1389
+ const result = compileFunctionForCJSLoader ( content , filename , isMain , shouldDetectModule ) ;
1386
1390
1387
- // Cache the source map for the module if present.
1388
- if ( result . sourceMapURL ) {
1389
- maybeCacheSourceMap ( filename , content , this , false , undefined , result . sourceMapURL ) ;
1390
- }
1391
+ // cachedDataRejected is only set for cache coming from SEA.
1392
+ if ( codeCache &&
1393
+ result . cachedDataRejected !== false &&
1394
+ internalBinding ( 'sea' ) . isSea ( ) ) {
1395
+ process . emitWarning ( 'Code cache data rejected.' ) ;
1396
+ }
1391
1397
1392
- return result ;
1393
- } catch ( err ) {
1394
- if ( process . mainModule === cjsModuleInstance ) {
1395
- if ( getOptionValue ( '--experimental-detect-module' ) ) {
1396
- // For the main entry point, cache the source to potentially retry as ESM.
1397
- module . exports . entryPointSource = content ;
1398
- } else {
1399
- // We only enrich the error (print a warning) if we're sure we're going to for-sure throw it; so if we're
1400
- // retrying as ESM, wait until we know whether we're going to retry before calling `enrichCJSError`.
1401
- const { enrichCJSError } = require ( 'internal/modules/esm/translators' ) ;
1402
- enrichCJSError ( err , content , filename ) ;
1403
- }
1404
- }
1405
- throw err ;
1398
+ // Cache the source map for the module if present.
1399
+ if ( result . sourceMapURL ) {
1400
+ maybeCacheSourceMap ( filename , content , this , false , undefined , result . sourceMapURL ) ;
1406
1401
}
1402
+
1403
+ return result ;
1407
1404
}
1408
1405
1409
1406
/**
1410
1407
* Run the file contents in the correct scope or sandbox. Expose the correct helper variables (`require`, `module`,
1411
1408
* `exports`) to the file. Returns exception, if any.
1412
1409
* @param {string } content The source code of the module
1413
1410
* @param {string } filename The file path of the module
1414
- * @param {boolean } loadAsESM Whether it's known to be ESM via .mjs or "type" in package.json .
1411
+ * @param {'module'|'commonjs'|undefined } format Intended format of the module .
1415
1412
*/
1416
- Module . prototype . _compile = function ( content , filename , loadAsESM = false ) {
1413
+ Module . prototype . _compile = function ( content , filename , format ) {
1417
1414
let moduleURL ;
1418
1415
let redirects ;
1419
1416
const manifest = policy ( ) ?. manifest ;
@@ -1423,17 +1420,24 @@ Module.prototype._compile = function(content, filename, loadAsESM = false) {
1423
1420
manifest . assertIntegrity ( moduleURL , content ) ;
1424
1421
}
1425
1422
1423
+ let compiledWrapper ;
1424
+ if ( format !== 'module' ) {
1425
+ const result = wrapSafe ( filename , content , this , undefined , format ) ;
1426
+ compiledWrapper = result . function ;
1427
+ if ( result . canParseAsESM ) {
1428
+ format = 'module' ;
1429
+ }
1430
+ }
1431
+
1426
1432
// TODO(joyeecheung): when the module is the entry point, consider allowing TLA.
1427
1433
// Only modules being require()'d really need to avoid TLA.
1428
- if ( loadAsESM ) {
1434
+ if ( format === 'module' ) {
1429
1435
// Pass the source into the .mjs extension handler indirectly through the cache.
1430
1436
this [ kModuleSource ] = content ;
1431
1437
loadESMFromCJS ( this , filename ) ;
1432
1438
return ;
1433
1439
}
1434
1440
1435
- const { function : compiledWrapper } = wrapSafe ( filename , content , this ) ;
1436
-
1437
1441
// TODO(joyeecheung): the detection below is unnecessarily complex. Using the
1438
1442
// kIsMainSymbol, or a kBreakOnStartSymbol that gets passed from
1439
1443
// higher level instead of doing hacky detection here.
@@ -1510,12 +1514,13 @@ Module._extensions['.js'] = function(module, filename) {
1510
1514
// If already analyzed the source, then it will be cached.
1511
1515
const content = getMaybeCachedSource ( module , filename ) ;
1512
1516
1517
+ let format ;
1513
1518
if ( StringPrototypeEndsWith ( filename , '.js' ) ) {
1514
1519
const pkg = packageJsonReader . getNearestParentPackageJSON ( filename ) ;
1515
1520
// Function require shouldn't be used in ES modules.
1516
1521
if ( pkg ?. data . type === 'module' ) {
1517
1522
if ( getOptionValue ( '--experimental-require-module' ) ) {
1518
- module . _compile ( content , filename , true ) ;
1523
+ module . _compile ( content , filename , 'module' ) ;
1519
1524
return ;
1520
1525
}
1521
1526
@@ -1549,10 +1554,14 @@ Module._extensions['.js'] = function(module, filename) {
1549
1554
}
1550
1555
}
1551
1556
throw err ;
1557
+ } else if ( pkg ?. data . type === 'commonjs' ) {
1558
+ format = 'commonjs' ;
1552
1559
}
1560
+ } else if ( StringPrototypeEndsWith ( filename , '.cjs' ) ) {
1561
+ format = 'commonjs' ;
1553
1562
}
1554
1563
1555
- module . _compile ( content , filename , false ) ;
1564
+ module . _compile ( content , filename , format ) ;
1556
1565
} ;
1557
1566
1558
1567
/**
0 commit comments