move flatter algo into InnerGraph

This commit is contained in:
Sergey Melyukov 2020-01-27 18:33:40 +03:00
parent 721ce54bdf
commit 68a61677dc
3 changed files with 78 additions and 74 deletions

View File

@ -82,12 +82,9 @@ module.exports = class HarmonyImportDependencyParserPlugin {
const addDepToInnerGraph = dep => {
if (!InnerGraph.isEnabled(parser.state)) return;
const allExportDependentDependencies = InnerGraph.getExportDependentDependencies(
parser.state
);
const currentTopLevelSymbol = InnerGraph.getTopLevelSymbol(parser.state);
allExportDependentDependencies.add(dep);
InnerGraph.addDependency(parser.state, dep);
if (!currentTopLevelSymbol) {
InnerGraph.setUsage(parser.state, dep, true);
} else {

View File

@ -86,13 +86,85 @@ exports.getUsage = (state, symbol) => {
/**
* @param {ParserState} state parser state
* @returns {IterableIterator<TopLevelSymbol | Dependency>} graph nodes
* @returns {Map<Dependency, Set<string | TopLevelSymbol> | true>} usage data
*/
exports.getNodesIterable = state => {
exports.inferDependencyUsage = state => {
const innerGraphState = getState(state);
if (!innerGraphState) {
return;
}
const { allExportDependentDependencies, innerGraph } = innerGraphState;
// flatten graph to terminal nodes (string, undefined or true)
const nonTerminal = new Set(innerGraph.keys());
while (nonTerminal.size > 0) {
for (const key of nonTerminal) {
/** @type {Set<string|TopLevelSymbol> | true} */
let newSet = new Set();
let isTerminal = true;
const value = innerGraph.get(key);
if (value !== true && value !== undefined) {
for (const item of value) {
if (typeof item === "string") {
newSet.add(item);
} else {
const itemValue = innerGraph.get(item);
if (itemValue === true) {
newSet = true;
break;
}
if (itemValue !== undefined) {
for (const i of itemValue) {
if (i === key) continue;
if (value.has(i)) continue;
newSet.add(i);
if (typeof i !== "string") {
isTerminal = false;
}
}
}
}
}
if (newSet === true) {
innerGraph.set(key, true);
} else if (newSet.size === 0) {
innerGraph.set(key, undefined);
} else {
innerGraph.set(key, newSet);
}
}
if (isTerminal) {
nonTerminal.delete(key);
}
}
}
for (const dep of allExportDependentDependencies) {
const value = innerGraph.get(dep);
switch (value) {
case undefined:
dep.usedByExports = false;
break;
case true:
dep.usedByExports = true;
break;
default:
dep.usedByExports = /** @type {Set<string>} */ (value);
break;
}
}
};
/**
* @param {ParserState} state parser state
* @param {PureExpressionDependency|HarmonyImportSpecifierDependency} dep dependency
*/
exports.addDependency = (state, dep) => {
const innerGraphState = getState(state);
if (innerGraphState) {
return innerGraphState.innerGraph.keys();
innerGraphState.allExportDependentDependencies.add(dep);
}
};

View File

@ -118,69 +118,7 @@ class InnerGraphPlugin {
parser.hooks.finish.tap("InnerGraphPlugin", () => {
if (!InnerGraph.isEnabled(parser.state)) return;
const allExportDependentDependencies = InnerGraph.getExportDependentDependencies(
parser.state
);
// flatten graph to terminal nodes (string, undefined or true)
const nonTerminal = new Set(
InnerGraph.getNodesIterable(parser.state)
);
while (nonTerminal.size > 0) {
for (const key of nonTerminal) {
/** @type {Set<string|TopLevelSymbol> | true} */
let newSet = new Set();
let isTerminal = true;
const value = InnerGraph.getUsage(parser.state, key);
if (value !== true && value !== undefined) {
for (const item of value) {
if (typeof item === "string") {
newSet.add(item);
} else {
const itemValue = InnerGraph.getUsage(parser.state, item);
if (itemValue === true) {
newSet = true;
break;
}
if (itemValue !== undefined) {
for (const i of itemValue) {
if (i === key) continue;
if (value.has(i)) continue;
newSet.add(i);
if (typeof i !== "string") {
isTerminal = false;
}
}
}
}
}
if (newSet === true) {
InnerGraph.setUsage(parser.state, key, true);
} else if (newSet.size === 0) {
InnerGraph.setUsage(parser.state, key, undefined);
} else {
InnerGraph.setUsage(parser.state, key, newSet);
}
}
if (isTerminal) {
nonTerminal.delete(key);
}
}
}
for (const dep of allExportDependentDependencies) {
const value = InnerGraph.getUsage(parser.state, dep);
switch (value) {
case undefined:
dep.usedByExports = false;
break;
case true:
dep.usedByExports = true;
break;
default:
dep.usedByExports = /** @type {Set<string>} */ (value);
break;
}
}
InnerGraph.inferDependencyUsage(parser.state);
});
/** @type {WeakMap<{}, TopLevelSymbol>} */
const statementWithTopLevelSymbol = new WeakMap();
@ -285,9 +223,6 @@ class InnerGraphPlugin {
});
parser.hooks.declarator.tap("InnerGraphPlugin", (decl, statement) => {
if (!InnerGraph.isEnabled(parser.state)) return;
const allExportDependentDependencies = InnerGraph.getExportDependentDependencies(
parser.state
);
const fn = declWithTopLevelSymbol.get(decl);
if (fn) {
if (pureDeclarators.has(decl)) {
@ -295,7 +230,7 @@ class InnerGraphPlugin {
dep.loc = decl.loc;
parser.state.module.addDependency(dep);
InnerGraph.setUsage(parser.state, dep, new Set([fn]));
allExportDependentDependencies.add(dep);
InnerGraph.addDependency(parser.state, dep);
}
InnerGraph.setTopLevelSymbol(parser.state, fn);
parser.walkExpression(decl.init);