}
private boolean execImpl() {
boolean changed = false;
for (int i = 0; i < program.getFragmentCount(); i++) {
JsBlock fragment = program.getFragmentBlock(i);
DuplicateFunctionBodyRecorder dfbr = new DuplicateFunctionBodyRecorder();
dfbr.accept(fragment);
Map<JsFunction, JsName> newNamesByHoistedFunction = Maps.newHashMap();
// Hoist all anonymous duplicate functions.
Map<JsFunction, JsFunction> dupMethodMap = dfbr.getDuplicateMethodMap();
for (JsFunction dupMethod : dupMethodMap.values()) {
if (newNamesByHoistedFunction.containsKey(dupMethod)) {
continue;
}
// move function to top scope and re-declaring it with a unique name
JsName newName = program.getScope().declareName(freshNameGenerator.getFreshName());
JsFunction newFunc = new JsFunction(dupMethod.getSourceInfo(),
program.getScope(), newName, dupMethod.isFromJava());
// we're not using the old function anymore, we can use reuse the body
// instead of cloning it
newFunc.setBody(dupMethod.getBody());
// also copy the parameters from the old function
newFunc.getParameters().addAll(dupMethod.getParameters());
// add the new function to the top level list of statements
fragment.getStatements().add(newFunc.makeStmt());
newNamesByHoistedFunction.put(dupMethod, newName);
}
ReplaceDuplicateInvocationNameRefs rdup = new ReplaceDuplicateInvocationNameRefs(
dfbr.getDuplicateMap(), dfbr.getBlacklist(), dupMethodMap, newNamesByHoistedFunction);