Moved CodeSplitter to before js optimizations.
- also eliminated indexed fields and functions in JsProgram.
- fixed an error due to the crossfragment reference computation
being performed too early.
Change-Id: Id88f17697ec47326b5e5d9e9d3be8c25942a3881
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index b23739c..d3144d0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -381,7 +381,7 @@
// TODO(stalcup): hide metrics gathering in a callback or subclass
if (CoverageInstrumentor.isCoverageEnabled()) {
- CoverageInstrumentor.exec(jsProgram, instrumentableLines);
+ CoverageInstrumentor.exec(jprogram, jsProgram, jjsmap, instrumentableLines);
}
// (6) Normalize the Js AST
@@ -389,17 +389,22 @@
// TODO(stalcup): move to AST construction
JsSymbolResolver.exec(jsProgram);
+
if (options.getNamespace() == JsNamespaceOption.PACKAGE) {
if (!jprogram.getRunAsyncs().isEmpty()) {
options.setNamespace(JsNamespaceOption.NONE);
logger.log(TreeLogger.Type.WARN,
"Namespace option is not compatible with CodeSplitter, turning it off.");
} else {
- JsNamespaceChooser.exec(jsProgram, jjsmap);
+ JsNamespaceChooser.exec(jprogram, jsProgram, jjsmap);
}
}
// TODO(stalcup): move to normalization
+ Pair<SyntheticArtifact, MultipleDependencyGraphRecorder> dependenciesAndRecorder =
+ splitJsIntoFragments(properties, permutationId, jjsmap);
+
+ // TODO(stalcup): move to normalization
EvalFunctionsAtTopScope.exec(jsProgram, jjsmap);
// (7) Optimize the JS AST.
@@ -413,13 +418,13 @@
// Must run before code splitter and namer.
JsStackEmulator.exec(jprogram, jsProgram, properties, jjsmap);
- // TODO(stalcup): move to normalization
- Pair<SyntheticArtifact, MultipleDependencyGraphRecorder> dependenciesAndRecorder =
- splitJsIntoFragments(properties, permutationId, jjsmap);
-
// TODO(stalcup): move to optimize.
Map<JsName, JsLiteral> internedLiteralByVariableName = renameJsSymbols(properties, jjsmap);
+ // No new JsNames or references to JSNames can be introduced after this
+ // point.
+ HandleCrossFragmentReferences.exec(jsProgram, properties);
+
// TODO(stalcup): move to normalization
JsBreakUpLargeVarStatements.exec(jsProgram, properties.getConfigurationProperties());
@@ -599,12 +604,7 @@
} else if (options.isSoycEnabled() || options.isJsonSoycEnabled()) {
dependencyRecorder = recordNonSplitDependencies(new ByteArrayOutputStream());
}
- dependenciesAndRecorder = Pair.create(
- dependencies, dependencyRecorder);
-
- // No new JsNames or references to JSNames can be introduced after this
- // point.
- HandleCrossFragmentReferences.exec(jsProgram, properties);
+ dependenciesAndRecorder = Pair.create(dependencies, dependencyRecorder);
return dependenciesAndRecorder;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index d710edc..3b33bdc 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -38,6 +38,7 @@
import com.google.gwt.thirdparty.guava.common.collect.HashBiMap;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
@@ -796,7 +797,8 @@
+ "either ImplementClassLiteralsAsField has not run yet or or there is an error computing"
+ "live class literals.";
- return new JMethodCall(sourceInfo, null, getIndexedMethod("Array.getClassLiteralForArray"),
+ return new JMethodCall(sourceInfo, null, getIndexedMethod(
+ RuntimeConstants.ARRAY_GET_CLASS_LITERAL_FOR_ARRAY),
new JFieldRef(sourceInfo, null, leafTypeClassLiteralField,
leafTypeClassLiteralField.getEnclosingType()), getLiteralInt(dimensions));
}
@@ -852,8 +854,8 @@
return field;
}
- public Collection<JField> getIndexedFields() {
- return Collections.unmodifiableCollection(indexedFields.values());
+ public Set<JField> getIndexedFields() {
+ return ImmutableSet.copyOf(indexedFields.values());
}
public JMethod getIndexedMethod(String string) {
@@ -864,8 +866,8 @@
return method;
}
- public Collection<JMethod> getIndexedMethods() {
- return Collections.unmodifiableCollection(indexedMethods.values());
+ public Set<JMethod> getIndexedMethods() {
+ return ImmutableSet.copyOf(indexedMethods.values());
}
public JMethod getIndexedMethodOrNull(String string) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/RuntimeConstants.java b/dev/core/src/com/google/gwt/dev/jjs/ast/RuntimeConstants.java
index 8fe30e7..6698033 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/RuntimeConstants.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/RuntimeConstants.java
@@ -44,6 +44,8 @@
public static final String COLLAPSED_PROPERTY_HOLDER_GET_PERMUTATION_ID
= "CollapsedPropertyHolder.getPermutationId";
+ public static final String COVERAGE_UTIL_ON_BEFORE_UNLOAD = "CoverageUtil.onBeforeUnload";
+ public static final String COVERAGE_UTIL_COVER = "CoverageUtil.cover";
public static final String COVERAGE_UTIL_COVERAGE = "CoverageUtil.coverage";
public static final String ENUM_CREATE_VALUE_OF_MAP = "Enum.createValueOfMap";
@@ -65,6 +67,8 @@
public static final String LONG_LIB_TO_INT = "LongLib.toInt";
public static final String LONG_LIB_TO_STRING = "LongLib.toString";
+ public static final String MODULE_UTILS_GWT_ON_LOAD = "ModuleUtils.gwtOnLoad";
+
public static final String OBJECT_CASTABLE_TYPE_MAP = "Object.castableTypeMap";
public static final String OBJECT_CLAZZ = "Object.___clazz";
public static final String OBJECT_GET_CLASS = "Object.getClass";
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DefaultJsInteropExportsGenerator.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DefaultJsInteropExportsGenerator.java
index b9ba337..f4fb795 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/DefaultJsInteropExportsGenerator.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DefaultJsInteropExportsGenerator.java
@@ -19,9 +19,7 @@
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JMember;
-import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.js.ast.JsExpression;
-import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameRef;
@@ -29,7 +27,6 @@
import com.google.gwt.dev.js.ast.JsStringLiteral;
import java.util.List;
-import java.util.Map;
/**
* Responsible for handling @JsExport code generation for non-Closure formatted code.
@@ -45,14 +42,14 @@
private final List<JsStatement> exportStmts;
private final JsName globalTemp;
- private final JsName provideFunc;
+ private final JsName provideFuncionName;
private String lastExportedNamespace;
public DefaultJsInteropExportsGenerator(List<JsStatement> exportStmts, JsName globalTemp,
- Map<String, JsFunction> indexedFunctions) {
+ JsName provideFunctionName) {
this.exportStmts = exportStmts;
this.globalTemp = globalTemp;
- this.provideFunc = indexedFunctions.get(RuntimeConstants.RUNTIME_PROVIDE).getName();
+ this.provideFuncionName = provideFunctionName;
}
@Override
@@ -96,7 +93,7 @@
// _ = JCHSU.provide('foo.bar')
SourceInfo sourceInfo = member.getSourceInfo();
JsInvocation provideCall = new JsInvocation(sourceInfo);
- provideCall.setQualifier(provideFunc.makeRef(sourceInfo));
+ provideCall.setQualifier(provideFuncionName.makeRef(sourceInfo));
provideCall.getArguments().add(new JsStringLiteral(sourceInfo, namespace));
if (ctor != null) {
provideCall.getArguments().add(ctor);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index 4cd3402..1ce0f44 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -246,9 +246,6 @@
: scopeStack.peek().declareName(mangleName(x), x.getName());
}
names.put(x, jsName);
- if (program.getIndexedFields().contains(x)) {
- indexedFields.put(JjsUtils.getIndexedName(x), jsName);
- }
recordSymbol(x, jsName);
}
@@ -424,10 +421,6 @@
jsFunctionsByJavaMethodBody.put(x.getBody(), function);
scopeStack.push(function.getScope());
- if (program.getIndexedMethods().contains(x)) {
- indexedFunctions.put(JjsUtils.getIndexedName(x), function);
- }
-
// Don't traverse the method body of methods in referenceOnly types since those method bodies
// only exist in JS output of other modules it is their responsibility to handle their naming.
return !program.isReferenceOnly(x.getEnclosingType());
@@ -1239,7 +1232,8 @@
// Perform necessary polyfills.
addTypeDefinitionStatement(
program.getIndexedType(RuntimeConstants.RUNTIME),
- constructInvocation(program.getSourceInfo(), RuntimeConstants.RUNTIME_BOOTSTRAP).makeStmt());
+ constructInvocation(program.getSourceInfo(), RuntimeConstants.RUNTIME_BOOTSTRAP)
+ .makeStmt());
Set<JDeclaredType> alreadyProcessed =
Sets.<JDeclaredType>newLinkedHashSet(program.immortalCodeGenTypes);
@@ -1287,8 +1281,10 @@
continue;
}
- JsExpression protoRef = getPrototypeQualifierOf(type, type.getSourceInfo());
- JsNameRef clazzField = indexedFields.get("Object.___clazz").makeRef(type.getSourceInfo());
+ SourceInfo sourceInfo = type.getSourceInfo();
+ JsExpression protoRef = getPrototypeQualifierOf(type, sourceInfo);
+ JsNameRef clazzField =
+ getIndexedFieldJsName(RuntimeConstants.OBJECT_CLAZZ).makeRef(sourceInfo);
clazzField.setQualifier(protoRef);
JsExprStmt stmt = createAssignment(clazzField, classLiteralRef).makeStmt();
addTypeDefinitionStatement(type, stmt);
@@ -1451,8 +1447,8 @@
JsInteropExportsGenerator exportGenerator =
closureCompilerFormatEnabled
? new ClosureJsInteropExportsGenerator(getGlobalStatements(), names)
- : new DefaultJsInteropExportsGenerator(
- getGlobalStatements(), globalTemp, indexedFunctions);
+ : new DefaultJsInteropExportsGenerator(getGlobalStatements(), globalTemp,
+ getIndexedMethodJsName(RuntimeConstants.RUNTIME_PROVIDE));
// Gather exported things in JsNamespace order.
for (JDeclaredType type : program.getDeclaredTypes()) {
@@ -1624,7 +1620,7 @@
if (jsName == null) {
// this can occur when JSNI references an instance method on a
// type that was never actually instantiated.
- jsName = indexedFunctions.get(RuntimeConstants.RUNTIME_EMPTY_METHOD).getName();
+ jsName = getIndexedMethodJsName(RuntimeConstants.RUNTIME_EMPTY_METHOD);
}
x.resolve(jsName);
}
@@ -1782,9 +1778,7 @@
private JsExpression generateCastableTypeMap(JDeclaredType type) {
JCastMap castMap = program.getCastMap(type);
- JField castableTypeMapField = program.getIndexedField(
- RuntimeConstants.OBJECT_CASTABLE_TYPE_MAP);
- JsName castableTypeMapName = names.get(castableTypeMapField);
+ JsName castableTypeMapName = getIndexedFieldJsName(RuntimeConstants.OBJECT_CASTABLE_TYPE_MAP);
if (castMap != null && castableTypeMapName != null) {
return transform(castMap);
@@ -1883,7 +1877,7 @@
JsName gwtOnLoad = topScope.findExistingUnobfuscatableName("gwtOnLoad");
JsVar varGwtOnLoad = new JsVar(sourceInfo, gwtOnLoad);
varGwtOnLoad.setInitExpr(createAssignment(gwtOnLoad.makeRef(sourceInfo),
- indexedFunctions.get("ModuleUtils.gwtOnLoad").getName().makeRef(sourceInfo)));
+ getIndexedMethodJsName(RuntimeConstants.MODULE_UTILS_GWT_ON_LOAD).makeRef(sourceInfo)));
getGlobalStatements().add(new JsVars(sourceInfo, varGwtOnLoad));
// ModuleUtils.addInitFunctions(init1, init2,...)
@@ -1945,8 +1939,8 @@
*/
private JsInvocation constructInvocation(SourceInfo sourceInfo,
String indexedFunctionName, List<JsExpression> args) {
- JsFunction functionToInvoke = indexedFunctions.get(indexedFunctionName);
- return new JsInvocation(sourceInfo, functionToInvoke, args);
+ JsName functionToInvoke = getIndexedMethodJsName(indexedFunctionName);
+ return new JsInvocation(sourceInfo, functionToInvoke.makeRef(sourceInfo), args);
}
private void generateImmortalTypes(JsVars globals) {
@@ -2159,16 +2153,16 @@
}
private void setupTypeMarkerOnJavaLangObjectPrototype(JDeclaredType type) {
- JsFunction typeMarkerMethod = indexedFunctions.get(RuntimeConstants.RUNTIME_TYPE_MARKER_FN);
+ JsName typeMarkerMethod = getIndexedMethodJsName(RuntimeConstants.RUNTIME_TYPE_MARKER_FN);
generatePrototypeAssignmentForJavaField(type, RuntimeConstants.OBJECT_TYPEMARKER,
- typeMarkerMethod.getName().makeRef(type.getSourceInfo()));
+ typeMarkerMethod.makeRef(type.getSourceInfo()));
}
private void generatePrototypeAssignmentForJavaField(JDeclaredType type, String javaField,
JsExpression rhs) {
SourceInfo sourceInfo = type.getSourceInfo();
JsNameRef protoRef = getPrototypeQualifierOf(type, sourceInfo);
- JsNameRef fieldRef = indexedFields.get(javaField).makeQualifiedRef(sourceInfo, protoRef);
+ JsNameRef fieldRef = getIndexedFieldJsName(javaField).makeQualifiedRef(sourceInfo, protoRef);
addTypeDefinitionStatement(type, createAssignment(fieldRef, rhs).makeStmt());
}
@@ -2213,8 +2207,7 @@
*/
private void setupCastMapForUnboxedType(JDeclaredType type, String castMapField) {
// Cast.[castMapName] = /* cast map */ { ..:1, ..:1}
- JField castableTypeMapField = program.getIndexedField(castMapField);
- JsName castableTypeMapName = names.get(castableTypeMapField);
+ JsName castableTypeMapName = getIndexedFieldJsName(castMapField);
JsNameRef castMapVarRef = castableTypeMapName.makeRef(type.getSourceInfo());
JsExpression castMapLiteral = generateCastableTypeMap(type);
@@ -2265,7 +2258,7 @@
// Some JS optimizers, e.g. the closure compiler, relies on this subtle difference for
// obfuscating property names.
JsNameRef definePropertyMethod =
- indexedFunctions.get(RuntimeConstants.RUNTIME_DEFINE_PROPERTIES).getName().makeRef(sourceInfo);
+ getIndexedMethodJsName(RuntimeConstants.RUNTIME_DEFINE_PROPERTIES).makeRef(sourceInfo);
JsObjectLiteral definePropertyLiteral =
JsObjectLiteral.builder(sourceInfo)
@@ -2422,10 +2415,10 @@
// mode the more costly Object constructor function is used as the noop method since doing so
// provides a better debug experience that does not step into already used clinits.
- JsFunction emptyFunctionFn = incremental ? objectConstructorFunction
- : indexedFunctions.get(RuntimeConstants.RUNTIME_EMPTY_METHOD);
+ JsName emptyFunctionFnName = incremental ? objectConstructorFunction.getName()
+ : getIndexedMethodJsName(RuntimeConstants.RUNTIME_EMPTY_METHOD);
JsExpression assignment = createAssignment(clinitFunction.getName().makeRef(sourceInfo),
- emptyFunctionFn.getName().makeRef(sourceInfo));
+ emptyFunctionFnName.makeRef(sourceInfo));
statements.add(0, assignment.makeStmt());
}
@@ -2820,10 +2813,6 @@
*/
private Set<JMethod> crossClassTargets = null;
- private Map<String, JsFunction> indexedFunctions = Maps.newHashMap();
-
- private Map<String, JsName> indexedFields = Maps.newHashMap();
-
/**
* Contains JsNames for all interface methods. A special scope is needed so
* that independent classes will obfuscate their interface implementation
@@ -3023,9 +3012,6 @@
new CreateNamesAndScopesVisitor().accept(program);
new GenerateJavaScriptTransformer().transform(program);
- jsProgram.setIndexedFields(indexedFields);
- jsProgram.setIndexedFunctions(indexedFunctions);
-
// TODO(spoon): Instead of gathering the information here, get it via
// SourceInfo
JavaToJavaScriptMap jjsMap = new JavaToJavaScriptMapImpl(program.getDeclaredTypes(),
@@ -3040,4 +3026,12 @@
private JsFunction getJsFunctionFor(JMethod jMethod) {
return jsFunctionsByJavaMethodBody.get(jMethod.getBody());
}
+
+ private JsName getIndexedMethodJsName(String indexedName) {
+ return names.get(program.getIndexedMethod(indexedName));
+ }
+
+ private JsName getIndexedFieldJsName(String indexedName) {
+ return names.get(program.getIndexedField(indexedName));
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/codesplitter/FragmentExtractor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/codesplitter/FragmentExtractor.java
index fa7eaa1..cd4efb1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/codesplitter/FragmentExtractor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/codesplitter/FragmentExtractor.java
@@ -25,13 +25,13 @@
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.JsHoister.Cloner;
+import com.google.gwt.dev.js.JsUtils;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
-import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsName;
@@ -148,12 +148,13 @@
return minimalDefineClassStatement;
}
- private final JProgram jprogram;
-
private final JsProgram jsprogram;
private final JavaToJavaScriptMap map;
+ private final JsName asyncFragmentLoaderOnLoadFnName;
+ private final JsName defineClassFnName;
+
private StatementLogger statementLogger = new StatementLogger() {
@Override
public void log(JsStatement statement, boolean include) {
@@ -161,20 +162,26 @@
};
public FragmentExtractor(JProgram jprogram, JsProgram jsprogram, JavaToJavaScriptMap map) {
- this.jprogram = jprogram;
+ this(jsprogram, map,
+ JsUtils.getJsNameForMethod(map, jprogram, RuntimeConstants.ASYNC_FRAGMENT_LOADER_ON_LOAD),
+ JsUtils.getJsNameForMethod(map, jprogram, (RuntimeConstants.RUNTIME_DEFINE_CLASS)));
+ }
+
+ public FragmentExtractor(JsProgram jsprogram, JavaToJavaScriptMap map,
+ JsName asyncFragmentLoaderOnLoadFnName, JsName defineClassFnName) {
this.jsprogram = jsprogram;
this.map = map;
+ this.asyncFragmentLoaderOnLoadFnName = asyncFragmentLoaderOnLoadFnName;
+ this.defineClassFnName = defineClassFnName;
}
/**
* Create a call to {@link AsyncFragmentLoader#onLoad}.
*/
public List<JsStatement> createOnLoadedCall(int fragmentId) {
- JMethod loadMethod = jprogram.getIndexedMethod(RuntimeConstants.ASYNC_FRAGMENT_LOADER_ON_LOAD);
- JsName loadMethodName = map.nameForMethod(loadMethod);
SourceInfo sourceInfo = jsprogram.getSourceInfo();
JsInvocation call = new JsInvocation(sourceInfo);
- call.setQualifier(wrapWithEntry(loadMethodName.makeRef(sourceInfo)));
+ call.setQualifier(wrapWithEntry(asyncFragmentLoaderOnLoadFnName.makeRef(sourceInfo)));
call.getArguments().add(new JsNumberLiteral(sourceInfo, fragmentId));
List<JsStatement> newStats = Collections.<JsStatement> singletonList(call.makeStmt());
return newStats;
@@ -409,9 +416,7 @@
return null;
}
JsNameRef func = (JsNameRef) call.getQualifier();
- JsFunction defineClassJsFunc =
- jsprogram.getIndexedFunction(RuntimeConstants.RUNTIME_DEFINE_CLASS);
- if (func.getName() != defineClassJsFunc.getName()) {
+ if (func.getName() != defineClassFnName) {
return null;
}
return map.typeForStatement(statement);
diff --git a/dev/core/src/com/google/gwt/dev/js/CoverageInstrumentor.java b/dev/core/src/com/google/gwt/dev/js/CoverageInstrumentor.java
index d7f7d84..9c7db5d 100644
--- a/dev/core/src/com/google/gwt/dev/js/CoverageInstrumentor.java
+++ b/dev/core/src/com/google/gwt/dev/js/CoverageInstrumentor.java
@@ -16,7 +16,9 @@
package com.google.gwt.dev.js;
import com.google.gwt.dev.jjs.SourceInfo;
+import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
+import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsContext;
@@ -24,6 +26,7 @@
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsModVisitor;
+import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
@@ -64,15 +67,30 @@
return;
}
JsInvocation update = new JsInvocation(info,
- jsProgram.getIndexedFunction("CoverageUtil.cover"),
+ coverFnName.makeRef(info),
new JsStringLiteral(info, info.getFileName()),
new JsNumberLiteral(info, info.getStartLine()));
ctx.replaceMe(new JsBinaryOperation(info, JsBinaryOperator.COMMA, update, x));
}
}
- public static void exec(JsProgram jsProgram, Multimap<String, Integer> instrumentableLines) {
- new CoverageInstrumentor(jsProgram, instrumentableLines).execImpl();
+ public static void exec(JProgram jprogram, JsProgram jsProgram, JavaToJavaScriptMap jjsmap,
+ Multimap<String, Integer> instrumentableLines) {
+
+ exec(jsProgram, instrumentableLines,
+ JsUtils
+ .getJsNameForMethod(jjsmap, jprogram, RuntimeConstants.COVERAGE_UTIL_ON_BEFORE_UNLOAD),
+ JsUtils.getJsNameForMethod(jjsmap, jprogram, RuntimeConstants.COVERAGE_UTIL_COVER),
+ JsUtils.getJsNameForField(jjsmap, jprogram, RuntimeConstants.COVERAGE_UTIL_COVERAGE));
+ }
+
+ @VisibleForTesting
+ static void exec(JsProgram jsProgram,
+ Multimap<String, Integer> instrumentableLines, JsName onBeforeUnloadFnName,
+ JsName coverFnName, JsName coverageFieldName) {
+
+ new CoverageInstrumentor(jsProgram, instrumentableLines, onBeforeUnloadFnName, coverFnName,
+ coverageFieldName).execImpl();
}
/**
@@ -95,17 +113,23 @@
private Multimap<String, Integer> instrumentableLines;
private JsProgram jsProgram;
+ private JsName onBeforeUnloadFnName;
+ private JsName coverFnName;
+ private JsName coverageFieldName;
- private CoverageInstrumentor(JsProgram jsProgram, Multimap<String, Integer> instrumentableLines) {
+ private CoverageInstrumentor(JsProgram jsProgram, Multimap<String, Integer> instrumentableLines,
+ JsName onBeforeUnloadFnName, JsName coverFnName, JsName coverageFieldName) {
this.instrumentableLines = instrumentableLines;
this.jsProgram = jsProgram;
+ this.onBeforeUnloadFnName = onBeforeUnloadFnName;
+ this.coverFnName = coverFnName;
+ this.coverageFieldName = coverageFieldName;
}
private void addBeforeUnloadListener(SourceInfo info) {
JsNameRef onbeforeunload = new JsNameRef(info, "onbeforeunload");
onbeforeunload.setQualifier(new JsNameRef(info, "window"));
- JsNameRef handler =
- jsProgram.getIndexedFunction("CoverageUtil.onBeforeUnload").getName().makeRef(info);
+ JsNameRef handler = onBeforeUnloadFnName.makeRef(info);
JsBinaryOperation assignment = new JsBinaryOperation(info, JsBinaryOperator.ASG,
onbeforeunload, handler);
jsProgram.getGlobalBlock().getStatements().add(assignment.makeStmt());
@@ -124,8 +148,7 @@
}
private void initializeBaselineCoverage(SourceInfo info) {
- JsNameRef coverageObject =
- jsProgram.getIndexedField(RuntimeConstants.COVERAGE_UTIL_COVERAGE).makeRef(info);
+ JsNameRef coverageObject = coverageFieldName.makeRef(info);
JsBinaryOperation init = new JsBinaryOperation(info, JsBinaryOperator.ASG, coverageObject,
baselineCoverage(info, instrumentableLines));
jsProgram.getGlobalBlock().getStatements().add(init.makeStmt());
diff --git a/dev/core/src/com/google/gwt/dev/js/JsNamespaceChooser.java b/dev/core/src/com/google/gwt/dev/js/JsNamespaceChooser.java
index 86fd0af..0c47a8e 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsNamespaceChooser.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsNamespaceChooser.java
@@ -19,6 +19,7 @@
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JMethod;
+import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
@@ -50,11 +51,12 @@
*/
public class JsNamespaceChooser {
- public static void exec(JsProgram program, JavaToJavaScriptMap jjsmap) {
- new JsNamespaceChooser(program, jjsmap).execImpl();
+ public static void exec(JProgram jprogram, JsProgram jsprogram, JavaToJavaScriptMap jjsmap) {
+ new JsNamespaceChooser(jprogram, jsprogram, jjsmap).execImpl();
}
- private final JsProgram program;
+ private final JProgram jprogram;
+ private final JsProgram jsprogram;
private final JavaToJavaScriptMap jjsmap;
/**
@@ -62,8 +64,9 @@
*/
private final Map<String, JsName> packageToNamespace = Maps.newLinkedHashMap();
- private JsNamespaceChooser(JsProgram program, JavaToJavaScriptMap jjsmap) {
- this.program = program;
+ private JsNamespaceChooser(JProgram jprogram, JsProgram jsprogram, JavaToJavaScriptMap jjsmap) {
+ this.jsprogram = jsprogram;
+ this.jprogram = jprogram;
this.jjsmap = jjsmap;
}
@@ -72,7 +75,7 @@
// First pass: visit each top-level statement in the program and move it if possible.
// (This isn't a standard visitor because we don't want to recurse.)
- List<JsStatement> globalStatements = program.getGlobalBlock().getStatements();
+ List<JsStatement> globalStatements = jsprogram.getGlobalBlock().getStatements();
List<JsStatement> after = Lists.newArrayList();
for (JsStatement before : globalStatements) {
if (before instanceof JsVars) {
@@ -102,7 +105,7 @@
globalStatements.addAll(after);
// Second pass: fix all references for moved names.
- new NameFixer().accept(program);
+ new NameFixer().accept(jsprogram);
}
/**
@@ -192,16 +195,13 @@
return false; // not compiled from Java
}
- if (name.getStaticRef() instanceof JsFunction) {
- JsFunction func = (JsFunction) name.getStaticRef();
- if (program.isIndexedFunction(func)) {
- return false; // may be called directly in another pass (for example JsStackEmulator).
- }
+ if (isIndexedName(name)) {
+ return false; // may be called directly in another pass (for example JsStackEmulator).
}
JsName namespace = packageToNamespace.get(packageName);
if (namespace == null) {
- namespace = program.getScope().declareName(chooseUnusedName(packageName));
+ namespace = jsprogram.getScope().declareName(chooseUnusedName(packageName));
packageToNamespace.put(packageName, namespace);
}
@@ -209,11 +209,17 @@
return true;
}
+ private boolean isIndexedName(JsName name) {
+ return jprogram != null
+ && (jprogram.getIndexedMethods().contains(jjsmap.nameToMethod(name))
+ || jprogram.getIndexedFields().contains(jjsmap.nameToField(name)));
+ }
+
private String chooseUnusedName(String packageName) {
String initials = initialsForPackage(packageName);
String candidate = initials;
int counter = 1;
- while (program.getScope().findExistingName(candidate) != null) {
+ while (jsprogram.getScope().findExistingName(candidate) != null) {
counter++;
candidate = initials + counter;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java b/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
index 71c37d6..bb7f1ff 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStackEmulator.java
@@ -22,6 +22,7 @@
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
+import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.ast.HasArguments;
import com.google.gwt.dev.js.ast.HasName;
@@ -136,7 +137,7 @@
}
// caughtFunction is the JsFunction translated from Exceptions.wrap
- if (name.getStaticRef() != wrapFunction) {
+ if (name != wrapFunctionName) {
return false;
}
return true;
@@ -465,7 +466,7 @@
JsName paramName = c.getParameter().getName();
// wrap(e)
- JsInvocation wrapCall = new JsInvocation(info, wrapFunction.getName().makeRef(info),
+ JsInvocation wrapCall = new JsInvocation(info, wrapFunctionName.makeRef(info),
paramName.makeRef(info));
// e = wrap(e)
@@ -966,7 +967,7 @@
return StackMode.valueOf(value.toUpperCase(Locale.ROOT));
}
- private JsFunction wrapFunction;
+ private JsName wrapFunctionName;
private JsName lineNumbers;
private JProgram jprogram;
private final JsProgram jsProgram;
@@ -1005,8 +1006,9 @@
}
private void execImpl() {
- wrapFunction = jsProgram.getIndexedFunction("Exceptions.wrap");
- if (wrapFunction == null) {
+ wrapFunctionName =
+ JsUtils.getJsNameForMethod(jjsmap, jprogram, RuntimeConstants.EXCEPTIONS_WRAP);
+ if (wrapFunctionName == null) {
// No exceptions caught? Weird, but possible.
return;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsUnusedFunctionRemover.java b/dev/core/src/com/google/gwt/dev/js/JsUnusedFunctionRemover.java
index 975d34a..007cf2a 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsUnusedFunctionRemover.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsUnusedFunctionRemover.java
@@ -48,8 +48,7 @@
JsName name = f.getName();
// Anonymous function, ignore it
- if (name == null || seen.contains(name)
- || program.getIndexedFunction("AsyncFragmentLoader.onLoad") == f) {
+ if (name == null || seen.contains(name)) {
return;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsUtils.java b/dev/core/src/com/google/gwt/dev/js/JsUtils.java
index 9bceaae..97d9186 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsUtils.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsUtils.java
@@ -20,6 +20,8 @@
import com.google.gwt.dev.jjs.ast.JMethod.JsPropertyAccessorType;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
+import com.google.gwt.dev.jjs.ast.JProgram;
+import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsBlock;
@@ -208,6 +210,16 @@
return null;
}
+ public static JsName getJsNameForMethod(JavaToJavaScriptMap jjsmap, JProgram jprogram,
+ String indexedMethodName) {
+ return jjsmap.nameForMethod(jprogram.getIndexedMethod(indexedMethodName));
+ }
+
+ public static JsName getJsNameForField(JavaToJavaScriptMap jjsmap, JProgram jprogram,
+ String indexedMethodName) {
+ return jjsmap.nameForField(jprogram.getIndexedField(indexedMethodName));
+ }
+
public static boolean isEmpty(JsStatement stmt) {
if (stmt == null) {
return true;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java b/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
index b6518e4..477bde4 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsProgram.java
@@ -20,10 +20,6 @@
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
/**
* A JavaScript program.
@@ -34,12 +30,6 @@
private JsProgramFragment[] fragments;
- private final Map<String, JsName> indexedFields = new HashMap<String, JsName>();
-
- private final Map<String, JsFunction> indexedFunctions = new HashMap<String, JsFunction>();
-
- private final Set<JsFunction> indexedFunctionSet = new HashSet<JsFunction>();
-
private final JsScope objectScope;
private final JsScope topScope;
@@ -98,18 +88,6 @@
return getFragmentBlock(0);
}
- public JsName getIndexedField(String name) {
- return indexedFields.get(name);
- }
-
- public JsFunction getIndexedFunction(String name) {
- return indexedFunctions.get(name);
- }
-
- public boolean isIndexedFunction(JsFunction func) {
- return indexedFunctionSet.contains(func);
- }
-
@Override
public NodeKind getKind() {
return NodeKind.PROGRAM;
@@ -133,18 +111,6 @@
}
}
- public void setIndexedFields(Map<String, JsName> indexedFields) {
- this.indexedFields.clear();
- this.indexedFields.putAll(indexedFields);
- }
-
- public void setIndexedFunctions(Map<String, JsFunction> indexedFunctions) {
- this.indexedFunctions.clear();
- this.indexedFunctions.putAll(indexedFunctions);
- this.indexedFunctionSet.clear();
- this.indexedFunctionSet.addAll(indexedFunctions.values());
- }
-
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/codesplitter/FragmentExtractorTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/codesplitter/FragmentExtractorTest.java
index 1e3a8ad..556a294 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/codesplitter/FragmentExtractorTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/codesplitter/FragmentExtractorTest.java
@@ -24,21 +24,16 @@
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.impl.JJSTestBase;
import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.js.ast.JsExprStmt;
-import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsProgram;
-import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsStatement;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
/**
* Unit tests for {@link com.google.gwt.dev.jjs.impl.codesplitter.FragmentExtractor}.
@@ -185,19 +180,15 @@
final JsName barConstructorName = new JsName(null, "Bar", "Bar");
final JConstructor barConstructor =
new JConstructor(nullSourceInfo, barType, AccessModifier.PUBLIC);
- Map<String, JsFunction> functionsByName = new HashMap<String, JsFunction>();
- functionsByName.put(RuntimeConstants.RUNTIME_DEFINE_CLASS,
- new JsFunction(nullSourceInfo, new JsRootScope(), DEFINE_CLASS_FUNCTION_NAME));
final JsExprStmt defineClassStatement = createDefineClassStatement(barConstructorName);
JsProgram jsProgram = new JsProgram();
- jsProgram.setIndexedFunctions(functionsByName);
// Defines the entirety of the JS program being split, to be the one defineClass statement.
jsProgram.getGlobalBlock().getStatements().add(defineClassStatement);
JavaToJavaScriptMap map = new MockJavaToJavaScriptMap() {
- @Override
+ @Override
public JMethod nameToMethod(JsName name) {
if (name == barConstructorName) {
// Finds the Bar constructor by name.
@@ -206,7 +197,7 @@
return null;
}
- @Override
+ @Override
public JClassType typeForStatement(JsStatement statement) {
if (statement == defineClassStatement) {
// Indicates that Bar is the type associated with the defineClass statement.
@@ -215,7 +206,7 @@
return null;
}
};
- fragmentExtractor = new FragmentExtractor(null, jsProgram, map);
+ fragmentExtractor = new FragmentExtractor(jsProgram, map, null, DEFINE_CLASS_FUNCTION_NAME);
constructorLivePredicate = new MockLivenessPredicate() {
@Override
public boolean isLive(JDeclaredType type) {
diff --git a/dev/core/test/com/google/gwt/dev/js/CoverageInstrumentorTest.java b/dev/core/test/com/google/gwt/dev/js/CoverageInstrumentorTest.java
index 1186b95..b4525fd 100644
--- a/dev/core/test/com/google/gwt/dev/js/CoverageInstrumentorTest.java
+++ b/dev/core/test/com/google/gwt/dev/js/CoverageInstrumentorTest.java
@@ -17,25 +17,23 @@
package com.google.gwt.dev.js;
import com.google.gwt.dev.jjs.SourceInfo;
+import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFunction;
-import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.thirdparty.guava.common.base.Splitter;
import com.google.gwt.thirdparty.guava.common.collect.HashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.LinkedHashMultimap;
-import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import junit.framework.TestCase;
import java.io.StringReader;
-import java.util.Map;
/**
* Tests for CoverageInstrumentor.
@@ -48,8 +46,6 @@
public void setUp() {
program = new JsProgram();
SourceInfo info = program.createSourceInfo(1, "Test.java");
- program.setIndexedFields(fields("CoverageUtil.coverage"));
- program.setIndexedFunctions(functions("CoverageUtil.cover", "CoverageUtil.onBeforeUnload"));
JsBlock globalBlock = program.getGlobalBlock();
JsFunction function = new JsFunction(info, program.getScope());
functionBody = new JsBlock(info);
@@ -57,28 +53,12 @@
globalBlock.getStatements().add(new JsExprStmt(info, function));
}
- private Map<String, JsName> fields(String... names) {
- Map<String, JsName> fields = Maps.newHashMap();
- for (String name : names) {
- JsName n = program.getScope().declareName(name, name);
- fields.put(name, n);
- }
- return fields;
- }
-
- private Map<String, JsFunction> functions(String... names) {
- Map<String, JsFunction> funcs = Maps.newHashMap();
- for (String name : names) {
- JsFunction f = new JsFunction(program.getSourceInfo(), program.getScope());
- f.setName(program.getScope().declareName(name));
- funcs.put(name, f);
- }
- return funcs;
- }
-
private String instrument(String code) throws Exception {
functionBody.getStatements().clear();
- CoverageInstrumentor.exec(program, parse(code));
+ CoverageInstrumentor.exec(program, parse(code),
+ program.getScope().declareName(RuntimeConstants.COVERAGE_UTIL_ON_BEFORE_UNLOAD),
+ program.getScope().declareName(RuntimeConstants.COVERAGE_UTIL_COVER),
+ program.getScope().declareName(RuntimeConstants.COVERAGE_UTIL_COVERAGE));
return functionBody.toSource().trim().replaceAll("\\s+", " ");
}
diff --git a/dev/core/test/com/google/gwt/dev/js/JsNamespaceChooserTest.java b/dev/core/test/com/google/gwt/dev/js/JsNamespaceChooserTest.java
index 7c80806..dae9969 100644
--- a/dev/core/test/com/google/gwt/dev/js/JsNamespaceChooserTest.java
+++ b/dev/core/test/com/google/gwt/dev/js/JsNamespaceChooserTest.java
@@ -162,7 +162,7 @@
typeForStatement, vtableInitForMethod);
// Run it.
- JsNamespaceChooser.exec(program, jjsmap);
+ JsNamespaceChooser.exec(null, program, jjsmap);
}
private static JsProgram parseJs(String js) throws IOException, JsParserException {
diff --git a/user/test/com/google/gwt/dev/jjs/test/RunAsyncTest.java b/user/test/com/google/gwt/dev/jjs/test/RunAsyncTest.java
index 04cb0b3..9f667cf 100644
--- a/user/test/com/google/gwt/dev/jjs/test/RunAsyncTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/RunAsyncTest.java
@@ -22,12 +22,16 @@
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.junit.client.GWTTestCase;
+import javaemul.internal.annotations.DoNotInline;
+
/**
* Tests runAsync in various ways.
*/
public class RunAsyncTest extends GWTTestCase {
private static final String HELLO = "hello";
+ private static final String LONG_INTERNED_STRING = "abcdefghijklmnopqrstuvwxyz";
+
private static final int RUNASYNC_TIMEOUT = 10000;
private static String staticWrittenInBaseButReadLater;
@@ -39,6 +43,11 @@
return "com.google.gwt.dev.jjs.CompilerSuite";
}
+ @DoNotInline
+ public String getTestString() {
+ return LONG_INTERNED_STRING;
+ }
+
public void testBasic() {
delayTestFinish(RUNASYNC_TIMEOUT);
@@ -56,6 +65,39 @@
}
/**
+ * Only tests the XSLinker/CrossSiteRunAsyncSuite.
+ * A string which is only referenced in > 0 fragment which gets interned needs to be
+ * processed by HandleCrossFragmentReferences, but JsLiteralInterner was running after
+ * HandleCrossFragmentReferences.
+ */
+ public void testHandleCrossFragmentReference() {
+ delayTestFinish(RUNASYNC_TIMEOUT);
+
+ GWT.runAsync(new RunAsyncCallback() {
+ @Override
+ public void onFailure(Throwable caught) {
+ throw new RuntimeException(caught);
+ }
+
+ @Override
+ public void onSuccess() {
+ assertEquals(LONG_INTERNED_STRING, getTestString());
+ GWT.runAsync(new RunAsyncCallback() {
+ @Override
+ public void onFailure(Throwable caught) {
+ throw new RuntimeException(caught);
+ }
+
+ @Override
+ public void onSuccess() {
+ assertEquals(LONG_INTERNED_STRING, getTestString());
+ finishTest();
+ }
+ });
+ }
+ });
+ }
+ /**
* Unlike with pruning, writing to a field should rescue it for code-splitting
* purposes.
*/