webpack 5.2.1 → 5.3.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.
- package/lib/ChunkGraph.js +19 -0
- package/lib/Compilation.js +25 -4
- package/lib/ConditionalInitFragment.js +109 -0
- package/lib/Dependency.js +1 -0
- package/lib/RuntimeGlobals.js +5 -0
- package/lib/RuntimePlugin.js +8 -0
- package/lib/RuntimeTemplate.js +37 -0
- package/lib/WebpackOptionsApply.js +3 -1
- package/lib/config/defaults.js +1 -1
- package/lib/dependencies/HarmonyAcceptDependency.js +33 -5
- package/lib/dependencies/HarmonyImportDependency.js +70 -28
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +2 -2
- package/lib/dependencies/PureExpressionDependency.js +30 -6
- package/lib/dependencies/WorkerPlugin.js +8 -3
- package/lib/optimize/ConcatenatedModule.js +85 -18
- package/lib/optimize/ModuleConcatenationPlugin.js +71 -6
- package/lib/optimize/SideEffectsFlagPlugin.js +112 -100
- package/lib/runtime/RuntimeIdRuntimeModule.js +29 -0
- package/lib/util/compileBooleanMatcher.js +13 -1
- package/lib/util/runtime.js +62 -0
- package/package.json +1 -1
- package/schemas/WebpackOptions.json +9 -2
- package/types.d.ts +34 -3
@@ -25,6 +25,12 @@ 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
|
+
mergeRuntime,
|
31
|
+
runtimeToString,
|
32
|
+
intersectRuntime
|
33
|
+
} = require("../util/runtime");
|
28
34
|
|
29
35
|
/** @typedef {import("eslint-scope").Scope} Scope */
|
30
36
|
/** @typedef {import("webpack-sources").Source} Source */
|
@@ -103,6 +109,7 @@ const propertyAccess = require("../util/propertyAccess");
|
|
103
109
|
* @typedef {Object} ExternalModuleInfo
|
104
110
|
* @property {"external"} type
|
105
111
|
* @property {Module} module
|
112
|
+
* @property {RuntimeSpec | boolean} runtimeCondition
|
106
113
|
* @property {number} index
|
107
114
|
* @property {string} name
|
108
115
|
* @property {boolean} interopNamespaceObjectUsed
|
@@ -185,6 +192,7 @@ const joinIterableWithComma = iterable => {
|
|
185
192
|
* @typedef {Object} ConcatenationEntry
|
186
193
|
* @property {"concatenated" | "external"} type
|
187
194
|
* @property {Module} module
|
195
|
+
* @property {RuntimeSpec | boolean} runtimeCondition
|
188
196
|
*/
|
189
197
|
|
190
198
|
/**
|
@@ -586,10 +594,11 @@ class ConcatenatedModule extends Module {
|
|
586
594
|
/**
|
587
595
|
* @param {Module} rootModule the root module of the concatenation
|
588
596
|
* @param {Set<Module>} modules all modules in the concatenation (including the root module)
|
597
|
+
* @param {RuntimeSpec} runtime the runtime
|
589
598
|
* @param {Object=} associatedObjectForCache object for caching
|
590
599
|
* @returns {ConcatenatedModule} the module
|
591
600
|
*/
|
592
|
-
static create(rootModule, modules, associatedObjectForCache) {
|
601
|
+
static create(rootModule, modules, runtime, associatedObjectForCache) {
|
593
602
|
const identifier = ConcatenatedModule._createIdentifier(
|
594
603
|
rootModule,
|
595
604
|
modules,
|
@@ -598,7 +607,8 @@ class ConcatenatedModule extends Module {
|
|
598
607
|
return new ConcatenatedModule({
|
599
608
|
identifier,
|
600
609
|
rootModule,
|
601
|
-
modules
|
610
|
+
modules,
|
611
|
+
runtime
|
602
612
|
});
|
603
613
|
}
|
604
614
|
|
@@ -606,9 +616,10 @@ class ConcatenatedModule extends Module {
|
|
606
616
|
* @param {Object} options options
|
607
617
|
* @param {string} options.identifier the identifier of the module
|
608
618
|
* @param {Module=} options.rootModule the root module of the concatenation
|
619
|
+
* @param {RuntimeSpec} options.runtime the selected runtime
|
609
620
|
* @param {Set<Module>=} options.modules all concatenated modules
|
610
621
|
*/
|
611
|
-
constructor({ identifier, rootModule, modules }) {
|
622
|
+
constructor({ identifier, rootModule, modules, runtime }) {
|
612
623
|
super("javascript/esm", null);
|
613
624
|
|
614
625
|
// Info from Factory
|
@@ -618,6 +629,7 @@ class ConcatenatedModule extends Module {
|
|
618
629
|
this.rootModule = rootModule;
|
619
630
|
/** @type {Set<Module>} */
|
620
631
|
this._modules = modules;
|
632
|
+
this._runtime = runtime;
|
621
633
|
this.factoryMeta = rootModule && rootModule.factoryMeta;
|
622
634
|
|
623
635
|
// Caching
|
@@ -637,6 +649,7 @@ class ConcatenatedModule extends Module {
|
|
637
649
|
this._identifier = m._identifier;
|
638
650
|
this.rootModule = m.rootModule;
|
639
651
|
this._modules = m._modules;
|
652
|
+
this._runtime = m._runtime;
|
640
653
|
}
|
641
654
|
/**
|
642
655
|
* @returns {Set<string>} types available (do not mutate)
|
@@ -789,7 +802,7 @@ class ConcatenatedModule extends Module {
|
|
789
802
|
|
790
803
|
/**
|
791
804
|
* @param {Module} module a module
|
792
|
-
* @returns {ModuleGraphConnection
|
805
|
+
* @returns {Iterable<{ connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | boolean }>} imported modules in order
|
793
806
|
*/
|
794
807
|
const getConcatenatedImports = module => {
|
795
808
|
let connections = Array.from(moduleGraph.getOutgoingConnections(module));
|
@@ -816,14 +829,38 @@ class ConcatenatedModule extends Module {
|
|
816
829
|
references.sort(
|
817
830
|
concatComparators(bySourceOrder, keepOriginalOrder(references))
|
818
831
|
);
|
819
|
-
|
832
|
+
/** @type {Map<Module, { connection, runtimeCondition }>} */
|
833
|
+
const referencesMap = new Map();
|
834
|
+
for (const { connection } of references) {
|
835
|
+
const runtimeCondition = filterRuntime(runtime, r =>
|
836
|
+
connection.isTargetActive(r)
|
837
|
+
);
|
838
|
+
const module = connection.module;
|
839
|
+
const entry = referencesMap.get(module);
|
840
|
+
if (entry === undefined) {
|
841
|
+
referencesMap.set(module, { connection, runtimeCondition });
|
842
|
+
continue;
|
843
|
+
}
|
844
|
+
if (runtimeCondition === false || entry.runtimeCondition === true)
|
845
|
+
continue;
|
846
|
+
if (entry.runtimeCondition === false || runtimeCondition === true) {
|
847
|
+
entry.runtimeCondition = runtimeCondition;
|
848
|
+
continue;
|
849
|
+
}
|
850
|
+
entry.runtimeCondition = mergeRuntime(
|
851
|
+
entry.runtimeCondition,
|
852
|
+
runtimeCondition
|
853
|
+
);
|
854
|
+
}
|
855
|
+
return referencesMap.values();
|
820
856
|
};
|
821
857
|
|
822
858
|
/**
|
823
859
|
* @param {ModuleGraphConnection} connection graph connection
|
860
|
+
* @param {RuntimeSpec | boolean} runtimeCondition runtime condition
|
824
861
|
* @returns {void}
|
825
862
|
*/
|
826
|
-
const enterModule = connection => {
|
863
|
+
const enterModule = (connection, runtimeCondition) => {
|
827
864
|
const module = connection.module;
|
828
865
|
if (!module) return;
|
829
866
|
if (existingEntries.has(module)) {
|
@@ -831,11 +868,20 @@ class ConcatenatedModule extends Module {
|
|
831
868
|
}
|
832
869
|
if (modulesSet.has(module)) {
|
833
870
|
existingEntries.add(module);
|
871
|
+
if (runtimeCondition !== true) {
|
872
|
+
throw new Error(
|
873
|
+
`Cannot runtime-conditional concatenate a module (${module.identifier()} in ${this.rootModule.identifier()}, ${
|
874
|
+
runtimeCondition && runtimeToString(runtimeCondition)
|
875
|
+
}). This should not happen.`
|
876
|
+
);
|
877
|
+
}
|
834
878
|
const imports = getConcatenatedImports(module);
|
835
|
-
imports
|
879
|
+
for (const { connection, runtimeCondition } of imports)
|
880
|
+
enterModule(connection, runtimeCondition);
|
836
881
|
list.push({
|
837
882
|
type: "concatenated",
|
838
|
-
module: connection.module
|
883
|
+
module: connection.module,
|
884
|
+
runtimeCondition
|
839
885
|
});
|
840
886
|
} else {
|
841
887
|
existingEntries.add(connection.module);
|
@@ -846,17 +892,20 @@ class ConcatenatedModule extends Module {
|
|
846
892
|
// could be replaced by some other process (i. e. also replaced with a
|
847
893
|
// concatenated module)
|
848
894
|
return connection.module;
|
849
|
-
}
|
895
|
+
},
|
896
|
+
runtimeCondition
|
850
897
|
});
|
851
898
|
}
|
852
899
|
};
|
853
900
|
|
854
901
|
existingEntries.add(rootModule);
|
855
902
|
const imports = getConcatenatedImports(rootModule);
|
856
|
-
imports
|
903
|
+
for (const { connection, runtimeCondition } of imports)
|
904
|
+
enterModule(connection, runtimeCondition);
|
857
905
|
list.push({
|
858
906
|
type: "concatenated",
|
859
|
-
module: rootModule
|
907
|
+
module: rootModule,
|
908
|
+
runtimeCondition: true
|
860
909
|
});
|
861
910
|
|
862
911
|
return list;
|
@@ -908,10 +957,11 @@ class ConcatenatedModule extends Module {
|
|
908
957
|
runtimeTemplate,
|
909
958
|
moduleGraph,
|
910
959
|
chunkGraph,
|
911
|
-
runtime
|
960
|
+
runtime: generationRuntime
|
912
961
|
}) {
|
913
962
|
/** @type {Set<string>} */
|
914
963
|
const runtimeRequirements = new Set();
|
964
|
+
const runtime = intersectRuntime(generationRuntime, this._runtime);
|
915
965
|
|
916
966
|
const requestShortener = runtimeTemplate.requestShortener;
|
917
967
|
// Meta info for each module
|
@@ -1337,6 +1387,7 @@ ${defineGetters}`
|
|
1337
1387
|
// evaluate modules in order
|
1338
1388
|
for (const info of modulesWithInfo) {
|
1339
1389
|
let name;
|
1390
|
+
let isConditional = false;
|
1340
1391
|
switch (info.type) {
|
1341
1392
|
case "concatenated": {
|
1342
1393
|
result.add(
|
@@ -1353,13 +1404,23 @@ ${defineGetters}`
|
|
1353
1404
|
name = info.namespaceObjectName;
|
1354
1405
|
break;
|
1355
1406
|
}
|
1356
|
-
case "external":
|
1407
|
+
case "external": {
|
1357
1408
|
result.add(
|
1358
1409
|
`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(
|
1359
1410
|
requestShortener
|
1360
1411
|
)}\n`
|
1361
1412
|
);
|
1362
1413
|
runtimeRequirements.add(RuntimeGlobals.require);
|
1414
|
+
const condition = runtimeTemplate.runtimeConditionExpression({
|
1415
|
+
chunkGraph,
|
1416
|
+
runtimeCondition: info.runtimeCondition,
|
1417
|
+
runtime,
|
1418
|
+
runtimeRequirements
|
1419
|
+
});
|
1420
|
+
if (condition !== "true") {
|
1421
|
+
isConditional = true;
|
1422
|
+
result.add(`if (${condition}) {\n`);
|
1423
|
+
}
|
1363
1424
|
result.add(
|
1364
1425
|
`var ${info.name} = __webpack_require__(${JSON.stringify(
|
1365
1426
|
chunkGraph.getModuleId(info.module)
|
@@ -1367,6 +1428,7 @@ ${defineGetters}`
|
|
1367
1428
|
);
|
1368
1429
|
name = info.name;
|
1369
1430
|
break;
|
1431
|
+
}
|
1370
1432
|
default:
|
1371
1433
|
// @ts-expect-error never is expected here
|
1372
1434
|
throw new Error(`Unsupported concatenation entry type ${info.type}`);
|
@@ -1375,7 +1437,7 @@ ${defineGetters}`
|
|
1375
1437
|
if (info.module.buildMeta.exportsType === "default") {
|
1376
1438
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
1377
1439
|
result.add(
|
1378
|
-
`\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2)
|
1440
|
+
`\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name}, 2);`
|
1379
1441
|
);
|
1380
1442
|
} else if (
|
1381
1443
|
info.module.buildMeta.exportsType === "flagged" ||
|
@@ -1384,16 +1446,19 @@ ${defineGetters}`
|
|
1384
1446
|
) {
|
1385
1447
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
1386
1448
|
result.add(
|
1387
|
-
`\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name})
|
1449
|
+
`\nvar ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${name});`
|
1388
1450
|
);
|
1389
1451
|
}
|
1390
1452
|
}
|
1391
1453
|
if (info.interopDefaultAccessUsed) {
|
1392
1454
|
runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
|
1393
1455
|
result.add(
|
1394
|
-
`\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name})
|
1456
|
+
`\nvar ${info.interopDefaultAccessName} = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${name});`
|
1395
1457
|
);
|
1396
1458
|
}
|
1459
|
+
if (isConditional) {
|
1460
|
+
result.add("\n}");
|
1461
|
+
}
|
1397
1462
|
}
|
1398
1463
|
|
1399
1464
|
/** @type {CodeGenerationResult} */
|
@@ -1539,6 +1604,7 @@ ${defineGetters}`
|
|
1539
1604
|
return {
|
1540
1605
|
type: "external",
|
1541
1606
|
module: info.module,
|
1607
|
+
runtimeCondition: info.runtimeCondition,
|
1542
1608
|
index,
|
1543
1609
|
name: undefined,
|
1544
1610
|
interopNamespaceObjectUsed: false,
|
@@ -1601,7 +1667,7 @@ ${defineGetters}`
|
|
1601
1667
|
for (const info of this._createConcatenationList(
|
1602
1668
|
this.rootModule,
|
1603
1669
|
this._modules,
|
1604
|
-
runtime,
|
1670
|
+
intersectRuntime(runtime, this._runtime),
|
1605
1671
|
chunkGraph.moduleGraph
|
1606
1672
|
)) {
|
1607
1673
|
switch (info.type) {
|
@@ -1620,7 +1686,8 @@ ${defineGetters}`
|
|
1620
1686
|
const obj = new ConcatenatedModule({
|
1621
1687
|
identifier: undefined,
|
1622
1688
|
rootModule: undefined,
|
1623
|
-
modules: undefined
|
1689
|
+
modules: undefined,
|
1690
|
+
runtime: undefined
|
1624
1691
|
});
|
1625
1692
|
obj.deserialize(context);
|
1626
1693
|
return obj;
|
@@ -14,7 +14,13 @@ const { STAGE_DEFAULT } = require("../OptimizationStages");
|
|
14
14
|
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
|
15
15
|
const StackedMap = require("../util/StackedMap");
|
16
16
|
const { compareModulesByIdentifier } = require("../util/comparators");
|
17
|
-
const {
|
17
|
+
const {
|
18
|
+
intersectRuntime,
|
19
|
+
mergeRuntimeOwned,
|
20
|
+
filterRuntime,
|
21
|
+
runtimeToString,
|
22
|
+
mergeRuntime
|
23
|
+
} = require("../util/runtime");
|
18
24
|
const ConcatenatedModule = require("./ConcatenatedModule");
|
19
25
|
|
20
26
|
/** @typedef {import("../Compilation")} Compilation */
|
@@ -211,13 +217,26 @@ class ModuleConcatenationPlugin {
|
|
211
217
|
// the other configuration is better and we can skip this one
|
212
218
|
if (usedAsInner.has(currentRoot)) continue;
|
213
219
|
|
214
|
-
let
|
220
|
+
let chunkRuntime = undefined;
|
215
221
|
for (const r of chunkGraph.getModuleRuntimes(currentRoot)) {
|
216
|
-
|
222
|
+
chunkRuntime = mergeRuntimeOwned(chunkRuntime, r);
|
217
223
|
}
|
224
|
+
const exportsInfo = moduleGraph.getExportsInfo(currentRoot);
|
225
|
+
const filteredRuntime = filterRuntime(chunkRuntime, r =>
|
226
|
+
exportsInfo.isModuleUsed(r)
|
227
|
+
);
|
228
|
+
const runtime =
|
229
|
+
filteredRuntime === true
|
230
|
+
? chunkRuntime
|
231
|
+
: filteredRuntime === false
|
232
|
+
? undefined
|
233
|
+
: filteredRuntime;
|
218
234
|
|
219
235
|
// create a configuration with the root
|
220
|
-
const currentConfiguration = new ConcatConfiguration(
|
236
|
+
const currentConfiguration = new ConcatConfiguration(
|
237
|
+
currentRoot,
|
238
|
+
runtime
|
239
|
+
);
|
221
240
|
|
222
241
|
// cache failures to add modules
|
223
242
|
const failureCache = new Map();
|
@@ -313,6 +332,7 @@ class ModuleConcatenationPlugin {
|
|
313
332
|
let newModule = ConcatenatedModule.create(
|
314
333
|
rootModule,
|
315
334
|
modules,
|
335
|
+
concatConfiguration.runtime,
|
316
336
|
compiler.root
|
317
337
|
);
|
318
338
|
|
@@ -657,6 +677,50 @@ class ModuleConcatenationPlugin {
|
|
657
677
|
return problem;
|
658
678
|
}
|
659
679
|
|
680
|
+
if (runtime !== undefined && typeof runtime !== "string") {
|
681
|
+
// Module must be consistently referenced in the same runtimes
|
682
|
+
/** @type {Map<Module, boolean | RuntimeSpec>} */
|
683
|
+
const runtimeConditionMap = new Map();
|
684
|
+
for (const connection of incomingConnections) {
|
685
|
+
const runtimeCondition = filterRuntime(runtime, runtime => {
|
686
|
+
return connection.isTargetActive(runtime);
|
687
|
+
});
|
688
|
+
if (runtimeCondition === false) continue;
|
689
|
+
const old = runtimeConditionMap.get(connection.originModule) || false;
|
690
|
+
if (old === true) continue;
|
691
|
+
if (old !== false && runtimeCondition !== true) {
|
692
|
+
runtimeConditionMap.set(
|
693
|
+
connection.originModule,
|
694
|
+
mergeRuntime(old, runtimeCondition)
|
695
|
+
);
|
696
|
+
} else {
|
697
|
+
runtimeConditionMap.set(connection.originModule, runtimeCondition);
|
698
|
+
}
|
699
|
+
}
|
700
|
+
const otherRuntimeConnections = Array.from(runtimeConditionMap).filter(
|
701
|
+
([, runtimeCondition]) => typeof runtimeCondition !== "boolean"
|
702
|
+
);
|
703
|
+
if (otherRuntimeConnections.length > 0) {
|
704
|
+
const problem = requestShortener => {
|
705
|
+
return `Module ${module.readableIdentifier(
|
706
|
+
requestShortener
|
707
|
+
)} is runtime-dependent referenced by these modules: ${Array.from(
|
708
|
+
otherRuntimeConnections,
|
709
|
+
([module, runtimeCondition]) =>
|
710
|
+
`${module.readableIdentifier(
|
711
|
+
requestShortener
|
712
|
+
)} (expected runtime ${runtimeToString(
|
713
|
+
runtime
|
714
|
+
)}, module is only referenced in ${runtimeToString(
|
715
|
+
/** @type {RuntimeSpec} */ (runtimeCondition)
|
716
|
+
)})`
|
717
|
+
).join(", ")}`;
|
718
|
+
};
|
719
|
+
failureCache.set(module, problem); // cache failures for performance
|
720
|
+
return problem;
|
721
|
+
}
|
722
|
+
}
|
723
|
+
|
660
724
|
const incomingModules = Array.from(
|
661
725
|
new Set(incomingConnections.map(c => c.originModule))
|
662
726
|
).sort(compareModulesByIdentifier);
|
@@ -689,11 +753,12 @@ class ModuleConcatenationPlugin {
|
|
689
753
|
|
690
754
|
class ConcatConfiguration {
|
691
755
|
/**
|
692
|
-
*
|
693
756
|
* @param {Module} rootModule the root module
|
757
|
+
* @param {RuntimeSpec} runtime the runtime
|
694
758
|
*/
|
695
|
-
constructor(rootModule) {
|
759
|
+
constructor(rootModule, runtime) {
|
696
760
|
this.rootModule = rootModule;
|
761
|
+
this.runtime = runtime;
|
697
762
|
/** @type {StackedMap<Module, true>} */
|
698
763
|
this.modules = new StackedMap();
|
699
764
|
this.modules.set(rootModule, true);
|
@@ -50,6 +50,12 @@ const globToRegexp = (glob, cache) => {
|
|
50
50
|
};
|
51
51
|
|
52
52
|
class SideEffectsFlagPlugin {
|
53
|
+
/**
|
54
|
+
* @param {boolean} analyseSource analyse source code for side effects
|
55
|
+
*/
|
56
|
+
constructor(analyseSource = true) {
|
57
|
+
this._analyseSource = analyseSource;
|
58
|
+
}
|
53
59
|
/**
|
54
60
|
* Apply the plugin
|
55
61
|
* @param {Compiler} compiler the compiler instance
|
@@ -98,108 +104,114 @@ class SideEffectsFlagPlugin {
|
|
98
104
|
}
|
99
105
|
return module;
|
100
106
|
});
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
statement.init
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
107
|
+
if (this._analyseSource) {
|
108
|
+
/**
|
109
|
+
* @param {JavascriptParser} parser the parser
|
110
|
+
* @returns {void}
|
111
|
+
*/
|
112
|
+
const parserHandler = parser => {
|
113
|
+
let hasSideEffects = false;
|
114
|
+
parser.hooks.program.tap("SideEffectsFlagPlugin", () => {
|
115
|
+
hasSideEffects = false;
|
116
|
+
});
|
117
|
+
parser.hooks.statement.tap(
|
118
|
+
{ name: "SideEffectsFlagPlugin", stage: -100 },
|
119
|
+
statement => {
|
120
|
+
if (hasSideEffects) return;
|
121
|
+
if (parser.scope.topLevelScope !== true) return;
|
122
|
+
switch (statement.type) {
|
123
|
+
case "ExpressionStatement":
|
124
|
+
if (
|
125
|
+
!parser.isPure(statement.expression, statement.range[0])
|
126
|
+
) {
|
127
|
+
hasSideEffects = true;
|
128
|
+
}
|
129
|
+
break;
|
130
|
+
case "IfStatement":
|
131
|
+
case "WhileStatement":
|
132
|
+
case "DoWhileStatement":
|
133
|
+
if (!parser.isPure(statement.test, statement.range[0])) {
|
134
|
+
hasSideEffects = true;
|
135
|
+
}
|
136
|
+
// statement hook will be called for child statements too
|
137
|
+
break;
|
138
|
+
case "ForStatement":
|
139
|
+
if (
|
140
|
+
!parser.isPure(statement.init, statement.range[0]) ||
|
141
|
+
!parser.isPure(
|
142
|
+
statement.test,
|
143
|
+
statement.init
|
144
|
+
? statement.init.range[1]
|
145
|
+
: statement.range[0]
|
146
|
+
) ||
|
147
|
+
!parser.isPure(
|
148
|
+
statement.update,
|
149
|
+
statement.test
|
150
|
+
? statement.test.range[1]
|
151
|
+
: statement.init
|
152
|
+
? statement.init.range[1]
|
153
|
+
: statement.range[0]
|
154
|
+
)
|
155
|
+
) {
|
156
|
+
hasSideEffects = true;
|
157
|
+
}
|
158
|
+
// statement hook will be called for child statements too
|
159
|
+
break;
|
160
|
+
case "SwitchStatement":
|
161
|
+
if (
|
162
|
+
!parser.isPure(statement.discriminant, statement.range[0])
|
163
|
+
) {
|
164
|
+
hasSideEffects = true;
|
165
|
+
}
|
166
|
+
// statement hook will be called for child statements too
|
167
|
+
break;
|
168
|
+
case "VariableDeclaration":
|
169
|
+
case "ClassDeclaration":
|
170
|
+
case "FunctionDeclaration":
|
171
|
+
if (!parser.isPure(statement, statement.range[0])) {
|
172
|
+
hasSideEffects = true;
|
173
|
+
}
|
174
|
+
break;
|
175
|
+
case "ExportDefaultDeclaration":
|
176
|
+
if (
|
177
|
+
!parser.isPure(statement.declaration, statement.range[0])
|
178
|
+
) {
|
179
|
+
hasSideEffects = true;
|
180
|
+
}
|
181
|
+
break;
|
182
|
+
case "ExportNamedDeclaration":
|
183
|
+
if (statement.source) {
|
184
|
+
hasSideEffects = true;
|
185
|
+
}
|
186
|
+
break;
|
187
|
+
case "LabeledStatement":
|
188
|
+
case "BlockStatement":
|
189
|
+
// statement hook will be called for child statements too
|
190
|
+
break;
|
191
|
+
case "EmptyStatement":
|
192
|
+
break;
|
193
|
+
case "ImportDeclaration":
|
194
|
+
// imports will be handled by the dependencies
|
195
|
+
break;
|
196
|
+
default:
|
173
197
|
hasSideEffects = true;
|
174
|
-
|
175
|
-
|
176
|
-
case "LabeledStatement":
|
177
|
-
case "BlockStatement":
|
178
|
-
// statement hook will be called for child statements too
|
179
|
-
break;
|
180
|
-
case "EmptyStatement":
|
181
|
-
break;
|
182
|
-
case "ImportDeclaration":
|
183
|
-
// imports will be handled by the dependencies
|
184
|
-
break;
|
185
|
-
default:
|
186
|
-
hasSideEffects = true;
|
187
|
-
break;
|
198
|
+
break;
|
199
|
+
}
|
188
200
|
}
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
}
|
195
|
-
}
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
201
|
+
);
|
202
|
+
parser.hooks.finish.tap("SideEffectsFlagPlugin", () => {
|
203
|
+
if (!hasSideEffects) {
|
204
|
+
parser.state.module.buildMeta.sideEffectFree = true;
|
205
|
+
}
|
206
|
+
});
|
207
|
+
};
|
208
|
+
for (const key of [
|
209
|
+
"javascript/auto",
|
210
|
+
"javascript/esm",
|
211
|
+
"javascript/dynamic"
|
212
|
+
]) {
|
213
|
+
nmf.hooks.parser.for(key).tap("SideEffectsFlagPlugin", parserHandler);
|
214
|
+
}
|
203
215
|
}
|
204
216
|
});
|
205
217
|
compiler.hooks.compilation.tap("SideEffectsFlagPlugin", compilation => {
|
@@ -0,0 +1,29 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
*/
|
4
|
+
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const RuntimeGlobals = require("../RuntimeGlobals");
|
8
|
+
const RuntimeModule = require("../RuntimeModule");
|
9
|
+
|
10
|
+
class RuntimeIdRuntimeModule extends RuntimeModule {
|
11
|
+
constructor() {
|
12
|
+
super("runtimeId");
|
13
|
+
}
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @returns {string} runtime code
|
17
|
+
*/
|
18
|
+
generate() {
|
19
|
+
const { chunk, compilation } = this;
|
20
|
+
const { chunkGraph } = compilation;
|
21
|
+
const runtime = chunk.runtime;
|
22
|
+
if (typeof runtime !== "string")
|
23
|
+
throw new Error("RuntimeIdRuntimeModule must be in a single runtime");
|
24
|
+
const id = chunkGraph.getRuntimeId(runtime);
|
25
|
+
return `${RuntimeGlobals.runtimeId} = ${JSON.stringify(id)};`;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
module.exports = RuntimeIdRuntimeModule;
|
@@ -25,6 +25,17 @@ const compileBooleanMatcher = map => {
|
|
25
25
|
const negativeItems = Object.keys(map).filter(i => !map[i]);
|
26
26
|
if (positiveItems.length === 0) return false;
|
27
27
|
if (negativeItems.length === 0) return true;
|
28
|
+
return compileBooleanMatcherFromLists(positiveItems, negativeItems);
|
29
|
+
};
|
30
|
+
|
31
|
+
/**
|
32
|
+
* @param {string[]} positiveItems positive items
|
33
|
+
* @param {string[]} negativeItems negative items
|
34
|
+
* @returns {function(string): string} a template function to determine the value at runtime
|
35
|
+
*/
|
36
|
+
const compileBooleanMatcherFromLists = (positiveItems, negativeItems) => {
|
37
|
+
if (positiveItems.length === 0) return () => "false";
|
38
|
+
if (negativeItems.length === 0) return () => "true";
|
28
39
|
if (positiveItems.length === 1)
|
29
40
|
return value => `${toSimpleString(positiveItems[0])} == ${value}`;
|
30
41
|
if (negativeItems.length === 1)
|
@@ -188,5 +199,6 @@ const itemsToRegexp = itemsArr => {
|
|
188
199
|
return `(${conditional.join("|")})`;
|
189
200
|
};
|
190
201
|
|
202
|
+
compileBooleanMatcher.fromLists = compileBooleanMatcherFromLists;
|
203
|
+
compileBooleanMatcher.itemsToRegexp = itemsToRegexp;
|
191
204
|
module.exports = compileBooleanMatcher;
|
192
|
-
module.exports.itemsToRegexp = itemsToRegexp;
|