Merge pull request #6904 from webpack/performance/concat

avoid walking scopes multiple times for performance reasons
This commit is contained in:
Tobias Koppers 2018-04-04 11:29:42 +02:00 committed by GitHub
commit 1958784433
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 18 deletions

View File

@ -168,17 +168,29 @@ const getFinalName = (
} }
}; };
const getSymbolsFromScope = (s, untilScope) => { const addScopeSymbols1 = (s, nameSet, scopeSet) => {
const allUsedNames = new Set();
let scope = s; let scope = s;
while (scope) { while (scope) {
if (scopeSet.has(scope)) break;
scopeSet.add(scope);
for (const variable of scope.variables) { for (const variable of scope.variables) {
allUsedNames.add(variable.name); nameSet.add(variable.name);
}
scope = scope.upper;
}
};
const addScopeSymbols2 = (s, nameSet, scopeSet1, scopeSet2) => {
let scope = s;
while (scope) {
if (scopeSet1.has(scope)) break;
if (scopeSet2.has(scope)) break;
scopeSet1.add(scope);
for (const variable of scope.variables) {
nameSet.add(variable.name);
} }
if (untilScope === scope) break;
scope = scope.upper; scope = scope.upper;
} }
return allUsedNames;
}; };
const getAllReferences = variable => { const getAllReferences = variable => {
@ -196,11 +208,6 @@ const getAllReferences = variable => {
return set; return set;
}; };
const reduceSet = (a, b) => {
for (const item of b) a.add(item);
return a;
};
const getPathInAst = (ast, node) => { const getPathInAst = (ast, node) => {
if (ast === node) { if (ast === node) {
return []; return [];
@ -816,8 +823,31 @@ class ConcatenatedModule extends Module {
"onsubmit" "onsubmit"
]); ]);
// Set of already checked scopes
const alreadyCheckedScopes = new Set();
// get all global names // get all global names
for (const info of modulesWithInfo) { for (const info of modulesWithInfo) {
const superClassExpressions = [];
// ignore symbols from moduleScope
if (info.moduleScope) {
alreadyCheckedScopes.add(info.moduleScope);
// The super class expression in class scopes behaves weird
// We store ranges of all super class expressions to make
// renaming to work correctly
for (const childScope of info.moduleScope.childScopes) {
if (childScope.type !== "class") continue;
if (!childScope.block.superClass) continue;
superClassExpressions.push({
range: childScope.block.superClass.range,
variables: childScope.variables
});
}
}
// add global symbols
if (info.globalScope) { if (info.globalScope) {
for (const reference of info.globalScope.through) { for (const reference of info.globalScope.through) {
const name = reference.identifier.name; const name = reference.identifier.name;
@ -826,12 +856,21 @@ class ConcatenatedModule extends Module {
name name
) )
) { ) {
for (const s of getSymbolsFromScope( for (const expr of superClassExpressions) {
reference.from, if (
info.moduleScope expr.range[0] <= reference.identifier.range[0] &&
)) { expr.range[1] >= reference.identifier.range[1]
allUsedNames.add(s); ) {
for (const variable of expr.variables) {
allUsedNames.add(variable.name);
} }
}
}
addScopeSymbols1(
reference.from,
allUsedNames,
alreadyCheckedScopes
);
} else { } else {
allUsedNames.add(name); allUsedNames.add(name);
} }
@ -856,9 +895,16 @@ class ConcatenatedModule extends Module {
const name = variable.name; const name = variable.name;
if (allUsedNames.has(name)) { if (allUsedNames.has(name)) {
const references = getAllReferences(variable); const references = getAllReferences(variable);
const symbolsInReferences = references const symbolsInReferences = new Set();
.map(ref => getSymbolsFromScope(ref.from, info.moduleScope)) const alreadyCheckedInnerScopes = new Set();
.reduce(reduceSet, new Set()); for (const ref of references) {
addScopeSymbols2(
ref.from,
symbolsInReferences,
alreadyCheckedInnerScopes,
alreadyCheckedScopes
);
}
const newName = this.findNewName( const newName = this.findNewName(
name, name,
allUsedNames, allUsedNames,

View File

@ -6,5 +6,15 @@ export function test() {
function file1_js_a() { function file1_js_a() {
return "fail"; return "fail";
} }
function file1_a() {
return "fail";
}
return a(); return a();
} }
function renaming_4967_file1_js_a() {
return "fail";
}
function renaming_4967_file1_a() {
return "fail";
}