webpack 5.2.1 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

@@ -25,6 +25,14 @@ const createHash = require("../util/createHash");
25
25
  const contextify = require("../util/identifier").contextify;
26
26
  const makeSerializable = require("../util/makeSerializable");
27
27
  const propertyAccess = require("../util/propertyAccess");
28
+ const {
29
+ filterRuntime,
30
+ intersectRuntime,
31
+ mergeRuntimeCondition,
32
+ mergeRuntimeConditionNonFalse,
33
+ runtimeConditionToString,
34
+ subtractRuntimeCondition
35
+ } = require("../util/runtime");
28
36
 
29
37
  /** @typedef {import("eslint-scope").Scope} Scope */
30
38
  /** @typedef {import("webpack-sources").Source} Source */
@@ -76,6 +84,7 @@ const propertyAccess = require("../util/propertyAccess");
76
84
  */
77
85
 
78
86
  /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo } ModuleInfo */
87
+ /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo | ReferenceToModuleInfo } ModuleInfoOrReference */
79
88
 
80
89
  /**
81
90
  * @typedef {Object} ConcatenatedModuleInfo
@@ -95,6 +104,8 @@ const propertyAccess = require("../util/propertyAccess");
95
104
  * @property {string} namespaceObjectName
96
105
  * @property {boolean} interopNamespaceObjectUsed
97
106
  * @property {string} interopNamespaceObjectName
107
+ * @property {boolean} interopNamespaceObject2Used
108
+ * @property {string} interopNamespaceObject2Name
98
109
  * @property {boolean} interopDefaultAccessUsed
99
110
  * @property {string} interopDefaultAccessName
100
111
  */
@@ -103,14 +114,24 @@ const propertyAccess = require("../util/propertyAccess");
103
114
  * @typedef {Object} ExternalModuleInfo
104
115
  * @property {"external"} type
105
116
  * @property {Module} module
117
+ * @property {RuntimeSpec | boolean} runtimeCondition
106
118
  * @property {number} index
107
119
  * @property {string} name
108
120
  * @property {boolean} interopNamespaceObjectUsed
109
121
  * @property {string} interopNamespaceObjectName
122
+ * @property {boolean} interopNamespaceObject2Used
123
+ * @property {string} interopNamespaceObject2Name
110
124
  * @property {boolean} interopDefaultAccessUsed
111
125
  * @property {string} interopDefaultAccessName
112
126
  */
113
127
 
128
+ /**
129
+ * @typedef {Object} ReferenceToModuleInfo
130
+ * @property {"reference"} type
131
+ * @property {RuntimeSpec | boolean} runtimeCondition
132
+ * @property {ConcatenatedModuleInfo | ExternalModuleInfo} target
133
+ */
134
+
114
135
  const RESERVED_NAMES = [
115
136
  // internal names (should always be renamed)
116
137
  ConcatenationScope.DEFAULT_EXPORT,
@@ -185,6 +206,7 @@ const joinIterableWithComma = iterable => {
185
206
  * @typedef {Object} ConcatenationEntry
186
207
  * @property {"concatenated" | "external"} type
187
208
  * @property {Module} module
209
+ * @property {RuntimeSpec | boolean} runtimeCondition
188
210
  */
189
211
 
190
212
  /**
@@ -223,6 +245,13 @@ const getFinalBinding = (
223
245
  if (exportName.length === 0) {
224
246
  switch (exportsType) {
225
247
  case "default-only":
248
+ info.interopNamespaceObject2Used = true;
249
+ return {
250
+ info,
251
+ rawName: info.interopNamespaceObject2Name,
252
+ ids: exportName,
253
+ exportName
254
+ };
226
255
  case "default-with-named":
227
256
  info.interopNamespaceObjectUsed = true;
228
257
  return {
@@ -568,28 +597,17 @@ const getPathInAst = (ast, node) => {
568
597
  }
569
598
  };
570
599
 
571
- /**
572
- * @param {ModuleInfo[]} modulesWithInfo modules
573
- * @returns {Map<Module, ModuleInfo>} mapping
574
- */
575
- const modulesWithInfoToMap = modulesWithInfo => {
576
- const moduleToInfoMap = new Map();
577
- for (const m of modulesWithInfo) {
578
- moduleToInfoMap.set(m.module, m);
579
- }
580
- return moduleToInfoMap;
581
- };
582
-
583
600
  const TYPES = new Set(["javascript"]);
584
601
 
585
602
  class ConcatenatedModule extends Module {
586
603
  /**
587
604
  * @param {Module} rootModule the root module of the concatenation
588
605
  * @param {Set<Module>} modules all modules in the concatenation (including the root module)
606
+ * @param {RuntimeSpec} runtime the runtime
589
607
  * @param {Object=} associatedObjectForCache object for caching
590
608
  * @returns {ConcatenatedModule} the module
591
609
  */
592
- static create(rootModule, modules, associatedObjectForCache) {
610
+ static create(rootModule, modules, runtime, associatedObjectForCache) {
593
611
  const identifier = ConcatenatedModule._createIdentifier(
594
612
  rootModule,
595
613
  modules,
@@ -598,7 +616,8 @@ class ConcatenatedModule extends Module {
598
616
  return new ConcatenatedModule({
599
617
  identifier,
600
618
  rootModule,
601
- modules
619
+ modules,
620
+ runtime
602
621
  });
603
622
  }
604
623
 
@@ -606,9 +625,10 @@ class ConcatenatedModule extends Module {
606
625
  * @param {Object} options options
607
626
  * @param {string} options.identifier the identifier of the module
608
627
  * @param {Module=} options.rootModule the root module of the concatenation
628
+ * @param {RuntimeSpec} options.runtime the selected runtime
609
629
  * @param {Set<Module>=} options.modules all concatenated modules
610
630
  */
611
- constructor({ identifier, rootModule, modules }) {
631
+ constructor({ identifier, rootModule, modules, runtime }) {
612
632
  super("javascript/esm", null);
613
633
 
614
634
  // Info from Factory
@@ -618,6 +638,7 @@ class ConcatenatedModule extends Module {
618
638
  this.rootModule = rootModule;
619
639
  /** @type {Set<Module>} */
620
640
  this._modules = modules;
641
+ this._runtime = runtime;
621
642
  this.factoryMeta = rootModule && rootModule.factoryMeta;
622
643
 
623
644
  // Caching
@@ -637,6 +658,7 @@ class ConcatenatedModule extends Module {
637
658
  this._identifier = m._identifier;
638
659
  this.rootModule = m.rootModule;
639
660
  this._modules = m._modules;
661
+ this._runtime = m._runtime;
640
662
  }
641
663
  /**
642
664
  * @returns {Set<string>} types available (do not mutate)
@@ -784,12 +806,12 @@ class ConcatenatedModule extends Module {
784
806
  _createConcatenationList(rootModule, modulesSet, runtime, moduleGraph) {
785
807
  /** @type {ConcatenationEntry[]} */
786
808
  const list = [];
787
- /** @type {Set<Module>} */
788
- const existingEntries = new Set();
809
+ /** @type {Map<Module, RuntimeSpec | true>} */
810
+ const existingEntries = new Map();
789
811
 
790
812
  /**
791
813
  * @param {Module} module a module
792
- * @returns {ModuleGraphConnection[]} imported modules in order
814
+ * @returns {Iterable<{ connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} imported modules in order
793
815
  */
794
816
  const getConcatenatedImports = module => {
795
817
  let connections = Array.from(moduleGraph.getOutgoingConnections(module));
@@ -816,29 +838,91 @@ class ConcatenatedModule extends Module {
816
838
  references.sort(
817
839
  concatComparators(bySourceOrder, keepOriginalOrder(references))
818
840
  );
819
- return references.map(({ connection }) => connection);
841
+ /** @type {Map<Module, { connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} */
842
+ const referencesMap = new Map();
843
+ for (const { connection } of references) {
844
+ const runtimeCondition = filterRuntime(runtime, r =>
845
+ connection.isTargetActive(r)
846
+ );
847
+ if (runtimeCondition === false) continue;
848
+ const module = connection.module;
849
+ const entry = referencesMap.get(module);
850
+ if (entry === undefined) {
851
+ referencesMap.set(module, { connection, runtimeCondition });
852
+ continue;
853
+ }
854
+ entry.runtimeCondition = mergeRuntimeConditionNonFalse(
855
+ entry.runtimeCondition,
856
+ runtimeCondition,
857
+ runtime
858
+ );
859
+ }
860
+ return referencesMap.values();
820
861
  };
821
862
 
822
863
  /**
823
864
  * @param {ModuleGraphConnection} connection graph connection
865
+ * @param {RuntimeSpec | true} runtimeCondition runtime condition
824
866
  * @returns {void}
825
867
  */
826
- const enterModule = connection => {
868
+ const enterModule = (connection, runtimeCondition) => {
827
869
  const module = connection.module;
828
870
  if (!module) return;
829
- if (existingEntries.has(module)) {
871
+ const existingEntry = existingEntries.get(module);
872
+ if (existingEntry === true) {
830
873
  return;
831
874
  }
832
875
  if (modulesSet.has(module)) {
833
- existingEntries.add(module);
876
+ existingEntries.set(module, true);
877
+ if (runtimeCondition !== true) {
878
+ throw new Error(
879
+ `Cannot runtime-conditional concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}, ${runtimeConditionToString(
880
+ runtimeCondition
881
+ )}). This should not happen.`
882
+ );
883
+ }
834
884
  const imports = getConcatenatedImports(module);
835
- imports.forEach(enterModule);
885
+ for (const { connection, runtimeCondition } of imports)
886
+ enterModule(connection, runtimeCondition);
836
887
  list.push({
837
888
  type: "concatenated",
838
- module: connection.module
889
+ module: connection.module,
890
+ runtimeCondition
839
891
  });
840
892
  } else {
841
- existingEntries.add(connection.module);
893
+ if (existingEntry !== undefined) {
894
+ const reducedRuntimeCondition = subtractRuntimeCondition(
895
+ runtimeCondition,
896
+ existingEntry,
897
+ runtime
898
+ );
899
+ if (reducedRuntimeCondition === false) return;
900
+ runtimeCondition = reducedRuntimeCondition;
901
+ existingEntries.set(
902
+ connection.module,
903
+ mergeRuntimeConditionNonFalse(
904
+ existingEntry,
905
+ runtimeCondition,
906
+ runtime
907
+ )
908
+ );
909
+ } else {
910
+ existingEntries.set(connection.module, runtimeCondition);
911
+ }
912
+ if (list.length > 0) {
913
+ const lastItem = list[list.length - 1];
914
+ if (
915
+ lastItem.type === "external" &&
916
+ lastItem.module === connection.module
917
+ ) {
918
+ lastItem.runtimeCondition = mergeRuntimeCondition(
919
+ lastItem.runtimeCondition,
920
+ runtimeCondition,
921
+ runtime
922
+ );
923
+ return;
924
+ }
925
+ }
842
926
  list.push({
843
927
  type: "external",
844
928
  get module() {
@@ -846,17 +930,20 @@ class ConcatenatedModule extends Module {
846
930
  // could be replaced by some other process (i. e. also replaced with a
847
931
  // concatenated module)
848
932
  return connection.module;
849
- }
933
+ },
934
+ runtimeCondition
850
935
  });
851
936
  }
852
937
  };
853
938
 
854
- existingEntries.add(rootModule);
939
+ existingEntries.set(rootModule, true);
855
940
  const imports = getConcatenatedImports(rootModule);
856
- imports.forEach(enterModule);
941
+ for (const { connection, runtimeCondition } of imports)
942
+ enterModule(connection, runtimeCondition);
857
943
  list.push({
858
944
  type: "concatenated",
859
- module: rootModule
945
+ module: rootModule,
946
+ runtimeCondition: true
860
947
  });
861
948
 
862
949
  return list;
@@ -908,17 +995,18 @@ class ConcatenatedModule extends Module {
908
995
  runtimeTemplate,
909
996
  moduleGraph,
910
997
  chunkGraph,
911
- runtime
998
+ runtime: generationRuntime
912
999
  }) {
913
1000
  /** @type {Set<string>} */
914
1001
  const runtimeRequirements = new Set();
1002
+ const runtime = intersectRuntime(generationRuntime, this._runtime);
915
1003
 
916
1004
  const requestShortener = runtimeTemplate.requestShortener;
917
1005
  // Meta info for each module
918
- const modulesWithInfo = this._getModulesWithInfo(moduleGraph, runtime);
919
-
920
- // Create mapping from module to info
921
- const moduleToInfoMap = modulesWithInfoToMap(modulesWithInfo);
1006
+ const [modulesWithInfo, moduleToInfoMap] = this._getModulesWithInfo(
1007
+ moduleGraph,
1008
+ runtime
1009
+ );
922
1010
 
923
1011
  // Set with modules that need a generated namespace object
924
1012
  /** @type {Set<ConcatenatedModuleInfo>} */
@@ -926,9 +1014,9 @@ class ConcatenatedModule extends Module {
926
1014
 
927
1015
  // Generate source code and analyse scopes
928
1016
  // Prepare a ReplaceSource for the final source
929
- for (const info of modulesWithInfo) {
1017
+ for (const info of moduleToInfoMap.values()) {
930
1018
  this._analyseModule(
931
- modulesWithInfo,
1019
+ moduleToInfoMap,
932
1020
  info,
933
1021
  dependencyTemplates,
934
1022
  runtimeTemplate,
@@ -968,16 +1056,20 @@ class ConcatenatedModule extends Module {
968
1056
  // get all global names
969
1057
  for (const info of modulesWithInfo) {
970
1058
  if (info.type === "concatenated") {
971
- const superClassExpressions = [];
972
-
973
1059
  // ignore symbols from moduleScope
974
1060
  if (info.moduleScope) {
975
1061
  ignoredScopes.add(info.moduleScope);
1062
+ }
976
1063
 
977
- // The super class expression in class scopes behaves weird
978
- // We store ranges of all super class expressions to make
979
- // renaming to work correctly
980
- for (const childScope of info.moduleScope.childScopes) {
1064
+ // The super class expression in class scopes behaves weird
1065
+ // We get ranges of all super class expressions to make
1066
+ // renaming to work correctly
1067
+ const superClassCache = new WeakMap();
1068
+ const getSuperClassExpressions = scope => {
1069
+ const cacheEntry = superClassCache.get(scope);
1070
+ if (cacheEntry !== undefined) return cacheEntry;
1071
+ const superClassExpressions = [];
1072
+ for (const childScope of scope.childScopes) {
981
1073
  if (childScope.type !== "class") continue;
982
1074
  const block = childScope.block;
983
1075
  if (
@@ -991,7 +1083,9 @@ class ConcatenatedModule extends Module {
991
1083
  });
992
1084
  }
993
1085
  }
994
- }
1086
+ superClassCache.set(scope, superClassExpressions);
1087
+ return superClassExpressions;
1088
+ };
995
1089
 
996
1090
  // add global symbols
997
1091
  if (info.globalScope) {
@@ -1000,9 +1094,12 @@ class ConcatenatedModule extends Module {
1000
1094
  if (ConcatenationScope.isModuleReference(name)) {
1001
1095
  const match = ConcatenationScope.matchModuleReference(name);
1002
1096
  if (!match) continue;
1097
+ const referencedInfo = modulesWithInfo[match.index];
1098
+ if (referencedInfo.type === "reference")
1099
+ throw new Error("Module reference can't point to a reference");
1003
1100
  const binding = getFinalBinding(
1004
1101
  moduleGraph,
1005
- modulesWithInfo[match.index],
1102
+ referencedInfo,
1006
1103
  match.ids,
1007
1104
  moduleToInfoMap,
1008
1105
  runtime,
@@ -1021,7 +1118,7 @@ class ConcatenatedModule extends Module {
1021
1118
  binding.info.module.identifier(),
1022
1119
  "name" in binding ? binding.name : ""
1023
1120
  );
1024
- for (const expr of superClassExpressions) {
1121
+ for (const expr of getSuperClassExpressions(reference.from)) {
1025
1122
  if (
1026
1123
  expr.range[0] <= reference.identifier.range[0] &&
1027
1124
  expr.range[1] >= reference.identifier.range[1]
@@ -1046,7 +1143,7 @@ class ConcatenatedModule extends Module {
1046
1143
  }
1047
1144
 
1048
1145
  // generate names for symbols
1049
- for (const info of modulesWithInfo) {
1146
+ for (const info of moduleToInfoMap.values()) {
1050
1147
  const { usedNames: namespaceObjectUsedNames } = getUsedNamesInScopeInfo(
1051
1148
  info.module.identifier(),
1052
1149
  ""
@@ -1129,12 +1226,7 @@ class ConcatenatedModule extends Module {
1129
1226
  break;
1130
1227
  }
1131
1228
  }
1132
- if (
1133
- info.module.buildMeta.exportsType === "default" ||
1134
- info.module.buildMeta.exportsType === "flagged" ||
1135
- info.module.buildMeta.exportsType === "dynamic" ||
1136
- !info.module.buildMeta.exportsType
1137
- ) {
1229
+ if (info.module.buildMeta.exportsType !== "namespace") {
1138
1230
  const externalNameInterop = this.findNewName(
1139
1231
  "namespaceObject",
1140
1232
  allUsedNames,
@@ -1144,6 +1236,19 @@ class ConcatenatedModule extends Module {
1144
1236
  allUsedNames.add(externalNameInterop);
1145
1237
  info.interopNamespaceObjectName = externalNameInterop;
1146
1238
  }
1239
+ if (
1240
+ info.module.buildMeta.exportsType === "default" &&
1241
+ info.module.buildMeta.defaultObject !== "redirect"
1242
+ ) {
1243
+ const externalNameInterop = this.findNewName(
1244
+ "namespaceObject2",
1245
+ allUsedNames,
1246
+ namespaceObjectUsedNames,
1247
+ info.module.readableIdentifier(requestShortener)
1248
+ );
1249
+ allUsedNames.add(externalNameInterop);
1250
+ info.interopNamespaceObject2Name = externalNameInterop;
1251
+ }
1147
1252
  if (
1148
1253
  info.module.buildMeta.exportsType === "dynamic" ||
1149
1254
  !info.module.buildMeta.exportsType
@@ -1160,15 +1265,18 @@ class ConcatenatedModule extends Module {
1160
1265
  }
1161
1266
 
1162
1267
  // Find and replace references to modules
1163
- for (const info of modulesWithInfo) {
1268
+ for (const info of moduleToInfoMap.values()) {
1164
1269
  if (info.type === "concatenated") {
1165
1270
  for (const reference of info.globalScope.through) {
1166
1271
  const name = reference.identifier.name;
1167
1272
  const match = ConcatenationScope.matchModuleReference(name);
1168
1273
  if (match) {
1274
+ const referencedInfo = modulesWithInfo[match.index];
1275
+ if (referencedInfo.type === "reference")
1276
+ throw new Error("Module reference can't point to a reference");
1169
1277
  const finalName = getFinalName(
1170
1278
  moduleGraph,
1171
- modulesWithInfo[match.index],
1279
+ referencedInfo,
1172
1280
  match.ids,
1173
1281
  moduleToInfoMap,
1174
1282
  runtime,
@@ -1335,8 +1443,10 @@ ${defineGetters}`
1335
1443
  }
1336
1444
 
1337
1445
  // evaluate modules in order
1338
- for (const info of modulesWithInfo) {
1446
+ for (const rawInfo of modulesWithInfo) {
1339
1447
  let name;
1448
+ let isConditional = false;
1449
+ const info = rawInfo.type === "reference" ? rawInfo.target : rawInfo;
1340
1450
  switch (info.type) {
1341
1451
  case "concatenated": {
1342
1452
  result.add(
@@ -1353,13 +1463,26 @@ ${defineGetters}`
1353
1463
  name = info.namespaceObjectName;
1354
1464
  break;
1355
1465
  }
1356
- case "external":
1466
+ case "external": {
1357
1467
  result.add(
1358
1468
  `\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
1359
1469
  requestShortener
1360
1470
  )}\n`
1361
1471
  );
1362
1472
  runtimeRequirements.add(RuntimeGlobals.require);
1473
+ const {
1474
+ runtimeCondition
1475
+ } = /** @type {ExternalModuleInfo | ReferenceToModuleInfo} */ (rawInfo);
1476
+ const condition = runtimeTemplate.runtimeConditionExpression({
1477
+ chunkGraph,
1478
+ runtimeCondition,
1479
+ runtime,
1480
+ runtimeRequirements
1481
+ });
1482
+ if (condition !== "true") {
1483
+ isConditional = true;
1484
+ result.add(`if (${condition}) {\n`);
1485
+ }
1363
1486
  result.add(
1364
1487
  `var ${info.name} = __webpack_require__(${JSON.stringify(
1365
1488
  chunkGraph.getModuleId(info.module)
@@ -1367,33 +1490,32 @@ ${defineGetters}`
1367
1490
  );
1368
1491
  name = info.name;
1369
1492
  break;
1493
+ }
1370
1494
  default:
1371
1495
  // @ts-expect-error never is expected here
1372
1496
  throw new Error(`Unsupported concatenation entry type ${info.type}`);
1373
1497
  }
1374
1498
  if (info.interopNamespaceObjectUsed) {
1375
- if (info.module.buildMeta.exportsType === "default") {
1376
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
1377
- result.add(
1378
- `\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2);\n`
1379
- );
1380
- } else if (
1381
- info.module.buildMeta.exportsType === "flagged" ||
1382
- info.module.buildMeta.exportsType === "dynamic" ||
1383
- !info.module.buildMeta.exportsType
1384
- ) {
1385
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
1386
- result.add(
1387
- `\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name});\n`
1388
- );
1389
- }
1499
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
1500
+ result.add(
1501
+ `\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2);`
1502
+ );
1503
+ }
1504
+ if (info.interopNamespaceObject2Used) {
1505
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
1506
+ result.add(
1507
+ `\nvar ${info.interopNamespaceObject2Name} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name});`
1508
+ );
1390
1509
  }
1391
1510
  if (info.interopDefaultAccessUsed) {
1392
1511
  runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
1393
1512
  result.add(
1394
- `\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name});\n`
1513
+ `\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name});`
1395
1514
  );
1396
1515
  }
1516
+ if (isConditional) {
1517
+ result.add("\n}");
1518
+ }
1397
1519
  }
1398
1520
 
1399
1521
  /** @type {CodeGenerationResult} */
@@ -1406,7 +1528,7 @@ ${defineGetters}`
1406
1528
  }
1407
1529
 
1408
1530
  /**
1409
- * @param {ModuleInfo[]} modulesWithInfo modulesWithInfo
1531
+ * @param {Map<Module, ModuleInfo>} modulesMap modulesMap
1410
1532
  * @param {ModuleInfo} info info
1411
1533
  * @param {DependencyTemplates} dependencyTemplates dependencyTemplates
1412
1534
  * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
@@ -1415,7 +1537,7 @@ ${defineGetters}`
1415
1537
  * @param {RuntimeSpec} runtime runtime
1416
1538
  */
1417
1539
  _analyseModule(
1418
- modulesWithInfo,
1540
+ modulesMap,
1419
1541
  info,
1420
1542
  dependencyTemplates,
1421
1543
  runtimeTemplate,
@@ -1427,10 +1549,7 @@ ${defineGetters}`
1427
1549
  const m = info.module;
1428
1550
  try {
1429
1551
  // Create a concatenation scope to track and capture information
1430
- const concatenationScope = new ConcatenationScope(
1431
- modulesWithInfo,
1432
- info
1433
- );
1552
+ const concatenationScope = new ConcatenationScope(modulesMap, info);
1434
1553
 
1435
1554
  // TODO cache codeGeneration results
1436
1555
  const codeGenResult = m.codeGeneration({
@@ -1502,7 +1621,7 @@ ${defineGetters}`
1502
1621
  /**
1503
1622
  * @param {ModuleGraph} moduleGraph the module graph
1504
1623
  * @param {RuntimeSpec} runtime the runtime
1505
- * @returns {ModuleInfo[]} module info items
1624
+ * @returns {[ModuleInfoOrReference[], Map<Module, ModuleInfo>]} module info items
1506
1625
  */
1507
1626
  _getModulesWithInfo(moduleGraph, runtime) {
1508
1627
  const orderedConcatenationList = this._createConcatenationList(
@@ -1511,45 +1630,69 @@ ${defineGetters}`
1511
1630
  runtime,
1512
1631
  moduleGraph
1513
1632
  );
1514
- return orderedConcatenationList.map((info, index) => {
1515
- switch (info.type) {
1516
- case "concatenated": {
1517
- return {
1518
- type: "concatenated",
1519
- module: info.module,
1520
- index,
1521
- ast: undefined,
1522
- internalSource: undefined,
1523
- runtimeRequirements: undefined,
1524
- source: undefined,
1525
- globalScope: undefined,
1526
- moduleScope: undefined,
1527
- internalNames: new Map(),
1528
- exportMap: undefined,
1529
- rawExportMap: undefined,
1530
- namespaceExportSymbol: undefined,
1531
- namespaceObjectName: undefined,
1532
- interopNamespaceObjectUsed: false,
1533
- interopNamespaceObjectName: undefined,
1534
- interopDefaultAccessUsed: false,
1535
- interopDefaultAccessName: undefined
1536
- };
1633
+ /** @type {Map<Module, ModuleInfo>} */
1634
+ const map = new Map();
1635
+ const list = orderedConcatenationList.map((info, index) => {
1636
+ let item = map.get(info.module);
1637
+ if (item === undefined) {
1638
+ switch (info.type) {
1639
+ case "concatenated":
1640
+ item = {
1641
+ type: "concatenated",
1642
+ module: info.module,
1643
+ index,
1644
+ ast: undefined,
1645
+ internalSource: undefined,
1646
+ runtimeRequirements: undefined,
1647
+ source: undefined,
1648
+ globalScope: undefined,
1649
+ moduleScope: undefined,
1650
+ internalNames: new Map(),
1651
+ exportMap: undefined,
1652
+ rawExportMap: undefined,
1653
+ namespaceExportSymbol: undefined,
1654
+ namespaceObjectName: undefined,
1655
+ interopNamespaceObjectUsed: false,
1656
+ interopNamespaceObjectName: undefined,
1657
+ interopNamespaceObject2Used: false,
1658
+ interopNamespaceObject2Name: undefined,
1659
+ interopDefaultAccessUsed: false,
1660
+ interopDefaultAccessName: undefined
1661
+ };
1662
+ break;
1663
+ case "external":
1664
+ item = {
1665
+ type: "external",
1666
+ module: info.module,
1667
+ runtimeCondition: info.runtimeCondition,
1668
+ index,
1669
+ name: undefined,
1670
+ interopNamespaceObjectUsed: false,
1671
+ interopNamespaceObjectName: undefined,
1672
+ interopNamespaceObject2Used: false,
1673
+ interopNamespaceObject2Name: undefined,
1674
+ interopDefaultAccessUsed: false,
1675
+ interopDefaultAccessName: undefined
1676
+ };
1677
+ break;
1678
+ default:
1679
+ throw new Error(
1680
+ `Unsupported concatenation entry type ${info.type}`
1681
+ );
1537
1682
  }
1538
- case "external":
1539
- return {
1540
- type: "external",
1541
- module: info.module,
1542
- index,
1543
- name: undefined,
1544
- interopNamespaceObjectUsed: false,
1545
- interopNamespaceObjectName: undefined,
1546
- interopDefaultAccessUsed: false,
1547
- interopDefaultAccessName: undefined
1548
- };
1549
- default:
1550
- throw new Error(`Unsupported concatenation entry type ${info.type}`);
1683
+ map.set(item.module, item);
1684
+ return item;
1685
+ } else {
1686
+ /** @type {ReferenceToModuleInfo} */
1687
+ const ref = {
1688
+ type: "reference",
1689
+ runtimeCondition: info.runtimeCondition,
1690
+ target: item
1691
+ };
1692
+ return ref;
1551
1693
  }
1552
1694
  });
1695
+ return [list, map];
1553
1696
  }
1554
1697
 
1555
1698
  findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
@@ -1601,7 +1744,7 @@ ${defineGetters}`
1601
1744
  for (const info of this._createConcatenationList(
1602
1745
  this.rootModule,
1603
1746
  this._modules,
1604
- runtime,
1747
+ intersectRuntime(runtime, this._runtime),
1605
1748
  chunkGraph.moduleGraph
1606
1749
  )) {
1607
1750
  switch (info.type) {
@@ -1610,6 +1753,7 @@ ${defineGetters}`
1610
1753
  break;
1611
1754
  case "external":
1612
1755
  hash.update(`${chunkGraph.getModuleId(info.module)}`);
1756
+ // TODO runtimeCondition
1613
1757
  break;
1614
1758
  }
1615
1759
  }
@@ -1620,7 +1764,8 @@ ${defineGetters}`
1620
1764
  const obj = new ConcatenatedModule({
1621
1765
  identifier: undefined,
1622
1766
  rootModule: undefined,
1623
- modules: undefined
1767
+ modules: undefined,
1768
+ runtime: undefined
1624
1769
  });
1625
1770
  obj.deserialize(context);
1626
1771
  return obj;