add Dependency.getCondition and conditional ModuleGraphConnections

getDependencyReference is no longer used to check of connection
This commit is contained in:
Tobias Koppers 2019-10-29 21:37:59 +01:00
parent 180eb8ba16
commit 8d46b21fad
30 changed files with 231 additions and 219 deletions

View File

@ -239,13 +239,16 @@ class ChunkGraph {
const { moduleGraph } = this;
return Array.from(
findGraphRoots(set, module => {
return moduleGraph
.getOutgoingConnections(module)
.reduce((arr, connection) => {
const module = connection.module;
if (module) arr.push(module);
return arr;
}, []);
const set = new Set();
for (const connection of moduleGraph.getOutgoingConnections(module)) {
if (!connection.module) continue;
if (connection.conditional) {
if (set.has(connection.module)) continue;
if (!connection.active) continue;
}
set.add(connection.module);
}
return set;
})
).sort(compareModulesByIdentifier);
}

View File

@ -1855,9 +1855,7 @@ class Compilation {
* @returns {DependencyReference} a reference for the dependency
*/
getDependencyReference(dependency) {
if (!this.moduleGraph.getModule(dependency)) throw new Error("TODO");
const ref = dependency.getReference(this.moduleGraph);
if (!ref) return null;
return this.hooks.dependencyReference.call(ref, dependency);
}

View File

@ -81,12 +81,15 @@ class Dependency {
* @returns {DependencyReference} reference
*/
getReference(moduleGraph) {
const module = moduleGraph.getModule(this);
if (!module) return null;
return new DependencyReference(
() => moduleGraph.getModule(this),
DependencyReference.NS_OBJECT_IMPORTED
);
return new DependencyReference(DependencyReference.NS_OBJECT_IMPORTED);
}
/**
* @param {ModuleGraph} moduleGraph module graph
* @returns {function(): boolean} function to determine if the connection is active
*/
getCondition(moduleGraph) {
return null;
}
/**

View File

@ -122,12 +122,15 @@ class FlagDependencyUsagePlugin {
* @returns {void}
*/
const processDependency = dep => {
const connection = moduleGraph.getConnection(dep);
if (!connection || !connection.module || !connection.active) {
return;
}
const reference = compilation.getDependencyReference(dep);
if (!reference) return;
const referenceModule = reference.module;
const importedNames = reference.importedNames;
processModule(referenceModule, importedNames);
processModule(connection.module, importedNames);
};
for (const module of modules) {

View File

@ -331,7 +331,7 @@ class Module extends DependenciesBlock {
const connections = moduleGraph.getIncomingConnections(this);
return (
connections.length > 0 &&
connections.every(r => r.dependency && r.dependency.optional)
connections.every(r => r.dependency && r.dependency.optional && r.active)
);
}
@ -384,6 +384,7 @@ class Module extends DependenciesBlock {
hasReasonForChunk(chunk, moduleGraph, chunkGraph) {
// check for each reason if we need the chunk
for (const connection of moduleGraph.getIncomingConnections(this)) {
if (!connection.active) continue;
const fromModule = connection.originModule;
for (const originChunk of chunkGraph.getModuleChunksIterable(
fromModule
@ -401,7 +402,7 @@ class Module extends DependenciesBlock {
* @returns {boolean} true if at least one other module depends on this module
*/
hasReasons(moduleGraph) {
return moduleGraph.getIncomingConnections(this).length > 0;
return moduleGraph.getIncomingConnections(this).some(c => c.active);
}
/**

View File

@ -719,7 +719,8 @@ class ModuleGraph {
dependency,
module,
undefined,
weak
weak,
dependency.getCondition(this)
);
const mgd = this._getModuleGraphDependency(dependency);
mgd.connection = connection;
@ -745,6 +746,20 @@ class ModuleGraph {
newMgm.incomingConnections.add(connection);
}
/**
* @param {Dependency} dependency the referencing dependency
* @returns {void}
*/
removeConnection(dependency) {
const mgd = this._getModuleGraphDependency(dependency);
const { connection } = mgd;
const targetMgm = this._getModuleGraphModule(connection.module);
targetMgm.incomingConnections.delete(connection);
const originMgm = this._getModuleGraphModule(connection.originModule);
originMgm.outgoingConnections.delete(connection);
mgd.connection = undefined;
}
/**
* @param {Dependency} dependency the referencing dependency
* @param {string} explanation an explanation

View File

@ -15,14 +15,25 @@ class ModuleGraphConnection {
* @param {Module} module the referenced module
* @param {string=} explanation some extra detail
* @param {boolean=} weak the reference is weak
* @param {function(): boolean=} condition condition for the connection
*/
constructor(originModule, dependency, module, explanation, weak = false) {
constructor(
originModule,
dependency,
module,
explanation,
weak = false,
condition = undefined
) {
this.originModule = originModule;
this.resolvedOriginModule = originModule;
this.dependency = dependency;
this.resolvedModule = module;
this.module = module;
this.weak = weak;
this.conditional = !!condition;
/** @type {function(): boolean} */
this.condition = condition;
/** @type {Set<string>} */
this.explanations = new Set();
if (explanation) {
@ -30,6 +41,20 @@ class ModuleGraphConnection {
}
}
/**
* @param {function(): boolean} condition condition for the connection
* @returns {void}
*/
addCondition(condition) {
if (this.conditional) {
const old = this.condition;
this.condition = () => old() && condition();
} else {
this.conditional = true;
this.condition = condition;
}
}
/**
* @param {string} explanation the explanation to add
* @returns {void}
@ -41,6 +66,11 @@ class ModuleGraphConnection {
get explanation() {
return Array.from(this.explanations).join(" ");
}
get active() {
if (!this.conditional) return true;
return this.condition();
}
}
module.exports = ModuleGraphConnection;

View File

@ -39,7 +39,7 @@ class InferAsyncModulesPlugin {
const connections = moduleGraph.getIncomingConnections(module);
for (const connection of connections) {
const dep = connection.dependency;
if (dep instanceof HarmonyImportDependency) {
if (dep instanceof HarmonyImportDependency && connection.active) {
if (
this.errorOnMissingAwait &&
dep instanceof HarmonyImportSideEffectDependency &&

View File

@ -69,22 +69,18 @@ const extraceBlockInfoMap = compilation => {
* @returns {void}
*/
const iteratorDependency = d => {
// We skip Dependencies without Reference
const ref = compilation.getDependencyReference(d);
if (!ref) {
return;
}
// We skip Dependencies without Module pointer
const refModule = ref.module;
if (!refModule) {
return;
}
// We skip weak Dependencies
if (d.weak) {
const connection = compilation.moduleGraph.getConnection(d);
if (
!connection ||
!connection.module ||
!connection.active ||
connection.weak
) {
return;
}
blockInfoModules.add(refModule);
blockInfoModules.add(connection.module);
};
/**

View File

@ -10,16 +10,12 @@
/** @typedef {string[]} StringArray */
class DependencyReference {
// module must be dynamic, you must pass a function returning a module
// The point is that the `module` in Dependency could be replaced i. e. because of Scope Hoisting
/**
*
* @param {ModuleCallback} moduleCallback a callback to get the referenced module
* @param {StringArray[]} importedNames imported named from the module
* @param {number} order the order information or NaN if don't care
*/
constructor(moduleCallback, importedNames, order = NaN) {
this.moduleCallback = moduleCallback;
constructor(importedNames, order = NaN) {
// true: full object
// false: only sideeffects/no export
// array of strings: the exports with this names
@ -28,19 +24,21 @@ class DependencyReference {
}
/**
* @param {DependencyReference[]} array an array (will be modified)
* @returns {DependencyReference[]} the array again
* @template T
* @param {T[]} array an array (will be modified)
* @param {function(T): DependencyReference} selector selector function
* @returns {T[]} the array again
*/
static sort(array) {
/** @type {WeakMap<DependencyReference, number>} */
const originalOrder = new WeakMap();
static sort(array, selector) {
/** @type {Map<T, number>} */
const originalOrder = new Map();
let i = 0;
for (const ref of array) {
originalOrder.set(ref, i++);
}
return array.sort((a, b) => {
const aOrder = a.order;
const bOrder = b.order;
const aOrder = selector(a).order;
const bOrder = selector(b).order;
if (isNaN(aOrder)) {
if (!isNaN(bOrder)) {
return 1;
@ -58,10 +56,6 @@ class DependencyReference {
return aOrg - bOrg;
});
}
get module() {
return this.moduleCallback();
}
}
DependencyReference.NO_IMPORTED_NAMES = [];

View File

@ -55,8 +55,6 @@ class ExportMode {
this.ignored = null;
/** @type {Set<string>|null} */
this.checked = null;
/** @type {null | function(): Module} */
this.getModule = null;
/** @type {string|null} */
this.userRequest = null;
}
@ -177,14 +175,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
);
mode.name = name;
mode.getModule = () => moduleGraph.getModule(this);
return mode;
} else if (importedModule.buildMeta.exportsType === "named") {
const mode = new ExportMode("reexport-named-default");
mode.name = name;
mode.getModule = () => moduleGraph.getModule(this);
return mode;
}
@ -227,8 +223,6 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
}
}
mode.getModule = () => moduleGraph.getModule(this);
return mode;
}
@ -254,8 +248,6 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
const mode = new ExportMode("dynamic-reexport");
mode.ignored = ignoredExports;
mode.getModule = () => moduleGraph.getModule(this);
return mode;
}
@ -303,8 +295,6 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
if (merged.size === 0) {
const mode = new ExportMode("empty-star");
mode.getModule = () => moduleGraph.getModule(this);
return mode;
}
@ -316,13 +306,24 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
const mode = new ExportMode("normal-reexport");
mode.getModule = () => moduleGraph.getModule(this);
mode.map = map;
mode.checked = checked;
return mode;
}
/**
* @param {ModuleGraph} moduleGraph module graph
* @returns {function(): boolean} function to determine if the connection is active
*/
getCondition(moduleGraph) {
return () => {
const mode = this.getMode(moduleGraph);
return mode.type !== "unused" && mode.type !== "empty-star";
};
}
/**
* Returns the referenced module and export
* @param {ModuleGraph} moduleGraph module graph
@ -339,11 +340,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
case "reexport-non-harmony-default":
case "reexport-named-default":
return new DependencyReference(
mode.getModule,
[["default"]],
this.sourceOrder
);
return new DependencyReference([["default"]], this.sourceOrder);
case "reexport-partial-namespace-object": {
/** @type {string[][]} */
@ -365,11 +362,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
}
};
processExportsInfo([], mode.partialNamespaceExportsInfo);
return new DependencyReference(
mode.getModule,
importedNames,
this.sourceOrder
);
return new DependencyReference(importedNames, this.sourceOrder);
}
case "reexport-namespace-object":
@ -378,14 +371,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
case "reexport-non-harmony-undefined":
case "dynamic-reexport":
return new DependencyReference(
mode.getModule,
DependencyReference.NS_OBJECT_IMPORTED,
this.sourceOrder
);
case "normal-reexport":
return new DependencyReference(
mode.getModule,
Array.from(mode.map.values()),
this.sourceOrder
);
@ -439,21 +430,21 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
return {
exports: true,
// TODO: consider passing `ignored` from `dynamic-reexport`
dependencies: [mode.getModule()]
dependencies: [moduleGraph.getModule(this)]
};
case "empty-star":
return {
exports: [],
dependencies: [mode.getModule()]
dependencies: [moduleGraph.getModule(this)]
};
case "normal-reexport":
return {
exports: Array.from(mode.map.keys()).map(name => ({
name,
from: mode.getModule(),
from: moduleGraph.getModule(this),
export: mode.map.get(name)
})),
dependencies: [mode.getModule()]
dependencies: [moduleGraph.getModule(this)]
};
case "reexport-fake-namespace-object":
case "reexport-non-harmony-default":
@ -462,7 +453,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
case "reexport-named-default":
return {
exports: [mode.name],
dependencies: [mode.getModule()]
dependencies: [moduleGraph.getModule(this)]
};
case "reexport-namespace-object":
case "reexport-partial-namespace-object":
@ -470,11 +461,11 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
exports: [
{
name: mode.name,
from: mode.getModule(),
from: moduleGraph.getModule(this),
export: null
}
],
dependencies: [mode.getModule()]
dependencies: [moduleGraph.getModule(this)]
};
default:
throw new Error(`Unknown mode ${mode.type}`);

View File

@ -41,9 +41,7 @@ class HarmonyImportDependency extends ModuleDependency {
* @returns {DependencyReference} reference
*/
getReference(moduleGraph) {
if (!moduleGraph.getModule(this)) return null;
return new DependencyReference(
() => moduleGraph.getModule(this),
DependencyReference.NO_IMPORTED_NAMES,
this.sourceOrder
);
@ -205,7 +203,10 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends
const dep = /** @type {HarmonyImportDependency} */ (dependency);
const { module, moduleGraph } = templateContext;
const referencedModule = moduleGraph.getModule(dep);
const connection = moduleGraph.getConnection(dep);
if (connection && !connection.active) return;
const referencedModule = connection && connection.module;
const moduleKey = referencedModule
? referencedModule.identifier()
: dep.request;

View File

@ -21,21 +21,6 @@ class HarmonyImportSideEffectDependency extends HarmonyImportDependency {
super(request, sourceOrder);
}
/**
* Returns the referenced module and export
* @param {ModuleGraph} moduleGraph module graph
* @returns {DependencyReference} reference
*/
getReference(moduleGraph) {
const module = moduleGraph.getModule(this);
if (module && module.factoryMeta.sideEffectFree) {
return null;
}
return super.getReference(moduleGraph);
}
get type() {
return "harmony side effect evaluation";
}
@ -46,21 +31,6 @@ makeSerializable(
"webpack/lib/dependencies/HarmonyImportSideEffectDependency"
);
HarmonyImportSideEffectDependency.Template = class HarmonyImportSideEffectDependencyTemplate extends HarmonyImportDependency.Template {
/**
* @param {Dependency} dependency the dependency for which the template should be applied
* @param {ReplaceSource} source the current replace source which can be modified
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, templateContext) {
const dep = /** @type {HarmonyImportSideEffectDependency} */ (dependency);
const { moduleGraph } = templateContext;
const module = moduleGraph.getModule(dep);
if (!module || !module.factoryMeta.sideEffectFree) {
super.apply(dependency, source, templateContext);
}
}
};
HarmonyImportSideEffectDependency.Template = HarmonyImportDependency.Template;
module.exports = HarmonyImportSideEffectDependency;

View File

@ -73,6 +73,14 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
moduleGraph.getMeta(this)[idsSymbol] = ids;
}
/**
* @param {ModuleGraph} moduleGraph module graph
* @returns {function(): boolean} function to determine if the connection is active
*/
getCondition(moduleGraph) {
return () => this.checkUsedByExports(moduleGraph);
}
checkUsedByExports(moduleGraph) {
if (this.usedByExports === false) return false;
if (this.usedByExports !== true && this.usedByExports !== undefined) {
@ -94,12 +102,8 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
* @returns {DependencyReference} reference
*/
getReference(moduleGraph) {
if (!this.checkUsedByExports(moduleGraph)) return null;
const module = moduleGraph.getModule(this);
if (!module) return null;
const ids = this.getIds(moduleGraph);
return new DependencyReference(
() => moduleGraph.getModule(this),
[this.namespaceObjectAsContext ? ids.slice(0, -1) : ids],
this.sourceOrder
);
@ -223,10 +227,12 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
apply(dependency, source, templateContext) {
const dep = /** @type {HarmonyImportSpecifierDependency} */ (dependency);
const { moduleGraph } = templateContext;
const connection = moduleGraph.getConnection(dep);
// Skip rendering depending when dependency is conditional
if (!dep.checkUsedByExports(moduleGraph)) return null;
if (connection && !connection.active) return;
super.apply(dependency, source, templateContext);
const { runtimeTemplate, module, runtimeRequirements } = templateContext;
const ids = dep.getIds(moduleGraph);
const exportExpr = runtimeTemplate.exportFromImport({

View File

@ -28,13 +28,8 @@ class RequireIncludeDependency extends ModuleDependency {
* @returns {DependencyReference} reference
*/
getReference(moduleGraph) {
const module = moduleGraph.getModule(this);
if (!module) return null;
// This doesn't use any export
return new DependencyReference(
() => moduleGraph.getModule(this),
DependencyReference.NO_IMPORTED_NAMES
);
return new DependencyReference(DependencyReference.NO_IMPORTED_NAMES);
}
get type() {

View File

@ -28,13 +28,7 @@ class WebAssemblyExportImportedDependency extends ModuleDependency {
* @returns {DependencyReference} reference
*/
getReference(moduleGraph) {
const module = moduleGraph.getModule(this);
if (!module) return null;
return new DependencyReference(() => moduleGraph.getModule(this), [
[this.name]
]);
return new DependencyReference([[this.name]]);
}
get type() {

View File

@ -37,13 +37,7 @@ class WebAssemblyImportDependency extends ModuleDependency {
* @returns {DependencyReference} reference
*/
getReference(moduleGraph) {
const module = moduleGraph.getModule(this);
if (!module) return null;
return new DependencyReference(() => moduleGraph.getModule(this), [
[this.name]
]);
return new DependencyReference([[this.name]]);
}
/**

View File

@ -99,6 +99,7 @@ class OccurrenceModuleIdsPlugin {
const result =
moduleGraph
.getIncomingConnections(m)
.filter(c => c.active)
.reduce(countOccursInEntry, 0) +
initialChunkChunkMap.get(m) +
entryCountMap.get(m);
@ -108,7 +109,10 @@ class OccurrenceModuleIdsPlugin {
for (const m of modules) {
const result =
moduleGraph.getIncomingConnections(m).reduce(countOccurs, 0) +
moduleGraph
.getIncomingConnections(m)
.filter(c => c.active)
.reduce(countOccurs, 0) +
chunkGraph.getNumberOfModuleChunks(m) +
entryCountMap.get(m);
occursInAllChunksMap.set(m, result);

View File

@ -731,7 +731,7 @@ class JavascriptModulesPlugin {
result.allowInlineStartup &&
moduleGraph
.getIncomingConnections(entryModule)
.some(c => c.originModule)
.some(c => c.originModule && c.active)
) {
buf2.push(
"// This entry module is referenced by other modules so it can't be inlined"

View File

@ -706,6 +706,8 @@ class ConcatenatedModule extends Module {
* @returns {ConcatenationEntry[]} concatenation list
*/
static _createConcatenationList(rootModule, modulesSet, compilation) {
const { moduleGraph } = compilation;
const list = [];
const set = new Set();
@ -715,12 +717,17 @@ class ConcatenatedModule extends Module {
*/
const getConcatenatedImports = module => {
const references = module.dependencies
.filter(dep => dep instanceof HarmonyImportDependency)
.map(dep => compilation.getDependencyReference(dep))
.filter(ref => ref !== null);
DependencyReference.sort(references);
return references.map(ref => {
return () => ref.module;
.filter(dep => {
if (!(dep instanceof HarmonyImportDependency)) return false;
const connection = moduleGraph.getConnection(dep);
return connection && connection.module && connection.active;
})
.map(dep => ({ dep, ref: compilation.getDependencyReference(dep) }))
.filter(({ ref }) => ref !== null);
// TODO improve this
DependencyReference.sort(references, x => x.ref);
return references.map(({ dep }) => {
return () => moduleGraph.getModule(dep);
});
};

View File

@ -298,10 +298,15 @@ class InnerGraphPlugin {
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("HarmonyModulesPlugin", handler);
.tap("InnerGraphPlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/esm")
.tap("HarmonyModulesPlugin", handler);
.tap("InnerGraphPlugin", handler);
compilation.hooks.optimizeDependencies.tap(
"InnerGraphPlugin",
modules => {}
);
}
);
}

View File

@ -175,12 +175,7 @@ class ModuleConcatenationPlugin {
const incomingConnections = moduleGraph
.getIncomingConnections(module)
.filter(connection => {
return (
!connection.originModule ||
connection.originModule.isModuleUsed(moduleGraph)
);
});
.filter(connection => connection.active);
// Module must only be used by Harmony Imports
const nonHarmonyConnections = incomingConnections.filter(
@ -381,30 +376,28 @@ class ModuleConcatenationPlugin {
*/
_getImports(compilation, module) {
const moduleGraph = compilation.moduleGraph;
return new Set(
module.dependencies
const set = new Set();
for (const dep of module.dependencies) {
// Get reference info only for harmony Dependencies
if (!(dep instanceof HarmonyImportDependency)) continue;
// Get reference info only for harmony Dependencies
.map(dep => {
if (!(dep instanceof HarmonyImportDependency)) return null;
if (!compilation) return dep.getReference(moduleGraph);
return compilation.getDependencyReference(dep);
})
const connection = moduleGraph.getConnection(dep);
// Reference is valid and has a module
if (!connection || !connection.module || !connection.active) continue;
// Reference is valid and has a module
// Dependencies are simple enough to concat them
.filter(
ref =>
ref &&
ref.module &&
((Array.isArray(ref.importedNames) &&
ref.importedNames.every(i => i.length > 0)) ||
Array.isArray(moduleGraph.getProvidedExports(ref.module)))
)
const ref = compilation.getDependencyReference(dep);
if (!ref) continue;
// Take the imported module
.map(ref => ref.module)
);
const importedNames = ref.importedNames;
if (
(Array.isArray(importedNames) &&
importedNames.every(i => i.length > 0)) ||
Array.isArray(moduleGraph.getProvidedExports(module))
) {
set.add(connection.module);
}
}
return set;
}
/**
@ -443,7 +436,7 @@ class ModuleConcatenationPlugin {
// Every module which depends on the added module must be in the configuration too.
for (const connection of moduleGraph.getIncomingConnections(module)) {
// Modules that are not used can be ignored
if (!connection.originModule.isModuleUsed(moduleGraph)) continue;
if (!connection.active) continue;
const problem = this._tryToAdd(
compilation,

View File

@ -8,6 +8,7 @@
const glob2regexp = require("glob-to-regexp");
const { STAGE_DEFAULT } = require("../OptimizationStages");
const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency");
const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
/** @typedef {import("../Compiler")} Compiler */
@ -107,13 +108,21 @@ class SideEffectsFlagPlugin {
for (const [key, ids] of mode.map) {
if (ids.length > 0 && !mode.checked.has(key)) {
map.set(key, {
module: mode.getModule(),
module: moduleGraph.getModule(dep),
exportName: ids[0]
});
}
}
}
}
} else if (dep instanceof HarmonyImportSideEffectDependency) {
const connection = moduleGraph.getConnection(dep);
if (connection) {
connection.addCondition(() => {
const refModule = moduleGraph.getModule(dep);
return !refModule || !refModule.factoryMeta.sideEffectFree;
});
}
}
}
}

View File

@ -739,6 +739,7 @@ const SIMPLE_EXTRACTORS = {
? reason.resolvedOriginModule.readableIdentifier(requestShortener)
: null,
type: reason.dependency ? reason.dependency.type : null,
active: reason.active,
explanation: reason.explanation,
userRequest:
depAsAny && "userRequest" in depAsAny ? depAsAny.userRequest : null

View File

@ -273,6 +273,8 @@ const SIMPLE_PRINTERS = {
"moduleReason.module": (module, { magenta }) => magenta(module),
"moduleReason.loc": loc => loc,
"moduleReason.explanation": (explanation, { cyan }) => cyan(explanation),
"moduleReason.active": (active, { formatFlag }) =>
active ? undefined : formatFlag("inactive"),
"moduleReason.resolvedModule": (module, { magenta }) => magenta(module),
"module.profile.total": (value, { formatTime }) => formatTime(value),
@ -594,6 +596,7 @@ const PREFERED_ORDERS = {
"modules"
],
moduleReason: [
"active",
"type",
"userRequest",
"moduleId",

View File

@ -33,10 +33,11 @@ class WasmFinalizeExportsPlugin {
for (const connection of compilation.moduleGraph.getIncomingConnections(
module
)) {
// 2. is referenced by a non-WebAssembly module
// 2. is active and referenced by a non-WebAssembly module
if (
connection.active &&
connection.originModule.type.startsWith("webassembly") ===
false
false
) {
const ref = compilation.getDependencyReference(
connection.dependency

View File

@ -2550,8 +2550,8 @@ Entrypoint main = main.js
./main.js + 1 modules 231 bytes [built]
[no exports used]
harmony side effect evaluation ./CompB ./components/src/CompAB/index.js 2:0-43
harmony export imported specifier ./CompB ./components/src/CompAB/index.js 2:0-43
harmony export imported specifier ./CompAB ./components/src/index.js 1:0-40 (skipped side-effect-free modules)
[inactive] harmony export imported specifier ./CompB ./components/src/CompAB/index.js 2:0-43
[inactive] harmony export imported specifier ./CompAB ./components/src/index.js 1:0-40 (skipped side-effect-free modules)
entry ./main.js main
| ./components/src/CompAB/CompB.js 77 bytes [built]
| [only some exports used: default]
@ -2560,33 +2560,33 @@ Entrypoint main = main.js
| [no exports used]
./components/src/CompAB/CompA.js 89 bytes [built]
[only some exports used: default]
harmony side effect evaluation ./CompA ./components/src/CompAB/index.js 1:0-43
harmony export imported specifier ./CompA ./components/src/CompAB/index.js 1:0-43
harmony export imported specifier ./CompAB ./components/src/index.js 1:0-40 (skipped side-effect-free modules)
[inactive] harmony side effect evaluation ./CompA ./components/src/CompAB/index.js 1:0-43
[inactive] harmony export imported specifier ./CompA ./components/src/CompAB/index.js 1:0-43
[inactive] harmony export imported specifier ./CompAB ./components/src/index.js 1:0-40 (skipped side-effect-free modules)
harmony import specifier ./components ./foo.js 3:20-25 (skipped side-effect-free modules)
harmony import specifier ./components ./main.js + 1 modules ./main.js 3:15-20 (skipped side-effect-free modules)
./foo.js 101 bytes [built]
import() ./foo ./main.js + 1 modules ./main.js 6:0-15
./components/src/index.js 84 bytes [orphan] [built]
[module unused]
harmony side effect evaluation ./components ./foo.js 1:0-37
harmony side effect evaluation ./components ./main.js + 1 modules ./main.js 1:0-44
[inactive] harmony side effect evaluation ./components ./foo.js 1:0-37
[inactive] harmony side effect evaluation ./components ./main.js + 1 modules ./main.js 1:0-44
./components/src/CompAB/utils.js 97 bytes [built]
harmony side effect evaluation ./utils ./components/src/CompAB/CompA.js 1:0-35
[inactive] harmony side effect evaluation ./utils ./components/src/CompAB/CompA.js 1:0-35
harmony import specifier ./utils ./components/src/CompAB/CompA.js 5:5-12
harmony side effect evaluation ./utils ./main.js + 1 modules ./components/src/CompAB/CompB.js 1:0-30
[inactive] harmony side effect evaluation ./utils ./main.js + 1 modules ./components/src/CompAB/CompB.js 1:0-30
harmony import specifier ./utils ./main.js + 1 modules ./components/src/CompAB/CompB.js 5:2-5
./components/src/CompAB/index.js 87 bytes [orphan] [built]
[module unused]
harmony side effect evaluation ./CompAB ./components/src/index.js 1:0-40
[inactive] harmony side effect evaluation ./CompAB ./components/src/index.js 1:0-40
./components/src/CompC/CompC.js 33 bytes [orphan] [built]
[module unused]
harmony side effect evaluation ./CompC ./components/src/CompC/index.js 1:0-34
harmony export imported specifier ./CompC ./components/src/CompC/index.js 1:0-34
harmony export imported specifier ./CompC ./components/src/index.js 2:0-43 (skipped side-effect-free modules)
[inactive] harmony side effect evaluation ./CompC ./components/src/CompC/index.js 1:0-34
[inactive] harmony export imported specifier ./CompC ./components/src/CompC/index.js 1:0-34
[inactive] harmony export imported specifier ./CompC ./components/src/index.js 2:0-43 (skipped side-effect-free modules)
./components/src/CompC/index.js 34 bytes [orphan] [built]
[module unused]
harmony side effect evaluation ./CompC ./components/src/index.js 2:0-43
[inactive] harmony side effect evaluation ./CompC ./components/src/index.js 2:0-43
+ 6 hidden modules"
`;
@ -2600,27 +2600,27 @@ Entrypoint main = main.js
./index.js + 2 modules 158 bytes [built]
[no exports used]
harmony side effect evaluation ./c ./node_modules/pmodule/b.js 5:0-24
harmony export imported specifier ./c ./node_modules/pmodule/b.js 5:0-24
[inactive] harmony export imported specifier ./c ./node_modules/pmodule/b.js 5:0-24
entry ./index main
| ./node_modules/pmodule/index.js 75 bytes [built]
| [only some exports used: default]
| harmony side effect evaluation pmodule ./index.js 1:0-33
| [inactive] harmony side effect evaluation pmodule ./index.js 1:0-33
| harmony import specifier pmodule ./index.js 3:12-15
| ./node_modules/pmodule/c.js 28 bytes [built]
| [only some exports used: z]
| harmony import specifier pmodule ./index.js 3:17-18 (skipped side-effect-free modules)
| harmony export imported specifier ./b ./node_modules/pmodule/index.js 2:0-30 (skipped side-effect-free modules)
| [inactive] harmony export imported specifier ./b ./node_modules/pmodule/index.js 2:0-30 (skipped side-effect-free modules)
| ./index.js 55 bytes [built]
| [no exports used]
./node_modules/pmodule/a.js 60 bytes [orphan] [built]
[module unused]
harmony side effect evaluation ./a ./index.js + 2 modules ./node_modules/pmodule/index.js 1:0-20
harmony export imported specifier ./a ./index.js + 2 modules ./node_modules/pmodule/index.js 1:0-20
[inactive] harmony side effect evaluation ./a ./index.js + 2 modules ./node_modules/pmodule/index.js 1:0-20
[inactive] harmony export imported specifier ./a ./index.js + 2 modules ./node_modules/pmodule/index.js 1:0-20
./node_modules/pmodule/b.js 69 bytes [orphan] [built]
[module unused]
harmony side effect evaluation ./b ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30
harmony export imported specifier ./b ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30
harmony export imported specifier ./b ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30"
[inactive] harmony side effect evaluation ./b ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30
[inactive] harmony export imported specifier ./b ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30
[inactive] harmony export imported specifier ./b ./index.js + 2 modules ./node_modules/pmodule/index.js 2:0-30"
`;
exports[`StatsTestCases should print correct stats for simple 1`] = `

View File

@ -26,7 +26,8 @@ const explain = object => {
value = JSON.stringify(value);
}
let msg = `${key} = ${value}`;
if (key !== "stack" && msg.length > 100) msg = msg.slice(0, 97) + "...";
if (key !== "stack" && key !== "details" && msg.length > 100)
msg = msg.slice(0, 97) + "...";
return msg;
})
.join("; ");

View File

@ -17,10 +17,11 @@ module.exports = {
compilation => {
compilation.hooks.dependencyReference.tap("Test", (ref, dep) => {
const module = compilation.moduleGraph.getParentModule(dep);
if (!module.identifier().endsWith("module.js")) return ref;
const refModule = compilation.moduleGraph.getModule(dep);
if (
module.identifier().endsWith("module.js") &&
ref.module &&
ref.module.identifier().endsWith("reference.js") &&
refModule &&
refModule.identifier().endsWith("reference.js") &&
Array.isArray(ref.importedNames) &&
ref.importedNames.some(
names => names.length === 1 && names[0] === "unused"
@ -29,11 +30,7 @@ module.exports = {
const newExports = ref.importedNames.filter(
names => names.length !== 1 || names[0] !== "unused"
);
return new DependencyReference(
() => ref.module,
newExports,
ref.order
);
return new DependencyReference(newExports, ref.order);
}
return ref;
});

View File

@ -12,10 +12,11 @@ module.exports = {
this.hooks.compilation.tap("Test", compilation => {
compilation.hooks.dependencyReference.tap("Test", (ref, dep) => {
const module = compilation.moduleGraph.getParentModule(dep);
if (!module.identifier().endsWith("module.js")) return ref;
const refModule = compilation.moduleGraph.getModule(dep);
if (
module.identifier().endsWith("module.js") &&
ref.module &&
ref.module.identifier().endsWith("reference.js") &&
refModule &&
refModule.identifier().endsWith("reference.js") &&
Array.isArray(ref.importedNames) &&
ref.importedNames.some(
names => names.length === 1 && names[0] === "unused"
@ -24,11 +25,7 @@ module.exports = {
const newExports = ref.importedNames.filter(
names => names.length !== 1 || names[0] !== "unused"
);
return new DependencyReference(
() => ref.module,
newExports,
ref.order
);
return new DependencyReference(newExports, ref.order);
}
return ref;
});