diff options
Diffstat (limited to 'node_modules/webpack/lib/optimize')
12 files changed, 1321 insertions, 451 deletions
diff --git a/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js b/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js index 826a6baa9..dc14ac300 100644 --- a/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js +++ b/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js @@ -23,7 +23,7 @@ class AggressiveMergingPlugin { return a + b;
}, 0);
}
- compiler.plugin("compilation", (compilation) => {
+ compiler.plugin("this-compilation", (compilation) => {
compilation.plugin("optimize-chunks-advanced", (chunks) => {
let combinations = [];
chunks.forEach((a, idx) => {
@@ -31,86 +31,80 @@ class AggressiveMergingPlugin { for(let i = 0; i < idx; i++) {
const b = chunks[i];
if(b.isInitial()) continue;
- combinations.push([b, a]);
+ combinations.push({
+ a,
+ b,
+ improvement: undefined
+ });
}
});
combinations.forEach((pair) => {
- const a = pair[0].size({
+ const a = pair.b.size({
chunkOverhead: 0
});
- const b = pair[1].size({
+ const b = pair.a.size({
chunkOverhead: 0
});
- const ab = pair[0].integratedSize(pair[1], {
+ const ab = pair.b.integratedSize(pair.a, {
chunkOverhead: 0
});
- pair.push({
- a: a,
- b: b,
- ab: ab
- });
let newSize;
if(ab === false) {
- pair.unshift(false);
+ pair.improvement = false;
+ return;
} else if(options.moveToParents) {
const aOnly = ab - b;
const bOnly = ab - a;
const common = a + b - ab;
- newSize = common + getParentsWeight(pair[0]) * aOnly + getParentsWeight(pair[1]) * bOnly;
- pair.push({
- aOnly: aOnly,
- bOnly: bOnly,
- common: common,
- newSize: newSize
- });
+ newSize = common + getParentsWeight(pair.b) * aOnly + getParentsWeight(pair.a) * bOnly;
} else {
newSize = ab;
}
- pair.unshift((a + b) / newSize);
+ pair.improvement = (a + b) / newSize;
});
combinations = combinations.filter((pair) => {
- return pair[0] !== false;
+ return pair.improvement !== false;
});
combinations.sort((a, b) => {
- return b[0] - a[0];
+ return b.improvement - a.improvement;
});
const pair = combinations[0];
if(!pair) return;
- if(pair[0] < minSizeReduce) return;
+ if(pair.improvement < minSizeReduce) return;
if(options.moveToParents) {
- const commonModules = pair[1].modules.filter((m) => {
- return pair[2].modules.indexOf(m) >= 0;
+ const commonModules = pair.b.modules.filter((m) => {
+ return pair.a.modules.indexOf(m) >= 0;
});
- const aOnlyModules = pair[1].modules.filter((m) => {
+ const aOnlyModules = pair.b.modules.filter((m) => {
return commonModules.indexOf(m) < 0;
});
- const bOnlyModules = pair[2].modules.filter((m) => {
+ const bOnlyModules = pair.a.modules.filter((m) => {
return commonModules.indexOf(m) < 0;
});
aOnlyModules.forEach((m) => {
- pair[1].removeModule(m);
- m.removeChunk(pair[1]);
- pair[1].parents.forEach((c) => {
+ pair.b.removeModule(m);
+ m.removeChunk(pair.b);
+ pair.b.parents.forEach((c) => {
c.addModule(m);
m.addChunk(c);
});
});
bOnlyModules.forEach((m) => {
- pair[2].removeModule(m);
- m.removeChunk(pair[2]);
- pair[2].parents.forEach((c) => {
+ pair.a.removeModule(m);
+ m.removeChunk(pair.a);
+ pair.a.parents.forEach((c) => {
c.addModule(m);
m.addChunk(c);
});
});
}
- if(pair[1].integrate(pair[2], "aggressive-merge")) {
- chunks.splice(chunks.indexOf(pair[2]), 1);
+ if(pair.b.integrate(pair.a, "aggressive-merge")) {
+ chunks.splice(chunks.indexOf(pair.a), 1);
return true;
}
});
diff --git a/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js b/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js index e05b3eb4c..b6f566a1c 100644 --- a/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js +++ b/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js @@ -6,18 +6,6 @@ const identifierUtils = require("../util/identifier");
-function toIndexOf(list) {
- return function(item) {
- return list.indexOf(item);
- };
-}
-
-function toChunkModuleIndices(modules) {
- return function(idx) {
- return modules[idx];
- };
-}
-
function moveModuleBetween(oldChunk, newChunk) {
return function(module) {
oldChunk.moveModule(module, newChunk);
@@ -49,8 +37,15 @@ class AggressiveSplittingPlugin { if(typeof this.options.entryChunkMultiplicator !== "number") this.options.entryChunkMultiplicator = 1;
}
apply(compiler) {
- compiler.plugin("compilation", (compilation) => {
+ compiler.plugin("this-compilation", (compilation) => {
compilation.plugin("optimize-chunks-advanced", (chunks) => {
+ // Precompute stuff
+ const nameToModuleMap = new Map();
+ compilation.modules.forEach(m => {
+ const name = identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache);
+ nameToModuleMap.set(name, m);
+ });
+
const savedSplits = compilation.records && compilation.records.aggressiveSplits || [];
const usedSplits = compilation._aggressiveSplittingSplits ?
savedSplits.concat(compilation._aggressiveSplittingSplits) : savedSplits;
@@ -60,50 +55,58 @@ class AggressiveSplittingPlugin { // 1. try to restore to recorded splitting
for(let j = 0; j < usedSplits.length; j++) {
const splitData = usedSplits[j];
- for(let i = 0; i < chunks.length; i++) {
- const chunk = chunks[i];
- const chunkModuleNames = chunk.modules.map(m => identifierUtils.makePathsRelative(compiler.context, m.identifier()));
+ const selectedModules = splitData.modules.map(name => nameToModuleMap.get(name));
- if(chunkModuleNames.length < splitData.modules.length)
- continue;
- const moduleIndicies = splitData.modules.map(toIndexOf(chunkModuleNames));
- const hasAllModules = moduleIndicies.every((idx) => {
- return idx >= 0;
- });
- if(hasAllModules) {
- if(chunkModuleNames.length > splitData.modules.length) {
- const selectedModules = moduleIndicies.map(toChunkModuleIndices(chunk.modules));
- const newChunk = compilation.addChunk();
- selectedModules.forEach(moveModuleBetween(chunk, newChunk));
- chunk.split(newChunk);
- chunk.name = null;
- newChunk._fromAggressiveSplitting = true;
- if(j < savedSplits.length)
- newChunk._fromAggressiveSplittingIndex = j;
- if(splitData.id !== null && splitData.id !== undefined) {
- newChunk.id = splitData.id;
- }
- newChunk.origins = chunk.origins.map(copyWithReason);
- chunk.origins = chunk.origins.map(copyWithReason);
- return true;
- } else {
- if(j < savedSplits.length)
- chunk._fromAggressiveSplittingIndex = j;
- chunk.name = null;
- if(splitData.id !== null && splitData.id !== undefined) {
- chunk.id = splitData.id;
+ // Does the modules exist at all?
+ if(selectedModules.every(Boolean)) {
+
+ // Find all chunks containing all modules in the split
+ for(let i = 0; i < chunks.length; i++) {
+ const chunk = chunks[i];
+
+ // Cheap check if chunk is suitable at all
+ if(chunk.getNumberOfModules() < splitData.modules.length)
+ continue;
+
+ // Check if all modules are in the chunk
+ if(selectedModules.every(m => chunk.containsModule(m))) {
+
+ // Is chunk identical to the split or do we need to split it?
+ if(chunk.getNumberOfModules() > splitData.modules.length) {
+ // split the chunk into two parts
+ const newChunk = compilation.addChunk();
+ selectedModules.forEach(moveModuleBetween(chunk, newChunk));
+ chunk.split(newChunk);
+ chunk.name = null;
+ newChunk._fromAggressiveSplitting = true;
+ if(j < savedSplits.length)
+ newChunk._fromAggressiveSplittingIndex = j;
+ if(splitData.id !== null && splitData.id !== undefined) {
+ newChunk.id = splitData.id;
+ }
+ newChunk.origins = chunk.origins.map(copyWithReason);
+ chunk.origins = chunk.origins.map(copyWithReason);
+ return true;
+ } else { // chunk is identical to the split
+ if(j < savedSplits.length)
+ chunk._fromAggressiveSplittingIndex = j;
+ chunk.name = null;
+ if(splitData.id !== null && splitData.id !== undefined) {
+ chunk.id = splitData.id;
+ }
}
}
}
}
}
+
// 2. for any other chunk which isn't splitted yet, split it
for(let i = 0; i < chunks.length; i++) {
const chunk = chunks[i];
const size = chunk.size(this.options);
- if(size > maxSize && chunk.modules.length > 1) {
+ if(size > maxSize && chunk.getNumberOfModules() > 1) {
const newChunk = compilation.addChunk();
- const modules = chunk.modules
+ const modules = chunk.getModules()
.filter(isNotAEntryModule(chunk.entryModule))
.sort((a, b) => {
a = a.identifier();
@@ -131,13 +134,13 @@ class AggressiveSplittingPlugin { break;
}
}
- if(newChunk.modules.length > 0) {
+ if(newChunk.getNumberOfModules() > 0) {
chunk.split(newChunk);
chunk.name = null;
newChunk.origins = chunk.origins.map(copyWithReason);
chunk.origins = chunk.origins.map(copyWithReason);
compilation._aggressiveSplittingSplits = (compilation._aggressiveSplittingSplits || []).concat({
- modules: newChunk.modules.map(m => identifierUtils.makePathsRelative(compiler.context, m.identifier()))
+ modules: newChunk.mapModules(m => identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache))
});
return true;
} else {
@@ -154,7 +157,7 @@ class AggressiveSplittingPlugin { if(chunk.hasEntryModule()) return;
const size = chunk.size(this.options);
const incorrectSize = size < minSize;
- const modules = chunk.modules.map(m => identifierUtils.makePathsRelative(compiler.context, m.identifier()));
+ const modules = chunk.mapModules(m => identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache));
if(typeof chunk._fromAggressiveSplittingIndex === "undefined") {
if(incorrectSize) return;
chunk.recorded = true;
diff --git a/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js b/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js index 8166fc315..262014dc5 100644 --- a/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js +++ b/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js @@ -11,9 +11,7 @@ class ChunkModuleIdRangePlugin { const options = this.options;
compiler.plugin("compilation", (compilation) => {
compilation.plugin("module-ids", (modules) => {
- const chunk = this.chunks.filter((chunk) => {
- return chunk.name === options.name;
- })[0];
+ const chunk = this.chunks.find((chunk) => chunk.name === options.name);
if(!chunk) throw new Error("ChunkModuleIdRangePlugin: Chunk with name '" + options.name + "' was not found");
let currentId = options.start;
let chunkModules;
diff --git a/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js b/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js index 3ef414198..465b7ff7a 100644 --- a/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js +++ b/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js @@ -60,8 +60,8 @@ The available options are: * that webpack will take care of loading this file.
*/
if(options.async && options.filename) {
- throw new Error(`You can not specify a filename if you use the \"async\" option.
-You can however specify the name of the async chunk by passing the desired string as the \"async\" option.`);
+ throw new Error(`You can not specify a filename if you use the "async" option.
+You can however specify the name of the async chunk by passing the desired string as the "async" option.`);
}
/**
@@ -115,7 +115,18 @@ You can however specify the name of the async chunk by passing the desired strin // override the "commonChunk" with the newly created async one and use it as commonChunk from now on
let asyncChunk;
if(this.async) {
- asyncChunk = this.createAsyncChunk(compilation, this.async, targetChunk);
+ // If async chunk is one of the affected chunks, just use it
+ asyncChunk = affectedChunks.filter(c => c.name === this.async)[0];
+ // Elsewise create a new one
+ if(!asyncChunk) {
+ asyncChunk = this.createAsyncChunk(
+ compilation,
+ targetChunks.length <= 1 || typeof this.async !== "string" ? this.async :
+ targetChunk.name ? `${this.async}-${targetChunk.name}` :
+ true,
+ targetChunk
+ );
+ }
targetChunk = asyncChunk;
}
@@ -190,7 +201,7 @@ You can however specify the name of the async chunk by passing the desired strin // we dont have named chunks specified, so we just take all of them
if(asyncOrNoSelectedChunk) {
- return allChunks.filter(chunk => !chunk.isInitial());
+ return allChunks;
}
/**
@@ -218,8 +229,15 @@ Take a look at the "name"/"names" or async/children option.`); }
return targetChunk.chunks.filter((chunk) => {
+ // we only are interested in on-demand chunks
+ if(chunk.isInitial())
+ return false;
+
// we can only move modules from this chunk if the "commonChunk" is the only parent
- return asyncOption || chunk.parents.length === 1;
+ if(!asyncOption)
+ return chunk.parents.length === 1;
+
+ return true;
});
}
@@ -275,7 +293,7 @@ Take a look at the "name"/"names" or async/children option.`); // count how many chunks contain a module
const commonModulesToCountMap = usedChunks.reduce((map, chunk) => {
- for(let module of chunk.modules) {
+ for(const module of chunk.modulesIterable) {
const count = map.has(module) ? map.get(module) : 0;
map.set(module, count + 1);
}
@@ -306,7 +324,7 @@ Take a look at the "name"/"names" or async/children option.`); extractModulesAndReturnAffectedChunks(reallyUsedModules, usedChunks) {
return reallyUsedModules.reduce((affectedChunksSet, module) => {
- for(let chunk of usedChunks) {
+ for(const chunk of usedChunks) {
// removeChunk returns true if the chunk was contained and succesfully removed
// false if the module did not have a connection to the chunk in question
if(module.removeChunk(chunk)) {
@@ -318,29 +336,32 @@ Take a look at the "name"/"names" or async/children option.`); }
addExtractedModulesToTargetChunk(chunk, modules) {
- for(let module of modules) {
+ for(const module of modules) {
chunk.addModule(module);
module.addChunk(chunk);
}
}
makeTargetChunkParentOfAffectedChunks(usedChunks, commonChunk) {
- for(let chunk of usedChunks) {
+ for(const chunk of usedChunks) {
// set commonChunk as new sole parent
chunk.parents = [commonChunk];
// add chunk to commonChunk
commonChunk.addChunk(chunk);
- for(let entrypoint of chunk.entrypoints) {
+ for(const entrypoint of chunk.entrypoints) {
entrypoint.insertChunk(commonChunk, chunk);
}
}
}
moveExtractedChunkBlocksToTargetChunk(chunks, targetChunk) {
- for(let chunk of chunks) {
- for(let block of chunk.blocks) {
- block.chunks.unshift(targetChunk);
+ for(const chunk of chunks) {
+ if(chunk === targetChunk) continue;
+ for(const block of chunk.blocks) {
+ if(block.chunks.indexOf(targetChunk) === -1) {
+ block.chunks.unshift(targetChunk);
+ }
targetChunk.addBlock(block);
}
}
@@ -348,8 +369,8 @@ Take a look at the "name"/"names" or async/children option.`); extractOriginsOfChunksWithExtractedModules(chunks) {
const origins = [];
- for(let chunk of chunks) {
- for(let origin of chunk.origins) {
+ for(const chunk of chunks) {
+ for(const origin of chunk.origins) {
const newOrigin = Object.create(origin);
newOrigin.reasons = (origin.reasons || []).concat("async commons");
origins.push(newOrigin);
diff --git a/node_modules/webpack/lib/optimize/ConcatenatedModule.js b/node_modules/webpack/lib/optimize/ConcatenatedModule.js new file mode 100644 index 000000000..6cb503f0d --- /dev/null +++ b/node_modules/webpack/lib/optimize/ConcatenatedModule.js @@ -0,0 +1,816 @@ +/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+const Module = require("../Module");
+const Template = require("../Template");
+const Parser = require("../Parser");
+const acorn = require("acorn");
+const escope = require("escope");
+const ReplaceSource = require("webpack-sources/lib/ReplaceSource");
+const ConcatSource = require("webpack-sources/lib/ConcatSource");
+const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
+const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
+const HarmonyExportSpecifierDependency = require("../dependencies/HarmonyExportSpecifierDependency");
+const HarmonyExportExpressionDependency = require("../dependencies/HarmonyExportExpressionDependency");
+const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
+const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
+const HarmonyModulesHelpers = require("../dependencies/HarmonyModulesHelpers");
+
+function ensureNsObjSource(info, moduleToInfoMap, requestShortener) {
+ if(!info.hasNamespaceObject) {
+ info.hasNamespaceObject = true;
+ const name = info.exportMap.get(true);
+ const nsObj = [`var ${name} = {};`];
+ for(const exportName of info.module.providedExports) {
+ const finalName = getFinalName(info, exportName, moduleToInfoMap, requestShortener, false);
+ nsObj.push(`__webpack_require__.d(${name}, ${JSON.stringify(exportName)}, function() { return ${finalName}; });`);
+ }
+ info.namespaceObjectSource = nsObj.join("\n") + "\n";
+ }
+}
+
+function getExternalImport(importedModule, info, exportName, asCall) {
+ if(exportName === true) return info.name;
+ const used = importedModule.isUsed(exportName);
+ if(!used) return "/* unused reexport */undefined";
+ if(info.interop && exportName === "default") {
+ return asCall ? `${info.interopName}()` : `${info.interopName}.a`;
+ }
+ // TODO use Template.toNormalComment when merging with pure-module
+ const comment = used !== exportName ? ` /* ${exportName} */` : "";
+ const reference = `${info.name}[${JSON.stringify(used)}${comment}]`;
+ if(asCall)
+ return `Object(${reference})`;
+ return reference;
+}
+
+function getFinalName(info, exportName, moduleToInfoMap, requestShortener, asCall) {
+ switch(info.type) {
+ case "concatenated":
+ {
+ const directExport = info.exportMap.get(exportName);
+ if(directExport) {
+ if(exportName === true)
+ ensureNsObjSource(info, moduleToInfoMap, requestShortener);
+ const name = info.internalNames.get(directExport);
+ if(!name)
+ throw new Error(`The export "${directExport}" in "${info.module.readableIdentifier(requestShortener)}" has no internal name`);
+ return name;
+ }
+ const reexport = info.reexportMap.get(exportName);
+ if(reexport) {
+ const refInfo = moduleToInfoMap.get(reexport.module);
+ if(refInfo) {
+ // module is in the concatenation
+ return getFinalName(refInfo, reexport.exportName, moduleToInfoMap, requestShortener, asCall);
+ }
+ }
+ const problem = `Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier(requestShortener)}"` +
+ ` (known exports: ${Array.from(info.exportMap.keys()).filter(name => name !== true).join(" ")}, ` +
+ `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`;
+ // TODO use Template.toNormalComment when merging with pure-module
+ return `/* ${problem} */ undefined`;
+ }
+ case "external":
+ {
+ const importedModule = info.module;
+ return getExternalImport(importedModule, info, exportName, asCall);
+ }
+ }
+}
+
+function getSymbolsFromScope(s, untilScope) {
+ const allUsedNames = new Set();
+ let scope = s;
+ while(scope) {
+ if(untilScope === scope) break;
+ scope.variables.forEach(variable => allUsedNames.add(variable.name));
+ scope = scope.upper;
+ }
+ return allUsedNames;
+}
+
+function getAllReferences(variable) {
+ let set = variable.references;
+ // Look for inner scope variables too (like in class Foo { t() { Foo } })
+ const identifiers = new Set(variable.identifiers);
+ for(const scope of variable.scope.childScopes) {
+ for(const innerVar of scope.variables) {
+ if(innerVar.identifiers.some(id => identifiers.has(id))) {
+ set = set.concat(innerVar.references);
+ break;
+ }
+ }
+ }
+ return set;
+}
+
+function reduceSet(a, b) {
+ for(const item of b)
+ a.add(item);
+ return a;
+}
+
+function getPathInAst(ast, node) {
+ if(ast === node) {
+ return [];
+ }
+ const nr = node.range;
+ var i;
+ if(Array.isArray(ast)) {
+ for(i = 0; i < ast.length; i++) {
+ const enterResult = enterNode(ast[i]);
+ if(typeof enterResult !== "undefined")
+ return enterResult;
+ }
+ } else if(ast && typeof ast === "object") {
+ const keys = Object.keys(ast);
+ for(i = 0; i < keys.length; i++) {
+ const value = ast[keys[i]];
+ if(Array.isArray(value)) {
+ const pathResult = getPathInAst(value, node);
+ if(typeof pathResult !== "undefined")
+ return pathResult;
+ } else if(value && typeof value === "object") {
+ const enterResult = enterNode(value);
+ if(typeof enterResult !== "undefined")
+ return enterResult;
+ }
+ }
+ }
+
+ function enterNode(n) {
+ const r = n.range;
+ if(r) {
+ if(r[0] <= nr[0] && r[1] >= nr[1]) {
+ const path = getPathInAst(n, node);
+ if(path) {
+ path.push(n);
+ return path;
+ }
+ }
+ }
+ return undefined;
+ }
+}
+
+class ConcatenatedModule extends Module {
+ constructor(rootModule, modules) {
+ super();
+ super.setChunks(rootModule._chunks);
+ this.rootModule = rootModule;
+ this.usedExports = rootModule.usedExports;
+ this.providedExports = rootModule.providedExports;
+ this.optimizationBailout = rootModule.optimizationBailout;
+ this.used = rootModule.used;
+ this.index = rootModule.index;
+ this.index2 = rootModule.index2;
+ this.depth = rootModule.depth;
+ this.built = modules.some(m => m.built);
+ this.cacheable = modules.every(m => m.cacheable);
+ const modulesSet = new Set(modules);
+ this.reasons = rootModule.reasons.filter(reason => !modulesSet.has(reason.module));
+ this.meta = rootModule.meta;
+ this.moduleArgument = rootModule.moduleArgument;
+ this.exportsArgument = rootModule.exportsArgument;
+ this.strict = true;
+ this._numberOfConcatenatedModules = modules.length;
+
+ this.dependencies = [];
+ this.dependenciesWarnings = [];
+ this.dependenciesErrors = [];
+ this.fileDependencies = [];
+ this.contextDependencies = [];
+ this.warnings = [];
+ this.errors = [];
+ this.assets = {};
+ this._orderedConcatenationList = this._createOrderedConcatenationList(rootModule, modulesSet);
+ for(const info of this._orderedConcatenationList) {
+ if(info.type === "concatenated") {
+ const m = info.module;
+
+ // populate dependencies
+ m.dependencies.filter(dep => !modulesSet.has(dep.module))
+ .forEach(d => this.dependencies.push(d));
+ // populate dep warning
+ m.dependenciesWarnings.forEach(depWarning => this.dependenciesWarnings.push(depWarning));
+ // populate dep errors
+ m.dependenciesErrors.forEach(depError => this.dependenciesErrors.push(depError));
+ // populate file dependencies
+ if(m.fileDependencies) m.fileDependencies.forEach(file => this.fileDependencies.push(file));
+ // populate context dependencies
+ if(m.contextDependencies) m.contextDependencies.forEach(context => this.contextDependencies.push(context));
+ // populate warnings
+ m.warnings.forEach(warning => this.warnings.push(warning));
+ // populate errors
+ m.errors.forEach(error => this.errors.push(error));
+
+ Object.assign(this.assets, m.assets);
+ }
+ }
+ }
+
+ get modules() {
+ return this._orderedConcatenationList
+ .filter(info => info.type === "concatenated")
+ .map(info => info.module);
+ }
+
+ identifier() {
+ return this._orderedConcatenationList.map(info => {
+ switch(info.type) {
+ case "concatenated":
+ return info.module.identifier();
+ }
+ }).filter(Boolean).join(" ");
+ }
+
+ readableIdentifier(requestShortener) {
+ return this.rootModule.readableIdentifier(requestShortener) + ` + ${this._numberOfConcatenatedModules - 1} modules`;
+ }
+
+ libIdent(options) {
+ return this.rootModule.libIdent(options);
+ }
+
+ nameForCondition() {
+ return this.rootModule.nameForCondition();
+ }
+
+ build(options, compilation, resolver, fs, callback) {
+ throw new Error("Cannot build this module. It should be already built.");
+ }
+
+ size() {
+ // Guess size from embedded modules
+ return this._orderedConcatenationList.reduce((sum, info) => {
+ switch(info.type) {
+ case "concatenated":
+ return sum + info.module.size();
+ case "external":
+ return sum + 5;
+ }
+ return sum;
+ }, 0);
+ }
+
+ _createOrderedConcatenationList(rootModule, modulesSet) {
+ const list = [];
+ const set = new Set();
+
+ function getConcatenatedImports(module) {
+ // TODO need changes when merging with the pure-module branch
+ const allDeps = module.dependencies
+ .filter(dep => dep instanceof HarmonyImportDependency && dep.module);
+
+ return allDeps.map(dep => () => dep.module);
+ }
+
+ function enterModule(getModule) {
+ const module = getModule();
+ if(set.has(module)) return;
+ set.add(module);
+ if(modulesSet.has(module)) {
+ const imports = getConcatenatedImports(module);
+ imports.forEach(enterModule);
+ list.push({
+ type: "concatenated",
+ module
+ });
+ } else {
+ list.push({
+ type: "external",
+ get module() {
+ // We need to use a getter here, because the module in the dependency
+ // could be replaced by some other process (i. e. also replaced with a
+ // concatenated module)
+ return getModule();
+ }
+ });
+ }
+ }
+
+ enterModule(() => rootModule);
+
+ return list;
+ }
+
+ source(dependencyTemplates, outputOptions, requestShortener) {
+ // Metainfo for each module
+ const modulesWithInfo = this._orderedConcatenationList.map((info, idx) => {
+ switch(info.type) {
+ case "concatenated":
+ {
+ const exportMap = new Map();
+ const reexportMap = new Map();
+ info.module.dependencies.forEach(dep => {
+ if(dep instanceof HarmonyExportSpecifierDependency) {
+ exportMap.set(dep.name, dep.id);
+ } else if(dep instanceof HarmonyExportExpressionDependency) {
+ exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__");
+ } else if(dep instanceof HarmonyExportImportedSpecifierDependency) {
+ const exportName = dep.name;
+ const importName = dep.id;
+ const importedModule = dep.importDependency.module;
+ if(exportName && importName) {
+ reexportMap.set(exportName, {
+ module: importedModule,
+ exportName: importName,
+ dependency: dep
+ });
+ } else if(exportName) {
+ reexportMap.set(exportName, {
+ module: importedModule,
+ exportName: true,
+ dependency: dep
+ });
+ } else {
+ var activeExports = new Set(HarmonyModulesHelpers.getActiveExports(dep.originModule, dep));
+ importedModule.providedExports.forEach(name => {
+ if(activeExports.has(name) || name === "default")
+ return;
+ reexportMap.set(name, {
+ module: importedModule,
+ exportName: name,
+ dependency: dep
+ });
+ });
+ }
+ }
+ });
+ return {
+ type: "concatenated",
+ module: info.module,
+ index: idx,
+ ast: undefined,
+ source: undefined,
+ globalScope: undefined,
+ moduleScope: undefined,
+ internalNames: new Map(),
+ exportMap: exportMap,
+ reexportMap: reexportMap,
+ needCompatibilityFlag: false,
+ hasNamespaceObject: false,
+ namespaceObjectSource: null
+ };
+ }
+ case "external":
+ return {
+ type: "external",
+ module: info.module,
+ index: idx,
+ name: undefined,
+ interopName: undefined,
+ interop: undefined
+ };
+ default:
+ throw new Error(`Unsupported concatenation entry type ${info.type}`);
+ }
+ });
+
+ // Create mapping from module to info
+ const moduleToInfoMap = new Map();
+ modulesWithInfo.forEach(m => moduleToInfoMap.set(m.module, m));
+
+ // Configure template decorators for dependencies
+ const innerDependencyTemplates = new Map(dependencyTemplates);
+
+ innerDependencyTemplates.set(HarmonyImportSpecifierDependency, new HarmonyImportSpecifierDependencyConcatenatedTemplate(
+ dependencyTemplates.get(HarmonyImportSpecifierDependency),
+ moduleToInfoMap
+ ));
+ innerDependencyTemplates.set(HarmonyImportDependency, new HarmonyImportDependencyConcatenatedTemplate(
+ dependencyTemplates.get(HarmonyImportDependency),
+ moduleToInfoMap
+ ));
+ innerDependencyTemplates.set(HarmonyExportSpecifierDependency, new HarmonyExportSpecifierDependencyConcatenatedTemplate(
+ dependencyTemplates.get(HarmonyExportSpecifierDependency),
+ this.rootModule
+ ));
+ innerDependencyTemplates.set(HarmonyExportExpressionDependency, new HarmonyExportExpressionDependencyConcatenatedTemplate(
+ dependencyTemplates.get(HarmonyExportExpressionDependency),
+ this.rootModule,
+ moduleToInfoMap
+ ));
+ innerDependencyTemplates.set(HarmonyExportImportedSpecifierDependency, new HarmonyExportImportedSpecifierDependencyConcatenatedTemplate(
+ dependencyTemplates.get(HarmonyExportImportedSpecifierDependency),
+ this.rootModule,
+ moduleToInfoMap
+ ));
+ innerDependencyTemplates.set(HarmonyCompatibilityDependency, new HarmonyCompatibilityDependencyConcatenatedTemplate(
+ dependencyTemplates.get(HarmonyCompatibilityDependency),
+ this.rootModule,
+ moduleToInfoMap
+ ));
+ innerDependencyTemplates.set("hash", innerDependencyTemplates.get("hash") + this.rootModule.identifier());
+
+ // Generate source code and analyse scopes
+ // Prepare a ReplaceSource for the final source
+ modulesWithInfo.forEach(info => {
+ if(info.type === "concatenated") {
+ const m = info.module;
+ const source = m.source(innerDependencyTemplates, outputOptions, requestShortener);
+ const code = source.source();
+ let ast;
+ try {
+ ast = acorn.parse(code, {
+ ranges: true,
+ locations: true,
+ ecmaVersion: Parser.ECMA_VERSION,
+ sourceType: "module"
+ });
+ } catch(err) {
+ if(err.loc && typeof err.loc === "object" && typeof err.loc.line === "number") {
+ const lineNumber = err.loc.line;
+ const lines = code.split("\n");
+ err.message += "\n| " + lines.slice(Math.max(0, lineNumber - 3), lineNumber + 2).join("\n| ");
+ }
+ throw err;
+ }
+ const scopeManager = escope.analyze(ast, {
+ ecmaVersion: 6,
+ sourceType: "module",
+ optimistic: true,
+ ignoreEval: true,
+ impliedStrict: true
+ });
+ const globalScope = scopeManager.acquire(ast);
+ const moduleScope = globalScope.childScopes[0];
+ const resultSource = new ReplaceSource(source);
+ info.ast = ast;
+ info.source = resultSource;
+ info.globalScope = globalScope;
+ info.moduleScope = moduleScope;
+ }
+ });
+
+ // List of all used names to avoid conflicts
+ const allUsedNames = new Set([
+ "__WEBPACK_MODULE_DEFAULT_EXPORT__", // avoid using this internal name
+
+ "abstract", "arguments", "await", "boolean", "break", "byte", "case", "catch", "char", "class",
+ "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "eval",
+ "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if",
+ "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new",
+ "null", "package", "private", "protected", "public", "return", "short", "static", "super",
+ "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof",
+ "var", "void", "volatile", "while", "with", "yield",
+
+ "module", "__dirname", "__filename", "exports",
+
+ "Array", "Date", "eval", "function", "hasOwnProperty", "Infinity", "isFinite", "isNaN",
+ "isPrototypeOf", "length", "Math", "NaN", "name", "Number", "Object", "prototype", "String",
+ "toString", "undefined", "valueOf",
+
+ "alert", "all", "anchor", "anchors", "area", "assign", "blur", "button", "checkbox",
+ "clearInterval", "clearTimeout", "clientInformation", "close", "closed", "confirm", "constructor",
+ "crypto", "decodeURI", "decodeURIComponent", "defaultStatus", "document", "element", "elements",
+ "embed", "embeds", "encodeURI", "encodeURIComponent", "escape", "event", "fileUpload", "focus",
+ "form", "forms", "frame", "innerHeight", "innerWidth", "layer", "layers", "link", "location",
+ "mimeTypes", "navigate", "navigator", "frames", "frameRate", "hidden", "history", "image",
+ "images", "offscreenBuffering", "open", "opener", "option", "outerHeight", "outerWidth",
+ "packages", "pageXOffset", "pageYOffset", "parent", "parseFloat", "parseInt", "password", "pkcs11",
+ "plugin", "prompt", "propertyIsEnum", "radio", "reset", "screenX", "screenY", "scroll", "secure",
+ "select", "self", "setInterval", "setTimeout", "status", "submit", "taint", "text", "textarea",
+ "top", "unescape", "untaint", "window",
+
+ "onblur", "onclick", "onerror", "onfocus", "onkeydown", "onkeypress", "onkeyup", "onmouseover",
+ "onload", "onmouseup", "onmousedown", "onsubmit"
+ ]);
+
+ // get all global names
+ modulesWithInfo.forEach(info => {
+ if(info.globalScope) {
+ info.globalScope.through.forEach(reference => {
+ const name = reference.identifier.name;
+ if(/^__WEBPACK_MODULE_REFERENCE__\d+_([\da-f]+|ns)(_call)?__$/.test(name)) {
+ for(const s of getSymbolsFromScope(reference.from, info.moduleScope)) {
+ allUsedNames.add(s);
+ }
+ } else {
+ allUsedNames.add(name);
+ }
+ });
+ }
+ });
+
+ // generate names for symbols
+ modulesWithInfo.forEach(info => {
+ switch(info.type) {
+ case "concatenated":
+ {
+ const namespaceObjectName = this.findNewName("namespaceObject", allUsedNames, null, info.module.readableIdentifier(requestShortener));
+ allUsedNames.add(namespaceObjectName);
+ info.internalNames.set(namespaceObjectName, namespaceObjectName);
+ info.exportMap.set(true, namespaceObjectName);
+ info.moduleScope.variables.forEach(variable => {
+ const name = variable.name;
+ if(allUsedNames.has(name)) {
+ const references = getAllReferences(variable);
+ const symbolsInReferences = references.map(ref => getSymbolsFromScope(ref.from, info.moduleScope)).reduce(reduceSet, new Set());
+ const newName = this.findNewName(name, allUsedNames, symbolsInReferences, info.module.readableIdentifier(requestShortener));
+ allUsedNames.add(newName);
+ info.internalNames.set(name, newName);
+ const source = info.source;
+ const allIdentifiers = new Set(references.map(r => r.identifier).concat(variable.identifiers));
+ for(const identifier of allIdentifiers) {
+ const r = identifier.range;
+ const path = getPathInAst(info.ast, identifier);
+ if(path && path.length > 1 && path[1].type === "Property" && path[1].shorthand) {
+ source.insert(r[1], `: ${newName}`);
+ } else {
+ source.replace(r[0], r[1] - 1, newName);
+ }
+ }
+ } else {
+ allUsedNames.add(name);
+ info.internalNames.set(name, name);
+ }
+ });
+ break;
+ }
+ case "external":
+ {
+ info.interop = info.module.meta && !info.module.meta.harmonyModule;
+ const externalName = this.findNewName("", allUsedNames, null, info.module.readableIdentifier(requestShortener));
+ allUsedNames.add(externalName);
+ info.name = externalName;
+ if(info.interop) {
+ const externalNameInterop = this.findNewName("default", allUsedNames, null, info.module.readableIdentifier(requestShortener));
+ allUsedNames.add(externalNameInterop);
+ info.interopName = externalNameInterop;
+ }
+ break;
+ }
+ }
+ });
+
+ // Find and replace referenced to modules
+ modulesWithInfo.forEach(info => {
+ if(info.type === "concatenated") {
+ info.globalScope.through.forEach(reference => {
+ const name = reference.identifier.name;
+ const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?__$/.exec(name);
+ if(match) {
+ const referencedModule = modulesWithInfo[+match[1]];
+ let exportName;
+ if(match[2] === "ns") {
+ exportName = true;
+ } else {
+ const exportData = match[2];
+ exportName = new Buffer(exportData, "hex").toString("utf-8"); // eslint-disable-line node/no-deprecated-api
+ }
+ const asCall = !!match[3];
+ const finalName = getFinalName(referencedModule, exportName, moduleToInfoMap, requestShortener, asCall);
+ const r = reference.identifier.range;
+ const source = info.source;
+ source.replace(r[0], r[1] - 1, finalName);
+ }
+ });
+ }
+ });
+
+ const result = new ConcatSource();
+
+ // add harmony compatibility flag (must be first because of possible circular dependencies)
+ if(moduleToInfoMap.get(this.rootModule).needCompatibilityFlag) {
+ result.add(`Object.defineProperty(${this.exportsArgument || "exports"}, "__esModule", { value: true });\n`);
+ }
+
+ // define required namespace objects (must be before evaluation modules)
+ modulesWithInfo.forEach(info => {
+ if(info.namespaceObjectSource) {
+ result.add(info.namespaceObjectSource);
+ }
+ });
+
+ // evaluate modules in order
+ modulesWithInfo.forEach(info => {
+ switch(info.type) {
+ case "concatenated":
+ result.add(`\n// CONCATENATED MODULE: ${info.module.readableIdentifier(requestShortener)}\n`);
+ result.add(info.source);
+ break;
+ case "external":
+ result.add(`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(requestShortener)}\n`);
+ result.add(`var ${info.name} = __webpack_require__(${JSON.stringify(info.module.id)});\n`);
+ if(info.interop) {
+ result.add(`var ${info.interopName} = /*#__PURE__*/__webpack_require__.n(${info.name});\n`);
+ }
+ break;
+ default:
+ throw new Error(`Unsupported concatenation entry type ${info.type}`);
+ }
+ });
+
+ return result;
+ }
+
+ findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
+ let name = oldName;
+
+ if(name === "__WEBPACK_MODULE_DEFAULT_EXPORT__")
+ name = "";
+
+ // Remove uncool stuff
+ extraInfo = extraInfo.replace(/\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g, "");
+
+ const splittedInfo = extraInfo.split("/");
+ while(splittedInfo.length) {
+ name = splittedInfo.pop() + (name ? "_" + name : "");
+ const nameIdent = Template.toIdentifier(name);
+ if(!usedNamed1.has(nameIdent) && (!usedNamed2 || !usedNamed2.has(nameIdent))) return nameIdent;
+ }
+
+ let i = 0;
+ let nameWithNumber = Template.toIdentifier(`${name}_${i}`);
+ while(usedNamed1.has(nameWithNumber) || (usedNamed2 && usedNamed2.has(nameWithNumber))) {
+ i++;
+ nameWithNumber = Template.toIdentifier(`${name}_${i}`);
+ }
+ return nameWithNumber;
+ }
+
+ updateHash(hash) {
+ for(const info of this._orderedConcatenationList) {
+ switch(info.type) {
+ case "concatenated":
+ info.module.updateHash(hash);
+ break;
+ case "external":
+ hash.update(`${info.module.id}`);
+ break;
+ }
+ }
+ super.updateHash(hash);
+ }
+
+}
+
+class HarmonyImportSpecifierDependencyConcatenatedTemplate {
+ constructor(originalTemplate, modulesMap) {
+ this.originalTemplate = originalTemplate;
+ this.modulesMap = modulesMap;
+ }
+
+ apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
+ const module = dep.importDependency.module;
+ const info = this.modulesMap.get(module);
+ if(!info) {
+ this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
+ return;
+ }
+ let content;
+ if(dep.id === null) {
+ content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__`;
+ } else if(dep.namespaceObjectAsContext) {
+ content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__[${JSON.stringify(dep.id)}]`;
+ } else {
+ const exportData = new Buffer(dep.id, "utf-8").toString("hex"); // eslint-disable-line node/no-deprecated-api
+ content = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}${dep.call ? "_call" : ""}__`;
+ }
+ if(dep.shorthand) {
+ content = dep.name + ": " + content;
+ }
+ source.replace(dep.range[0], dep.range[1] - 1, content);
+ }
+}
+
+class HarmonyImportDependencyConcatenatedTemplate {
+ constructor(originalTemplate, modulesMap) {
+ this.originalTemplate = originalTemplate;
+ this.modulesMap = modulesMap;
+ }
+
+ apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
+ const module = dep.module;
+ const info = this.modulesMap.get(module);
+ if(!info) {
+ this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
+ return;
+ }
+ source.replace(dep.range[0], dep.range[1] - 1, "");
+ }
+}
+
+class HarmonyExportSpecifierDependencyConcatenatedTemplate {
+ constructor(originalTemplate, rootModule) {
+ this.originalTemplate = originalTemplate;
+ this.rootModule = rootModule;
+ }
+
+ apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
+ if(dep.originModule === this.rootModule) {
+ this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
+ }
+ }
+}
+
+class HarmonyExportExpressionDependencyConcatenatedTemplate {
+ constructor(originalTemplate, rootModule) {
+ this.originalTemplate = originalTemplate;
+ this.rootModule = rootModule;
+ }
+
+ apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
+ let content = "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = ";
+ if(dep.originModule === this.rootModule) {
+ const used = dep.originModule.isUsed("default");
+ const exportsName = dep.originModule.exportsArgument || "exports";
+ if(used) content += `${exportsName}[${JSON.stringify(used)}] = `;
+ }
+
+ if(dep.range) {
+ source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "(");
+ source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");");
+ return;
+ }
+
+ source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content);
+ }
+}
+
+class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate {
+ constructor(originalTemplate, rootModule, modulesMap) {
+ this.originalTemplate = originalTemplate;
+ this.rootModule = rootModule;
+ this.modulesMap = modulesMap;
+ }
+
+ getExports(dep) {
+ const active = HarmonyModulesHelpers.isActive(dep.originModule, dep);
+ if(!active) return [];
+ const importModule = dep.importDependency.module;
+ if(dep.id) {
+ // export { named } from "module"
+ return [{
+ name: dep.name,
+ id: dep.id,
+ module: importModule
+ }];
+ }
+ if(dep.name) {
+ // export * as abc from "module"
+ return [{
+ name: dep.name,
+ id: true,
+ module: importModule
+ }];
+ }
+ // export * from "module"
+ const activeExports = new Set(HarmonyModulesHelpers.getActiveExports(dep.originModule, dep));
+ return importModule.providedExports.filter(exp => exp !== "default" && !activeExports.has(exp)).map(exp => {
+ return {
+ name: exp,
+ id: exp,
+ module: importModule
+ };
+ });
+ }
+
+ apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
+ if(dep.originModule === this.rootModule) {
+ if(this.modulesMap.get(dep.importDependency.module)) {
+ const exportDefs = this.getExports(dep);
+ exportDefs.forEach(def => {
+ const info = this.modulesMap.get(def.module);
+ const used = dep.originModule.isUsed(def.name);
+ if(!used) {
+ source.insert(-1, `/* unused concated harmony import ${dep.name} */\n`);
+ }
+ let finalName;
+ if(def.id === true) {
+ finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__`;
+ } else {
+ const exportData = new Buffer(def.id, "utf-8").toString("hex"); // eslint-disable-line node/no-deprecated-api
+ finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}__`;
+ }
+ const exportsName = this.rootModule.exportsArgument || "exports";
+ const content = `/* concated harmony reexport */__webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${finalName}; });\n`;
+ source.insert(-1, content);
+ });
+ } else {
+ this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
+ }
+ }
+ }
+}
+
+class HarmonyCompatibilityDependencyConcatenatedTemplate {
+ constructor(originalTemplate, rootModule, modulesMap) {
+ this.originalTemplate = originalTemplate;
+ this.rootModule = rootModule;
+ this.modulesMap = modulesMap;
+ }
+
+ apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
+ if(dep.originModule === this.rootModule) {
+ this.modulesMap.get(this.rootModule).needCompatibilityFlag = true;
+ }
+ }
+}
+
+module.exports = ConcatenatedModule;
diff --git a/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js b/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js index 71ee18533..46324c4e9 100644 --- a/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js +++ b/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js @@ -8,16 +8,19 @@ class EnsureChunkConditionsPlugin { apply(compiler) {
compiler.plugin("compilation", (compilation) => {
+ const triesMap = new Map();
compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => {
let changed = false;
chunks.forEach((chunk) => {
- chunk.modules.slice().forEach((module) => {
+ chunk.forEachModule((module) => {
if(!module.chunkCondition) return;
if(!module.chunkCondition(chunk)) {
- const usedChunks = module._EnsureChunkConditionsPlugin_usedChunks = (module._EnsureChunkConditionsPlugin_usedChunks || []).concat(chunk);
+ let usedChunks = triesMap.get(module);
+ if(!usedChunks) triesMap.set(module, usedChunks = new Set());
+ usedChunks.add(chunk);
const newChunks = [];
chunk.parents.forEach((parent) => {
- if(usedChunks.indexOf(parent) < 0) {
+ if(!usedChunks.has(parent)) {
parent.addModule(module);
newChunks.push(parent);
}
diff --git a/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js b/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js index e8b5a9457..75277b5aa 100644 --- a/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js +++ b/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js @@ -17,13 +17,13 @@ class FlagIncludedChunksPlugin { // instead of swapping A and B just bail
// as we loop twice the current A will be B and B then A
- if(chunkA.modules.length < chunkB.modules.length) return;
+ if(chunkA.getNumberOfModules() < chunkB.getNumberOfModules()) return;
- if(chunkB.modules.length === 0) return;
+ if(chunkB.getNumberOfModules() === 0) return;
// is chunkB in chunkA?
- for(let i = 0; i < chunkB.modules.length; i++) {
- if(chunkA.modules.indexOf(chunkB.modules[i]) < 0) return;
+ for(const m of chunkB.modulesIterable) {
+ if(!chunkA.containsModule(m)) return;
}
chunkA.ids.push(chunkB.id);
});
diff --git a/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js b/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js index 90df06b51..7b006fd17 100644 --- a/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js +++ b/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js @@ -4,23 +4,18 @@ */
"use strict";
-function getChunkIdentifier(chunk) {
- return chunk.modules.map((m) => {
- return m.identifier();
- }).sort().join(", ");
-}
-
class MergeDuplicateChunksPlugin {
apply(compiler) {
compiler.plugin("compilation", (compilation) => {
compilation.plugin("optimize-chunks-basic", (chunks) => {
- const map = {};
+ const map = Object.create(null);
chunks.slice().forEach((chunk) => {
if(chunk.hasRuntime() || chunk.hasEntryModule()) return;
- const ident = getChunkIdentifier(chunk);
- if(map[ident]) {
- if(map[ident].integrate(chunk, "duplicate"))
+ const ident = chunk.getModulesIdent();
+ const otherChunk = map[ident];
+ if(otherChunk) {
+ if(otherChunk.integrate(chunk, "duplicate"))
chunks.splice(chunks.indexOf(chunk), 1);
return;
}
diff --git a/node_modules/webpack/lib/optimize/ModuleConcatenationPlugin.js b/node_modules/webpack/lib/optimize/ModuleConcatenationPlugin.js new file mode 100644 index 000000000..9e797c75e --- /dev/null +++ b/node_modules/webpack/lib/optimize/ModuleConcatenationPlugin.js @@ -0,0 +1,307 @@ +/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
+const ModuleHotAcceptDependency = require("../dependencies/ModuleHotAcceptDependency");
+const ModuleHotDeclineDependency = require("../dependencies/ModuleHotDeclineDependency");
+const ConcatenatedModule = require("./ConcatenatedModule");
+const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
+const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
+
+function formatBailoutReason(msg) {
+ return "ModuleConcatenation bailout: " + msg;
+}
+
+class ModuleConcatenationPlugin {
+ constructor(options) {
+ if(typeof options !== "object") options = {};
+ this.options = options;
+ }
+
+ apply(compiler) {
+ compiler.plugin("compilation", (compilation, params) => {
+ params.normalModuleFactory.plugin("parser", (parser, parserOptions) => {
+ parser.plugin("call eval", () => {
+ parser.state.module.meta.hasEval = true;
+ });
+ });
+ const bailoutReasonMap = new Map();
+
+ function setBailoutReason(module, reason) {
+ bailoutReasonMap.set(module, reason);
+ module.optimizationBailout.push(typeof reason === "function" ? (rs) => formatBailoutReason(reason(rs)) : formatBailoutReason(reason));
+ }
+
+ function getBailoutReason(module, requestShortener) {
+ const reason = bailoutReasonMap.get(module);
+ if(typeof reason === "function") return reason(requestShortener);
+ return reason;
+ }
+
+ compilation.plugin("optimize-chunk-modules", (chunks, modules) => {
+ const relevantModules = [];
+ const possibleInners = new Set();
+ for(const module of modules) {
+ // Only harmony modules are valid for optimization
+ if(!module.meta || !module.meta.harmonyModule || !module.dependencies.some(d => d instanceof HarmonyCompatibilityDependency)) {
+ setBailoutReason(module, "Module is not an ECMAScript module");
+ continue;
+ }
+
+ // Because of variable renaming we can't use modules with eval
+ if(module.meta && module.meta.hasEval) {
+ setBailoutReason(module, "Module uses eval()");
+ continue;
+ }
+
+ // Exports must be known (and not dynamic)
+ if(!Array.isArray(module.providedExports)) {
+ setBailoutReason(module, "Module exports are unknown");
+ continue;
+ }
+
+ // Using dependency variables is not possible as this wraps the code in a function
+ if(module.variables.length > 0) {
+ setBailoutReason(module, `Module uses injected variables (${module.variables.map(v => v.name).join(", ")})`);
+ continue;
+ }
+
+ // Hot Module Replacement need it's own module to work correctly
+ if(module.dependencies.some(dep => dep instanceof ModuleHotAcceptDependency || dep instanceof ModuleHotDeclineDependency)) {
+ setBailoutReason(module, "Module uses Hot Module Replacement");
+ continue;
+ }
+
+ relevantModules.push(module);
+
+ // Module must not be the entry points
+ if(module.getChunks().some(chunk => chunk.entryModule === module)) {
+ setBailoutReason(module, "Module is an entry point");
+ continue;
+ }
+
+ // Module must only be used by Harmony Imports
+ const nonHarmonyReasons = module.reasons.filter(reason => !(reason.dependency instanceof HarmonyImportDependency));
+ if(nonHarmonyReasons.length > 0) {
+ const importingModules = new Set(nonHarmonyReasons.map(r => r.module));
+ const importingModuleTypes = new Map(Array.from(importingModules).map(m => [m, new Set(nonHarmonyReasons.filter(r => r.module === m).map(r => r.dependency.type).sort())]));
+ setBailoutReason(module, (requestShortener) => {
+ const names = Array.from(importingModules).map(m => `${m.readableIdentifier(requestShortener)} (referenced with ${Array.from(importingModuleTypes.get(m)).join(", ")})`).sort();
+ return `Module is referenced from these modules with unsupported syntax: ${names.join(", ")}`;
+ });
+ continue;
+ }
+
+ possibleInners.add(module);
+ }
+ // sort by depth
+ // modules with lower depth are more likely suited as roots
+ // this improves performance, because modules already selected as inner are skipped
+ relevantModules.sort((a, b) => {
+ return a.depth - b.depth;
+ });
+ const concatConfigurations = [];
+ const usedAsInner = new Set();
+ for(const currentRoot of relevantModules) {
+ // when used by another configuration as inner:
+ // the other configuration is better and we can skip this one
+ if(usedAsInner.has(currentRoot))
+ continue;
+
+ // create a configuration with the root
+ const currentConfiguration = new ConcatConfiguration(currentRoot);
+
+ // cache failures to add modules
+ const failureCache = new Map();
+
+ // try to add all imports
+ for(const imp of this.getImports(currentRoot)) {
+ const problem = this.tryToAdd(currentConfiguration, imp, possibleInners, failureCache);
+ if(problem) {
+ failureCache.set(imp, problem);
+ currentConfiguration.addWarning(imp, problem);
+ }
+ }
+ if(!currentConfiguration.isEmpty()) {
+ concatConfigurations.push(currentConfiguration);
+ for(const module of currentConfiguration.modules) {
+ if(module !== currentConfiguration.rootModule)
+ usedAsInner.add(module);
+ }
+ }
+ }
+ // HACK: Sort configurations by length and start with the longest one
+ // to get the biggers groups possible. Used modules are marked with usedModules
+ // TODO: Allow to reuse existing configuration while trying to add dependencies.
+ // This would improve performance. O(n^2) -> O(n)
+ concatConfigurations.sort((a, b) => {
+ return b.modules.size - a.modules.size;
+ });
+ const usedModules = new Set();
+ for(const concatConfiguration of concatConfigurations) {
+ if(usedModules.has(concatConfiguration.rootModule))
+ continue;
+ const newModule = new ConcatenatedModule(concatConfiguration.rootModule, Array.from(concatConfiguration.modules));
+ concatConfiguration.sortWarnings();
+ for(const warning of concatConfiguration.warnings) {
+ newModule.optimizationBailout.push((requestShortener) => {
+ const reason = getBailoutReason(warning[0], requestShortener);
+ const reasonWithPrefix = reason ? ` (<- ${reason})` : "";
+ if(warning[0] === warning[1])
+ return formatBailoutReason(`Cannot concat with ${warning[0].readableIdentifier(requestShortener)}${reasonWithPrefix}`);
+ else
+ return formatBailoutReason(`Cannot concat with ${warning[0].readableIdentifier(requestShortener)} because of ${warning[1].readableIdentifier(requestShortener)}${reasonWithPrefix}`);
+ });
+ }
+ const chunks = concatConfiguration.rootModule.getChunks();
+ for(const m of concatConfiguration.modules) {
+ usedModules.add(m);
+ chunks.forEach(chunk => chunk.removeModule(m));
+ }
+ chunks.forEach(chunk => {
+ chunk.addModule(newModule);
+ if(chunk.entryModule === concatConfiguration.rootModule)
+ chunk.entryModule = newModule;
+ });
+ compilation.modules.push(newModule);
+ newModule.reasons.forEach(reason => reason.dependency.module = newModule);
+ newModule.dependencies.forEach(dep => {
+ if(dep.module) {
+ dep.module.reasons.forEach(reason => {
+ if(reason.dependency === dep)
+ reason.module = newModule;
+ });
+ }
+ });
+ }
+ compilation.modules = compilation.modules.filter(m => !usedModules.has(m));
+ });
+ });
+ }
+
+ getImports(module) {
+ return Array.from(new Set(module.dependencies
+
+ // Only harmony Dependencies
+ .filter(dep => dep instanceof HarmonyImportDependency && dep.module)
+
+ // Dependencies are simple enough to concat them
+ .filter(dep => {
+ return !module.dependencies.some(d =>
+ d instanceof HarmonyExportImportedSpecifierDependency &&
+ d.importDependency === dep &&
+ !d.id &&
+ !Array.isArray(dep.module.providedExports)
+ );
+ })
+
+ // Take the imported module
+ .map(dep => dep.module)
+ ));
+ }
+
+ tryToAdd(config, module, possibleModules, failureCache) {
+ const cacheEntry = failureCache.get(module);
+ if(cacheEntry) {
+ return cacheEntry;
+ }
+
+ // Already added?
+ if(config.has(module)) {
+ return null;
+ }
+
+ // Not possible to add?
+ if(!possibleModules.has(module)) {
+ failureCache.set(module, module); // cache failures for performance
+ return module;
+ }
+
+ // module must be in the same chunks
+ if(!config.rootModule.hasEqualsChunks(module)) {
+ failureCache.set(module, module); // cache failures for performance
+ return module;
+ }
+
+ // Clone config to make experimental changes
+ const testConfig = config.clone();
+
+ // Add the module
+ testConfig.add(module);
+
+ // Every module which depends on the added module must be in the configuration too.
+ for(const reason of module.reasons) {
+ const problem = this.tryToAdd(testConfig, reason.module, possibleModules, failureCache);
+ if(problem) {
+ failureCache.set(module, problem); // cache failures for performance
+ return problem;
+ }
+ }
+
+ // Eagerly try to add imports too if possible
+ for(const imp of this.getImports(module)) {
+ const problem = this.tryToAdd(testConfig, imp, possibleModules, failureCache);
+ if(problem) {
+ config.addWarning(module, problem);
+ }
+ }
+
+ // Commit experimental changes
+ config.set(testConfig);
+ return null;
+ }
+}
+
+class ConcatConfiguration {
+ constructor(rootModule) {
+ this.rootModule = rootModule;
+ this.modules = new Set([rootModule]);
+ this.warnings = new Map();
+ }
+
+ add(module) {
+ this.modules.add(module);
+ }
+
+ has(module) {
+ return this.modules.has(module);
+ }
+
+ isEmpty() {
+ return this.modules.size === 1;
+ }
+
+ addWarning(module, problem) {
+ this.warnings.set(module, problem);
+ }
+
+ sortWarnings() {
+ this.warnings = new Map(Array.from(this.warnings).sort((a, b) => {
+ const ai = a[0].identifier();
+ const bi = b[0].identifier();
+ if(ai < bi) return -1;
+ if(ai > bi) return 1;
+ return 0;
+ }));
+ }
+
+ clone() {
+ const clone = new ConcatConfiguration(this.rootModule);
+ for(const module of this.modules)
+ clone.add(module);
+ for(const pair of this.warnings)
+ clone.addWarning(pair[0], pair[1]);
+ return clone;
+ }
+
+ set(config) {
+ this.rootModule = config.rootModule;
+ this.modules = new Set(config.modules);
+ this.warnings = new Map(config.warnings);
+ }
+}
+
+module.exports = ModuleConcatenationPlugin;
diff --git a/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js b/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js index a6bb30b34..45ec34719 100644 --- a/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js +++ b/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js @@ -15,98 +15,84 @@ class OccurrenceOrderPlugin { const preferEntry = this.preferEntry;
compiler.plugin("compilation", (compilation) => {
compilation.plugin("optimize-module-order", (modules) => {
- function entryChunks(m) {
- return m.chunks.map((c) => {
- const sum = (c.isInitial() ? 1 : 0) + (c.entryModule === m ? 1 : 0);
- return sum;
- }).reduce((a, b) => {
- return a + b;
- }, 0);
- }
+ const occursInInitialChunksMap = new Map();
+ const occursInAllChunksMap = new Map();
- function occursInEntry(m) {
- if(typeof m.__OccurenceOrderPlugin_occursInEntry === "number") return m.__OccurenceOrderPlugin_occursInEntry;
- const result = m.reasons.map((r) => {
- if(!r.module) return 0;
- return entryChunks(r.module);
- }).reduce((a, b) => {
- return a + b;
- }, 0) + entryChunks(m);
- return m.__OccurenceOrderPlugin_occursInEntry = result;
- }
+ const initialChunkChunkMap = new Map();
+ const entryCountMap = new Map();
+ modules.forEach(m => {
+ let initial = 0;
+ let entry = 0;
+ m.forEachChunk(c => {
+ if(c.isInitial()) initial++;
+ if(c.entryModule === m) entry++;
+ });
+ initialChunkChunkMap.set(m, initial);
+ entryCountMap.set(m, entry);
+ });
+
+ const countOccursInEntry = (sum, r) => {
+ if(!r.module) return sum;
+ return sum + initialChunkChunkMap.get(r.module);
+ };
+ const countOccurs = (sum, r) => {
+ if(!r.module) return sum;
+ return sum + r.module.getNumberOfChunks();
+ };
- function occurs(m) {
- if(typeof m.__OccurenceOrderPlugin_occurs === "number") return m.__OccurenceOrderPlugin_occurs;
- const result = m.reasons.map((r) => {
- if(!r.module) return 0;
- return r.module.chunks.length;
- }).reduce((a, b) => {
- return a + b;
- }, 0) + m.chunks.length + m.chunks.filter((c) => {
- return c.entryModule === m;
- }).length;
- return m.__OccurenceOrderPlugin_occurs = result;
+ if(preferEntry) {
+ modules.forEach(m => {
+ const result = m.reasons.reduce(countOccursInEntry, 0) + initialChunkChunkMap.get(m) + entryCountMap.get(m);
+ occursInInitialChunksMap.set(m, result);
+ });
}
+
+ modules.forEach(m => {
+ const result = m.reasons.reduce(countOccurs, 0) + m.getNumberOfChunks() + entryCountMap.get(m);
+ occursInAllChunksMap.set(m, result);
+ });
+
modules.sort((a, b) => {
if(preferEntry) {
- const aEntryOccurs = occursInEntry(a);
- const bEntryOccurs = occursInEntry(b);
+ const aEntryOccurs = occursInInitialChunksMap.get(a);
+ const bEntryOccurs = occursInInitialChunksMap.get(b);
if(aEntryOccurs > bEntryOccurs) return -1;
if(aEntryOccurs < bEntryOccurs) return 1;
}
- const aOccurs = occurs(a);
- const bOccurs = occurs(b);
+ const aOccurs = occursInAllChunksMap.get(a);
+ const bOccurs = occursInAllChunksMap.get(b);
if(aOccurs > bOccurs) return -1;
if(aOccurs < bOccurs) return 1;
- if(a.identifier() > b.identifier()) return 1;
- if(a.identifier() < b.identifier()) return -1;
+ if(a.index > b.index) return 1;
+ if(a.index < b.index) return -1;
return 0;
});
- // TODO refactor to Map
- modules.forEach((m) => {
- m.__OccurenceOrderPlugin_occursInEntry = undefined;
- m.__OccurenceOrderPlugin_occurs = undefined;
- });
});
compilation.plugin("optimize-chunk-order", (chunks) => {
- function occursInEntry(c) {
- if(typeof c.__OccurenceOrderPlugin_occursInEntry === "number") return c.__OccurenceOrderPlugin_occursInEntry;
- const result = c.parents.filter((p) => {
- return p.isInitial();
- }).length;
- return c.__OccurenceOrderPlugin_occursInEntry = result;
- }
+ const occursInInitialChunksMap = new Map();
+
+ chunks.forEach(c => {
+ const result = c.parents.reduce((sum, p) => {
+ if(p.isInitial()) return sum + 1;
+ return sum;
+ }, 0);
+ return occursInInitialChunksMap.set(c, result);
+ });
function occurs(c) {
return c.blocks.length;
}
- chunks.forEach((c) => {
- c.modules.sort((a, b) => {
- if(a.identifier() > b.identifier()) return 1;
- if(a.identifier() < b.identifier()) return -1;
- return 0;
- });
- });
+
chunks.sort((a, b) => {
- const aEntryOccurs = occursInEntry(a);
- const bEntryOccurs = occursInEntry(b);
+ const aEntryOccurs = occursInInitialChunksMap.get(a);
+ const bEntryOccurs = occursInInitialChunksMap.get(b);
if(aEntryOccurs > bEntryOccurs) return -1;
if(aEntryOccurs < bEntryOccurs) return 1;
const aOccurs = occurs(a);
const bOccurs = occurs(b);
if(aOccurs > bOccurs) return -1;
if(aOccurs < bOccurs) return 1;
- if(a.modules.length > b.modules.length) return -1;
- if(a.modules.length < b.modules.length) return 1;
- for(let i = 0; i < a.modules.length; i++) {
- if(a.modules[i].identifier() > b.modules[i].identifier()) return -1;
- if(a.modules[i].identifier() < b.modules[i].identifier()) return 1;
- }
- return 0;
- });
- // TODO refactor to Map
- chunks.forEach((c) => {
- c.__OccurenceOrderPlugin_occursInEntry = undefined;
+ return a.compareTo(b);
});
});
});
diff --git a/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js b/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js index e73add989..43550819c 100644 --- a/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js +++ b/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js @@ -4,59 +4,31 @@ */
"use strict";
-function chunkContainsModule(chunk, module) {
- const chunks = module.chunks;
- const modules = chunk.modules;
- if(chunks.length < modules.length) {
- return chunks.indexOf(chunk) >= 0;
- } else {
- return modules.indexOf(module) >= 0;
- }
-}
-
function hasModule(chunk, module, checkedChunks) {
- if(chunkContainsModule(chunk, module)) return [chunk];
+ if(chunk.containsModule(module)) return [chunk];
if(chunk.parents.length === 0) return false;
return allHaveModule(chunk.parents.filter((c) => {
- return checkedChunks.indexOf(c) < 0;
+ return !checkedChunks.has(c);
}), module, checkedChunks);
}
function allHaveModule(someChunks, module, checkedChunks) {
- if(!checkedChunks) checkedChunks = [];
- var chunks = [];
+ if(!checkedChunks) checkedChunks = new Set();
+ var chunks = new Set();
for(var i = 0; i < someChunks.length; i++) {
- checkedChunks.push(someChunks[i]);
+ checkedChunks.add(someChunks[i]);
var subChunks = hasModule(someChunks[i], module, checkedChunks);
if(!subChunks) return false;
for(var index = 0; index < subChunks.length; index++) {
var item = subChunks[index];
- if(!chunks.length || chunks.indexOf(item) < 0) {
- chunks.push(item);
- }
+ chunks.add(item);
}
}
return chunks;
}
-function debugIds(chunks) {
- var list = [];
- for(var i = 0; i < chunks.length; i++) {
- var debugId = chunks[i].debugId;
-
- if(typeof debugId !== "number") {
- return "no";
- }
-
- list.push(debugId);
- }
-
- list.sort();
- return list.join(",");
-}
-
class RemoveParentModulesPlugin {
apply(compiler) {
compiler.plugin("compilation", (compilation) => {
@@ -67,19 +39,21 @@ class RemoveParentModulesPlugin { // TODO consider Map when performance has improved https://gist.github.com/sokra/b36098368da7b8f6792fd7c85fca6311
var cache = Object.create(null);
- var modules = chunk.modules.slice();
+ var modules = chunk.getModules();
for(var i = 0; i < modules.length; i++) {
var module = modules[i];
- var dId = debugIds(module.chunks);
+ var dId = module.getChunkIdsIdent();
var parentChunksWithModule;
- if((dId in cache) && dId !== "no") {
+ if(dId === null) {
+ parentChunksWithModule = allHaveModule(chunk.parents, module);
+ } else if(dId in cache) {
parentChunksWithModule = cache[dId];
} else {
parentChunksWithModule = cache[dId] = allHaveModule(chunk.parents, module);
}
if(parentChunksWithModule) {
- module.rewriteChunkInReasons(chunk, parentChunksWithModule);
+ module.rewriteChunkInReasons(chunk, Array.from(parentChunksWithModule));
chunk.removeModule(module);
}
}
diff --git a/node_modules/webpack/lib/optimize/UglifyJsPlugin.js b/node_modules/webpack/lib/optimize/UglifyJsPlugin.js index f95dc8eef..1caa10817 100644 --- a/node_modules/webpack/lib/optimize/UglifyJsPlugin.js +++ b/node_modules/webpack/lib/optimize/UglifyJsPlugin.js @@ -4,233 +4,6 @@ */
"use strict";
-const SourceMapConsumer = require("source-map").SourceMapConsumer;
-const SourceMapSource = require("webpack-sources").SourceMapSource;
-const RawSource = require("webpack-sources").RawSource;
-const ConcatSource = require("webpack-sources").ConcatSource;
-const RequestShortener = require("../RequestShortener");
-const ModuleFilenameHelpers = require("../ModuleFilenameHelpers");
-const uglify = require("uglify-js");
-
-class UglifyJsPlugin {
- constructor(options) {
- if(typeof options !== "object" || Array.isArray(options)) options = {};
- if(typeof options.compressor !== "undefined") options.compress = options.compressor;
- this.options = options;
- }
-
- apply(compiler) {
- const options = this.options;
- options.test = options.test || /\.js($|\?)/i;
- const warningsFilter = options.warningsFilter || (() => true);
-
- const requestShortener = new RequestShortener(compiler.context);
- compiler.plugin("compilation", (compilation) => {
- if(options.sourceMap) {
- compilation.plugin("build-module", (module) => {
- // to get detailed location info about errors
- module.useSourceMap = true;
- });
- }
- compilation.plugin("optimize-chunk-assets", (chunks, callback) => {
- const files = [];
- chunks.forEach((chunk) => files.push.apply(files, chunk.files));
- files.push.apply(files, compilation.additionalChunkAssets);
- const filterdFiles = files.filter(ModuleFilenameHelpers.matchObject.bind(undefined, options));
- filterdFiles.forEach((file) => {
- const oldWarnFunction = uglify.AST_Node.warn_function;
- const warnings = [];
- let sourceMap;
- try {
- const asset = compilation.assets[file];
- if(asset.__UglifyJsPlugin) {
- compilation.assets[file] = asset.__UglifyJsPlugin;
- return;
- }
- let input;
- let inputSourceMap;
- if(options.sourceMap) {
- if(asset.sourceAndMap) {
- const sourceAndMap = asset.sourceAndMap();
- inputSourceMap = sourceAndMap.map;
- input = sourceAndMap.source;
- } else {
- inputSourceMap = asset.map();
- input = asset.source();
- }
- sourceMap = new SourceMapConsumer(inputSourceMap);
- uglify.AST_Node.warn_function = (warning) => { // eslint-disable-line camelcase
- const match = /\[.+:([0-9]+),([0-9]+)\]/.exec(warning);
- const line = +match[1];
- const column = +match[2];
- const original = sourceMap.originalPositionFor({
- line: line,
- column: column
- });
- if(!original || !original.source || original.source === file) return;
- if(!warningsFilter(original.source)) return;
- warnings.push(warning.replace(/\[.+:([0-9]+),([0-9]+)\]/, "") +
- "[" + requestShortener.shorten(original.source) + ":" + original.line + "," + original.column + "]");
- };
- } else {
- input = asset.source();
- uglify.AST_Node.warn_function = (warning) => { // eslint-disable-line camelcase
- warnings.push(warning);
- };
- }
- uglify.base54.reset();
- let ast = uglify.parse(input, {
- filename: file
- });
- if(options.compress !== false) {
- ast.figure_out_scope();
- const compress = uglify.Compressor(options.compress || {
- warnings: false
- }); // eslint-disable-line new-cap
- ast = compress.compress(ast);
- }
- if(options.mangle !== false) {
- ast.figure_out_scope(options.mangle || {});
- ast.compute_char_frequency(options.mangle || {});
- ast.mangle_names(options.mangle || {});
- if(options.mangle && options.mangle.props) {
- uglify.mangle_properties(ast, options.mangle.props);
- }
- }
- const output = {};
- output.comments = Object.prototype.hasOwnProperty.call(options, "comments") ? options.comments : /^\**!|@preserve|@license/;
- output.beautify = options.beautify;
- for(let k in options.output) {
- output[k] = options.output[k];
- }
- const extractedComments = [];
- if(options.extractComments) {
- const condition = {};
- if(typeof options.extractComments === "string" || options.extractComments instanceof RegExp) {
- // extractComments specifies the extract condition and output.comments specifies the preserve condition
- condition.preserve = output.comments;
- condition.extract = options.extractComments;
- } else if(Object.prototype.hasOwnProperty.call(options.extractComments, "condition")) {
- // Extract condition is given in extractComments.condition
- condition.preserve = output.comments;
- condition.extract = options.extractComments.condition;
- } else {
- // No extract condition is given. Extract comments that match output.comments instead of preserving them
- condition.preserve = false;
- condition.extract = output.comments;
- }
-
- // Ensure that both conditions are functions
- ["preserve", "extract"].forEach(key => {
- switch(typeof condition[key]) {
- case "boolean":
- var b = condition[key];
- condition[key] = () => b;
- break;
- case "function":
- break;
- case "string":
- if(condition[key] === "all") {
- condition[key] = () => true;
- break;
- }
- var regex = new RegExp(condition[key]);
- condition[key] = (astNode, comment) => regex.test(comment.value);
- break;
- default:
- regex = condition[key];
- condition[key] = (astNode, comment) => regex.test(comment.value);
- }
- });
-
- // Redefine the comments function to extract and preserve
- // comments according to the two conditions
- output.comments = (astNode, comment) => {
- if(condition.extract(astNode, comment)) {
- extractedComments.push(
- comment.type === "comment2" ? "/*" + comment.value + "*/" : "//" + comment.value
- );
- }
- return condition.preserve(astNode, comment);
- };
- }
- let map;
- if(options.sourceMap) {
- map = uglify.SourceMap({ // eslint-disable-line new-cap
- file: file,
- root: ""
- });
- output.source_map = map; // eslint-disable-line camelcase
- }
- const stream = uglify.OutputStream(output); // eslint-disable-line new-cap
- ast.print(stream);
- if(map) map = map + "";
- const stringifiedStream = stream + "";
- let outputSource = (map ?
- new SourceMapSource(stringifiedStream, file, JSON.parse(map), input, inputSourceMap) :
- new RawSource(stringifiedStream));
- if(extractedComments.length > 0) {
- let commentsFile = options.extractComments.filename || file + ".LICENSE";
- if(typeof commentsFile === "function") {
- commentsFile = commentsFile(file);
- }
-
- // Write extracted comments to commentsFile
- const commentsSource = new RawSource(extractedComments.join("\n\n") + "\n");
- if(commentsFile in compilation.assets) {
- // commentsFile already exists, append new comments...
- if(compilation.assets[commentsFile] instanceof ConcatSource) {
- compilation.assets[commentsFile].add("\n");
- compilation.assets[commentsFile].add(commentsSource);
- } else {
- compilation.assets[commentsFile] = new ConcatSource(
- compilation.assets[commentsFile], "\n", commentsSource
- );
- }
- } else {
- compilation.assets[commentsFile] = commentsSource;
- }
-
- // Add a banner to the original file
- if(options.extractComments.banner !== false) {
- let banner = options.extractComments.banner || "For license information please see " + commentsFile;
- if(typeof banner === "function") {
- banner = banner(commentsFile);
- }
- if(banner) {
- outputSource = new ConcatSource(
- "/*! " + banner + " */\n", outputSource
- );
- }
- }
- }
- asset.__UglifyJsPlugin = compilation.assets[file] = outputSource;
- if(warnings.length > 0) {
- compilation.warnings.push(new Error(file + " from UglifyJs\n" + warnings.join("\n")));
- }
- } catch(err) {
- if(err.line) {
- const original = sourceMap && sourceMap.originalPositionFor({
- line: err.line,
- column: err.col
- });
- if(original && original.source) {
- compilation.errors.push(new Error(file + " from UglifyJs\n" + err.message + " [" + requestShortener.shorten(original.source) + ":" + original.line + "," + original.column + "][" + file + ":" + err.line + "," + err.col + "]"));
- } else {
- compilation.errors.push(new Error(file + " from UglifyJs\n" + err.message + " [" + file + ":" + err.line + "," + err.col + "]"));
- }
- } else if(err.msg) {
- compilation.errors.push(new Error(file + " from UglifyJs\n" + err.msg));
- } else
- compilation.errors.push(new Error(file + " from UglifyJs\n" + err.stack));
- } finally {
- uglify.AST_Node.warn_function = oldWarnFunction; // eslint-disable-line camelcase
- }
- });
- callback();
- });
- });
- }
-}
+const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = UglifyJsPlugin;
|