aboutsummaryrefslogtreecommitdiff
path: root/node_modules/webpack/lib/optimize
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/webpack/lib/optimize')
-rw-r--r--node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js121
-rw-r--r--node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js192
-rw-r--r--node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js55
-rw-r--r--node_modules/webpack/lib/optimize/CommonsChunkPlugin.js362
-rw-r--r--node_modules/webpack/lib/optimize/DedupePlugin.js15
-rw-r--r--node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js36
-rw-r--r--node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js35
-rw-r--r--node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js59
-rw-r--r--node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js33
-rw-r--r--node_modules/webpack/lib/optimize/MinChunkSizePlugin.js65
-rw-r--r--node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js116
-rw-r--r--node_modules/webpack/lib/optimize/RemoveEmptyChunksPlugin.js21
-rw-r--r--node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js91
-rw-r--r--node_modules/webpack/lib/optimize/UglifyJsPlugin.js236
14 files changed, 1437 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js b/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js
new file mode 100644
index 000000000..826a6baa9
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/AggressiveMergingPlugin.js
@@ -0,0 +1,121 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+class AggressiveMergingPlugin {
+ constructor(options) {
+ if(options !== undefined && typeof options !== "object" || Array.isArray(options)) {
+ throw new Error("Argument should be an options object. To use defaults, pass in nothing.\nFor more info on options, see https://webpack.js.org/plugins/");
+ }
+ this.options = options || {};
+ }
+
+ apply(compiler) {
+ const options = this.options;
+ const minSizeReduce = options.minSizeReduce || 1.5;
+
+ function getParentsWeight(chunk) {
+ return chunk.parents.map((p) => {
+ return p.isInitial() ? options.entryChunkMultiplicator || 10 : 1;
+ }).reduce((a, b) => {
+ return a + b;
+ }, 0);
+ }
+ compiler.plugin("compilation", (compilation) => {
+ compilation.plugin("optimize-chunks-advanced", (chunks) => {
+ let combinations = [];
+ chunks.forEach((a, idx) => {
+ if(a.isInitial()) return;
+ for(let i = 0; i < idx; i++) {
+ const b = chunks[i];
+ if(b.isInitial()) continue;
+ combinations.push([b, a]);
+ }
+ });
+
+ combinations.forEach((pair) => {
+ const a = pair[0].size({
+ chunkOverhead: 0
+ });
+ const b = pair[1].size({
+ chunkOverhead: 0
+ });
+ const ab = pair[0].integratedSize(pair[1], {
+ chunkOverhead: 0
+ });
+ pair.push({
+ a: a,
+ b: b,
+ ab: ab
+ });
+ let newSize;
+ if(ab === false) {
+ pair.unshift(false);
+ } 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
+ });
+ } else {
+ newSize = ab;
+ }
+
+ pair.unshift((a + b) / newSize);
+ });
+ combinations = combinations.filter((pair) => {
+ return pair[0] !== false;
+ });
+ combinations.sort((a, b) => {
+ return b[0] - a[0];
+ });
+
+ const pair = combinations[0];
+
+ if(!pair) return;
+ if(pair[0] < minSizeReduce) return;
+
+ if(options.moveToParents) {
+ const commonModules = pair[1].modules.filter((m) => {
+ return pair[2].modules.indexOf(m) >= 0;
+ });
+ const aOnlyModules = pair[1].modules.filter((m) => {
+ return commonModules.indexOf(m) < 0;
+ });
+ const bOnlyModules = pair[2].modules.filter((m) => {
+ return commonModules.indexOf(m) < 0;
+ });
+ aOnlyModules.forEach((m) => {
+ pair[1].removeModule(m);
+ m.removeChunk(pair[1]);
+ pair[1].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) => {
+ c.addModule(m);
+ m.addChunk(c);
+ });
+ });
+ }
+ if(pair[1].integrate(pair[2], "aggressive-merge")) {
+ chunks.splice(chunks.indexOf(pair[2]), 1);
+ return true;
+ }
+ });
+ });
+ }
+}
+
+module.exports = AggressiveMergingPlugin;
diff --git a/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js b/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js
new file mode 100644
index 000000000..e05b3eb4c
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/AggressiveSplittingPlugin.js
@@ -0,0 +1,192 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+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);
+ };
+}
+
+function isNotAEntryModule(entryModule) {
+ return function(module) {
+ return entryModule !== module;
+ };
+}
+
+function copyWithReason(obj) {
+ const newObj = {};
+ Object.keys(obj).forEach((key) => {
+ newObj[key] = obj[key];
+ });
+ if(!newObj.reasons || newObj.reasons.indexOf("aggressive-splitted") < 0)
+ newObj.reasons = (newObj.reasons || []).concat("aggressive-splitted");
+ return newObj;
+}
+
+class AggressiveSplittingPlugin {
+ constructor(options) {
+ this.options = options || {};
+ if(typeof this.options.minSize !== "number") this.options.minSize = 30 * 1024;
+ if(typeof this.options.maxSize !== "number") this.options.maxSize = 50 * 1024;
+ if(typeof this.options.chunkOverhead !== "number") this.options.chunkOverhead = 0;
+ if(typeof this.options.entryChunkMultiplicator !== "number") this.options.entryChunkMultiplicator = 1;
+ }
+ apply(compiler) {
+ compiler.plugin("compilation", (compilation) => {
+ compilation.plugin("optimize-chunks-advanced", (chunks) => {
+ const savedSplits = compilation.records && compilation.records.aggressiveSplits || [];
+ const usedSplits = compilation._aggressiveSplittingSplits ?
+ savedSplits.concat(compilation._aggressiveSplittingSplits) : savedSplits;
+
+ const minSize = this.options.minSize;
+ const maxSize = this.options.maxSize;
+ // 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()));
+
+ 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;
+ }
+ }
+ }
+ }
+ }
+ // 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) {
+ const newChunk = compilation.addChunk();
+ const modules = chunk.modules
+ .filter(isNotAEntryModule(chunk.entryModule))
+ .sort((a, b) => {
+ a = a.identifier();
+ b = b.identifier();
+ if(a > b) return 1;
+ if(a < b) return -1;
+ return 0;
+ });
+ for(let k = 0; k < modules.length; k++) {
+ chunk.moveModule(modules[k], newChunk);
+ const newSize = newChunk.size(this.options);
+ const chunkSize = chunk.size(this.options);
+ // break early if it's fine
+ if(chunkSize < maxSize && newSize < maxSize && newSize >= minSize && chunkSize >= minSize)
+ break;
+ if(newSize > maxSize && k === 0) {
+ // break if there is a single module which is bigger than maxSize
+ break;
+ }
+ if(newSize > maxSize || chunkSize < minSize) {
+ // move it back
+ newChunk.moveModule(modules[k], chunk);
+ // check if it's fine now
+ if(newSize < maxSize && newSize >= minSize && chunkSize >= minSize)
+ break;
+ }
+ }
+ if(newChunk.modules.length > 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()))
+ });
+ return true;
+ } else {
+ chunks.splice(chunks.indexOf(newChunk), 1);
+ }
+ }
+ }
+ });
+ compilation.plugin("record-hash", (records) => {
+ // 3. save to made splittings to records
+ const minSize = this.options.minSize;
+ if(!records.aggressiveSplits) records.aggressiveSplits = [];
+ compilation.chunks.forEach((chunk) => {
+ 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()));
+ if(typeof chunk._fromAggressiveSplittingIndex === "undefined") {
+ if(incorrectSize) return;
+ chunk.recorded = true;
+ records.aggressiveSplits.push({
+ modules: modules,
+ hash: chunk.hash,
+ id: chunk.id
+ });
+ } else {
+ const splitData = records.aggressiveSplits[chunk._fromAggressiveSplittingIndex];
+ if(splitData.hash !== chunk.hash || incorrectSize) {
+ if(chunk._fromAggressiveSplitting) {
+ chunk._aggressiveSplittingInvalid = true;
+ splitData.invalid = true;
+ } else {
+ splitData.hash = chunk.hash;
+ }
+ }
+ }
+ });
+ records.aggressiveSplits = records.aggressiveSplits.filter((splitData) => {
+ return !splitData.invalid;
+ });
+ });
+ compilation.plugin("need-additional-seal", (callback) => {
+ const invalid = compilation.chunks.some((chunk) => {
+ return chunk._aggressiveSplittingInvalid;
+ });
+ if(invalid)
+ return true;
+ });
+ });
+ }
+}
+module.exports = AggressiveSplittingPlugin;
diff --git a/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js b/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js
new file mode 100644
index 000000000..8166fc315
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/ChunkModuleIdRangePlugin.js
@@ -0,0 +1,55 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+class ChunkModuleIdRangePlugin {
+ constructor(options) {
+ this.options = options;
+ }
+ apply(compiler) {
+ 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];
+ if(!chunk) throw new Error("ChunkModuleIdRangePlugin: Chunk with name '" + options.name + "' was not found");
+ let currentId = options.start;
+ let chunkModules;
+ if(options.order) {
+ chunkModules = chunk.modules.slice();
+ switch(options.order) {
+ case "index":
+ chunkModules.sort((a, b) => {
+ return a.index - b.index;
+ });
+ break;
+ case "index2":
+ chunkModules.sort((a, b) => {
+ return a.index2 - b.index2;
+ });
+ break;
+ default:
+ throw new Error("ChunkModuleIdRangePlugin: unexpected value of order");
+ }
+
+ } else {
+ chunkModules = modules.filter((m) => {
+ return m.chunks.indexOf(chunk) >= 0;
+ });
+ }
+
+ for(let i = 0; i < chunkModules.length; i++) {
+ const m = chunkModules[i];
+ if(m.id === null) {
+ m.id = currentId++;
+ }
+ if(options.end && currentId > options.end)
+ break;
+ }
+ });
+ });
+ }
+}
+module.exports = ChunkModuleIdRangePlugin;
diff --git a/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js b/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js
new file mode 100644
index 000000000..d7c4849fe
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js
@@ -0,0 +1,362 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+let nextIdent = 0;
+class CommonsChunkPlugin {
+ constructor(options) {
+ if(arguments.length > 1) {
+ throw new Error(`Deprecation notice: CommonsChunkPlugin now only takes a single argument. Either an options
+object *or* the name of the chunk.
+Example: if your old code looked like this:
+ new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js')
+You would change it to:
+ new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.bundle.js' })
+The available options are:
+ name: string
+ names: string[]
+ filename: string
+ minChunks: number
+ chunks: string[]
+ children: boolean
+ async: boolean
+ minSize: number`);
+ }
+
+ const normalizedOptions = this.normalizeOptions(options);
+
+ this.chunkNames = normalizedOptions.chunkNames;
+ this.filenameTemplate = normalizedOptions.filenameTemplate;
+ this.minChunks = normalizedOptions.minChunks;
+ this.selectedChunks = normalizedOptions.selectedChunks;
+ this.children = normalizedOptions.children;
+ this.async = normalizedOptions.async;
+ this.minSize = normalizedOptions.minSize;
+ this.ident = __filename + (nextIdent++);
+ }
+
+ normalizeOptions(options) {
+ if(Array.isArray(options)) {
+ return {
+ chunkNames: options,
+ };
+ }
+
+ if(typeof options === "string") {
+ return {
+ chunkNames: [options],
+ };
+ }
+
+ // options.children and options.chunk may not be used together
+ if(options.children && options.chunks) {
+ throw new Error("You can't and it does not make any sense to use \"children\" and \"chunk\" options together.");
+ }
+
+ /**
+ * options.async and options.filename are also not possible together
+ * as filename specifies how the chunk is called but "async" implies
+ * 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.`);
+ }
+
+ /**
+ * Make sure this is either an array or undefined.
+ * "name" can be a string and
+ * "names" a string or an array
+ */
+ const chunkNames = options.name || options.names ? [].concat(options.name || options.names) : undefined;
+ return {
+ chunkNames: chunkNames,
+ filenameTemplate: options.filename,
+ minChunks: options.minChunks,
+ selectedChunks: options.chunks,
+ children: options.children,
+ async: options.async,
+ minSize: options.minSize
+ };
+ }
+
+ apply(compiler) {
+ compiler.plugin("this-compilation", (compilation) => {
+ compilation.plugin(["optimize-chunks", "optimize-extracted-chunks"], (chunks) => {
+ // only optimize once
+ if(compilation[this.ident]) return;
+ compilation[this.ident] = true;
+
+ /**
+ * Creates a list of "common"" chunks based on the options.
+ * The list is made up of preexisting or newly created chunks.
+ * - If chunk has the name as specified in the chunkNames it is put in the list
+ * - If no chunk with the name as given in chunkNames exists a new chunk is created and added to the list
+ *
+ * These chunks are the "targets" for extracted modules.
+ */
+ const targetChunks = this.getTargetChunks(chunks, compilation, this.chunkNames, this.children, this.async);
+
+ // iterate over all our new chunks
+ targetChunks.forEach((targetChunk, idx) => {
+
+ /**
+ * These chunks are subject to get "common" modules extracted and moved to the common chunk
+ */
+ const affectedChunks = this.getAffectedChunks(compilation, chunks, targetChunk, targetChunks, idx, this.selectedChunks, this.async, this.children);
+
+ // bail if no chunk is affected
+ if(!affectedChunks) {
+ return;
+ }
+
+ // If we are async create an async chunk now
+ // 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);
+ targetChunk = asyncChunk;
+ }
+
+ /**
+ * Check which modules are "common" and could be extracted to a "common" chunk
+ */
+ const extractableModules = this.getExtractableModules(this.minChunks, affectedChunks, targetChunk);
+
+ // If the minSize option is set check if the size extracted from the chunk is reached
+ // else bail out here.
+ // As all modules/commons are interlinked with each other, common modules would be extracted
+ // if we reach this mark at a later common chunk. (quirky I guess).
+ if(this.minSize) {
+ const modulesSize = this.calculateModulesSize(extractableModules);
+ // if too small, bail
+ if(modulesSize < this.minSize)
+ return;
+ }
+
+ // Remove modules that are moved to commons chunk from their original chunks
+ // return all chunks that are affected by having modules removed - we need them later (apparently)
+ const chunksWithExtractedModules = this.extractModulesAndReturnAffectedChunks(extractableModules, affectedChunks);
+
+ // connect all extracted modules with the common chunk
+ this.addExtractedModulesToTargetChunk(targetChunk, extractableModules);
+
+ // set filenameTemplate for chunk
+ if(this.filenameTemplate)
+ targetChunk.filenameTemplate = this.filenameTemplate;
+
+ // if we are async connect the blocks of the "reallyUsedChunk" - the ones that had modules removed -
+ // with the commonChunk and get the origins for the asyncChunk (remember "asyncChunk === commonChunk" at this moment).
+ // bail out
+ if(this.async) {
+ this.moveExtractedChunkBlocksToTargetChunk(chunksWithExtractedModules, targetChunk);
+ asyncChunk.origins = this.extractOriginsOfChunksWithExtractedModules(chunksWithExtractedModules);
+ return;
+ }
+
+ // we are not in "async" mode
+ // connect used chunks with commonChunk - shouldnt this be reallyUsedChunks here?
+ this.makeTargetChunkParentOfAffectedChunks(affectedChunks, targetChunk);
+ });
+ return true;
+ });
+ });
+ }
+
+ getTargetChunks(allChunks, compilation, chunkNames, children, asyncOption) {
+ const asyncOrNoSelectedChunk = children || asyncOption;
+
+ // we have specified chunk names
+ if(chunkNames) {
+ // map chunks by chunkName for quick access
+ const allChunksNameMap = allChunks.reduce((map, chunk) => {
+ if(chunk.name) {
+ map.set(chunk.name, chunk);
+ }
+ return map;
+ }, new Map());
+
+ // Ensure we have a chunk per specified chunk name.
+ // Reuse existing chunks if possible
+ return chunkNames.map(chunkName => {
+ if(allChunksNameMap.has(chunkName)) {
+ return allChunksNameMap.get(chunkName);
+ }
+ // add the filtered chunks to the compilation
+ return compilation.addChunk(chunkName);
+ });
+ }
+
+ // we dont have named chunks specified, so we just take all of them
+ if(asyncOrNoSelectedChunk) {
+ return allChunks;
+ }
+
+ /**
+ * No chunk name(s) was specified nor is this an async/children commons chunk
+ */
+ throw new Error(`You did not specify any valid target chunk settings.
+Take a look at the "name"/"names" or async/children option.`);
+ }
+
+ getAffectedChunks(compilation, allChunks, targetChunk, targetChunks, currentIndex, selectedChunks, asyncOption, children) {
+ const asyncOrNoSelectedChunk = children || asyncOption;
+
+ if(Array.isArray(selectedChunks)) {
+ return allChunks.filter(chunk => {
+ const notCommmonChunk = chunk !== targetChunk;
+ const isSelectedChunk = selectedChunks.indexOf(chunk.name) > -1;
+ return notCommmonChunk && isSelectedChunk;
+ });
+ }
+
+ if(asyncOrNoSelectedChunk) {
+ // nothing to do here
+ if(!targetChunk.chunks) {
+ return [];
+ }
+
+ return targetChunk.chunks.filter((chunk) => {
+ // we can only move modules from this chunk if the "commonChunk" is the only parent
+ return asyncOption || chunk.parents.length === 1;
+ });
+ }
+
+ /**
+ * past this point only entry chunks are allowed to become commonChunks
+ */
+ if(targetChunk.parents.length > 0) {
+ compilation.errors.push(new Error("CommonsChunkPlugin: While running in normal mode it's not allowed to use a non-entry chunk (" + targetChunk.name + ")"));
+ return;
+ }
+
+ /**
+ * If we find a "targetchunk" that is also a normal chunk (meaning it is probably specified as an entry)
+ * and the current target chunk comes after that and the found chunk has a runtime*
+ * make that chunk be an 'affected' chunk of the current target chunk.
+ *
+ * To understand what that means take a look at the "examples/chunkhash", this basically will
+ * result in the runtime to be extracted to the current target chunk.
+ *
+ * *runtime: the "runtime" is the "webpack"-block you may have seen in the bundles that resolves modules etc.
+ */
+ return allChunks.filter((chunk) => {
+ const found = targetChunks.indexOf(chunk);
+ if(found >= currentIndex) return false;
+ return chunk.hasRuntime();
+ });
+ }
+
+ createAsyncChunk(compilation, asyncOption, targetChunk) {
+ const asyncChunk = compilation.addChunk(typeof asyncOption === "string" ? asyncOption : undefined);
+ asyncChunk.chunkReason = "async commons chunk";
+ asyncChunk.extraAsync = true;
+ asyncChunk.addParent(targetChunk);
+ targetChunk.addChunk(asyncChunk);
+ return asyncChunk;
+ }
+
+ // If minChunks is a function use that
+ // otherwhise check if a module is used at least minChunks or 2 or usedChunks.length time
+ getModuleFilter(minChunks, targetChunk, usedChunksLength) {
+ if(typeof minChunks === "function") {
+ return minChunks;
+ }
+ const minCount = (minChunks || Math.max(2, usedChunksLength));
+ const isUsedAtLeastMinTimes = (module, count) => count >= minCount;
+ return isUsedAtLeastMinTimes;
+ }
+
+ getExtractableModules(minChunks, usedChunks, targetChunk) {
+ if(minChunks === Infinity) {
+ return [];
+ }
+
+ // count how many chunks contain a module
+ const commonModulesToCountMap = usedChunks.reduce((map, chunk) => {
+ for(let module of chunk.modules) {
+ const count = map.has(module) ? map.get(module) : 0;
+ map.set(module, count + 1);
+ }
+ return map;
+ }, new Map());
+
+ // filter by minChunks
+ const moduleFilterCount = this.getModuleFilter(minChunks, targetChunk, usedChunks.length);
+ // filter by condition
+ const moduleFilterCondition = (module, chunk) => {
+ if(!module.chunkCondition) {
+ return true;
+ }
+ return module.chunkCondition(chunk);
+ };
+
+ return Array.from(commonModulesToCountMap).filter(entry => {
+ const module = entry[0];
+ const count = entry[1];
+ // if the module passes both filters, keep it.
+ return moduleFilterCount(module, count) && moduleFilterCondition(module, targetChunk);
+ }).map(entry => entry[0]);
+ }
+
+ calculateModulesSize(modules) {
+ return modules.reduce((totalSize, module) => totalSize + module.size(), 0);
+ }
+
+ extractModulesAndReturnAffectedChunks(reallyUsedModules, usedChunks) {
+ return reallyUsedModules.reduce((affectedChunksSet, module) => {
+ for(let 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)) {
+ affectedChunksSet.add(chunk);
+ }
+ }
+ return affectedChunksSet;
+ }, new Set());
+ }
+
+ addExtractedModulesToTargetChunk(chunk, modules) {
+ for(let module of modules) {
+ chunk.addModule(module);
+ module.addChunk(chunk);
+ }
+ }
+
+ makeTargetChunkParentOfAffectedChunks(usedChunks, commonChunk) {
+ for(let 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) {
+ entrypoint.insertChunk(commonChunk, chunk);
+ }
+ }
+ }
+
+ moveExtractedChunkBlocksToTargetChunk(chunks, targetChunk) {
+ for(let chunk of chunks) {
+ for(let block of chunk.blocks) {
+ block.chunks.unshift(targetChunk);
+ targetChunk.addBlock(block);
+ }
+ }
+ }
+
+ extractOriginsOfChunksWithExtractedModules(chunks) {
+ const origins = [];
+ for(let chunk of chunks) {
+ for(let origin of chunk.origins) {
+ const newOrigin = Object.create(origin);
+ newOrigin.reasons = (origin.reasons || []).concat("async commons");
+ origins.push(newOrigin);
+ }
+ }
+ return origins;
+ }
+}
+
+module.exports = CommonsChunkPlugin;
diff --git a/node_modules/webpack/lib/optimize/DedupePlugin.js b/node_modules/webpack/lib/optimize/DedupePlugin.js
new file mode 100644
index 000000000..cffa43aaf
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/DedupePlugin.js
@@ -0,0 +1,15 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+class DedupePlugin {
+ apply(compiler) {
+ compiler.plugin("compilation", (compilation) => {
+ compilation.warnings.push(new Error("DedupePlugin: This plugin was removed from webpack. Remove it from your configuration."));
+ });
+ }
+}
+
+module.exports = DedupePlugin;
diff --git a/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js b/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js
new file mode 100644
index 000000000..71ee18533
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/EnsureChunkConditionsPlugin.js
@@ -0,0 +1,36 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+class EnsureChunkConditionsPlugin {
+
+ apply(compiler) {
+ compiler.plugin("compilation", (compilation) => {
+ compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => {
+ let changed = false;
+ chunks.forEach((chunk) => {
+ chunk.modules.slice().forEach((module) => {
+ if(!module.chunkCondition) return;
+ if(!module.chunkCondition(chunk)) {
+ const usedChunks = module._EnsureChunkConditionsPlugin_usedChunks = (module._EnsureChunkConditionsPlugin_usedChunks || []).concat(chunk);
+ const newChunks = [];
+ chunk.parents.forEach((parent) => {
+ if(usedChunks.indexOf(parent) < 0) {
+ parent.addModule(module);
+ newChunks.push(parent);
+ }
+ });
+ module.rewriteChunkInReasons(chunk, newChunks);
+ chunk.removeModule(module);
+ changed = true;
+ }
+ });
+ });
+ if(changed) return true;
+ });
+ });
+ }
+}
+module.exports = EnsureChunkConditionsPlugin;
diff --git a/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js b/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js
new file mode 100644
index 000000000..e8b5a9457
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/FlagIncludedChunksPlugin.js
@@ -0,0 +1,35 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+class FlagIncludedChunksPlugin {
+
+ apply(compiler) {
+ compiler.plugin("compilation", (compilation) => {
+ compilation.plugin("optimize-chunk-ids", (chunks) => {
+ chunks.forEach((chunkA) => {
+ chunks.forEach((chunkB) => {
+ // as we iterate the same iterables twice
+ // skip if we find ourselves
+ if(chunkA === chunkB) return;
+
+ // 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(chunkB.modules.length === 0) return;
+
+ // is chunkB in chunkA?
+ for(let i = 0; i < chunkB.modules.length; i++) {
+ if(chunkA.modules.indexOf(chunkB.modules[i]) < 0) return;
+ }
+ chunkA.ids.push(chunkB.id);
+ });
+ });
+ });
+ });
+ }
+}
+module.exports = FlagIncludedChunksPlugin;
diff --git a/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js b/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js
new file mode 100644
index 000000000..c156338ff
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js
@@ -0,0 +1,59 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+class LimitChunkCountPlugin {
+ constructor(options) {
+ if(options !== undefined && typeof options !== "object" || Array.isArray(options)) {
+ throw new Error("Argument should be an options object.\nFor more info on options, see https://webpack.js.org/plugins/");
+ }
+ this.options = options || {};
+ }
+ apply(compiler) {
+ const options = this.options;
+ compiler.plugin("compilation", (compilation) => {
+ compilation.plugin("optimize-chunks-advanced", (chunks) => {
+ const maxChunks = options.maxChunks;
+ if(!maxChunks) return;
+ if(maxChunks < 1) return;
+ if(chunks.length <= maxChunks) return;
+
+ if(chunks.length > maxChunks) {
+ const sortedExtendedPairCombinations = chunks.reduce((combinations, a, idx) => {
+ // create combination pairs
+ for(let i = 0; i < idx; i++) {
+ const b = chunks[i];
+ combinations.push([b, a]);
+ }
+ return combinations;
+ }, []).map((pair) => {
+ // extend combination pairs with size and integrated size
+ const a = pair[0].size(options);
+ const b = pair[1].size(options);
+ const ab = pair[0].integratedSize(pair[1], options);
+ return [a + b - ab, ab, pair[0], pair[1], a, b];
+ }).filter((extendedPair) => {
+ // filter pairs that do not have an integratedSize
+ // meaning they can NOT be integrated!
+ return extendedPair[1] !== false;
+ }).sort((a, b) => { // sadly javascript does an inplace sort here
+ // sort them by size
+ const diff = b[0] - a[0];
+ if(diff !== 0) return diff;
+ return a[1] - b[1];
+ });
+
+ const pair = sortedExtendedPairCombinations[0];
+
+ if(pair && pair[2].integrate(pair[3], "limit")) {
+ chunks.splice(chunks.indexOf(pair[3]), 1);
+ return true;
+ }
+ }
+ });
+ });
+ }
+}
+module.exports = LimitChunkCountPlugin;
diff --git a/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js b/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js
new file mode 100644
index 000000000..90df06b51
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/MergeDuplicateChunksPlugin.js
@@ -0,0 +1,33 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"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 = {};
+ chunks.slice().forEach((chunk) => {
+ if(chunk.hasRuntime() || chunk.hasEntryModule()) return;
+ const ident = getChunkIdentifier(chunk);
+ if(map[ident]) {
+ if(map[ident].integrate(chunk, "duplicate"))
+ chunks.splice(chunks.indexOf(chunk), 1);
+ return;
+ }
+ map[ident] = chunk;
+ });
+ });
+ });
+ }
+}
+module.exports = MergeDuplicateChunksPlugin;
diff --git a/node_modules/webpack/lib/optimize/MinChunkSizePlugin.js b/node_modules/webpack/lib/optimize/MinChunkSizePlugin.js
new file mode 100644
index 000000000..87a4c21af
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/MinChunkSizePlugin.js
@@ -0,0 +1,65 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+class MinChunkSizePlugin {
+ constructor(options) {
+ if(typeof options !== "object" || Array.isArray(options)) {
+ throw new Error("Argument should be an options object.\nFor more info on options, see https://webpack.js.org/plugins/");
+ }
+ this.options = options;
+ }
+
+ apply(compiler) {
+ const options = this.options;
+ const minChunkSize = options.minChunkSize;
+ compiler.plugin("compilation", (compilation) => {
+ compilation.plugin("optimize-chunks-advanced", (chunks) => {
+ const equalOptions = {
+ chunkOverhead: 1,
+ entryChunkMultiplicator: 1
+ };
+
+ const sortedSizeFilteredExtendedPairCombinations = chunks.reduce((combinations, a, idx) => {
+ // create combination pairs
+ for(let i = 0; i < idx; i++) {
+ const b = chunks[i];
+ combinations.push([b, a]);
+ }
+ return combinations;
+ }, []).filter((pair) => {
+ // check if one of the chunks sizes is smaller than the minChunkSize
+ const p0SmallerThanMinChunkSize = pair[0].size(equalOptions) < minChunkSize;
+ const p1SmallerThanMinChunkSize = pair[1].size(equalOptions) < minChunkSize;
+ return p0SmallerThanMinChunkSize || p1SmallerThanMinChunkSize;
+ }).map((pair) => {
+ // extend combination pairs with size and integrated size
+ const a = pair[0].size(options);
+ const b = pair[1].size(options);
+ const ab = pair[0].integratedSize(pair[1], options);
+ return [a + b - ab, ab, pair[0], pair[1]];
+ }).filter((pair) => {
+ // filter pairs that do not have an integratedSize
+ // meaning they can NOT be integrated!
+ return pair[1] !== false;
+ }).sort((a, b) => { // sadly javascript does an inplace sort here
+ // sort by size
+ const diff = b[0] - a[0];
+ if(diff !== 0) return diff;
+ return a[1] - b[1];
+ });
+
+ if(sortedSizeFilteredExtendedPairCombinations.length === 0) return;
+
+ const pair = sortedSizeFilteredExtendedPairCombinations[0];
+
+ pair[2].integrate(pair[3], "min-size");
+ chunks.splice(chunks.indexOf(pair[3]), 1);
+ return true;
+ });
+ });
+ }
+}
+module.exports = MinChunkSizePlugin;
diff --git a/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js b/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js
new file mode 100644
index 000000000..a6bb30b34
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js
@@ -0,0 +1,116 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+class OccurrenceOrderPlugin {
+ constructor(preferEntry) {
+ if(preferEntry !== undefined && typeof preferEntry !== "boolean") {
+ throw new Error("Argument should be a boolean.\nFor more info on this plugin, see https://webpack.js.org/plugins/");
+ }
+ this.preferEntry = preferEntry;
+ }
+ apply(compiler) {
+ 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);
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+ modules.sort((a, b) => {
+ if(preferEntry) {
+ const aEntryOccurs = occursInEntry(a);
+ const bEntryOccurs = occursInEntry(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.identifier() > b.identifier()) return 1;
+ if(a.identifier() < b.identifier()) 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;
+ }
+
+ 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);
+ 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;
+ });
+ });
+ });
+ }
+}
+
+module.exports = OccurrenceOrderPlugin;
diff --git a/node_modules/webpack/lib/optimize/RemoveEmptyChunksPlugin.js b/node_modules/webpack/lib/optimize/RemoveEmptyChunksPlugin.js
new file mode 100644
index 000000000..4b75e4617
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/RemoveEmptyChunksPlugin.js
@@ -0,0 +1,21 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"use strict";
+
+class RemoveEmptyChunksPlugin {
+
+ apply(compiler) {
+ compiler.plugin("compilation", (compilation) => {
+ compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => {
+ chunks.filter((chunk) => chunk.isEmpty() && !chunk.hasRuntime() && !chunk.hasEntryModule())
+ .forEach((chunk) => {
+ chunk.remove("empty");
+ chunks.splice(chunks.indexOf(chunk), 1);
+ });
+ });
+ });
+ }
+}
+module.exports = RemoveEmptyChunksPlugin;
diff --git a/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js b/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js
new file mode 100644
index 000000000..e73add989
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/RemoveParentModulesPlugin.js
@@ -0,0 +1,91 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"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.parents.length === 0) return false;
+ return allHaveModule(chunk.parents.filter((c) => {
+ return checkedChunks.indexOf(c) < 0;
+ }), module, checkedChunks);
+}
+
+function allHaveModule(someChunks, module, checkedChunks) {
+ if(!checkedChunks) checkedChunks = [];
+ var chunks = [];
+ for(var i = 0; i < someChunks.length; i++) {
+ checkedChunks.push(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);
+ }
+ }
+ }
+ 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) => {
+ compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => {
+ for(var index = 0; index < chunks.length; index++) {
+ var chunk = chunks[index];
+ if(chunk.parents.length === 0) continue;
+
+ // TODO consider Map when performance has improved https://gist.github.com/sokra/b36098368da7b8f6792fd7c85fca6311
+ var cache = Object.create(null);
+ var modules = chunk.modules.slice();
+ for(var i = 0; i < modules.length; i++) {
+ var module = modules[i];
+
+ var dId = debugIds(module.chunks);
+ var parentChunksWithModule;
+ if((dId in cache) && dId !== "no") {
+ parentChunksWithModule = cache[dId];
+ } else {
+ parentChunksWithModule = cache[dId] = allHaveModule(chunk.parents, module);
+ }
+ if(parentChunksWithModule) {
+ module.rewriteChunkInReasons(chunk, parentChunksWithModule);
+ chunk.removeModule(module);
+ }
+ }
+ }
+ });
+ });
+ }
+}
+module.exports = RemoveParentModulesPlugin;
diff --git a/node_modules/webpack/lib/optimize/UglifyJsPlugin.js b/node_modules/webpack/lib/optimize/UglifyJsPlugin.js
new file mode 100644
index 000000000..f95dc8eef
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/UglifyJsPlugin.js
@@ -0,0 +1,236 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+"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();
+ });
+ });
+ }
+}
+
+module.exports = UglifyJsPlugin;