@@ -31,7 +31,11 @@ import EventEmitter from 'events';
31
31
import http from 'http' ;
32
32
import https from 'https' ;
33
33
34
- import { makeDeferredWithPromise , normalizeSeparators } from '@parcel/utils' ;
34
+ import {
35
+ makeDeferredWithPromise ,
36
+ normalizeSeparators ,
37
+ loadConfig ,
38
+ } from '@parcel/utils' ;
35
39
import _chalk from 'chalk' ;
36
40
import resolve from 'resolve' ;
37
41
@@ -303,6 +307,8 @@ export async function runBundles(
303
307
let target = env . context ;
304
308
let outputFormat = env . outputFormat ;
305
309
310
+ nodeCache . clear ( ) ;
311
+
306
312
let ctx , promises ;
307
313
switch ( target ) {
308
314
case 'browser' :
@@ -315,23 +321,11 @@ export async function runBundles(
315
321
case 'node' :
316
322
case 'electron-main' :
317
323
case 'react-server' :
318
- nodeCache . clear ( ) ;
319
- ctx = prepareNodeContext (
320
- outputFormat === 'commonjs' && parent . filePath ,
321
- globals ,
322
- undefined ,
323
- externalModules ,
324
- ) ;
324
+ ctx = prepareNodeContext ( globals ) ;
325
325
break ;
326
326
case 'electron-renderer' : {
327
- nodeCache. clear ( ) ;
328
327
let prepared = prepareBrowserContext ( parent , globals ) ;
329
- prepareNodeContext (
330
- outputFormat === 'commonjs' && parent . filePath ,
331
- globals ,
332
- prepared . ctx ,
333
- externalModules ,
334
- ) ;
328
+ prepareNodeContext ( globals , prepared . ctx ) ;
335
329
ctx = prepared . ctx ;
336
330
promises = prepared . promises ;
337
331
break ;
@@ -357,6 +351,7 @@ export async function runBundles(
357
351
358
352
vm . createContext ( ctx ) ;
359
353
let esmOutput ;
354
+ let cjsOutput ;
360
355
if ( outputFormat === 'esmodule' ) {
361
356
let res = await runESM (
362
357
bundles [ 0 ] [ 1 ] . target . distDir ,
@@ -371,9 +366,21 @@ export async function runBundles(
371
366
) ;
372
367
373
368
esmOutput = bundles . length === 1 ? res [ 0 ] : res ;
369
+ } else if (outputFormat === 'commonjs' || env.isNode()) {
370
+ for ( let [ code , b ] of bundles ) {
371
+ let res = runModule (
372
+ b . target . distDir ,
373
+ ctx ,
374
+ b . filePath ,
375
+ code ,
376
+ externalModules ,
377
+ opts . strict ?? false ,
378
+ ) ;
379
+ cjsOutput ??= res ;
380
+ }
374
381
} else {
375
382
for ( let [ code , b ] of bundles ) {
376
- // require, parcelRequire was set up in prepare*Context
383
+ // parcelRequire was set up in prepare*Context
377
384
new vm . Script ( ( opts . strict ? '"use strict";\n' : '' ) + code , {
378
385
filename :
379
386
b . bundleBehavior === 'inline'
@@ -395,6 +402,7 @@ export async function runBundles(
395
402
} ) . runInContext ( ctx ) ;
396
403
}
397
404
}
405
+
398
406
if ( promises ) {
399
407
// await any ongoing dynamic imports during the run
400
408
await Promise . all ( promises ) ;
@@ -413,8 +421,7 @@ export async function runBundles(
413
421
case 'global' :
414
422
return typeof ctx . output !== 'undefined' ? ctx . output : undefined ;
415
423
case 'commonjs' :
416
- invariant ( typeof ctx . module === 'object' && ctx . module != null ) ;
417
- return ctx . module . exports ;
424
+ return nullthrows ( cjsOutput ) ;
418
425
case 'esmodule' :
419
426
return esmOutput ;
420
427
default :
@@ -525,14 +532,16 @@ export function assertBundles(
525
532
return ;
526
533
}
527
534
528
- if (
529
- opts ?. skipNodeModules &&
530
- / n o d e _ m o d u l e s | e s m o d u l e - h e l p e r s .j s / . test ( asset . filePath )
531
- ) {
535
+ if ( opts ?. skipNodeModules && / n o d e _ m o d u l e s / . test ( asset . filePath ) ) {
532
536
return ;
533
537
}
534
538
535
- if ( opts ?. skipHelpers && / e s m o d u l e - h e l p e r s .j s / . test ( asset . filePath ) ) {
539
+ if (
540
+ ( opts ?. skipHelpers || opts ?. skipNodeModules ) &&
541
+ / e s m o d u l e - h e l p e r s .j s | j s x - d e v - r u n t i m e .j s | j s x - r u n t i m e .j s | r s c - h e l p e r s .j s / . test (
542
+ asset . filePath ,
543
+ )
544
+ ) {
536
545
return ;
537
546
}
538
547
@@ -683,8 +692,6 @@ function prepareBrowserContext(
683
692
currentScript : null ,
684
693
} ;
685
694
686
- var exports = { } ;
687
-
688
695
function PatchedError ( message ) {
689
696
const patchedError = new Error ( message ) ;
690
697
const stackStart = patchedError . stack . match ( / a t ( n e w ) ? E r r o r / ) ?. index ;
@@ -721,8 +728,6 @@ function prepareBrowserContext(
721
728
var ctx = Object.assign(
722
729
{
723
730
Error : PatchedError ,
724
- exports ,
725
- module : { exports} ,
726
731
document : fakeDocument ,
727
732
WebSocket ,
728
733
TextEncoder ,
@@ -819,11 +824,8 @@ function prepareWorkerContext(
819
824
| } {
820
825
let promises = [ ] ;
821
826
822
- var exports = { } ;
823
827
var ctx = Object . assign (
824
828
{
825
- exports,
826
- module : { exports} ,
827
829
WebSocket,
828
830
console,
829
831
TextEncoder,
@@ -878,15 +880,83 @@ function prepareWorkerContext(
878
880
}
879
881
880
882
const nodeCache = new Map ( ) ;
881
- // no filepath = ESM
882
883
function prepareNodeContext (
883
- filePath ,
884
884
globals ,
885
885
// $FlowFixMe
886
886
ctx : any = { } ,
887
+ ) {
888
+ ctx . console = console ;
889
+ ctx . process = process ;
890
+ ctx . setTimeout = setTimeout ;
891
+ ctx . setImmediate = setImmediate ;
892
+ ctx . global = ctx ;
893
+ ctx . URL = URL ;
894
+ ctx . TextEncoder = TextEncoder ;
895
+ ctx . TextDecoder = TextDecoder ;
896
+ Object . assign ( ctx , globals ) ;
897
+ return ctx ;
898
+ }
899
+
900
+ function runModule(
901
+ distDir: string,
902
+ // $FlowFixMe
903
+ ctx: any,
904
+ filePath: string,
905
+ code: string,
887
906
externalModules?: ExternalModules,
907
+ strict: boolean,
888
908
) {
889
- let exports = { } ;
909
+ let cached = nodeCache . get ( filePath ) ;
910
+ if ( cached ) {
911
+ return cached . exports ;
912
+ }
913
+
914
+ let f = vm . compileFunction (
915
+ ( strict ? '"use strict";\n' : '' ) + code ,
916
+ [ 'module' , 'exports' , '__filename' , '__dirname' , 'require' ] ,
917
+ {
918
+ filename : path . basename ( filePath ) ,
919
+ parsingContext : ctx ,
920
+ async importModuleDynamically ( specifier ) {
921
+ let resolved = path . resolve ( path . dirname ( filePath ) , specifier ) ;
922
+ let code = await overlayFS . readFile ( resolved , 'utf8' ) ;
923
+ if ( path . extname ( resolved ) === '.mjs' || ( await isESM ( resolved ) ) ) {
924
+ let modules = await runESM (
925
+ distDir ,
926
+ [ [ code , filePath ] ] ,
927
+ ctx ,
928
+ overlayFS ,
929
+ externalModules ,
930
+ true ,
931
+ ) ;
932
+ return modules [ 0 ] ;
933
+ } else {
934
+ let mod = runModule (
935
+ distDir ,
936
+ ctx ,
937
+ resolved ,
938
+ code ,
939
+ externalModules ,
940
+ strict ,
941
+ ) ;
942
+ // $FlowFixMe Experimental
943
+ let m = new vm . SyntheticModule (
944
+ Object . keys ( mod ) ,
945
+ function ( ) {
946
+ for ( let [ k , v ] of Object . entries ( mod ) ) {
947
+ this . setExport ( k , v ) ;
948
+ }
949
+ } ,
950
+ { identifier : resolved , context : ctx } ,
951
+ ) ;
952
+ await m . link ( ( ) => { } ) ;
953
+ await m . evaluate ( ) ;
954
+ return m ;
955
+ }
956
+ } ,
957
+ } ,
958
+ ) ;
959
+
890
960
let req =
891
961
filePath &&
892
962
( specifier => {
@@ -950,59 +1020,26 @@ function prepareNodeContext(
950
1020
return require ( res ) ;
951
1021
}
952
1022
953
- let cached = nodeCache . get ( res ) ;
954
- if ( cached ) {
955
- return cached . module . exports ;
956
- }
957
-
958
- let g = {
959
- ...globals ,
960
- } ;
961
-
962
- for ( let key in ctx ) {
963
- if (
964
- key !== 'module' &&
965
- key !== 'exports' &&
966
- key !== '__filename' &&
967
- key !== '__dirname' &&
968
- key !== 'require'
969
- ) {
970
- g [ key ] = ctx [ key ] ;
971
- }
972
- }
973
-
974
- let childCtx = prepareNodeContext ( res , g ) ;
975
- nodeCache . set ( res , childCtx ) ;
976
-
977
- vm . createContext ( childCtx ) ;
978
- new vm . Script (
979
- //'"use strict";\n' +
1023
+ return runModule (
1024
+ distDir ,
1025
+ ctx ,
1026
+ res ,
980
1027
overlayFS . readFileSync ( res , 'utf8' ) ,
981
- {
982
- filename : path . basename ( res ) ,
983
- } ,
984
- ) . runInContext ( childCtx ) ;
985
- return childCtx . module . exports ;
1028
+ externalModules ,
1029
+ strict ,
1030
+ ) ;
986
1031
} ) ;
987
1032
988
- if ( filePath ) {
989
- ctx . module = { exports, require : req } ;
990
- ctx . exports = exports ;
991
- ctx . __filename = filePath ;
992
- ctx . __dirname = path . dirname ( filePath ) ;
993
- ctx . require = req ;
994
- }
1033
+ let exports = { } ;
1034
+ let module = { exports , require : req } ;
1035
+ nodeCache.set(filePath, module);
1036
+ f(module, exports, filePath, path.dirname(filePath), req);
1037
+ return module.exports;
1038
+ }
995
1039
996
- ctx.console = console;
997
- ctx.process = process;
998
- ctx.setTimeout = setTimeout;
999
- ctx.setImmediate = setImmediate;
1000
- ctx.global = ctx;
1001
- ctx.URL = URL;
1002
- ctx.TextEncoder = TextEncoder;
1003
- ctx.TextDecoder = TextDecoder;
1004
- Object.assign(ctx, globals);
1005
- return ctx;
1040
+ async function isESM ( filePath : string ) {
1041
+ let pkg = await loadConfig ( overlayFS , filePath , [ 'package.json' ] , '/' ) ;
1042
+ return pkg ?. config ?. type === 'module' ;
1006
1043
}
1007
1044
1008
1045
let instanceId = 0;
@@ -1152,7 +1189,7 @@ export async function assertESMExports(
1152
1189
let [ nodeResult ] = await runESM (
1153
1190
b . getBundles ( ) [ 0 ] . target . distDir ,
1154
1191
[ [ await inputFS . readFile ( entry . filePath , 'utf8' ) , entry . filePath ] ] ,
1155
- vm . createContext ( prepareNodeContext ( false , { } ) ) ,
1192
+ vm . createContext ( prepareNodeContext ( { } ) ) ,
1156
1193
inputFS ,
1157
1194
externalModules ,
1158
1195
) ;
0 commit comments