webpack 3.3.0 → 3.5.1

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.
Files changed (40) hide show
  1. package/README.md +34 -11
  2. package/bin/config-optimist.js +1 -0
  3. package/bin/config-yargs.js +12 -4
  4. package/bin/convert-argv.js +28 -8
  5. package/bin/webpack.js +198 -182
  6. package/lib/ContextModule.js +87 -13
  7. package/lib/DelegatedModule.js +10 -4
  8. package/lib/DelegatedModuleFactoryPlugin.js +5 -4
  9. package/lib/DelegatedPlugin.js +3 -0
  10. package/lib/DllReferencePlugin.js +3 -0
  11. package/lib/ExternalModule.js +6 -1
  12. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  13. package/lib/HotModuleReplacement.runtime.js +13 -5
  14. package/lib/MultiCompiler.js +2 -2
  15. package/lib/NormalModule.js +32 -9
  16. package/lib/NormalModuleFactory.js +133 -145
  17. package/lib/Parser.js +52 -58
  18. package/lib/RecordIdsPlugin.js +3 -3
  19. package/lib/SourceMapDevToolPlugin.js +57 -41
  20. package/lib/Stats.js +58 -24
  21. package/lib/Template.js +1 -1
  22. package/lib/dependencies/DelegatedExportsDependency.js +33 -0
  23. package/lib/dependencies/HarmonyCompatibilityDependency.js +1 -1
  24. package/lib/dependencies/ImportParserPlugin.js +11 -4
  25. package/lib/dependencies/ImportPlugin.js +8 -0
  26. package/lib/dependencies/ImportWeakContextDependency.js +22 -0
  27. package/lib/dependencies/ImportWeakDependency.js +47 -0
  28. package/lib/dependencies/RequireContextDependency.js +5 -1
  29. package/lib/dependencies/RequireContextDependencyParserPlugin.js +9 -1
  30. package/lib/dependencies/RequireResolveDependencyParserPlugin.js +1 -1
  31. package/lib/optimize/AggressiveMergingPlugin.js +27 -33
  32. package/lib/optimize/AggressiveSplittingPlugin.js +46 -33
  33. package/lib/optimize/ChunkModuleIdRangePlugin.js +1 -3
  34. package/lib/optimize/CommonsChunkPlugin.js +11 -4
  35. package/lib/optimize/ConcatenatedModule.js +403 -229
  36. package/lib/optimize/ModuleConcatenationPlugin.js +30 -35
  37. package/lib/util/identifier.js +23 -1
  38. package/lib/webpack.js +52 -55
  39. package/package.json +10 -10
  40. package/schemas/webpackOptionsSchema.json +27 -12
@@ -19,39 +19,74 @@ const HarmonyExportImportedSpecifierDependency = require("../dependencies/Harmon
19
19
  const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
20
20
  const HarmonyModulesHelpers = require("../dependencies/HarmonyModulesHelpers");
21
21
 
22
- function getFinalName(info, exportName, moduleToInfoMap, requestShortener) {
23
- const directExport = info.exportMap.get(exportName);
24
- if(directExport) {
25
- if(exportName === true)
26
- info.needNamespaceObject = true;
27
- const name = info.internalNames.get(directExport);
28
- if(!name)
29
- throw new Error(`The export "${directExport}" in "${info.module.readableIdentifier(requestShortener)}" has no internal name`);
30
- return name;
31
- }
32
- const reexport = info.reexportMap.get(exportName);
33
- if(reexport) {
34
- const refInfo = moduleToInfoMap.get(reexport.module);
35
- if(refInfo) {
36
- // module is in the concatenation
37
- return getFinalName(refInfo, reexport.exportName, moduleToInfoMap, requestShortener);
38
- } else {
39
- const dep = reexport.dependency;
40
- const importedModule = reexport.module;
41
- const exportName = reexport.exportName;
42
- const isHarmonyModule = importedModule && (!importedModule.meta || importedModule.meta.harmonyModule);
43
- const importedVar = dep.importedVar;
44
- const used = importedModule.isUsed(exportName);
45
- if(!used) return "/* unused reexport */undefined";
46
- if(!isHarmonyModule && exportName === "default") {
47
- return `${importedVar}_default.a`;
48
- }
49
- return `${importedVar}[${JSON.stringify(used)}]`;
22
+ function ensureNsObjSource(info, moduleToInfoMap, requestShortener) {
23
+ if(!info.hasNamespaceObject) {
24
+ info.hasNamespaceObject = true;
25
+ const name = info.exportMap.get(true);
26
+ const nsObj = [`var ${name} = {};`];
27
+ for(const exportName of info.module.providedExports) {
28
+ const finalName = getFinalName(info, exportName, moduleToInfoMap, requestShortener, false);
29
+ nsObj.push(`__webpack_require__.d(${name}, ${JSON.stringify(exportName)}, function() { return ${finalName}; });`);
50
30
  }
31
+ info.namespaceObjectSource = nsObj.join("\n") + "\n";
32
+ }
33
+ }
34
+
35
+ function getExternalImport(importedModule, importedVar, exportName, asCall) {
36
+ const isHarmonyModule = importedModule && (!importedModule.meta || importedModule.meta.harmonyModule);
37
+ if(exportName === true) return importedVar;
38
+ const used = importedModule.isUsed(exportName);
39
+ if(!used) return "/* unused reexport */undefined";
40
+ if(!isHarmonyModule && exportName === "default") {
41
+ return asCall ? `${importedVar}_default()` : `${importedVar}_default.a`;
42
+ }
43
+ // TODO use Template.toNormalComment when merging with pure-module
44
+ const comment = used !== exportName ? ` /* ${exportName} */` : "";
45
+ const reference = `${importedVar}[${JSON.stringify(used)}${comment}]`;
46
+ if(asCall)
47
+ return `Object(${reference})`;
48
+ return reference;
49
+ }
50
+
51
+ function getFinalName(info, exportName, moduleToInfoMap, requestShortener, asCall) {
52
+ switch(info.type) {
53
+ case "concatenated":
54
+ {
55
+ const directExport = info.exportMap.get(exportName);
56
+ if(directExport) {
57
+ if(exportName === true)
58
+ ensureNsObjSource(info, moduleToInfoMap, requestShortener);
59
+ const name = info.internalNames.get(directExport);
60
+ if(!name)
61
+ throw new Error(`The export "${directExport}" in "${info.module.readableIdentifier(requestShortener)}" has no internal name`);
62
+ return name;
63
+ }
64
+ const reexport = info.reexportMap.get(exportName);
65
+ if(reexport) {
66
+ const refInfo = moduleToInfoMap.get(reexport.module);
67
+ if(refInfo) {
68
+ // module is in the concatenation
69
+ return getFinalName(refInfo, reexport.exportName, moduleToInfoMap, requestShortener, asCall);
70
+ } else {
71
+ const dep = reexport.dependency;
72
+ const importedModule = reexport.module;
73
+ const exportName = reexport.exportName;
74
+ const importedVar = dep.importedVar;
75
+ return getExternalImport(importedModule, importedVar, exportName, asCall);
76
+ }
77
+ }
78
+ const problem = `Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier(requestShortener)}"` +
79
+ ` (known exports: ${Array.from(info.exportMap.keys()).filter(name => name !== true).join(" ")}, ` +
80
+ `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`;
81
+ // TODO use Template.toNormalComment when merging with pure-module
82
+ return `/* ${problem} */ undefined`;
83
+ }
84
+ case "external":
85
+ {
86
+ const importedModule = info.module;
87
+ return getExternalImport(importedModule, info.name, exportName, asCall);
88
+ }
51
89
  }
52
- throw new Error(`Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier(requestShortener)}"` +
53
- ` (known exports: ${Array.from(info.exportMap.keys()).join(" ")}, ` +
54
- `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`);
55
90
  }
56
91
 
57
92
  function getSymbolsFromScope(s, untilScope) {
@@ -134,7 +169,6 @@ class ConcatenatedModule extends Module {
134
169
  super();
135
170
  super.setChunks(rootModule._chunks);
136
171
  this.rootModule = rootModule;
137
- this.modules = modules;
138
172
  this.usedExports = rootModule.usedExports;
139
173
  this.providedExports = rootModule.providedExports;
140
174
  this.optimizationBailout = rootModule.optimizationBailout;
@@ -150,6 +184,7 @@ class ConcatenatedModule extends Module {
150
184
  this.moduleArgument = rootModule.moduleArgument;
151
185
  this.exportsArgument = rootModule.exportsArgument;
152
186
  this.strict = true;
187
+ this._numberOfConcatenatedModules = modules.length;
153
188
 
154
189
  this.dependencies = [];
155
190
  this.dependenciesWarnings = [];
@@ -159,33 +194,38 @@ class ConcatenatedModule extends Module {
159
194
  this.warnings = [];
160
195
  this.errors = [];
161
196
  this.assets = {};
162
- for(const m of modules) {
163
- // populate dependencies
164
- m.dependencies.filter(dep => !modulesSet.has(dep.module))
165
- .forEach(d => this.dependencies.push(d));
166
- // populate dep warning
167
- m.dependenciesWarnings.forEach(depWarning => this.dependenciesWarnings.push(depWarning));
168
- // populate dep errors
169
- m.dependenciesErrors.forEach(depError => this.dependenciesErrors.push(depError));
170
- // populate file dependencies
171
- if(m.fileDependencies) m.fileDependencies.forEach(file => this.fileDependencies.push(file));
172
- // populate context dependencies
173
- if(m.contextDependencies) m.contextDependencies.forEach(context => this.contextDependencies.push(context));
174
- // populate warnings
175
- m.warnings.forEach(warning => this.warnings.push(warning));
176
- // populate errors
177
- m.errors.forEach(error => this.errors.push(error));
178
-
179
- Object.assign(this.assets, m.assets);
197
+ this._orderedConcatenationList = this._createOrderedConcatenationList(rootModule, modulesSet);
198
+ for(const info of this._orderedConcatenationList) {
199
+ if(info.type === "concatenated") {
200
+ const m = info.module;
201
+
202
+ // populate dependencies
203
+ m.dependencies.filter(dep => !modulesSet.has(dep.module))
204
+ .forEach(d => this.dependencies.push(d));
205
+ // populate dep warning
206
+ m.dependenciesWarnings.forEach(depWarning => this.dependenciesWarnings.push(depWarning));
207
+ // populate dep errors
208
+ m.dependenciesErrors.forEach(depError => this.dependenciesErrors.push(depError));
209
+ // populate file dependencies
210
+ if(m.fileDependencies) m.fileDependencies.forEach(file => this.fileDependencies.push(file));
211
+ // populate context dependencies
212
+ if(m.contextDependencies) m.contextDependencies.forEach(context => this.contextDependencies.push(context));
213
+ // populate warnings
214
+ m.warnings.forEach(warning => this.warnings.push(warning));
215
+ // populate errors
216
+ m.errors.forEach(error => this.errors.push(error));
217
+
218
+ Object.assign(this.assets, m.assets);
219
+ }
180
220
  }
181
221
  }
182
222
 
183
223
  identifier() {
184
- return this.modules.map(m => m.identifier()).join(" ");
224
+ return this._orderedConcatenationList.map(info => info.module.identifier()).join(" ");
185
225
  }
186
226
 
187
227
  readableIdentifier(requestShortener) {
188
- return this.rootModule.readableIdentifier(requestShortener) + ` + ${this.modules.length - 1} modules`;
228
+ return this.rootModule.readableIdentifier(requestShortener) + ` + ${this._numberOfConcatenatedModules - 1} modules`;
189
229
  }
190
230
 
191
231
  libIdent(options) {
@@ -202,69 +242,127 @@ class ConcatenatedModule extends Module {
202
242
 
203
243
  size() {
204
244
  // Guess size from embedded modules
205
- return this.modules.reduce((sum, m) => sum + m.size(), 0);
245
+ return this._orderedConcatenationList.reduce((sum, info) => {
246
+ switch(info.type) {
247
+ case "concatenated":
248
+ return sum + info.module.size();
249
+ case "external":
250
+ return sum + 5;
251
+ }
252
+ return sum;
253
+ }, 0);
206
254
  }
207
255
 
208
- source(dependencyTemplates, outputOptions, requestShortener) {
209
- const modulesSet = new Set();
210
- this.modules.forEach(m => modulesSet.add(m));
256
+ _createOrderedConcatenationList(rootModule, modulesSet) {
257
+ const list = [];
258
+ const set = new Set();
259
+
260
+ function getConcatenatedImports(module) {
261
+ // TODO need changes when merging with the pure-module branch
262
+ const allDeps = module.dependencies
263
+ .filter(dep => dep instanceof HarmonyImportDependency && dep.module);
264
+
265
+ return allDeps.map(dep => () => dep.module);
266
+ }
211
267
 
268
+ function enterModule(getModule) {
269
+ const module = getModule();
270
+ if(set.has(module)) return;
271
+ set.add(module);
272
+ if(modulesSet.has(module)) {
273
+ const imports = getConcatenatedImports(module);
274
+ imports.forEach(enterModule);
275
+ list.push({
276
+ type: "concatenated",
277
+ module
278
+ });
279
+ } else {
280
+ list.push({
281
+ type: "external",
282
+ get module() {
283
+ // We need to use a getter here, because the module in the dependency
284
+ // could be replaced by some other process (i. e. also replaced with a
285
+ // concatenated module)
286
+ return getModule();
287
+ }
288
+ });
289
+ }
290
+ }
291
+
292
+ enterModule(() => rootModule);
293
+
294
+ return list;
295
+ }
296
+
297
+ source(dependencyTemplates, outputOptions, requestShortener) {
212
298
  // Metainfo for each module
213
- const modulesWithInfo = this.modules.map((m, idx) => {
214
- const exportMap = new Map();
215
- const reexportMap = new Map();
216
- m.dependencies.forEach(dep => {
217
- if(dep instanceof HarmonyExportSpecifierDependency) {
218
- exportMap.set(dep.name, dep.id);
219
- } else if(dep instanceof HarmonyExportExpressionDependency) {
220
- exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__");
221
- } else if(dep instanceof HarmonyExportImportedSpecifierDependency) {
222
- const exportName = dep.name;
223
- const importName = dep.id;
224
- const importModule = dep.importDependency.module;
225
- const innerReexport = modulesSet.has(importModule);
226
- if(exportName && importName) {
227
- reexportMap.set(exportName, {
228
- module: importModule,
229
- exportName: importName,
230
- dependency: dep
231
- });
232
- } else if(exportName) {
233
- reexportMap.set(exportName, {
234
- module: importModule,
235
- exportName: true,
236
- dependency: dep
237
- });
238
- } else if(Array.isArray(importModule.providedExports)) {
239
- var activeExports = new Set(HarmonyModulesHelpers.getActiveExports(dep.originModule, dep));
240
- importModule.providedExports.forEach(name => {
241
- if(activeExports.has(name) || name === "default")
242
- return;
243
- reexportMap.set(name, {
244
- module: importModule,
245
- exportName: name,
246
- dependency: dep
247
- });
299
+ const modulesWithInfo = this._orderedConcatenationList.map((info, idx) => {
300
+ switch(info.type) {
301
+ case "concatenated":
302
+ {
303
+ const exportMap = new Map();
304
+ const reexportMap = new Map();
305
+ info.module.dependencies.forEach(dep => {
306
+ if(dep instanceof HarmonyExportSpecifierDependency) {
307
+ exportMap.set(dep.name, dep.id);
308
+ } else if(dep instanceof HarmonyExportExpressionDependency) {
309
+ exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__");
310
+ } else if(dep instanceof HarmonyExportImportedSpecifierDependency) {
311
+ const exportName = dep.name;
312
+ const importName = dep.id;
313
+ const importedModule = dep.importDependency.module;
314
+ if(exportName && importName) {
315
+ reexportMap.set(exportName, {
316
+ module: importedModule,
317
+ exportName: importName,
318
+ dependency: dep
319
+ });
320
+ } else if(exportName) {
321
+ reexportMap.set(exportName, {
322
+ module: importedModule,
323
+ exportName: true,
324
+ dependency: dep
325
+ });
326
+ } else {
327
+ var activeExports = new Set(HarmonyModulesHelpers.getActiveExports(dep.originModule, dep));
328
+ importedModule.providedExports.forEach(name => {
329
+ if(activeExports.has(name) || name === "default")
330
+ return;
331
+ reexportMap.set(name, {
332
+ module: importedModule,
333
+ exportName: name,
334
+ dependency: dep
335
+ });
336
+ });
337
+ }
338
+ }
248
339
  });
249
- } else if(innerReexport) {
250
- throw new Error(`Module "${importModule.readableIdentifier(requestShortener)}" doesn't provide static exports for "export *" in ${m.readableIdentifier(requestShortener)}`);
340
+ return {
341
+ type: "concatenated",
342
+ module: info.module,
343
+ index: idx,
344
+ ast: undefined,
345
+ source: undefined,
346
+ globalScope: undefined,
347
+ moduleScope: undefined,
348
+ internalNames: new Map(),
349
+ exportMap: exportMap,
350
+ reexportMap: reexportMap,
351
+ needCompatibilityFlag: false,
352
+ hasNamespaceObject: false,
353
+ namespaceObjectSource: null
354
+ };
251
355
  }
252
- }
253
- });
254
- return {
255
- module: m,
256
- index: idx,
257
- ast: undefined,
258
- source: undefined,
259
- globalScope: undefined,
260
- moduleScope: undefined,
261
- internalNames: new Map(),
262
- exportMap: exportMap,
263
- reexportMap: reexportMap,
264
- needCompatibilityFlag: false,
265
- needNamespaceObject: false,
266
- namespaceObjectSource: null
267
- };
356
+ case "external":
357
+ return {
358
+ type: "external",
359
+ module: info.module,
360
+ index: idx,
361
+ name: undefined
362
+ };
363
+ default:
364
+ throw new Error(`Unsupported concatenation entry type ${info.type}`);
365
+ }
268
366
  });
269
367
 
270
368
  // Create mapping from module to info
@@ -306,127 +404,192 @@ class ConcatenatedModule extends Module {
306
404
  // Generate source code and analyse scopes
307
405
  // Prepare a ReplaceSource for the final source
308
406
  modulesWithInfo.forEach(info => {
309
- const m = info.module;
310
- const source = m.source(innerDependencyTemplates, outputOptions, requestShortener);
311
- const code = source.source();
312
- const ast = acorn.parse(code, {
313
- ranges: true,
314
- locations: true,
315
- ecmaVersion: Parser.ECMA_VERSION,
316
- sourceType: "module"
317
- });
318
- const scopeManager = escope.analyze(ast, {
319
- ecmaVersion: 6,
320
- sourceType: "module",
321
- optimistic: true,
322
- ignoreEval: true,
323
- impliedStrict: true
324
- });
325
- const globalScope = scopeManager.acquire(ast);
326
- const moduleScope = globalScope.childScopes[0];
327
- const resultSource = new ReplaceSource(source);
328
- info.ast = ast;
329
- info.source = resultSource;
330
- info.globalScope = globalScope;
331
- info.moduleScope = moduleScope;
407
+ if(info.type === "concatenated") {
408
+ const m = info.module;
409
+ const source = m.source(innerDependencyTemplates, outputOptions, requestShortener);
410
+ const code = source.source();
411
+ let ast;
412
+ try {
413
+ ast = acorn.parse(code, {
414
+ ranges: true,
415
+ locations: true,
416
+ ecmaVersion: Parser.ECMA_VERSION,
417
+ sourceType: "module"
418
+ });
419
+ } catch(err) {
420
+ if(err.loc && typeof err.loc === "object" && typeof err.loc.line === "number") {
421
+ const lineNumber = err.loc.line;
422
+ const lines = code.split("\n");
423
+ err.message += "\n| " + lines.slice(Math.max(0, lineNumber - 3), lineNumber + 2).join("\n| ");
424
+ }
425
+ throw err;
426
+ }
427
+ const scopeManager = escope.analyze(ast, {
428
+ ecmaVersion: 6,
429
+ sourceType: "module",
430
+ optimistic: true,
431
+ ignoreEval: true,
432
+ impliedStrict: true
433
+ });
434
+ const globalScope = scopeManager.acquire(ast);
435
+ const moduleScope = globalScope.childScopes[0];
436
+ const resultSource = new ReplaceSource(source);
437
+ info.ast = ast;
438
+ info.source = resultSource;
439
+ info.globalScope = globalScope;
440
+ info.moduleScope = moduleScope;
441
+ }
332
442
  });
333
443
 
334
444
  // List of all used names to avoid conflicts
335
- const allUsedNames = new Set(["__WEBPACK_MODULE_DEFAULT_EXPORT__", "defaultExport", "Object"]);
445
+ const allUsedNames = new Set([
446
+ "__WEBPACK_MODULE_DEFAULT_EXPORT__", // avoid using this internal name
447
+
448
+ "abstract", "arguments", "await", "boolean", "break", "byte", "case", "catch", "char", "class",
449
+ "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "eval",
450
+ "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if",
451
+ "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new",
452
+ "null", "package", "private", "protected", "public", "return", "short", "static", "super",
453
+ "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof",
454
+ "var", "void", "volatile", "while", "with", "yield",
455
+
456
+ "Array", "Date", "eval", "function", "hasOwnProperty", "Infinity", "isFinite", "isNaN",
457
+ "isPrototypeOf", "length", "Math", "NaN", "name", "Number", "Object", "prototype", "String",
458
+ "toString", "undefined", "valueOf",
459
+
460
+ "alert", "all", "anchor", "anchors", "area", "assign", "blur", "button", "checkbox",
461
+ "clearInterval", "clearTimeout", "clientInformation", "close", "closed", "confirm", "constructor",
462
+ "crypto", "decodeURI", "decodeURIComponent", "defaultStatus", "document", "element", "elements",
463
+ "embed", "embeds", "encodeURI", "encodeURIComponent", "escape", "event", "fileUpload", "focus",
464
+ "form", "forms", "frame", "innerHeight", "innerWidth", "layer", "layers", "link", "location",
465
+ "mimeTypes", "navigate", "navigator", "frames", "frameRate", "hidden", "history", "image",
466
+ "images", "offscreenBuffering", "open", "opener", "option", "outerHeight", "outerWidth",
467
+ "packages", "pageXOffset", "pageYOffset", "parent", "parseFloat", "parseInt", "password", "pkcs11",
468
+ "plugin", "prompt", "propertyIsEnum", "radio", "reset", "screenX", "screenY", "scroll", "secure",
469
+ "select", "self", "setInterval", "setTimeout", "status", "submit", "taint", "text", "textarea",
470
+ "top", "unescape", "untaint", "window",
471
+
472
+ "onblur", "onclick", "onerror", "onfocus", "onkeydown", "onkeypress", "onkeyup", "onmouseover",
473
+ "onload", "onmouseup", "onmousedown", "onsubmit"
474
+ ]);
336
475
 
337
476
  // get all global names
338
477
  modulesWithInfo.forEach(info => {
339
- info.globalScope.through.forEach(reference => {
340
- const name = reference.identifier.name;
341
- if(/^__WEBPACK_MODULE_REFERENCE__\d+_(\d+|ns)__$/.test(name)) {
342
- for(const s of getSymbolsFromScope(reference.from, info.moduleScope)) {
343
- allUsedNames.add(s);
478
+ if(info.globalScope) {
479
+ info.globalScope.through.forEach(reference => {
480
+ const name = reference.identifier.name;
481
+ if(/^__WEBPACK_MODULE_REFERENCE__\d+_([\da-f]+|ns)(_call)?__$/.test(name)) {
482
+ for(const s of getSymbolsFromScope(reference.from, info.moduleScope)) {
483
+ allUsedNames.add(s);
484
+ }
485
+ } else {
486
+ allUsedNames.add(name);
344
487
  }
345
- } else {
346
- allUsedNames.add(name);
347
- }
348
- });
488
+ });
489
+ }
349
490
  });
350
491
 
492
+ // generate names for symbols
351
493
  modulesWithInfo.forEach(info => {
352
- const namespaceObjectName = this.findNewName("namespaceObject", allUsedNames, null, info.module.readableIdentifier(requestShortener));
353
- allUsedNames.add(namespaceObjectName);
354
- info.internalNames.set(namespaceObjectName, namespaceObjectName);
355
- info.exportMap.set(true, namespaceObjectName);
356
- info.moduleScope.variables.forEach(variable => {
357
- const name = variable.name;
358
- if(allUsedNames.has(name)) {
359
- const references = getAllReferences(variable);
360
- const symbolsInReferences = references.map(ref => getSymbolsFromScope(ref.from, info.moduleScope)).reduce(reduceSet, new Set());
361
- const newName = this.findNewName(name, allUsedNames, symbolsInReferences, info.module.readableIdentifier(requestShortener));
362
- allUsedNames.add(newName);
363
- info.internalNames.set(name, newName);
364
- const source = info.source;
365
- const allIdentifiers = new Set(references.map(r => r.identifier).concat(variable.identifiers));
366
- for(const identifier of allIdentifiers) {
367
- const r = identifier.range;
368
- const path = getPathInAst(info.ast, identifier);
369
- if(path && path.length > 1 && path[1].type === "Property" && path[1].shorthand) {
370
- source.insert(r[1], `: ${newName}`);
371
- } else {
372
- source.replace(r[0], r[1] - 1, newName);
373
- }
494
+ switch(info.type) {
495
+ case "concatenated":
496
+ {
497
+ const namespaceObjectName = this.findNewName("namespaceObject", allUsedNames, null, info.module.readableIdentifier(requestShortener));
498
+ allUsedNames.add(namespaceObjectName);
499
+ info.internalNames.set(namespaceObjectName, namespaceObjectName);
500
+ info.exportMap.set(true, namespaceObjectName);
501
+ info.moduleScope.variables.forEach(variable => {
502
+ const name = variable.name;
503
+ if(allUsedNames.has(name)) {
504
+ const references = getAllReferences(variable);
505
+ const symbolsInReferences = references.map(ref => getSymbolsFromScope(ref.from, info.moduleScope)).reduce(reduceSet, new Set());
506
+ const newName = this.findNewName(name, allUsedNames, symbolsInReferences, info.module.readableIdentifier(requestShortener));
507
+ allUsedNames.add(newName);
508
+ info.internalNames.set(name, newName);
509
+ const source = info.source;
510
+ const allIdentifiers = new Set(references.map(r => r.identifier).concat(variable.identifiers));
511
+ for(const identifier of allIdentifiers) {
512
+ const r = identifier.range;
513
+ const path = getPathInAst(info.ast, identifier);
514
+ if(path && path.length > 1 && path[1].type === "Property" && path[1].shorthand) {
515
+ source.insert(r[1], `: ${newName}`);
516
+ } else {
517
+ source.replace(r[0], r[1] - 1, newName);
518
+ }
519
+ }
520
+ } else {
521
+ allUsedNames.add(name);
522
+ info.internalNames.set(name, name);
523
+ }
524
+ });
525
+ break;
374
526
  }
375
- } else {
376
- allUsedNames.add(name);
377
- info.internalNames.set(name, name);
378
- }
379
- });
527
+ case "external":
528
+ {
529
+ const externalName = this.findNewName("", allUsedNames, null, info.module.readableIdentifier(requestShortener));
530
+ allUsedNames.add(externalName);
531
+ info.name = externalName;
532
+ break;
533
+ }
534
+ }
380
535
  });
381
536
 
537
+ // Find and replace referenced to modules
382
538
  modulesWithInfo.forEach(info => {
383
- info.globalScope.through.forEach(reference => {
384
- const name = reference.identifier.name;
385
- const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_(\d+|ns)__$/.exec(name);
386
- if(match) {
387
- const referencedModule = modulesWithInfo[+match[1]];
388
- let exportName;
389
- if(match[2] === "ns") {
390
- exportName = true;
391
- } else {
392
- const exportIdx = +match[2];
393
- exportName = referencedModule.module.providedExports[exportIdx];
539
+ if(info.type === "concatenated") {
540
+ info.globalScope.through.forEach(reference => {
541
+ const name = reference.identifier.name;
542
+ const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?__$/.exec(name);
543
+ if(match) {
544
+ const referencedModule = modulesWithInfo[+match[1]];
545
+ let exportName;
546
+ if(match[2] === "ns") {
547
+ exportName = true;
548
+ } else {
549
+ const exportData = match[2];
550
+ exportName = new Buffer(exportData, "hex").toString("utf-8"); // eslint-disable-line node/no-deprecated-api
551
+ }
552
+ const asCall = !!match[3];
553
+ const finalName = getFinalName(referencedModule, exportName, moduleToInfoMap, requestShortener, asCall);
554
+ const r = reference.identifier.range;
555
+ const source = info.source;
556
+ source.replace(r[0], r[1] - 1, finalName);
394
557
  }
395
- const finalName = getFinalName(referencedModule, exportName, moduleToInfoMap, requestShortener);
396
- const r = reference.identifier.range;
397
- const source = info.source;
398
- source.replace(r[0], r[1] - 1, finalName);
399
- }
400
- });
558
+ });
559
+ }
401
560
  });
402
561
 
403
562
  const result = new ConcatSource();
563
+
564
+ // add harmony compatibility flag (must be first because of possible circular dependencies)
404
565
  if(moduleToInfoMap.get(this.rootModule).needCompatibilityFlag) {
405
- result.add(`Object.defineProperty(${this.rootModule.exportsArgument || "exports"}, "__esModule", { value: true });\n`);
406
- }
407
- let generated = true;
408
- const ensureNsObjSource = info => {
409
- if(info.needNamespaceObject && !info.namespaceObjectSource) {
410
- const name = info.exportMap.get(true);
411
- const nsObj = [`var ${name} = {};`];
412
- for(const exportName of info.module.providedExports) {
413
- const finalName = getFinalName(info, exportName, moduleToInfoMap, requestShortener);
414
- nsObj.push(`__webpack_require__.d(${name}, ${JSON.stringify(exportName)}, function() { return ${finalName}; });`);
415
- }
416
- info.namespaceObjectSource = nsObj.join("\n") + "\n";
417
- generated = true;
418
- }
419
- };
420
- while(generated) {
421
- generated = false;
422
- modulesWithInfo.forEach(ensureNsObjSource);
566
+ result.add(`Object.defineProperty(${this.exportsArgument || "exports"}, "__esModule", { value: true });\n`);
423
567
  }
568
+
569
+ // define required namespace objects (must be before evaluation modules)
424
570
  modulesWithInfo.forEach(info => {
425
- result.add(`\n// CONCATENATED MODULE: ${info.module.readableIdentifier(requestShortener)}\n`);
426
571
  if(info.namespaceObjectSource) {
427
572
  result.add(info.namespaceObjectSource);
428
573
  }
429
- result.add(info.source);
574
+ });
575
+
576
+ // evaluate modules in order
577
+ modulesWithInfo.forEach(info => {
578
+ switch(info.type) {
579
+ case "concatenated":
580
+ result.add(`\n// CONCATENATED MODULE: ${info.module.readableIdentifier(requestShortener)}\n`);
581
+ result.add(info.source);
582
+ break;
583
+ case "external":
584
+ result.add(`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(requestShortener)}\n`);
585
+ result.add(`var ${info.name} = __webpack_require__(${JSON.stringify(info.module.id)});\n`);
586
+ if(info.module.meta && !info.module.meta.harmonyModule) {
587
+ result.add(`var ${info.name}_default = /*#__PURE__*/__webpack_require__.n(${info.name});\n`);
588
+ }
589
+ break;
590
+ default:
591
+ throw new Error(`Unsupported concatenation entry type ${info.type}`);
592
+ }
430
593
  });
431
594
 
432
595
  return result;
@@ -436,25 +599,37 @@ class ConcatenatedModule extends Module {
436
599
  let name = oldName;
437
600
 
438
601
  if(name === "__WEBPACK_MODULE_DEFAULT_EXPORT__")
439
- name = "defaultExport";
602
+ name = "";
440
603
 
441
604
  // Remove uncool stuff
442
- extraInfo = extraInfo.replace(/(\/index)?\.([a-zA-Z0-9]{1,4})$/, "");
605
+ extraInfo = extraInfo.replace(/\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g, "");
443
606
 
444
607
  const splittedInfo = extraInfo.split("/");
445
608
  while(splittedInfo.length) {
446
- name = splittedInfo.pop() + "_" + name;
609
+ name = splittedInfo.pop() + (name ? "_" + name : "");
447
610
  const nameIdent = Template.toIdentifier(name);
448
611
  if(!usedNamed1.has(nameIdent) && (!usedNamed2 || !usedNamed2.has(nameIdent))) return nameIdent;
449
612
  }
450
613
 
451
- while(usedNamed1.has(name = name + "_") || (usedNamed2 && usedNamed2.has(name))) { /* do nothing */ }
452
- return name;
614
+ let i = 0;
615
+ let nameWithNumber = Template.toIdentifier(`${name}_${i}`);
616
+ while(usedNamed1.has(nameWithNumber) || (usedNamed2 && usedNamed2.has(nameWithNumber))) {
617
+ i++;
618
+ nameWithNumber = Template.toIdentifier(`${name}_${i}`);
619
+ }
620
+ return nameWithNumber;
453
621
  }
454
622
 
455
623
  updateHash(hash) {
456
- for(const m of this.modules) {
457
- m.updateHash(hash);
624
+ for(const info of this._orderedConcatenationList) {
625
+ switch(info.type) {
626
+ case "concatenated":
627
+ info.module.updateHash(hash);
628
+ break;
629
+ case "external":
630
+ hash.update(`${info.module.id}`);
631
+ break;
632
+ }
458
633
  }
459
634
  super.updateHash(hash);
460
635
  }
@@ -474,16 +649,14 @@ class HarmonyImportSpecifierDependencyConcatenatedTemplate {
474
649
  this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
475
650
  return;
476
651
  }
477
- if(!Array.isArray(module.providedExports))
478
- throw new Error(`Module ${module.resource} has no static exports ${module.providedExports}`);
479
652
  let content;
480
653
  if(dep.id === null) {
481
654
  content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__`;
482
655
  } else if(dep.namespaceObjectAsContext) {
483
656
  content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__[${JSON.stringify(dep.id)}]`;
484
657
  } else {
485
- const exportIdx = (module.providedExports).indexOf(dep.id);
486
- content = exportIdx === -1 ? "undefined" : `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportIdx}__`;
658
+ const exportData = new Buffer(dep.id, "utf-8").toString("hex"); // eslint-disable-line node/no-deprecated-api
659
+ content = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}${dep.call ? "_call" : ""}__`;
487
660
  }
488
661
  if(dep.shorthand) {
489
662
  content = dep.name + ": " + content;
@@ -529,19 +702,20 @@ class HarmonyExportExpressionDependencyConcatenatedTemplate {
529
702
  }
530
703
 
531
704
  apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
705
+ let content = "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = ";
532
706
  if(dep.originModule === this.rootModule) {
533
- this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
534
- } else {
535
- const content = "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = ";
536
-
537
- if(dep.range) {
538
- source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "(");
539
- source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");");
540
- return;
541
- }
707
+ const used = dep.originModule.isUsed("default");
708
+ const exportsName = dep.originModule.exportsArgument || "exports";
709
+ if(used) content += `${exportsName}[${JSON.stringify(used)}] = `;
710
+ }
542
711
 
543
- source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content);
712
+ if(dep.range) {
713
+ source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "(");
714
+ source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");");
715
+ return;
544
716
  }
717
+
718
+ source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content);
545
719
  }
546
720
  }
547
721
 
@@ -597,8 +771,8 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate {
597
771
  if(def.id === true) {
598
772
  finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__`;
599
773
  } else {
600
- const exportIdx = def.module.providedExports.indexOf(def.id);
601
- finalName = exportIdx < 0 ? "undefined" : `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportIdx}__`;
774
+ const exportData = new Buffer(def.id, "utf-8").toString("hex"); // eslint-disable-line node/no-deprecated-api
775
+ finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}__`;
602
776
  }
603
777
  const exportsName = this.rootModule.exportsArgument || "exports";
604
778
  const content = `/* concated harmony reexport */__webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${finalName}; });\n`;