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