| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 | /*	MIT License http://www.opensource.org/licenses/mit-license.php	Author Tobias Koppers @sokra*/"use strict";/** @typedef {import("./Module")} Module *//** @typedef {import("./DependenciesBlock")} DependenciesBlock *//** @typedef {false | true | string[]} UsedExports */const addToSet = (a, b) => {	for (const item of b) {		if (!a.includes(item)) a.push(item);	}	return a;};const isSubset = (biggerSet, subset) => {	if (biggerSet === true) return true;	if (subset === true) return false;	return subset.every(item => biggerSet.indexOf(item) >= 0);};class FlagDependencyUsagePlugin {	apply(compiler) {		compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => {			compilation.hooks.optimizeDependencies.tap(				"FlagDependencyUsagePlugin",				modules => {					const processModule = (module, usedExports) => {						module.used = true;						if (module.usedExports === true) return;						if (usedExports === true) {							module.usedExports = true;						} else if (Array.isArray(usedExports)) {							const old = module.usedExports ? module.usedExports.length : -1;							module.usedExports = addToSet(								module.usedExports || [],								usedExports							);							if (module.usedExports.length === old) {								return;							}						} else if (Array.isArray(module.usedExports)) {							return;						} else {							module.usedExports = false;						}						// for a module without side effects we stop tracking usage here when no export is used						// This module won't be evaluated in this case						if (module.factoryMeta.sideEffectFree) {							if (module.usedExports === false) return;							if (								Array.isArray(module.usedExports) &&								module.usedExports.length === 0							)								return;						}						queue.push([module, module, module.usedExports]);					};					const processDependenciesBlock = (module, depBlock, usedExports) => {						for (const dep of depBlock.dependencies) {							processDependency(module, dep);						}						for (const variable of depBlock.variables) {							for (const dep of variable.dependencies) {								processDependency(module, dep);							}						}						for (const block of depBlock.blocks) {							queue.push([module, block, usedExports]);						}					};					const processDependency = (module, dep) => {						const reference = compilation.getDependencyReference(module, dep);						if (!reference) return;						const referenceModule = reference.module;						const importedNames = reference.importedNames;						const oldUsed = referenceModule.used;						const oldUsedExports = referenceModule.usedExports;						if (							!oldUsed ||							(importedNames &&								(!oldUsedExports || !isSubset(oldUsedExports, importedNames)))						) {							processModule(referenceModule, importedNames);						}					};					for (const module of modules) {						if (!module.used) module.used = false;					}					/** @type {[Module, DependenciesBlock, UsedExports][]} */					const queue = [];					for (const preparedEntrypoint of compilation._preparedEntrypoints) {						if (preparedEntrypoint.module) {							processModule(preparedEntrypoint.module, true);						}					}					while (queue.length) {						const queueItem = queue.pop();						processDependenciesBlock(queueItem[0], queueItem[1], queueItem[2]);					}				}			);		});	}}module.exports = FlagDependencyUsagePlugin;
 |