mirror of https://github.com/webpack/webpack.git
fix handling of circular references in the inner graph
This commit is contained in:
parent
c47e1f8071
commit
f01e7d253b
|
|
@ -96,41 +96,49 @@ class InnerGraphPlugin {
|
||||||
const innerGraph =
|
const innerGraph =
|
||||||
/** @type {InnerGraph} */ (parser.state.harmonyInnerGraph);
|
/** @type {InnerGraph} */ (parser.state.harmonyInnerGraph);
|
||||||
if (!innerGraph) return;
|
if (!innerGraph) return;
|
||||||
// flatten graph
|
// flatten graph to terminal nodes (string, undefined or true)
|
||||||
const unexpanded = new Set(innerGraph.keys());
|
const nonTerminal = new Set(innerGraph.keys());
|
||||||
const expand = key => {
|
while (nonTerminal.size > 0) {
|
||||||
if (!unexpanded.has(key)) return;
|
for (const key of nonTerminal) {
|
||||||
unexpanded.delete(key);
|
/** @type {Set<string|TopLevelSymbol> | true} */
|
||||||
|
let newSet = new Set();
|
||||||
|
let isTerminal = true;
|
||||||
const value = innerGraph.get(key);
|
const value = innerGraph.get(key);
|
||||||
if (value !== true && value !== undefined) {
|
if (value !== true && value !== undefined) {
|
||||||
const newSet = new Set();
|
|
||||||
for (const item of value) {
|
for (const item of value) {
|
||||||
if (typeof item === "string") {
|
if (typeof item === "string") {
|
||||||
newSet.add(item);
|
newSet.add(item);
|
||||||
} else {
|
} else {
|
||||||
expand(item);
|
|
||||||
const itemValue = innerGraph.get(item);
|
const itemValue = innerGraph.get(item);
|
||||||
if (itemValue === true) {
|
if (itemValue === true) {
|
||||||
innerGraph.set(key, true);
|
newSet = true;
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
if (itemValue !== undefined) {
|
if (itemValue !== undefined) {
|
||||||
for (const i of itemValue) {
|
for (const i of itemValue) {
|
||||||
if (typeof i === "string") newSet.add(i);
|
if (i === key) continue;
|
||||||
|
newSet.add(i);
|
||||||
|
if (typeof i !== "string") {
|
||||||
|
isTerminal = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newSet.size === 0) {
|
}
|
||||||
|
if (newSet === true) {
|
||||||
|
innerGraph.set(key, true);
|
||||||
|
} else if (newSet.size === 0) {
|
||||||
innerGraph.set(key, undefined);
|
innerGraph.set(key, undefined);
|
||||||
} else {
|
} else {
|
||||||
innerGraph.set(key, newSet);
|
innerGraph.set(key, newSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
if (isTerminal) {
|
||||||
for (const item of unexpanded) {
|
nonTerminal.delete(key);
|
||||||
expand(item);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const dep of parser.state
|
for (const dep of parser.state
|
||||||
.harmonyAllExportDependentDependencies) {
|
.harmonyAllExportDependentDependencies) {
|
||||||
const value = innerGraph.get(dep);
|
const value = innerGraph.get(dep);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
import "./inner";
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { exportAUsed, exportBUsed, exportCUsed } from "./inner";
|
||||||
|
import { y } from "./module";
|
||||||
|
|
||||||
|
it("export should be unused when only unused functions use it", () => {
|
||||||
|
expect(y("a")).toBe("okBAA");
|
||||||
|
expect(exportAUsed).toBe(true);
|
||||||
|
expect(exportBUsed).toBe(true);
|
||||||
|
if (process.env.NODE_ENV === "production") {
|
||||||
|
expect(exportCUsed).toBe(false);
|
||||||
|
}
|
||||||
|
return import("./chunk");
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
export function A(s) {
|
||||||
|
return s + "A";
|
||||||
|
}
|
||||||
|
export function B(s) {
|
||||||
|
return s + "B";
|
||||||
|
}
|
||||||
|
export function C(s) {
|
||||||
|
return s + "C";
|
||||||
|
}
|
||||||
|
|
||||||
|
export const exportAUsed = __webpack_exports_info__.A.used;
|
||||||
|
export const exportBUsed = __webpack_exports_info__.B.used;
|
||||||
|
export const exportCUsed = __webpack_exports_info__.C.used;
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { A, B, C } from "./inner";
|
||||||
|
|
||||||
|
function x(type) {
|
||||||
|
switch (type) {
|
||||||
|
case "a":
|
||||||
|
return withA("b");
|
||||||
|
case "b":
|
||||||
|
return withB("c");
|
||||||
|
case "c":
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function y(v) {
|
||||||
|
return withA(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
function withA(v) {
|
||||||
|
const value = x(v);
|
||||||
|
|
||||||
|
return A(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function withB(v) {
|
||||||
|
const value = x(v);
|
||||||
|
|
||||||
|
return B(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function withC(v) {
|
||||||
|
const value = x(v);
|
||||||
|
|
||||||
|
return C(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { x, y };
|
||||||
Loading…
Reference in New Issue