Allow for additional modules in the initial load sequence prior to the leftovers module.
Review by: acleung@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10805 8db76d5a-ed1c-0410-87a9-c151d255dfc7
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 9fcc051..9a028a8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -424,8 +424,8 @@
options.isSoycEnabled() || options.isCompilerMetricsEnabled()
? new SizeBreakdown[js.length] : null;
List<Map<Range, SourceInfo>> sourceInfoMaps = new ArrayList<Map<Range, SourceInfo>>();
- generateJavaScriptCode(options, jsProgram, jjsmap, js, ranges, sizeBreakdowns,
- sourceInfoMaps, splitBlocks, isSourceMapsEnabled);
+ generateJavaScriptCode(options, jprogram, jsProgram, jjsmap, js, ranges,
+ sizeBreakdowns, sourceInfoMaps, splitBlocks, isSourceMapsEnabled);
PermutationResult toReturn =
new PermutationResultImpl(js, permutation, makeSymbolMap(symbolTable, jsProgram), ranges);
@@ -971,6 +971,7 @@
* information about that transformation.
*
* @param options The options this compiler instance is running with
+ * @param jprogram The original Java program AST
* @param jsProgram The AST to convert to source code
* @param jjsMap A map between the JavaScript AST and the Java AST it came
* from
@@ -984,7 +985,7 @@
* @param sourceMapsEnabled
*/
private static void generateJavaScriptCode(JJSOptions options,
- JsProgram jsProgram,
+ JProgram jprogram, JsProgram jsProgram,
JavaToJavaScriptMap jjsMap, String[] js, StatementRanges[] ranges,
SizeBreakdown[] sizeBreakdowns,
List<Map<Range, SourceInfo>> sourceInfoMaps,
@@ -993,7 +994,7 @@
boolean useClosureCompiler = options.isClosureCompilerEnabled();
if (useClosureCompiler) {
ClosureJsRunner runner = new ClosureJsRunner();
- runner.compile(jsProgram, js, options.getOutput());
+ runner.compile(jprogram, jsProgram, js, options.getOutput());
return;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ClosureJsRunner.java b/dev/core/src/com/google/gwt/dev/js/ClosureJsRunner.java
index 2bef925..23ba2ad 100644
--- a/dev/core/src/com/google/gwt/dev/js/ClosureJsRunner.java
+++ b/dev/core/src/com/google/gwt/dev/js/ClosureJsRunner.java
@@ -1,11 +1,11 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
@@ -15,6 +15,7 @@
package com.google.gwt.dev.js;
import com.google.gwt.dev.jjs.JsOutputOption;
+import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsProgramFragment;
import com.google.gwt.thirdparty.guava.common.base.Preconditions;
@@ -56,7 +57,7 @@
import java.util.zip.ZipInputStream;
/**
- * A wrapper to simplify the interactions to the Closure Compiler
+ * A class that represents an single invocation of the Closure Compiler.
*/
public class ClosureJsRunner {
// The externs expected in externs.zip, in sorted order.
@@ -130,18 +131,47 @@
return externs;
}
+ /**
+ * The instance of the Closure Compiler used for the compile.
+ */
private Compiler compiler = null;
+
+ /**
+ * The set of external properties discovered in the provided AST.
+ */
private Set<String> externalProps = Sets.newHashSet();
+
+ /**
+ * The set of external global variables discovered in the provided AST.
+ */
private Set<String> externalVars = Sets.newHashSet();
+ /**
+ * The set of internal global variables discovered in the provided AST.
+ */
private Set<String> globalVars = Sets.newHashSet();
+ /**
+ * Whether AST validation should be performed on the the generated
+ * Closure Compiler AST.
+ */
private final boolean validate = true;
+ /**
+ * A map of GWT fragment numbers to Closure module indexes.
+ */
+ private int[] closureModuleSequenceMap;
+
+ /**
+ * The number of non-exclusive fragments that are part of the load sequence
+ * (including the main and leftovers).
+ */
+ private int loadModulesCount;
+
public ClosureJsRunner() {
}
- public void compile(JsProgram program, String[] js, JsOutputOption jsOutputOption) {
+ public void compile(JProgram jprogram, JsProgram program, String[] js, JsOutputOption jsOutputOption) {
CompilerOptions options = getClosureCompilerOptions(jsOutputOption);
// Turn off Closure Compiler logging
Logger.getLogger("com.google.gwt.thirdparty.javascript.jscomp").setLevel(Level.OFF);
@@ -150,6 +180,7 @@
compiler = new Compiler();
// Translate the ASTs and build the modules
+ computeFragmentMap(jprogram, program);
List<JSModule> modules = createClosureModules(program);
// Build the externs based on what we discovered building the modules.
@@ -159,7 +190,7 @@
if (result.success) {
int fragments = program.getFragmentCount();
for (int i = 0; i < fragments; i++) {
- int module = mapFragmentIndexToModuleIndex(fragments, i);
+ int module = mapFragmentIndexToModuleIndex(i);
js[i] = compiler.toSource(modules.get(module));
}
} else {
@@ -181,6 +212,47 @@
}
}
+ private void computeFragmentMap(JProgram jprogram, JsProgram jsProgram) {
+ int fragments = jsProgram.getFragmentCount();
+ List<Integer> initSeq = jprogram.getSplitPointInitialSequence();
+
+ //
+ // The fragments are expected in a specific order:
+ // init, split-1, split-2, ...,
+ // where the leftovers are dependent on the init module
+ // and the split modules are dependent on the leftovers
+ //
+ // However, Closure Compiler modules must be in dependency order
+ //
+
+ assert closureModuleSequenceMap == null;
+ closureModuleSequenceMap = new int[fragments];
+ for (int i = 0; i < fragments; i++) {
+ closureModuleSequenceMap[i] = -1;
+ }
+
+ int module = 0;
+ // The initial fragments is always first.
+ closureModuleSequenceMap[0] = module++;
+
+ // Then come the specified load order sequence
+ for (int i = 0; i < initSeq.size(); i++) {
+ closureModuleSequenceMap[initSeq.get(i)] = module++;
+ }
+
+ // Then the leftovers fragments:
+ closureModuleSequenceMap[fragments - 1] = module++;
+
+ // Finally, the exclusive fragments.
+ // The order of the remaining fragments doesn't matter.
+ for (int i = 0; i < fragments; i++) {
+ if (closureModuleSequenceMap[i] == -1) {
+ closureModuleSequenceMap[i] = module++;
+ }
+ }
+ loadModulesCount = 1 + initSeq.size() + 1; // main + init sequence + leftovers
+ }
+
private CompilerInput createClosureJsAst(JsProgram program, JsProgramFragment fragment,
String source) {
String inputName = source;
@@ -206,7 +278,7 @@
JSModule[] modules = new JSModule[fragments];
for (int i = 0; i < fragments; i++) {
- modules[mapFragmentIndexToModuleIndex(fragments, i)] =
+ modules[mapFragmentIndexToModuleIndex(i)] =
createClosureModule(program, program.getFragment(i), "module" + i);
}
if (fragments > 1) {
@@ -215,10 +287,12 @@
// init, split-1, split-2, ...,
// where the leftovers are dependent on the init module
// and the split modules are dependent on the leftovers
- JSModule init = modules[0];
- JSModule leftovers = modules[1];
- leftovers.addDependency(init);
- for (int i = 2; i < modules.length; i++) {
+ for (int i = 1; i < loadModulesCount; i++) {
+ modules[i].addDependency(modules[i - 1]);
+ }
+
+ JSModule leftovers = modules[loadModulesCount - 1];
+ for (int i = loadModulesCount; i < modules.length; i++) {
Preconditions.checkNotNull(modules[i], "Module: ", i);
modules[i].addDependency(leftovers);
}
@@ -232,14 +306,26 @@
List<JSSourceFile> externs = getDefaultExternsList();
externs.add(JSSourceFile.fromCode("gwt_externs",
- "var gwtOnLoad;\n" + "var $entry;\n" + " var $gwt_version;\n" + " var $wnd;\n"
- + " var $doc;\n" + " var $moduleName\n" + " var $moduleBase;\n"
- + " var $strongName;\n" + " var $stats;\n" + " var $sessionId;\n"
- + " window.prototype.__gwtStatsEvent;\n" + " window.prototype.__gwtStatsSessionId;\n"
- + " window.prototype.moduleName;\n" + " window.prototype.sessionId;\n"
- + " window.prototype.subSystem;\n" + " window.prototype.evtGroup;\n"
- + " window.prototype.millis;\n" + " window.prototype.type;\n"
- + " window.prototype.$h;\n" + "\n"));
+ "var gwtOnLoad;\n"
+ + "var $entry;\n"
+ + " var $gwt_version;\n"
+ + " var $wnd;\n"
+ + " var $doc;\n"
+ + " var $moduleName\n"
+ + " var $moduleBase;\n"
+ + " var $strongName;\n"
+ + " var $stats;\n"
+ + " var $sessionId;\n"
+ + " window.prototype.__gwtStatsEvent;\n"
+ + " window.prototype.__gwtStatsSessionId;\n"
+ + " window.prototype.moduleName;\n"
+ + " window.prototype.sessionId;\n"
+ + " window.prototype.subSystem;\n"
+ + " window.prototype.evtGroup;\n"
+ + " window.prototype.millis;\n"
+ + " window.prototype.type;\n"
+ + " window.prototype.$h;\n"
+ + "\n"));
// Generate externs
String generatedExterns = "var gwt_externs;\n";
@@ -330,21 +416,8 @@
return options;
}
- private int mapFragmentIndexToModuleIndex(int fragments, int index) {
- //
- // The fragments are expected in a specific order:
- // init, split-1, split-2, ...,
- // where the leftovers are dependent on the init module
- // and the split modules are dependent on the leftovers
- //
- // However, Closure Compiler modules must be in dependency order
- //
- if (index == 0) {
- return 0;
- } else if (index == fragments - 1) {
- return 1;
- } else {
- return index + 1;
- }
+ private int mapFragmentIndexToModuleIndex(int index) {
+ assert closureModuleSequenceMap.length > index;
+ return closureModuleSequenceMap[index];
}
}