mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			132 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| /*
 | |
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | |
| 	Author Tobias Koppers @sokra
 | |
| */
 | |
| "use strict";
 | |
| 
 | |
| const Queue = require("./util/Queue");
 | |
| 
 | |
| const addToSet = (a, b) => {
 | |
| 	let changed = false;
 | |
| 	for(const item of b) {
 | |
| 		if(!a.has(item)) {
 | |
| 			a.add(item);
 | |
| 			changed = true;
 | |
| 		}
 | |
| 	}
 | |
| 	return changed;
 | |
| };
 | |
| 
 | |
| class FlagDependencyExportsPlugin {
 | |
| 
 | |
| 	apply(compiler) {
 | |
| 		compiler.hooks.compilation.tap("FlagDependencyExportsPlugin", (compilation) => {
 | |
| 			compilation.hooks.finishModules.tap("FlagDependencyExportsPlugin", (modules) => {
 | |
| 				const dependencies = new Map();
 | |
| 
 | |
| 				const queue = new Queue();
 | |
| 
 | |
| 				let module;
 | |
| 				let moduleWithExports;
 | |
| 				let moduleProvidedExports;
 | |
| 
 | |
| 				const processDependenciesBlock = depBlock => {
 | |
| 					for(const dep of depBlock.dependencies) {
 | |
| 						if(processDependency(dep))
 | |
| 							return true;
 | |
| 					}
 | |
| 					for(const variable of depBlock.variables) {
 | |
| 						for(const dep of variable.dependencies) {
 | |
| 							if(processDependency(dep))
 | |
| 								return true;
 | |
| 						}
 | |
| 					}
 | |
| 					for(const block of depBlock.blocks) {
 | |
| 						if(processDependenciesBlock(block))
 | |
| 							return true;
 | |
| 					}
 | |
| 					return false;
 | |
| 				};
 | |
| 
 | |
| 				const processDependency = dep => {
 | |
| 					const exportDesc = dep.getExports && dep.getExports();
 | |
| 					if(!exportDesc) return;
 | |
| 					moduleWithExports = true;
 | |
| 					const exports = exportDesc.exports;
 | |
| 					// break early if it's only in the worst state
 | |
| 					if(module.buildMeta.providedExports === true) {
 | |
| 						return true;
 | |
| 					}
 | |
| 					// break if it should move to the worst state
 | |
| 					if(exports === true) {
 | |
| 						module.buildMeta.providedExports = true;
 | |
| 						notifyDependencies();
 | |
| 						return true;
 | |
| 					}
 | |
| 					// merge in new exports
 | |
| 					if(Array.isArray(exports)) {
 | |
| 						if(addToSet(moduleProvidedExports, exports)) {
 | |
| 							notifyDependencies();
 | |
| 						}
 | |
| 					}
 | |
| 					// store dependencies
 | |
| 					const exportDeps = exportDesc.dependencies;
 | |
| 					if(exportDeps) {
 | |
| 						for(const exportDependency of exportDeps) {
 | |
| 							// add dependency for this module
 | |
| 							const set = dependencies.get(exportDependency);
 | |
| 							if(set === undefined) {
 | |
| 								dependencies.set(exportDependency, new Set([module]));
 | |
| 							} else {
 | |
| 								set.add(module);
 | |
| 							}
 | |
| 						}
 | |
| 					}
 | |
| 					return false;
 | |
| 				};
 | |
| 
 | |
| 				const notifyDependencies = () => {
 | |
| 					const deps = dependencies.get(module);
 | |
| 					if(deps !== undefined) {
 | |
| 						for(const dep of deps) {
 | |
| 							queue.enqueue(dep);
 | |
| 						}
 | |
| 					}
 | |
| 				};
 | |
| 
 | |
| 				// Start with all modules without provided exports
 | |
| 				for(const module of modules) {
 | |
| 					if(!module.buildMeta.providedExports) {
 | |
| 						queue.enqueue(module);
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				while(queue.length > 0) {
 | |
| 					module = queue.dequeue();
 | |
| 
 | |
| 					if(module.buildMeta.providedExports !== true) {
 | |
| 						moduleWithExports = module.buildMeta && module.buildMeta.harmonyModule;
 | |
| 						moduleProvidedExports = Array.isArray(module.buildMeta.providedExports) ? new Set(module.buildMeta.providedExports) : new Set();
 | |
| 						processDependenciesBlock(module);
 | |
| 						if(!moduleWithExports) {
 | |
| 							module.buildMeta.providedExports = true;
 | |
| 							notifyDependencies();
 | |
| 						} else if(module.buildMeta.providedExports !== true) {
 | |
| 							module.buildMeta.providedExports = Array.from(moduleProvidedExports);
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			});
 | |
| 			const providedExportsCache = new WeakMap();
 | |
| 			compilation.hooks.rebuildModule.tap("FlagDependencyExportsPlugin", module => {
 | |
| 				providedExportsCache.set(module, module.buildMeta.providedExports);
 | |
| 			});
 | |
| 			compilation.hooks.finishRebuildingModule.tap("FlagDependencyExportsPlugin", module => {
 | |
| 				module.buildMeta.providedExports = providedExportsCache.get(module);
 | |
| 			});
 | |
| 		});
 | |
| 	}
 | |
| }
 | |
| 
 | |
| module.exports = FlagDependencyExportsPlugin;
 |