const { ModuleAnalyser } = require("deep-scope-analyser");
// const version = require("./package.json").version;
const pluginName = "WebpackDeepScopeAnalysisPlugin";
class WebpackDeepScopeAnalysisPlugin {
constructor() {
this.moduleMap = new WeakMap();
}
apply(compiler) {
compiler.hooks.compilation.tap(
pluginName,
(compilation, { normalModuleFactory }) => {
compilation.hooks.dependencyReference.tap(
pluginName,
(depRef, dep, module) => {
if (dep.type === "harmony import specifier") {
const moduleScopeAnalyser = this.moduleMap.get(module);
if (typeof moduleScopeAnalyser === "undefined") {
return depRef;
}
let { usedExports } = dep.originModule;
if (usedExports === false) usedExports = [];
if (
usedExports &&
dep.id &&
!dep.namespaceObjectAsContext &&
Array.isArray(usedExports)
) {
const exportInfo = moduleScopeAnalyser.generateExportInfo(usedExports);
if (dep.request in exportInfo) {
const names = exportInfo[dep.request];
if (names === true) {
return depRef;
} else if (names.indexOf(dep.id) >= 0) {
return depRef;
} else {
return null;
}
} else {
return null;
}
}
}
},
);
const handler = (parser, parserOptions) => {
if (
typeof parserOptions.harmony !== "undefined" &&
!parserOptions.harmony
) {
return;
}
parser.hooks.program.tap(pluginName, (ast, comments) => {
const { module } = parser.state;
const resourceName = module.resource;
if (!this.moduleMap.has(module)) {
const analyser = new ModuleAnalyser(resourceName, module);
analyser.analyze(ast, {
comments,
});
this.moduleMap.set(module, analyser);
}
});
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap(pluginName, handler);
normalModuleFactory.hooks.parser
.for("javascript/esm")
.tap(pluginName, handler);
},
);
}
}
module.exports = {
default: WebpackDeepScopeAnalysisPlugin,
ModuleAnalyser,
};