Merging startup optimization into trunk from branches/opt_imgs_and_startup@538. Had to hand-merge several things.
Patch by: jgw
me
Review by: me
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@539 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
index 2d7c52c..fa7ab4b 100644
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -477,14 +477,11 @@
private String getHtmlSuffix() {
StringBuffer sb = new StringBuffer();
+ String moduleFunction = module.getName().replace('.', '_');
// Generate the call to tell the bootstrap code that we're ready to go.
sb.append("\n");
- sb.append("if ($wnd.__gwt_tryGetModuleControlBlock) {\n");
- sb.append(" var $mcb = $wnd.__gwt_tryGetModuleControlBlock(location.search);\n");
- sb.append(" if ($mcb) $mcb.compilationLoaded(window);\n");
- sb.append("}\n");
-
+ sb.append("parent." + moduleFunction + ".onScriptLoad(window);\n");
sb.append("--></script></body></html>\n");
String s = sb.toString();
@@ -783,8 +780,8 @@
private void writeSelectionScript(TreeLogger logger,
SelectionScriptGenerator selGen) {
- String html = selGen.generateSelectionScript();
- String fn = module.getName() + ".nocache.html";
+ String html = selGen.generateSelectionScript(obfuscate);
+ String fn = module.getName() + ".nocache.js";
File selectionFile = new File(outDir, fn);
Util.writeStringAsFile(selectionFile, html);
String msg = "Compilation selection script written to "
diff --git a/dev/core/src/com/google/gwt/dev/cfg/DefaultPropertyProvider.java b/dev/core/src/com/google/gwt/dev/cfg/DefaultPropertyProvider.java
index d3d589e..c94eb07 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/DefaultPropertyProvider.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/DefaultPropertyProvider.java
@@ -37,10 +37,10 @@
* were to include the selector script in the host page itself rather than in
* an iframe.
*/
- public DefaultPropertyProvider(Property property) {
- super(property);
+ public DefaultPropertyProvider(ModuleDef module, Property property) {
+ super(module, property);
String src = "function () {";
- src += "return parent.__gwt_getMetaProperty(\"";
+ src += "return _gwt_getMetaProperty(\"";
src += property.getName();
src += "\"); }";
setBody(parseFunction(src));
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
index 9187655..2ccbd63 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDef.java
@@ -224,6 +224,10 @@
return (String[]) entryPointTypeNames.toArray(new String[n]);
}
+ public synchronized String getFunctionName() {
+ return name.replace('.', '_');
+ }
+
public synchronized String getName() {
return name;
}
@@ -379,7 +383,7 @@
if (prop.getProvider() == null) {
// Create a default provider.
//
- prop.setProvider(new DefaultPropertyProvider(prop));
+ prop.setProvider(new DefaultPropertyProvider(this, prop));
}
} else {
prop.setActiveValue(knownValues[0]);
diff --git a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
index a28b172..6a6ca54 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
@@ -49,12 +49,12 @@
protected final String __define_property_2_values = null;
+ protected final String __entry_point_1_class = null;
+
protected final String __extend_property_1_name = null;
protected final String __extend_property_2_values = null;
- protected final String __entry_point_1_class = null;
-
protected final String __generate_with_1_class = null;
protected final String __inherits_1_name = null;
@@ -145,7 +145,7 @@
}
protected Schema __property_provider_begin(Property property) {
- property.setProvider(new PropertyProvider(property));
+ property.setProvider(new PropertyProvider(moduleDef, property));
return fChild = new PropertyProviderBodySchema();
}
@@ -211,12 +211,12 @@
protected void __script_end(String src) throws UnableToCompleteException {
ScriptReadyBodySchema childSchema = (ScriptReadyBodySchema) fChild;
String js = childSchema.getScriptReadyBlock();
- if (js == null) {
+ if (js != null) {
// This is a problem.
//
logger.log(
- TreeLogger.ERROR,
- "Injected scripts require an associated JavaScript block that indicates when the corresponding script is fully loaded and ready for use",
+ TreeLogger.WARN,
+ "Injected scripts no longer require an associated JavaScript block.",
null);
throw new UnableToCompleteException();
}
@@ -773,4 +773,4 @@
}
}
-//CHECKSTYLE_NAMING_ON
\ No newline at end of file
+// CHECKSTYLE_NAMING_ON
diff --git a/dev/core/src/com/google/gwt/dev/cfg/PropertyProvider.java b/dev/core/src/com/google/gwt/dev/cfg/PropertyProvider.java
index 3657ac2..13c44d6 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/PropertyProvider.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/PropertyProvider.java
@@ -24,9 +24,11 @@
private JsBlock body;
+ private final ModuleDef module;
private final Property property;
- public PropertyProvider(Property property) {
+ public PropertyProvider(ModuleDef module, Property property) {
+ this.module = module;
this.property = property;
}
@@ -34,6 +36,10 @@
return body;
}
+ public ModuleDef getModule() {
+ return module;
+ }
+
public Property getProperty() {
return property;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsSymbolResolver.java b/dev/core/src/com/google/gwt/dev/js/JsSymbolResolver.java
index e5e02c6..6921de1 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsSymbolResolver.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsSymbolResolver.java
@@ -69,6 +69,10 @@
x.resolve(name);
}
+ public void endVisit(JsProgram x) {
+ popScope();
+ }
+
public boolean visit(JsCatch x) {
pushScope(x.getScope());
return true;
@@ -79,6 +83,11 @@
return true;
}
+ public boolean visit(JsProgram x) {
+ pushScope(x.getScope());
+ return true;
+ }
+
private JsScope getScope() {
return (JsScope) scopeStack.peek();
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java b/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
index 1dc3f54..f73f95f 100644
--- a/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
+++ b/dev/core/src/com/google/gwt/dev/shell/GWTShellServlet.java
@@ -72,21 +72,14 @@
}
}
- /**
- * When the GWT bootstrap JavaScript starts in hosted mode, it appends this
- * query param to the url for the nocache file so that this servlet can
- * generate one on-the-fly.
- */
- private static final String HOSTED_MODE_QUERY_PARAM = "h";
-
private final Map loadedModulesByName = new HashMap();
private final Map loadedServletsByClassName = new HashMap();
- private final Map modulesByServletPath = new HashMap();
-
private final Map mimeTypes = new HashMap();
+ private final Map modulesByServletPath = new HashMap();
+
private int nextRequestId;
private File outDir;
@@ -259,6 +252,37 @@
}
}
+ /**
+ * Handle auto-generated resources.
+ *
+ * @return <code>true</code> if a resource was generated
+ */
+ private boolean autoGenerateResources(HttpServletRequest request,
+ HttpServletResponse response, TreeLogger logger, String partialPath,
+ String moduleName) throws IOException {
+
+ // If the request is of the form ".../moduleName.nocache.js", then
+ // we generate the selection script for them.
+ if (partialPath.equals(moduleName + ".nocache.js")) {
+ // If the '?compiled' request property is specified, don't auto-generate.
+ if (request.getParameter("compiled") == null) {
+ // Generate the .js file.
+ try {
+ String js = genSelectionScript(logger, moduleName);
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("text/javascript");
+ response.getWriter().println(js);
+ return true;
+ } catch (UnableToCompleteException e) {
+ // Quietly continue, since this could actually be a request for a
+ // static file that happens to have an unfortunately confusing name.
+ }
+ }
+ }
+
+ return false;
+ }
+
private void doGetModule(HttpServletRequest request,
HttpServletResponse response, TreeLogger logger, RequestParts parts)
throws IOException {
@@ -325,23 +349,10 @@
+ partialPath + "' in module '" + moduleName + "' ";
logger = logger.branch(TreeLogger.TRACE, msg, null);
- // If the request is of the form ".../moduleName.nocache.html[?...]", then
- // we generate the selection script for them.
- if (partialPath.equals(moduleName + ".nocache.html")) {
- // Only generate a selection script for a hosted-mode client.
- // Otherwise, fall through.
- if (request.getParameterMap().containsKey(HOSTED_MODE_QUERY_PARAM)) {
- // Generate the .nocache.html file.
- try {
- String html = genSelectionPage(logger, moduleName);
- response.setContentType("text/html");
- response.getWriter().println(html);
- return;
- } catch (UnableToCompleteException e) {
- // Quietly continue, since this could actually be a request for a
- // static file that happens to have an unfortunately confusing name.
- }
- }
+ // Handle auto-generation of resources.
+ if (autoGenerateResources(request, response, logger, partialPath,
+ moduleName)) {
+ return;
}
URL foundResource;
@@ -392,9 +403,13 @@
logger.log(TreeLogger.TRACE, msg, null);
}
- // Maybe serve it up. Don't let the client cache anything because
- // this servlet is for development (so files change a lot), and we do at
- // least honor "If-Modified-Since".
+ // Maybe serve it up. Don't let the client cache anything other than
+ // xxx.cache.yyy files because this servlet is for development (so user
+ // files are assumed to change a lot), although we do honor
+ // "If-Modified-Since".
+
+ boolean infinitelyCacheable = isInfinitelyCacheable(path);
+
InputStream is = null;
try {
// Check for up-to-datedness.
@@ -402,11 +417,14 @@
long lastModified = conn.getLastModified();
if (isNotModified(request, lastModified)) {
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ if (infinitelyCacheable) {
+ response.setHeader(HttpHeaders.CACHE_CONTROL,
+ HttpHeaders.CACHE_CONTROL_MAXAGE_FOREVER);
+ }
return;
}
// Set up headers to really send it.
- //
response.setStatus(HttpServletResponse.SC_OK);
long now = new Date().getTime();
response.setHeader(HttpHeaders.DATE,
@@ -414,13 +432,26 @@
response.setContentType(mimeType);
String lastModifiedStr = HttpHeaders.toInternetDateFormat(lastModified);
response.setHeader(HttpHeaders.LAST_MODIFIED, lastModifiedStr);
- final long jan2nd1980 = 315637200000L;
- String inThePastStr = HttpHeaders.toInternetDateFormat(jan2nd1980);
- response.setHeader(HttpHeaders.EXPIRES, inThePastStr);
- // Send the bytes. To keep it simple, we don't compute the length.
- // This prevents keep-alive.
- //
+ // Expiration header. Either immediately stale (requiring an
+ // "If-Modified-Since") or infinitely cacheable (not requiring even a
+ // freshness check).
+ String maxAgeStr;
+ if (infinitelyCacheable) {
+ maxAgeStr = HttpHeaders.CACHE_CONTROL_MAXAGE_FOREVER;
+ } else {
+ maxAgeStr = HttpHeaders.CACHE_CONTROL_MAXAGE_EXPIRED;
+ }
+ response.setHeader(HttpHeaders.CACHE_CONTROL, maxAgeStr);
+
+ // Content length.
+ int contentLength = conn.getContentLength();
+ if (contentLength >= 0) {
+ response.setHeader(HttpHeaders.CONTENT_LENGTH,
+ Integer.toString(contentLength));
+ }
+
+ // Send the bytes.
is = foundResource.openStream();
streamOut(is, response.getOutputStream(), 1024 * 8);
} finally {
@@ -436,19 +467,19 @@
}
/**
- * Generates a nocache file on the fly. Note that the nocache file that is
+ * Generates a module.js file on the fly. Note that the nocache file that is
* generated that can only be used for hosted mode. It cannot produce a web
* mode version, since this servlet doesn't know strong names, since by
* definition of "hosted mode" JavaScript hasn't been compiled at this point.
*/
- private String genSelectionPage(TreeLogger logger, String moduleName)
+ private String genSelectionScript(TreeLogger logger, String moduleName)
throws UnableToCompleteException {
- String msg = "Generating a selector page for module " + moduleName;
+ String msg = "Generating a selection script for module " + moduleName;
logger.log(TreeLogger.TRACE, msg, null);
ModuleDef moduleDef = getModuleDef(logger, moduleName);
SelectionScriptGenerator gen = new SelectionScriptGenerator(moduleDef);
- return gen.generateSelectionScript();
+ return gen.generateSelectionScript(false);
}
private synchronized TreeLogger getLogger() {
@@ -668,6 +699,20 @@
}
/**
+ * A file is infinitely cacheable if it ends with ".cache.xxx", where "xxx"
+ * can be any extension.
+ */
+ private boolean isInfinitelyCacheable(String path) {
+ int lastDot = path.lastIndexOf('.');
+ if (lastDot >= 0) {
+ if (path.substring(0, lastDot).endsWith(".cache")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Checks to see whether or not a client's file is out of date relative to the
* original.
*/
diff --git a/dev/core/src/com/google/gwt/dev/shell/ModuleSpacePropertyOracle.java b/dev/core/src/com/google/gwt/dev/shell/ModuleSpacePropertyOracle.java
index 702334b..fde7a85 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ModuleSpacePropertyOracle.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ModuleSpacePropertyOracle.java
@@ -20,7 +20,6 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.cfg.Properties;
import com.google.gwt.dev.cfg.Property;
-import com.google.gwt.dev.util.Empty;
import java.util.HashMap;
import java.util.Map;
@@ -31,12 +30,12 @@
*/
public class ModuleSpacePropertyOracle implements PropertyOracle {
+ private final Map prevAnswers = new HashMap();
+
private final Properties props;
private final ModuleSpace space;
- private final Map prevAnswers = new HashMap();
-
public ModuleSpacePropertyOracle(Properties props, ModuleSpace space) {
this.space = space;
this.props = props;
@@ -100,12 +99,11 @@
if (value == null) {
// Invokes the script function.
//
- String scriptFnName = makeScriptFnName(prop);
try {
// Invoke the property provider function in JavaScript.
//
- value = space.invokeNativeString(scriptFnName, null, Empty.CLASSES,
- Empty.OBJECTS);
+ value = space.invokeNativeString("__gwt_getProperty", null,
+ new Class[] {String.class}, new Object[] {prop.getName()});
} catch (RuntimeException e) {
// Treat as an unknown value.
//
@@ -119,12 +117,4 @@
// value may be null if the provider returned an unknown property value.
return value;
}
-
- /**
- * Coordinate this property provider function name with the one generated in
- * {@link com.google.gwt.dev.util.SelectionScriptGenerator#genPropProviders(PrintWriter)}.
- */
- private String makeScriptFnName(Property prop) {
- return "prop$" + prop.getName();
- }
}
diff --git a/dev/core/src/com/google/gwt/dev/util/HttpHeaders.java b/dev/core/src/com/google/gwt/dev/util/HttpHeaders.java
index 6d48d06..2d5da0a 100644
--- a/dev/core/src/com/google/gwt/dev/util/HttpHeaders.java
+++ b/dev/core/src/com/google/gwt/dev/util/HttpHeaders.java
@@ -27,40 +27,45 @@
*/
public final class HttpHeaders {
- public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
-
- public static final String CONTENT_TYPE = "Content-Type";
- public static final String CONTENT_TYPE_APPLICATION_XJAVASCRIPT_UTF8 = "application/x-javascript; charset=utf-8";
- public static final String CONTENT_TYPE_TEXT_HTML = "text/html";
- public static final String CONTENT_TYPE_TEXT_HTML_UTF8 = "text/html; charset=utf-8";
- public static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain";
- public static final String CONTENT_TYPE_TEXT_CSS = "text/css";
-
- public static final String CONTENT_ENCODING = "Content-Encoding";
- public static final String CONTENT_ENCODING_GZIP = "gzip";
-
public static final long MS_SEC = 1000;
public static final long MS_MIN = MS_SEC * 60;
public static final long MS_HR = MS_MIN * 60;
public static final long MS_DAY = MS_HR * 24;
+ public static final long SEC_MIN = 60;
+ public static final long SEC_HR = SEC_MIN * 60;
+ public static final long SEC_DAY = SEC_HR * 24;
+ public static final long SEC_YR = SEC_DAY * 365;
+
public static final String CACHE_CONTROL = "Cache-Control";
+ public static final String CACHE_CONTROL_MAXAGE_EXPIRED = "max-age=0";
+
+ /*
+ * "Forever" = 1 year according to
+ * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21
+ */
+ public static final String CACHE_CONTROL_MAXAGE_FOREVER = "max-age=" + SEC_YR;
+ public static final String CACHE_CONTROL_MUST_REVALIDATE = "must-revalidate";
public static final String CACHE_CONTROL_NO_CACHE = "no-cache";
public static final String CACHE_CONTROL_PRIVATE = "private";
- public static final String CACHE_CONTROL_MUST_REVALIDATE = "must-revalidate";
- public static final String CACHE_FOREVER = "max-age="
- + String.valueOf(90 * MS_DAY);
- public static final String CACHE_MINUTE = "max-age=" + String.valueOf(MS_MIN);
+ public static final String CACHE_CONTROL_PUBLIC = "public";
- public static final String LAST_MODIFIED = "Last-Modified";
-
- public static final String ETAG = "ETag";
-
- public static final String IF_NONE_MATCH = "If-None-Match";
+ public static final String CONTENT_ENCODING = "Content-Encoding";
+ public static final String CONTENT_ENCODING_GZIP = "gzip";
+ public static final String CONTENT_LENGTH = "Content-Length";
+ public static final String CONTENT_TYPE = "Content-Type";
+ public static final String CONTENT_TYPE_APPLICATION_XJAVASCRIPT_UTF8 = "application/x-javascript; charset=utf-8";
+ public static final String CONTENT_TYPE_TEXT_CSS = "text/css";
+ public static final String CONTENT_TYPE_TEXT_HTML = "text/html";
+ public static final String CONTENT_TYPE_TEXT_HTML_UTF8 = "text/html; charset=utf-8";
+ public static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain";
public static final String DATE = "Date";
-
+ public static final String ETAG = "ETag";
public static final String EXPIRES = "Expires";
+ public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
+ public static final String IF_NONE_MATCH = "If-None-Match";
+ public static final String LAST_MODIFIED = "Last-Modified";
/**
* The Internet date format for HTTP.
diff --git a/dev/core/src/com/google/gwt/dev/util/SelectionScriptGenerator.java b/dev/core/src/com/google/gwt/dev/util/SelectionScriptGenerator.java
index e293d13..aa3709a 100644
--- a/dev/core/src/com/google/gwt/dev/util/SelectionScriptGenerator.java
+++ b/dev/core/src/com/google/gwt/dev/util/SelectionScriptGenerator.java
@@ -22,8 +22,21 @@
import com.google.gwt.dev.cfg.Script;
import com.google.gwt.dev.cfg.Scripts;
import com.google.gwt.dev.cfg.Styles;
+import com.google.gwt.dev.js.JsObfuscateNamer;
+import com.google.gwt.dev.js.JsParser;
+import com.google.gwt.dev.js.JsParserException;
+import com.google.gwt.dev.js.JsSourceGenerationVisitor;
+import com.google.gwt.dev.js.JsSymbolResolver;
+import com.google.gwt.dev.js.JsVerboseNamer;
+import com.google.gwt.dev.js.ast.JsName;
+import com.google.gwt.dev.js.ast.JsProgram;
+import com.google.gwt.dev.js.ast.JsScope;
+import com.google.gwt.util.tools.Utility;
+import java.io.IOException;
import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.StringReader;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
@@ -42,6 +55,33 @@
*/
public class SelectionScriptGenerator {
+ private static String cssInjector(String cssUrl) {
+ return " if (!__gwt_stylesLoaded['" + cssUrl + "']) {\n"
+ + " __gwt_stylesLoaded['" + cssUrl + "'] = true;\n"
+ + " document.write('<link rel=\\\"stylesheet\\\" href=\\\"" + cssUrl
+ + "\\\">');\n" + " }\n";
+ }
+
+ private static void replaceAll(StringBuffer buf, String search, String replace) {
+ int len = search.length();
+ for (int pos = buf.indexOf(search); pos >= 0; pos = buf.indexOf(search,
+ pos + 1)) {
+ buf.replace(pos, pos + len, replace);
+ }
+ }
+
+ private static String scriptInjector(String scriptUrl) {
+ return " if (!__gwt_scriptsLoaded['" + scriptUrl + "']) {\n"
+ + " __gwt_scriptsLoaded['" + scriptUrl + "'] = true;\n"
+ + " document.write('<script language=\\\"javascript\\\" src=\\\""
+ + scriptUrl + "\\\"></script>');\n" + " }\n";
+ }
+
+ private final String moduleFunction;
+ private final String moduleName;
+ private final Properties moduleProps;
+ private final Property[] orderedProps;
+
/**
* Maps compilation strong name onto a <code>Set</code> of
* <code>String[]</code>. We use a <code>TreeMap</code> to produce the
@@ -49,12 +89,6 @@
*/
private final Map propertyValuesSetByStrongName = new TreeMap();
- private final Property[] orderedProps;
-
- private final Properties moduleProps;
-
- private final String moduleName;
-
private final Scripts scripts;
private final Styles styles;
@@ -68,6 +102,7 @@
*/
public SelectionScriptGenerator(ModuleDef moduleDef) {
this.moduleName = moduleDef.getName();
+ this.moduleFunction = moduleDef.getFunctionName();
this.scripts = moduleDef.getScripts();
this.styles = moduleDef.getStyles();
this.moduleProps = moduleDef.getProperties();
@@ -86,6 +121,7 @@
*/
public SelectionScriptGenerator(ModuleDef moduleDef, Property[] props) {
this.moduleName = moduleDef.getName();
+ this.moduleFunction = moduleName.replace('.', '_');
this.scripts = moduleDef.getScripts();
this.styles = moduleDef.getStyles();
this.moduleProps = moduleDef.getProperties();
@@ -95,40 +131,52 @@
/**
* Generates a selection script based on the current settings.
*
- * @return an html document whose contents are the definition of a
- * module.nocache.html file
+ * @return an JavaScript whose contents are the definition of a module.js file
*/
- public String generateSelectionScript() {
- StringWriter src = new StringWriter();
- PrintWriter pw = new PrintWriter(src, true);
+ public String generateSelectionScript(boolean obfuscate) {
+ try {
+ String rawSource;
+ {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
- pw.println("<html>");
+ String template = Utility.getFileFromClassPath("com/google/gwt/dev/util/SelectionScriptTemplate.js");
+ genScript(pw, template);
- // Emit the head and script.
- //
- pw.println("<head><script>");
- String onloadExpr = genScript(pw);
- pw.println("</script></head>");
+ pw.close();
+ rawSource = sw.toString();
+ }
- // Emit the body.
- //
- pw.print("<body onload='");
- pw.print(onloadExpr);
- pw.println("'>");
+ {
+ JsParser parser = new JsParser();
+ Reader r = new StringReader(rawSource);
+ JsProgram jsProgram = new JsProgram();
+ JsScope topScope = jsProgram.getScope();
+ JsName funcName = topScope.declareName(moduleFunction);
+ funcName.setObfuscatable(false);
- // This body text won't be seen unless you open the html alone.
- pw.print("<font face='arial' size='-1'>");
- pw.print("This script is part of module</font> <code>");
- pw.print(moduleName);
- pw.println("</code>");
+ parser.parseInto(topScope, jsProgram.getGlobalBlock(), r, 1);
+ JsSymbolResolver.exec(jsProgram);
+ if (obfuscate) {
+ JsObfuscateNamer.exec(jsProgram);
+ } else {
+ JsVerboseNamer.exec(jsProgram);
+ }
- pw.println("</body>");
-
- pw.println("</html>");
-
- pw.close();
- String html = src.toString();
- return html;
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ TextOutputOnPrintWriter out = new TextOutputOnPrintWriter(pw, obfuscate);
+ JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out);
+ jsProgram.traverse(v);
+ return sw.toString();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Error processing selection script template.",
+ e);
+ } catch (JsParserException e) {
+ throw new RuntimeException("Error processing selection script template.",
+ e);
+ }
}
/**
@@ -149,22 +197,6 @@
valuesSet.add(values.clone());
}
- private void genAnswerFunction(PrintWriter pw) {
- pw.println("function O(a,v) {");
- pw.println(" var answer = O.answers;");
- pw.println(" var i = -1;");
- pw.println(" var n = a.length - 1;");
- pw.println(" while (++i < n) {");
- pw.println(" if (!(a[i] in answer)) {");
- pw.println(" answer[a[i]] = [];");
- pw.println(" }");
- pw.println(" answer = answer[a[i]];");
- pw.println(" }");
- pw.println(" answer[a[n]] = v;");
- pw.println("}");
- pw.println("O.answers = [];");
- }
-
private void genAnswers(PrintWriter pw) {
for (Iterator iter = propertyValuesSetByStrongName.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Entry) iter.next();
@@ -176,7 +208,7 @@
for (Iterator iterator = propValuesSet.iterator(); iterator.hasNext();) {
String[] propValues = (String[]) iterator.next();
- pw.print(" O([");
+ pw.print(" O([");
for (int i = 0; i < orderedProps.length; i++) {
if (i > 0) {
pw.print(",");
@@ -191,123 +223,22 @@
}
}
- /**
- * Generates a function that injects calls to a shared file-injection
- * functions.
- *
- * @param pw generate source onto this writer
- */
- private void genInjectExternalFiles(PrintWriter pw) {
- pw.println();
- pw.println("function injectExternalFiles() {");
- pw.println(" var mcb = $wnd.__gwt_tryGetModuleControlBlock(location.search);");
- pw.println(" if (!mcb) return;");
- pw.println(" var base = mcb.getBaseURL();");
-
- // Styles come first to give them a little more time to load.
- pw.println(" mcb.addStyles([");
- boolean needComma = false;
- for (Iterator iter = styles.iterator(); iter.hasNext();) {
- String src = (String) iter.next();
- if (needComma) {
- pw.println(",");
- }
- needComma = true;
-
- pw.print(" ");
- if (isRelativeURL(src)) {
- pw.print("base+");
- }
- pw.print("'");
- pw.print(src);
- pw.print("'");
- }
- pw.println();
- pw.println(" ]);");
-
- // Scripts
- pw.println(" mcb.addScripts([");
- needComma = false;
- for (Iterator iter = scripts.iterator(); iter.hasNext();) {
- Script script = (Script) iter.next();
- if (needComma) {
- pw.println(",");
- }
- needComma = true;
-
- // Emit the src followed by the module-ready function.
- // Note that the module-ready function is a string because it gets
- // eval'ed in the context of the host html window. This is absolutely
- // required because otherwise in web mode (IE) you get an
- // "cannot execute code from a freed script" error.
- String src = script.getSrc();
- pw.print(" ");
- if (isRelativeURL(src)) {
- pw.print("base+");
- }
- pw.print("'");
- pw.print(src);
- pw.print("', \"");
- String readyFnJs = Jsni.generateEscapedJavaScript(script.getJsReadyFunction());
- pw.print(readyFnJs);
- pw.print("\"");
- }
- pw.println();
- pw.println(" ]);");
-
- pw.println("}");
- }
-
- private void genOnLoad(PrintWriter pw) {
- // Emit the onload() function.
- pw.println();
- pw.println("function onLoad() {");
-
- // Early out (or fall through below) if the page is loaded out of context.
- pw.println(" if (!$wnd.__gwt_isHosted) return;");
-
- // Maybe inject scripts.
- if (hasExternalFiles()) {
- pw.println(" injectExternalFiles();");
- }
-
- // If we're in web mode, run the compilation selector logic.
- // The compilation will call mcb.compilationLoaded() itself.
- pw.println(" if (!$wnd.__gwt_isHosted()) {");
- pw.println(" selectScript();");
- pw.println(" }");
-
- // If we're in hosted mode, notify $wnd that we're ready to go.
- // Requires that we get the module control block.
- pw.println(" else {");
- pw.println(" var mcb = $wnd.__gwt_tryGetModuleControlBlock(location.search);");
- pw.println(" if (mcb) {");
- pw.println(" $moduleName = mcb.getName();");
- pw.println(" mcb.compilationLoaded(window);");
- pw.println(" }");
- pw.println(" }");
- pw.println("}");
- }
-
private void genPropProviders(PrintWriter pw) {
- pw.println();
-
for (Iterator iter = moduleProps.iterator(); iter.hasNext();) {
Property prop = (Property) iter.next();
String activeValue = prop.getActiveValue();
if (activeValue == null) {
// Emit a provider function, defined by the user in module config.
- pw.println();
PropertyProvider provider = prop.getProvider();
assert (provider != null) : "expecting a default property provider to have been set";
String js = Jsni.generateJavaScript(provider.getBody());
- pw.print("window[\"provider$" + prop.getName() + "\"] = function() ");
+ pw.print("providers['" + prop.getName() + "'] = function() ");
pw.print(js);
pw.println(";");
// Emit a map of allowed property values as an object literal.
pw.println();
- pw.println("window[\"values$" + prop.getName() + "\"] = {");
+ pw.println("values['" + prop.getName() + "'] = {");
String[] knownValues = prop.getKnownValues();
for (int i = 0; i < knownValues.length; i++) {
if (i > 0) {
@@ -326,9 +257,9 @@
// Emit a wrapper that verifies that the value is valid.
// It is this function that is called directly to get the propery.
pw.println();
- pw.println("window[\"prop$" + prop.getName() + "\"] = function() {");
- pw.println(" var v = window[\"provider$" + prop.getName() + "\"]();");
- pw.println(" var ok = window[\"values$" + prop.getName() + "\"];");
+ pw.println("props['" + prop.getName() + "'] = function() {");
+ pw.println(" var v = providers['" + prop.getName() + "']();");
+ pw.println(" var ok = values['" + prop.getName() + "'];");
// Make sure this is an allowed value; if so, return.
pw.println(" if (v in ok)");
pw.println(" return v;");
@@ -336,20 +267,19 @@
pw.println(" var a = new Array(" + knownValues.length + ");");
pw.println(" for (var k in ok)");
pw.println(" a[ok[k]] = k;");
- pw.print(" $wnd.__gwt_onBadProperty(");
- pw.print(literal(moduleName));
- pw.print(", ");
+ pw.print(" " + moduleFunction + ".onBadProperty(");
pw.print(literal(prop.getName()));
pw.println(", a, v);");
pw.println(" if (arguments.length > 0) throw null; else return null;");
pw.println("};");
+ pw.println();
}
}
}
private void genPropValues(PrintWriter pw) {
- pw.println(" var F;");
- pw.print(" var I = [");
+ pw.println(" var F;");
+ pw.print(" var I = [");
for (int i = 0; i < orderedProps.length; i++) {
if (i > 0) {
pw.print(", ");
@@ -365,7 +295,7 @@
// When we call the provider, we supply a bogus argument to indicate
// that it should throw an exception if the property is a bad value.
// The absence of arguments (as in hosted mode) tells it to return null.
- pw.print("(F=window[\"prop$" + prop.getName() + "\"],F(1))");
+ pw.print("(F=props['" + prop.getName() + "'],F(1))");
} else {
// This property was explicitly set at compile-time.
//
@@ -380,87 +310,87 @@
* a compilation.
*
* @param pw
- * @return an expression that should be called as the body's onload handler
*/
- private String genScript(PrintWriter pw) {
- // Emit $wnd and $doc for dynamic property providers.
- pw.println("var $wnd = parent;");
- pw.println("var $doc = $wnd.document;");
- pw.println("var $moduleName = null;");
+ private void genScript(PrintWriter mainPw, String template) {
+ StringBuffer buf = new StringBuffer(template);
+ replaceAll(buf, "__MODULE_FUNC__", moduleFunction);
+ replaceAll(buf, "__MODULE_NAME__", moduleName);
- // Emit property providers; these are used in both modes.
- genPropProviders(pw);
-
- // If the ordered props are specified, then we're generating for both modes.
+ // Remove hosted mode only stuff
if (orderedProps != null) {
- // Web mode or hosted mode.
- if (orderedProps.length > 0) {
- pw.println();
- genAnswerFunction(pw);
- pw.println();
- genSrcSetFunction(pw, null);
- } else {
- // Rare case of no properties; happens if you inherit from Core alone.
- assert (orderedProps.length == 0);
- Set entrySet = propertyValuesSetByStrongName.entrySet();
- assert (entrySet.size() == 1);
- Map.Entry entry = (Entry) entrySet.iterator().next();
- String strongName = (String) entry.getKey();
- genSrcSetFunction(pw, strongName);
+ int startPos = buf.indexOf("// __SHELL_SERVLET_ONLY_BEGIN__");
+ int endPos = buf.indexOf("// __SHELL_SERVLET_ONLY_END__");
+ buf.delete(startPos, endPos);
+ }
+
+ // Add external dependencies
+ int startPos = buf.indexOf("// __MODULE_DEPS_END__");
+ for (Iterator iter = styles.iterator(); iter.hasNext();) {
+ String style = (String) iter.next();
+ String text = cssInjector(style);
+ buf.insert(startPos, text);
+ startPos += text.length();
+ }
+
+ for (Iterator iter = scripts.iterator(); iter.hasNext();) {
+ Script script = (Script) iter.next();
+ String text = scriptInjector(script.getSrc());
+ buf.insert(startPos, text);
+ startPos += text.length();
+ }
+
+ // Add property providers
+ {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ genPropProviders(pw);
+ pw.close();
+ String stuff = sw.toString();
+ startPos = buf.indexOf("// __PROPERTIES_END__");
+ buf.insert(startPos, stuff);
+ }
+
+ // Add permutations
+ {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+
+ // If the ordered props are specified, then we're generating for both
+ // modes.
+ if (orderedProps != null) {
+ // Web mode or hosted mode.
+ if (orderedProps.length > 0) {
+ pw.println();
+ genPropValues(pw);
+ pw.println();
+ genAnswers(pw);
+ pw.println();
+ pw.print(" strongName = answers");
+ for (int i = 0; i < orderedProps.length; i++) {
+ pw.print("[I[" + i + "]]");
+ }
+ } else {
+ // Rare case of no properties; happens if you inherit from Core
+ // alone.
+ assert (orderedProps.length == 0);
+ Set entrySet = propertyValuesSetByStrongName.entrySet();
+ assert (entrySet.size() == 1);
+ Map.Entry entry = (Entry) entrySet.iterator().next();
+ String strongName = (String) entry.getKey();
+ // There is exactly one compilation, so it is unconditionally
+ // selected.
+ pw.print(" strongName = " + literal(strongName));
+ }
+ pw.println(";");
}
- } else {
- // Hosted mode only, so there is no strong name selection (i.e. because
- // there is no compiled JavaScript); do nothing
+
+ pw.close();
+ String stuff = sw.toString();
+ startPos = buf.indexOf("// __PERMUTATIONS_END__");
+ buf.insert(startPos, stuff);
}
- // Emit dynamic file injection logic; same logic is used in both modes.
- if (hasExternalFiles()) {
- genInjectExternalFiles(pw);
- }
-
- genOnLoad(pw);
-
- return "onLoad()";
- }
-
- /**
- * @param pw generate source onto this writer
- * @param oneAndOnlyStrongName if <code>null</code>, use the normal logic;
- * otherwise, there are no client properties and thus there is
- * exactly one permutation, specified by this parameter
- */
- private void genSrcSetFunction(PrintWriter pw, String oneAndOnlyStrongName) {
- pw.println();
- pw.println("function selectScript() {");
- if (oneAndOnlyStrongName == null) {
- pw.println(" try {");
- genPropValues(pw);
- pw.println();
- genAnswers(pw);
- pw.println();
- pw.print(" var strongName = O.answers");
- for (int i = 0; i < orderedProps.length; i++) {
- pw.print("[I[" + i + "]]");
- }
- pw.println(";");
- pw.println(" var query = location.search;");
- pw.println(" query = query.substring(0, query.indexOf('&'));");
- pw.println(" var newUrl = strongName + '.cache.html' + query;");
- pw.println(" location.replace(newUrl);");
- pw.println(" } catch (e) {");
- pw.println(" // intentionally silent on property failure");
- pw.println(" }");
- } else {
- // There is exactly one compilation, so it is unconditionally selected.
- //
- String scriptToLoad = oneAndOnlyStrongName + ".cache.html";
- pw.println(" location.replace('" + scriptToLoad + "');");
- }
- pw.println("}");
- }
-
- private boolean hasExternalFiles() {
- return !scripts.isEmpty() || !styles.isEmpty();
+ mainPw.print(buf.toString());
}
/**
@@ -493,4 +423,5 @@
private String literal(String lit) {
return "\"" + lit + "\"";
}
+
}
diff --git a/dev/core/src/com/google/gwt/dev/util/SelectionScriptTemplate.js b/dev/core/src/com/google/gwt/dev/util/SelectionScriptTemplate.js
new file mode 100644
index 0000000..e10caba
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/util/SelectionScriptTemplate.js
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2006 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
+ * the License.
+ */
+
+function __MODULE_FUNC__() {
+ // ---------------- INTERNAL GLOBALS ----------------
+
+ // Cache symbols locally for good obfuscation
+ var wnd = window;
+ var external = wnd.external;
+
+ // These two variables gate calling gwtOnLoad; both must be true to start
+ var scriptsDone, loadDone;
+
+ // A map of properties that were declared in meta tags
+ var __gwt_metaProps = {};
+
+ // A map of module rebasings
+ var __gwt_base = {};
+
+ // These variables contain deferred-binding properties, values, and
+ // providers.
+ //
+ var props = [];
+ var values = [];
+ var providers = [];
+
+ // Property answers go here
+ var answers = [];
+
+ // ------------------ TRUE GLOBALS ------------------
+
+ // Maps to synchronize the loading of styles and scripts; resources are loaded
+ // only once, even when multiple modules depend on them. This API must not
+ // change across GWT versions.
+ if (!wnd.__gwt_stylesLoaded) { wnd.__gwt_stylesLoaded = {}; }
+ if (!wnd.__gwt_scriptsLoaded) { wnd.__gwt_scriptsLoaded = {}; }
+
+ // --------------- INTERNAL FUNCTIONS ---------------
+
+ // The default module load error function; may be overwritten via meta props
+ //
+ function __gwt_onLoadError() {
+ alert('Failed to load module __MODULE_NAME__' +
+ '".\nPlease see the log in the development shell for details.');
+ }
+
+ // The default bad property error function; may be overwritten via meta props
+ //
+ function __gwt_onPropertyError(propName, allowedValues, badValue) {
+ var msg = 'While attempting to load module __MODULE_NAME__, property \"'
+ + propName;
+ if (badValue != null) {
+ msg += '\" was set to the unexpected value \"' + badValue + '\"';
+ } else {
+ msg += '\" was not specified';
+ }
+ msg += 'Allowed values: ' + allowedValues;
+ alert(msg);
+ }
+
+
+ function isHostedMode() {
+ return (external && external.gwtOnLoad &&
+ (document.location.href.indexOf('gwt.hybrid') == -1));
+ }
+
+
+ // Called by both onScriptLoad() and onInjectionDone(). It causes
+ // the specified module to be cranked up.
+ //
+ function maybeStartModule() {
+ if (scriptsDone && loadDone) {
+ var iframe = document.getElementById('__MODULE_NAME__');
+ var frameWnd = iframe.contentWindow;
+ // copy the init handlers function into the iframe
+ frameWnd.__gwt_initHandlers = __MODULE_FUNC__.__gwt_initHandlers;
+ // remove this whole function from the global namespace to allow GC
+ __MODULE_FUNC__ = null;
+ iframe.contentWindow.gwtOnLoad(__gwt_onLoadError, '__MODULE_NAME__');
+ }
+ }
+
+ // Called to slurp up all <meta> tags:
+ // gwt:property, gwt:base, gwt:onPropertyErrorFn, gwt:onLoadErrorFn
+ //
+ function processMetas() {
+ var metas = document.getElementsByTagName('meta');
+
+ for (var i = 0, n = metas.length; i < n; ++i) {
+ var meta = metas[i];
+ var name = meta.getAttribute('name');
+
+ if (name) {
+ if (name == 'gwt:property') {
+ var content = meta.getAttribute('content');
+ if (content) {
+ var name = content, value = '';
+ var eq = content.indexOf('=');
+ if (eq != -1) {
+ name = content.substring(0, eq);
+ value = content.substring(eq+1);
+ }
+ __gwt_metaProps[name] = value;
+ }
+ } else if (name == 'gwt:onPropertyErrorFn') {
+ var content = meta.getAttribute('content');
+ if (content) {
+ try {
+ __gwt_onPropertyError = eval(content);
+ } catch (e) {
+ alert('Bad handler \"' + content +
+ '\" for \"gwt:onPropertyErrorFn\"');
+ }
+ }
+ } else if (name == 'gwt:onLoadErrorFn') {
+ var content = meta.getAttribute('content');
+ if (content) {
+ try {
+ __gwt_onLoadError = eval(content);
+ } catch (e) {
+ alert('Bad handler \"' + content + '\" for \"gwt:onLoadErrorFn\"');
+ }
+ }
+ } else if (name == 'gwt:base') {
+ var content = meta.getAttribute('content');
+ var eqPos = content.lastIndexOf('=');
+ if (eqPos == -1) {
+ continue;
+ }
+ var moduleBase = content.substring(0, eqPos);
+ var moduleName = content.substring(eqPos + 1);
+ __gwt_base[moduleName] = moduleBase;
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines whether or not a particular property value is allowed. Called by
+ * property providers.
+ *
+ * @param propName the name of the property being checked
+ * @param propValue the property value being tested
+ */
+ function __gwt_isKnownPropertyValue(propName, propValue) {
+ return propValue in values[propName];
+ }
+
+ /**
+ * Returns a meta property value, if any. Used by DefaultPropertyProvider.
+ */
+ function __gwt_getMetaProperty(name) {
+ var value = __gwt_metaProps[name];
+ return (value == null) ? null : value;
+ }
+
+ // Deferred-binding mapper function.
+ //
+ function O(a,v) {
+ var answer = answers;
+ var i = -1;
+ var n = a.length - 1;
+ while (++i < n) {
+ if (!(a[i] in answer)) {
+ answer[a[i]] = [];
+ }
+ answer = answer[a[i]];
+ }
+ answer[a[n]] = v;
+ }
+
+ // --------------- PROPERTY PROVIDERS ---------------
+
+// __PROPERTIES_BEGIN__
+// __PROPERTIES_END__
+
+ // --------------- EXPOSED FUNCTIONS ----------------
+
+ // Called when the script injection is complete.
+ //
+ __MODULE_FUNC__.onInjectionDone = function() {
+ // Mark this module's script injection done and (possibly) start the module.
+ scriptsDone = true;
+ maybeStartModule();
+ }
+
+ // Called when the compiled script identified by moduleName is done loading.
+ //
+ __MODULE_FUNC__.onScriptLoad = function() {
+ // Mark this module's script as done loading and (possibly) start the module.
+ loadDone = true;
+ maybeStartModule();
+ }
+
+ // --------------- STRAIGHT-LINE CODE ---------------
+
+// __SHELL_SERVLET_ONLY_BEGIN__
+ // Force shell servlet to serve compiled output for web mode
+ if (!isHostedMode()) {
+ document.write('<script src="__MODULE_NAME__.nocache.js?compiled"></script>');
+ return;
+ }
+// __SHELL_SERVLET_ONLY_END__
+
+ processMetas();
+
+ var strongName;
+ if (isHostedMode()) {
+ // In hosted mode, inject the script frame directly.
+ var iframe = document.createElement('iframe');
+ iframe.id = '__MODULE_NAME__';
+ iframe.style.width = '0px';
+ iframe.style.height = '0px';
+ iframe.style.border = '0px';
+ document.body.appendChild(iframe);
+
+ iframe.src = 'blank.html';
+ iframe.onload = function() {
+ var frameWnd = iframe.contentWindow;
+ frameWnd.$wnd = wnd;
+ frameWnd.$doc = wnd.document;
+
+ // inject hosted mode property evaluation function
+ frameWnd.__gwt_getProperty = function(name) {
+ return providers[name]();
+ };
+
+ // inject gwtOnLoad
+ frameWnd.gwtOnLoad = function(errFn, modName) {
+ if (!external.gwtOnLoad(frameWnd, modName)) {
+ errFn(modName);
+ }
+ }
+
+ // Hook the iframe's onunload, so that the hosted browser has a chance
+ // to clean up its ModuleSpaces.
+ frameWnd.onunload = function() {
+ external.gwtOnLoad(frameWnd, null);
+ };
+
+ __MODULE_FUNC__.onScriptLoad();
+ };
+ } else {
+ try {
+// __PERMUTATIONS_BEGIN__
+ // Permutation logic
+// __PERMUTATIONS_END__
+ } catch (e) {
+ // intentionally silent on property failure
+ return;
+ }
+
+ // TODO: do we still need this query stuff?
+ var query = location.search;
+ query = query.substring(0, query.indexOf('&'));
+
+ var base = __gwt_base['__MODULE_NAME__'];
+ var newUrl = (base ? base + '/' : '') + strongName + '.cache.html' + query;
+ document.write('<iframe id="__MODULE_NAME__" style="width:0;height:0;border:0" src="' + newUrl + '"></iframe>');
+ }
+
+// __MODULE_DEPS_BEGIN__
+ // Module dependencies, such as scripts and css
+// __MODULE_DEPS_END__
+ document.write('<script>__MODULE_FUNC__.onInjectionDone(\'__MODULE_NAME__\')</script>');
+}
+
+// Called from compiled code to hook the window's resize & load events (the
+// code running in the script frame is not allowed to hook these directly).
+//
+// Notes:
+// 1) We declare it here in the global scope so that it won't closure the
+// internals of the module func.
+//
+// 2) We hang it off the module func to avoid polluting the global namespace.
+//
+// 3) This function will be copied directly into the script frame window!
+//
+__MODULE_FUNC__.__gwt_initHandlers = function(resize, beforeunload, unload) {
+ var wnd = window;
+ var oldOnResize = wnd.onresize;
+ wnd.onresize = function() {
+ resize();
+ if (oldOnResize)
+ oldOnResize();
+ };
+
+ var oldOnBeforeUnload = wnd.onbeforeunload;
+ wnd.onbeforeunload = function() {
+ var ret = beforeunload();
+
+ var oldRet;
+ if (oldOnBeforeUnload)
+ oldRet = oldOnBeforeUnload();
+
+ if (ret !== null)
+ return ret;
+ return oldRet;
+ };
+
+ var oldOnUnload = wnd.onunload;
+ wnd.onunload = function() {
+ unload();
+ if (oldOnUnload)
+ oldOnUnload();
+ };
+}
+
+__MODULE_FUNC__();
diff --git a/eclipse/settings/english.dictionary b/eclipse/settings/english.dictionary
index 61a9e4c..2ba576b 100644
--- a/eclipse/settings/english.dictionary
+++ b/eclipse/settings/english.dictionary
@@ -21230,7 +21230,6 @@
homomorphisms
hone
honed
-honer
hones
honest
honestly
@@ -21249,6 +21248,7 @@
honeys
honeysuckle
honing
+honor
honorary
hood
hood's
@@ -47224,4 +47224,9 @@
polymorphically
modeled
reentrancy
-temp
+temp
+servlet
+deprecated
+recognize
+minimalist
+cacheable
diff --git a/samples/dynatable/src/com/google/gwt/sample/dynatable/public/DynaTable.html b/samples/dynatable/src/com/google/gwt/sample/dynatable/public/DynaTable.html
index 629378b..016e829 100644
--- a/samples/dynatable/src/com/google/gwt/sample/dynatable/public/DynaTable.html
+++ b/samples/dynatable/src/com/google/gwt/sample/dynatable/public/DynaTable.html
@@ -2,14 +2,12 @@
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
- <meta name='gwt:module' content='com.google.gwt.sample.dynatable.DynaTable' />
<link type="text/css" rel="stylesheet" href="DynaTable.css" />
<title></title>
</head>
<body>
- <iframe id='__gwt_historyFrame' style='width:0;height:0;border:0'></iframe> <script
- type="text/javascript" language='javascript' src='gwt.js'>
- </script>
+ <iframe id='__gwt_historyFrame' style='width:0;height:0;border:0'></iframe>
+ <script type="text/javascript" language='javascript' src='com.google.gwt.sample.dynatable.DynaTable.nocache.js'></script>
<h1>School Schedule for Professors and Students</h1>
<table width="100%" border="0" summary="School Schedule for Professors and Students">
<tr valign="top">
diff --git a/samples/hello/src/com/google/gwt/sample/hello/public/Hello.html b/samples/hello/src/com/google/gwt/sample/hello/public/Hello.html
index f97006b..1dc9a6f 100644
--- a/samples/hello/src/com/google/gwt/sample/hello/public/Hello.html
+++ b/samples/hello/src/com/google/gwt/sample/hello/public/Hello.html
@@ -1,9 +1,8 @@
<html>
<head>
- <meta name='gwt:module' content='com.google.gwt.sample.hello.Hello'>
<title>Hello</title>
</head>
<body bgcolor="white">
- <script language="javascript" src="gwt.js"></script>
+ <script language="javascript" src="com.google.gwt.sample.hello.Hello.nocache.js"></script>
</body>
</html>
diff --git a/samples/i18n/src/com/google/gwt/sample/i18n/public/I18N.html b/samples/i18n/src/com/google/gwt/sample/i18n/public/I18N.html
index 77dab1d..a919760 100644
--- a/samples/i18n/src/com/google/gwt/sample/i18n/public/I18N.html
+++ b/samples/i18n/src/com/google/gwt/sample/i18n/public/I18N.html
@@ -1,6 +1,5 @@
<html>
<head>
- <meta name='gwt:module' content='com.google.gwt.sample.i18n.I18N'>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<script language=javaScript>
// Create dictionaries using the following style:
@@ -18,7 +17,7 @@
<title>Internationalization sample</title>
</head>
<body bgcolor="white">
- <script language="javascript" src="gwt.js"></script>
+ <script language="javascript" src="com.google.gwt.sample.i18n.I18N.nocache.js"></script>
<h1>
Îñţérñåţîöñåļîžåţîöñ
diff --git a/samples/json/src/com/google/gwt/sample/json/public/JSON.html b/samples/json/src/com/google/gwt/sample/json/public/JSON.html
index f546797..903eeb7 100644
--- a/samples/json/src/com/google/gwt/sample/json/public/JSON.html
+++ b/samples/json/src/com/google/gwt/sample/json/public/JSON.html
@@ -1,11 +1,10 @@
<html>
<head>
- <meta name='gwt:module' content='com.google.gwt.sample.json.JSON'>
<link rel='stylesheet' href='JSON.css'>
<title>JSON Interoperability Example</title>
</head>
<body>
- <script language='javascript' src='gwt.js'></script>
+ <script language='javascript' src='com.google.gwt.sample.json.JSON.nocache.js'></script>
<h1>JSON Interop Using JSNI</h1>
diff --git a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/KitchenSink.html b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/KitchenSink.html
index 5d052e1..d8f4593 100644
--- a/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/KitchenSink.html
+++ b/samples/kitchensink/src/com/google/gwt/sample/kitchensink/public/KitchenSink.html
@@ -1,12 +1,9 @@
<html>
<head>
- <meta name='gwt:module' content='com.google.gwt.sample.kitchensink.KitchenSink'>
<title>Kitchen Sink</title>
</head>
<body>
- <!-- This script is the bootstrap stuff that simply must be there; it is sent down uncompressed -->
- <script language='javascript' src='gwt.js'></script>
-
+ <script language='javascript' src='com.google.gwt.sample.kitchensink.KitchenSink.nocache.js'></script>
<iframe id='__gwt_historyFrame' style='width:0;height:0;border:0'></iframe>
</body>
</html>
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/Mail.html b/samples/mail/src/com/google/gwt/sample/mail/public/Mail.html
index 30d6d6f..468557b 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/public/Mail.html
+++ b/samples/mail/src/com/google/gwt/sample/mail/public/Mail.html
@@ -1,10 +1,8 @@
<html>
<head>
- <meta name='gwt:module' content='com.google.gwt.sample.mail.Mail'>
<title>Mail App</title>
</head>
<body style='background-color: #EEEEEE'>
- <!-- This script is the bootstrap stuff that simply must be there; it is sent down uncompressed -->
- <script language='javascript' src='gwt.js'></script>
+ <script language='javascript' src='com.google.gwt.sample.mail.Mail.nocache.js'></script>
</body>
</html>
diff --git a/samples/simplexml/src/com/google/gwt/sample/simplexml/public/SimpleXML.html b/samples/simplexml/src/com/google/gwt/sample/simplexml/public/SimpleXML.html
index 2b32316..a2a3522 100644
--- a/samples/simplexml/src/com/google/gwt/sample/simplexml/public/SimpleXML.html
+++ b/samples/simplexml/src/com/google/gwt/sample/simplexml/public/SimpleXML.html
@@ -1,10 +1,9 @@
<html>
<head>
- <meta name='gwt:module' content='com.google.gwt.sample.simplexml.SimpleXML'>
<title>Simple XML Example</title>
- <link rel="stylesheet" type="text/css" href="SimpleXML.css" />
+ <link rel="stylesheet" type="text/css" href="SimpleXML.css" />
</head>
<body bgcolor="white">
- <script language="javascript" src="gwt.js"></script>
+ <script language="javascript" src="com.google.gwt.sample.simplexml.SimpleXML.nocache.js"></script>
</body>
</html>
diff --git a/user/src/com/google/gwt/core/public/blank.html b/user/src/com/google/gwt/core/public/blank.html
new file mode 100644
index 0000000..8c7fe21
--- /dev/null
+++ b/user/src/com/google/gwt/core/public/blank.html
@@ -0,0 +1,2 @@
+<html>
+</html>
\ No newline at end of file
diff --git a/user/src/com/google/gwt/core/public/gwt.js b/user/src/com/google/gwt/core/public/gwt.js
index cfe9c1c..a5468a4 100644
--- a/user/src/com/google/gwt/core/public/gwt.js
+++ b/user/src/com/google/gwt/core/public/gwt.js
@@ -1,4 +1,4 @@
-// Copyright 2006 Google Inc.
+// Copyright 2007 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
@@ -15,577 +15,27 @@
// This startup script should be included in host pages either just after
// <body> or inside the <head> after module <meta> tags.
//
+(function(){
+ var metas = document.getElementsByTagName("meta");
-//////////////////////////////////////////////////////////////////////////////
-// DynamicResources
-//
-
-function DynamicResources() {
- this.pendingElemsBySrc_ = {};
- this.pendingScriptElems_ = new Array();
-}
-DynamicResources.prototype = {};
-
-// The array is set up such that, pairwise, the entries are (src, readyFnStr).
-// Called once for each module that is attached to the host page.
-// It is theoretically possible that addScripts() could be called reentrantly
-// if the browser event loop is pumped during this function and an iframe loads;
-// we may want to enhance this method in the future to support that case.
-DynamicResources.prototype.addScripts = function(scriptArray, insertBeforeElem) {
- var wasEmpty = (this.pendingScriptElems_.length == 0);
- var anyAdded = false;
- for (var i = 0, n = scriptArray.length; i < n; i += 2) {
- var src = scriptArray[i];
- if (this.pendingElemsBySrc_[src]) {
- // Don't load the same script twice.
- continue;
- }
- // Set up the element but don't add it to the DOM until its turn.
- anyAdded = true;
- var e = document.createElement("script");
- this.pendingElemsBySrc_[src] = e;
- var readyFn;
- eval("readyFn = " + scriptArray[i+1]);
- e.__readyFn = readyFn;
- e.type = "text/javascript";
- e.src = src;
- e.__insertBeforeElem = insertBeforeElem;
- this.pendingScriptElems_ = this.pendingScriptElems_.concat(e);
- }
-
- if (wasEmpty && anyAdded) {
- // Kickstart.
- this.injectScript(this.pendingScriptElems_[0]);
- }
-}
-
-DynamicResources.prototype.injectScript = function(scriptElem) {
- var parentElem = scriptElem.__insertBeforeElem.parentNode;
- parentElem.insertBefore(scriptElem, scriptElem.__insertBeforeElem);
-}
-
-DynamicResources.prototype.addStyles = function(styleSrcArray, insertBeforeElem) {
- var parent = insertBeforeElem.parentNode;
- for (var i = 0, n = styleSrcArray.length; i < n; ++i) {
- var src = styleSrcArray[i];
- if (this.pendingElemsBySrc_[src])
- continue;
- var e = document.createElement("link");
- this.pendingElemsBySrc_[src] = e;
- e.type = "text/css";
- e.rel = "stylesheet";
- e.href = src;
- parent.insertBefore(e, insertBeforeElem);
- }
-}
-
-DynamicResources.prototype.isReady = function() {
- var elems = this.pendingScriptElems_;
- if (elems.length > 0) {
- var e = elems[0];
- if (!e.__readyFn()) {
- // The pending script isn't ready yet.
- return false;
- }
-
- // The pending script has now finished loading. Enqueue the next, if any.
- e.__readyFn = null;
- elems.shift();
- if (elems.length > 0) {
- // There is another script.
- this.injectScript(elems[0]);
- return false;
- }
- }
-
- // There are no more pending scripts.
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// ModuleControlBlock
-//
-function ModuleControlBlock(metaElem, rawName) {
- var parts = ["", rawName];
- var i = rawName.lastIndexOf("=");
- if (i != -1) {
- parts[0] = rawName.substring(0, i) + '/';
- parts[1] = rawName.substring(i+1);
- }
-
- this.metaElem_ = metaElem;
- this.baseUrl_ = parts[0];
- this.name_ = parts[1];
- this.compilationLoaded_ = false;
- this.frameWnd_ = null;
-}
-ModuleControlBlock.prototype = {};
-
-/**
- * Determines whether this module is fully loaded and ready to run.
- */
-ModuleControlBlock.prototype.isReady = function() {
- return this.compilationLoaded_;
-};
-
-/**
- * Called when the compilation for this module is loaded.
- */
-ModuleControlBlock.prototype.compilationLoaded = function(frameWnd) {
- this.frameWnd_ = frameWnd;
- this.compilationLoaded_ = true;
-}
-
-/**
- * Gets the logical module name, not including a base url prefix if one was
- * specified.
- */
-ModuleControlBlock.prototype.getName = function() {
- return this.name_;
-}
-
-/**
- * Gets the base URL of the module, guaranteed to end with a slash.
- */
-ModuleControlBlock.prototype.getBaseURL = function() {
- return this.baseUrl_;
-}
-
-/**
- * Gets the window of the module's frame.
- */
-ModuleControlBlock.prototype.getModuleFrameWindow = function() {
- return this.frameWnd_;
-}
-
-/**
- * Injects a set of dynamic scripts.
- * The array is set up such that, pairwise, the entries are (src, readyFnStr).
- */
-ModuleControlBlock.prototype.addScripts = function(scriptSrcArray) {
- return ModuleControlBlocks.dynamicResources_.addScripts(scriptSrcArray, this.metaElem_);
-}
-
-/**
- * Injects a set of dynamic styles.
- */
-ModuleControlBlock.prototype.addStyles = function(styleSrcArray) {
- return ModuleControlBlocks.dynamicResources_.addStyles(styleSrcArray, this.metaElem_);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// ModuleControlBlocks
-//
-function ModuleControlBlocks() {
- this.blocks_ = [];
-}
-ModuleControlBlocks.dynamicResources_ = new DynamicResources(); // "static"
-ModuleControlBlocks.prototype = {};
-
-/**
- * Adds a module control control block for the named module.
- * @param metaElem the meta element that caused the module to be added
- * @param name the name of the module being added, optionally preceded by
- * an alternate base url of the form "_path_=_module_".
- */
-ModuleControlBlocks.prototype.add = function(metaElem, name) {
- var mcb = new ModuleControlBlock(metaElem, name);
- this.blocks_ = this.blocks_.concat(mcb);
-};
-
-/**
- * Determines whether all the modules are loaded and ready to run.
- */
-ModuleControlBlocks.prototype.isReady = function() {
- for (var i = 0, n = this.blocks_.length; i < n; ++i) {
- var mcb = this.blocks_[i];
- if (!mcb.isReady()) {
- return false;
- }
- }
-
- // Are there any pending dynamic resources (e.g. styles, scripts)?
- if (!ModuleControlBlocks.dynamicResources_.isReady()) {
- // No, we're still waiting on one or more dynamic resources.
- return false;
- }
-
- return true;
-}
-
-/**
- * Determines whether there are any module control blocks.
- */
-ModuleControlBlocks.prototype.isEmpty = function() {
- return this.blocks_.length == 0;
-}
-
-/**
- * Gets the module control block at the specified index.
- */
-ModuleControlBlocks.prototype.get = function(index) {
- return this.blocks_[index];
-}
-
-/**
- * Injects an iframe for each module.
- */
-ModuleControlBlocks.prototype.injectFrames = function() {
- for (var i = 0, n = this.blocks_.length; i < n; ++i) {
- var mcb = this.blocks_[i];
-
- // Insert an iframe for the module
- var iframe = document.createElement("iframe");
- var selectorUrl = mcb.getBaseURL() + mcb.getName() + ".nocache.html";
- selectorUrl += "?" + (__gwt_isHosted() ? "h&" : "" ) + i;
- var unique = new Date().getTime();
- selectorUrl += "&" + unique;
- iframe.style.border = '0px';
- iframe.style.width = '0px';
- iframe.style.height = '0px';
-
- // Fragile browser-specific ordering issues below
-
-/*@cc_on
- // prevent extra clicky noises on IE
- iframe.src = selectorUrl;
-@*/
-
- if (document.body.firstChild) {
- document.body.insertBefore(iframe, document.body.firstChild);
- } else {
- document.body.appendChild(iframe);
- }
-
-/*@cc_on
- // prevent extra clicky noises on IE
- return;
-@*/
-
- if (iframe.contentWindow) {
- // Older Mozilla has a caching bug for the iframe and won't reload the nocache.
- iframe.contentWindow.location.replace(selectorUrl);
- } else {
- // Older Safari doesn't have a contentWindow.
- iframe.src = selectorUrl;
- }
- }
-}
-
-/**
- * Runs the entry point for each module.
- */
-ModuleControlBlocks.prototype.run = function() {
- for (var i = 0, n = this.blocks_.length; i < n; ++i) {
- var mcb = this.blocks_[i];
- var name = mcb.getName();
- var frameWnd = mcb.getModuleFrameWindow();
- if (__gwt_isHosted()) {
- if (!window.external.gwtOnLoad(frameWnd, name)) {
- // Module failed to load.
- if (__gwt_onLoadError) {
- __gwt_onLoadError(name);
- } else {
- window.alert("Failed to load module '" + name +
- "'.\nPlease see the log in the development shell for details.");
- }
- }
- } else {
- // The compilation itself handles calling the error function.
- frameWnd.gwtOnLoad(__gwt_onLoadError, name);
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Globals
-//
-
-var __gwt_retryWaitMillis = 10;
-var __gwt_isHostPageLoaded = false;
-var __gwt_metaProps = {};
-var __gwt_onPropertyError = null;
-var __gwt_onLoadError = null;
-var __gwt_moduleControlBlocks = new ModuleControlBlocks();
-
-//////////////////////////////////////////////////////////////////////////////
-// Common
-//
-
-/**
- * Determines whether or not the page is being loaded in the GWT hosted browser.
- */
-function __gwt_isHosted() {
- if (window.external && window.external.gwtOnLoad) {
- // gwt.hybrid makes the hosted browser pretend not to be
- if (document.location.href.indexOf("gwt.hybrid") == -1) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Tries to get a module control block based on a query string passed in from
- * the caller. Used by iframes to get references back to their mcbs.
- * @param queryString the entire query string as returned by location.search,
- * which notably includes the leading '?' if one is specified
- * @return the relevant module control block, or <code>null</code> if it cannot
- * be derived based on <code>queryString</code>
- */
-function __gwt_tryGetModuleControlBlock(queryString) {
- if (queryString.length > 0) {
- // The pattern is ?[h&]<index>[&<unique>]
- var queryString = queryString.substring(1);
- if (queryString.indexOf("h&") == 0) {
- // Ignore the hosted mode flag here; only GWTShellServlet cares about it.
- queryString = queryString.substring(2);
- }
- var pos = queryString.indexOf("&");
- if (pos >= 0) {
- queryString = queryString.substring(0, pos);
- }
- var mcbIndex = parseInt(queryString);
- if (!isNaN(mcbIndex)) {
- var mcb = __gwt_moduleControlBlocks.get(mcbIndex);
- return mcb;
- }
- // Ignore the unique number that remains on the query string.
- }
- return null;
-}
-
-/**
- * Parses meta tags from the host html.
- *
- * <meta name="gwt:module" content="_module-name_">
- * causes the specified module to be loaded
- *
- * <meta name="gwt:property" content="_name_=_value_">
- * statically defines a deferred binding client property
- *
- * <meta name="gwt:onPropertyErrorFn" content="_fnName_">
- * specifies the name of a function to call if a client property is set to
- * an invalid value (meaning that no matching compilation will be found)
- *
- * <meta name="gwt:onLoadErrorFn" content="_fnName_">
- * specifies the name of a function to call if an exception happens during
- * bootstrapping or if a module throws an exception out of onModuleLoad();
- * the function should take a message parameter
- */
-function __gwt_processMetas() {
- var metas = document.getElementsByTagName("meta");
- for (var i = 0, n = metas.length; i < n; ++i) {
- var meta = metas[i];
- var name = meta.getAttribute("name");
- if (name) {
- if (name == "gwt:module") {
- var moduleName = meta.getAttribute("content");
- if (moduleName) {
- __gwt_moduleControlBlocks.add(meta, moduleName);
- }
- } else if (name == "gwt:property") {
- var content = meta.getAttribute("content");
- if (content) {
- var name = content, value = "";
- var eq = content.indexOf("=");
- if (eq != -1) {
- name = content.substring(0, eq);
- value = content.substring(eq+1);
- }
- __gwt_metaProps[name] = value;
- }
- } else if (name == "gwt:onPropertyErrorFn") {
- var content = meta.getAttribute("content");
- if (content) {
- try {
- __gwt_onPropertyError = eval(content);
- } catch (e) {
- window.alert("Bad handler \"" + content +
- "\" for \"gwt:onPropertyErrorFn\"");
- }
- }
- } else if (name == "gwt:onLoadErrorFn") {
- var content = meta.getAttribute("content");
- if (content) {
- try {
- __gwt_onLoadError = eval(content);
- } catch (e) {
- window.alert("Bad handler \"" + content +
- "\" for \"gwt:onLoadErrorFn\"");
- }
- }
- }
- }
- }
-}
-
-/**
- * Determines the value of a deferred binding client property specified
- * statically in host html.
- */
-function __gwt_getMetaProperty(name) {
- var value = __gwt_metaProps[name];
- if (value) {
- return value;
- } else {
- return null;
- }
-}
-
-/**
- * Determines whether or not a particular property value is allowed.
- * @param wnd the caller's window object (not $wnd!)
- * @param propName the name of the property being checked
- * @param propValue the property value being tested
- */
-function __gwt_isKnownPropertyValue(wnd, propName, propValue) {
- return propValue in wnd["values$" + propName];
-}
-
-/**
- * Called by the selection script when a property has a bad value or is missing.
- * 'allowedValues' is an array of strings. Can be hooked in the host page using
- * gwt:onPropertyErrorFn.
- */
-function __gwt_onBadProperty(moduleName, propName, allowedValues, badValue) {
- if (__gwt_onPropertyError) {
- __gwt_onPropertyError(moduleName, propName, allowedValues, badValue);
- return;
- } else {
- var msg = "While attempting to load module \"" + moduleName + "\", ";
- if (badValue != null) {
- msg += "property \"" + propName + "\" was set to the unexpected value \""
- + badValue + "\"";
- } else {
- msg += "property \"" + propName + "\" was not specified";
- }
-
- msg += "\n\nAllowed values: " + allowedValues;
-
- window.alert(msg);
- }
-}
-
-/**
- * Called directly from compiled code.
- */
-function __gwt_initHandlers(resize, beforeunload, unload) {
- var oldOnResize = window.onresize;
- window.onresize = function() {
- resize();
- if (oldOnResize)
- oldOnResize();
- };
-
- var oldOnBeforeUnload = window.onbeforeunload;
- window.onbeforeunload = function() {
- var ret = beforeunload();
-
- var oldRet;
- if (oldOnBeforeUnload)
- oldRet = oldOnBeforeUnload();
-
- if (ret !== null)
- return ret;
- return oldRet;
- };
-
- var oldOnUnload = window.onunload;
- window.onunload = function() {
- unload();
- if (oldOnUnload)
- oldOnUnload();
- };
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Hosted Mode
-//
-function __gwt_onUnloadHostedMode() {
- window.external.gwtOnLoad(null, null);
- if (__gwt_onUnloadHostedMode.oldUnloadHandler) {
- __gwt_onUnloadHostedMode.oldUnloadHandler();
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Bootstrap
-//
-
-/**
- * Waits until all startup preconditions are satisfied, then launches the
- * user-defined startup code for each module.
- */
-function __gwt_latchAndLaunch() {
- var ready = true;
-
- // Are there any compilations still pending?
- if (ready && !__gwt_moduleControlBlocks.isReady()) {
- // Yes, we're still waiting on one or more compilations.
- ready = false;
- }
-
- // Has the host html onload event fired?
- if (ready && !__gwt_isHostPageLoaded) {
- // No, the host html page hasn't fully loaded.
- ready = false;
- }
-
- // Are we ready to run user code?
- if (ready) {
- // Yes: run entry points.
- __gwt_moduleControlBlocks.run();
- } else {
- // No: try again soon.
- window.setTimeout(__gwt_latchAndLaunch, __gwt_retryWaitMillis);
- }
-}
-
-/**
- * Starts the module-loading sequence after meta tags have been processed and
- * the body element exists.
- */
-function __gwt_loadModules() {
- // Make sure the body element exists before starting.
- if (!document.body) {
- // Try again soon.
- window.setTimeout(__gwt_loadModules, __gwt_retryWaitMillis);
- return;
- }
-
- // Inject a frame for each module.
- __gwt_moduleControlBlocks.injectFrames();
-
- // Try to launch module entry points once everything is ready.
- __gwt_latchAndLaunch();
-}
-
-/**
- * The very first thing to run, and it runs exactly once unconditionally.
- */
-function __gwt_bootstrap() {
- // Hook onunload for hosted mode.
- if (__gwt_isHosted()) {
- __gwt_onUnloadHostedMode.oldUnloadHandler = window.onunload;
- window.onunload = __gwt_onUnloadHostedMode;
- }
-
- // Hook the current window onload handler.
- var oldHandler = window.onload;
- window.onload = function() {
- __gwt_isHostPageLoaded = true;
- if (oldHandler) {
- oldHandler();
- }
- };
-
- // Parse meta tags from host html.
- __gwt_processMetas();
-
- // Load any modules.
- __gwt_loadModules();
-}
-
-// Go.
-__gwt_bootstrap();
+ for (var i = 0, n = metas.length; i < n; ++i) {
+ var meta = metas[i];
+ var name = meta.getAttribute("name");
+ if (name) {
+ if (name == "gwt:module") {
+ var moduleName = meta.getAttribute("content");
+ if (moduleName) {
+ var eqPos = moduleName.lastIndexOf("=");
+ if (eqPos != -1) {
+ var base = moduleName.substring(0, eqPos);
+ moduleName = moduleName.substring(eqPos + 1);
+ window.__gwt_base = { };
+ window.__gwt_base[moduleName] = base;
+ moduleName = base + '/' + moduleName;
+ }
+ document.write('<script src="' + moduleName + '.nocache.js"></script>');
+ }
+ }
+ }
+ }
+})();
diff --git a/user/src/com/google/gwt/i18n/I18N.gwt.xml b/user/src/com/google/gwt/i18n/I18N.gwt.xml
index e6a9971..8d5dd0a 100644
--- a/user/src/com/google/gwt/i18n/I18N.gwt.xml
+++ b/user/src/com/google/gwt/i18n/I18N.gwt.xml
@@ -13,41 +13,42 @@
try {
var locale;
- //Look for the locale as a url argument
- if(locale==null) {
- var args = parent.location.search;
+ // Look for the locale as a url argument
+ if (locale == null) {
+ var args = location.search;
var startLang = args.indexOf("locale");
- if(startLang>=0){
- var language = args.substring(startLang);
- var begin = language.indexOf("=") + 1;
- var end = language.indexOf("&");
- if (end == -1) {
- end = language.length;
- }
- locale = language.substring(begin, end);
+ if (startLang >= 0) {
+ var language = args.substring(startLang);
+ var begin = language.indexOf("=") + 1;
+ var end = language.indexOf("&");
+ if (end == -1) {
+ end = language.length;
+ }
+ locale = language.substring(begin, end);
}
}
- if(locale == null){
- //Look for the locale on the web page
- locale = parent.__gwt_getMetaProperty("locale")
+
+ if (locale == null) {
+ // Look for the locale on the web page
+ locale = __gwt_getMetaProperty("locale")
}
- if(locale == null){
+ if (locale == null) {
return "default";
}
- while(!parent.__gwt_isKnownPropertyValue(window, "locale", locale)){
+ while (!__gwt_isKnownPropertyValue("locale", locale)) {
var lastIndex = locale.lastIndexOf("_");
- if(lastIndex == -1){
+ if (lastIndex == -1) {
locale = "default";
break;
- } else{
+ } else {
locale = locale.substring(0,lastIndex);
}
}
return locale;
} catch(e){
- $wnd.alert("Unexpected exception in locale creator, using default: " + e);
+ alert("Unexpected exception in locale detection, using default: " + e);
return "default";
}
]]>
diff --git a/user/src/com/google/gwt/user/client/Window.java b/user/src/com/google/gwt/user/client/Window.java
index 61cf745..4805015 100644
--- a/user/src/com/google/gwt/user/client/Window.java
+++ b/user/src/com/google/gwt/user/client/Window.java
@@ -74,9 +74,9 @@
}-*/;
/**
- * Use this method to explicitly disable the window's scrollbars.
- * Applications that choose to resize their user-interfaces to fit within the
- * window's client area will normally want to disable window scrolling.
+ * Use this method to explicitly disable the window's scrollbars. Applications
+ * that choose to resize their user-interfaces to fit within the window's
+ * client area will normally want to disable window scrolling.
*
* @param enable <code>false</code> to disable window scrolling
*/
@@ -147,7 +147,7 @@
}
/**
- * Sets the size of the margins used within the window's client area. It is
+ * Sets the size of the margins used within the window's client area. It is
* sometimes necessary to do this because some browsers, such as Internet
* Explorer, add margins by default, which can confound attempts to resize
* panels to fit exactly within the window.
@@ -249,7 +249,8 @@
}
private static native void init() /*-{
- $wnd.__gwt_initHandlers(
+ // Magic function defined by the selection script
+ __gwt_initHandlers(
function() {
@com.google.gwt.user.client.Window::onResize()();
},
diff --git a/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc b/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
index 73c5b4e..2b09787 100644
--- a/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
+++ b/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
@@ -18,11 +18,11 @@
</style>
<!-- -->
- <!-- The module reference below is the link -->
- <!-- between html and your Web Toolkit module -->
+ <!-- This script loads your compiled module. -->
+ <!-- If you add any GWT meta tags, they must -->
+ <!-- be added before this line. -->
<!-- -->
- <meta name='gwt:module' content='@moduleName'>
-
+ <script language='javascript' src='@moduleName.nocache.js'></script>
</head>
<!-- -->
@@ -32,13 +32,6 @@
<!-- -->
<body>
- <!-- -->
- <!-- This script is required bootstrap stuff. -->
- <!-- You can put it in the HEAD, but startup -->
- <!-- is slightly faster if you include it here. -->
- <!-- -->
- <script language="javascript" src="gwt.js"></script>
-
<!-- OPTIONAL: include this if you want history support -->
<iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>