2016-09-06 05:41:03 +08:00
|
|
|
/*
|
|
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
|
|
Author Tobias Koppers @sokra
|
|
|
|
*/
|
2017-01-10 18:59:56 +08:00
|
|
|
"use strict";
|
2016-09-06 05:41:03 +08:00
|
|
|
|
2017-12-01 17:42:43 +08:00
|
|
|
const Queue = require("./util/Queue");
|
|
|
|
|
2017-11-08 18:32:05 +08:00
|
|
|
const addToSet = (a, b) => {
|
|
|
|
let changed = false;
|
2017-12-01 17:42:43 +08:00
|
|
|
for(const item of b) {
|
2017-11-08 18:32:05 +08:00
|
|
|
if(!a.has(item)) {
|
|
|
|
a.add(item);
|
|
|
|
changed = true;
|
|
|
|
}
|
2017-12-01 17:42:43 +08:00
|
|
|
}
|
2017-11-08 18:32:05 +08:00
|
|
|
return changed;
|
|
|
|
};
|
|
|
|
|
2017-01-10 18:59:56 +08:00
|
|
|
class FlagDependencyExportsPlugin {
|
2016-09-06 05:41:03 +08:00
|
|
|
|
2017-01-10 18:59:56 +08:00
|
|
|
apply(compiler) {
|
2017-12-06 22:01:25 +08:00
|
|
|
compiler.hooks.compilation.tap("FlagDependencyExportsPlugin", (compilation) => {
|
|
|
|
compilation.hooks.finishModules.tap("FlagDependencyExportsPlugin", (modules) => {
|
2017-12-01 17:42:43 +08:00
|
|
|
const dependencies = new Map();
|
2016-09-06 05:41:03 +08:00
|
|
|
|
2017-12-01 17:42:43 +08:00
|
|
|
const queue = new Queue();
|
2017-11-08 18:32:05 +08:00
|
|
|
|
2017-01-10 18:59:56 +08:00
|
|
|
let module;
|
|
|
|
let moduleWithExports;
|
2017-03-14 19:55:19 +08:00
|
|
|
let moduleProvidedExports;
|
2016-09-06 05:41:03 +08:00
|
|
|
|
2017-11-08 18:32:05 +08:00
|
|
|
const processDependenciesBlock = depBlock => {
|
2017-12-01 17:42:43 +08:00
|
|
|
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;
|
2017-11-08 18:32:05 +08:00
|
|
|
};
|
2017-01-10 18:59:56 +08:00
|
|
|
|
2017-11-08 18:32:05 +08:00
|
|
|
const processDependency = dep => {
|
2017-01-10 18:59:56 +08:00
|
|
|
const exportDesc = dep.getExports && dep.getExports();
|
|
|
|
if(!exportDesc) return;
|
|
|
|
moduleWithExports = true;
|
|
|
|
const exports = exportDesc.exports;
|
2017-12-01 17:42:43 +08:00
|
|
|
// break early if it's only in the worst state
|
2017-12-07 00:39:42 +08:00
|
|
|
if(module.buildMeta.providedExports === true) {
|
2017-12-01 17:42:43 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// break if it should move to the worst state
|
|
|
|
if(exports === true) {
|
2017-12-07 00:39:42 +08:00
|
|
|
module.buildMeta.providedExports = true;
|
2017-12-01 17:42:43 +08:00
|
|
|
notifyDependencies();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// merge in new exports
|
|
|
|
if(Array.isArray(exports)) {
|
|
|
|
if(addToSet(moduleProvidedExports, exports)) {
|
|
|
|
notifyDependencies();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// store dependencies
|
2017-01-10 18:59:56 +08:00
|
|
|
const exportDeps = exportDesc.dependencies;
|
|
|
|
if(exportDeps) {
|
2017-12-01 17:42:43 +08:00
|
|
|
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);
|
2017-02-05 10:44:18 +08:00
|
|
|
}
|
2016-09-09 20:20:29 +08:00
|
|
|
}
|
2016-11-21 08:00:25 +08:00
|
|
|
}
|
2017-12-01 17:42:43 +08:00
|
|
|
return false;
|
2017-11-08 18:32:05 +08:00
|
|
|
};
|
2016-09-09 20:50:14 +08:00
|
|
|
|
2017-11-08 18:32:05 +08:00
|
|
|
const notifyDependencies = () => {
|
2017-12-01 17:42:43 +08:00
|
|
|
const deps = dependencies.get(module);
|
|
|
|
if(deps !== undefined) {
|
|
|
|
for(const dep of deps) {
|
|
|
|
queue.enqueue(dep);
|
|
|
|
}
|
2017-01-10 18:59:56 +08:00
|
|
|
}
|
2017-11-08 18:32:05 +08:00
|
|
|
};
|
|
|
|
|
2017-12-01 17:42:43 +08:00
|
|
|
// Start with all modules without provided exports
|
|
|
|
for(const module of modules) {
|
2017-12-07 00:39:42 +08:00
|
|
|
if(!module.buildMeta.providedExports) {
|
2017-12-01 17:42:43 +08:00
|
|
|
queue.enqueue(module);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while(queue.length > 0) {
|
|
|
|
module = queue.dequeue();
|
2017-01-10 18:59:56 +08:00
|
|
|
|
2017-12-07 00:39:42 +08:00
|
|
|
if(module.buildMeta.providedExports !== true) {
|
2017-12-23 01:23:20 +08:00
|
|
|
moduleWithExports = module.buildMeta && module.buildMeta.exportsType;
|
2017-12-07 00:39:42 +08:00
|
|
|
moduleProvidedExports = Array.isArray(module.buildMeta.providedExports) ? new Set(module.buildMeta.providedExports) : new Set();
|
2017-11-08 18:32:05 +08:00
|
|
|
processDependenciesBlock(module);
|
|
|
|
if(!moduleWithExports) {
|
2017-12-07 00:39:42 +08:00
|
|
|
module.buildMeta.providedExports = true;
|
2017-11-08 18:32:05 +08:00
|
|
|
notifyDependencies();
|
2017-12-07 00:39:42 +08:00
|
|
|
} else if(module.buildMeta.providedExports !== true) {
|
|
|
|
module.buildMeta.providedExports = Array.from(moduleProvidedExports);
|
2017-11-08 18:32:05 +08:00
|
|
|
}
|
2017-01-10 18:59:56 +08:00
|
|
|
}
|
2017-11-08 18:32:05 +08:00
|
|
|
}
|
|
|
|
});
|
2017-12-07 00:39:42 +08:00
|
|
|
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);
|
|
|
|
});
|
2016-09-06 05:41:03 +08:00
|
|
|
});
|
2017-01-10 18:59:56 +08:00
|
|
|
}
|
|
|
|
}
|
2016-09-06 05:41:03 +08:00
|
|
|
|
2017-01-10 18:59:56 +08:00
|
|
|
module.exports = FlagDependencyExportsPlugin;
|