Revision: 9158
Author: [email protected]
Date: Wed Oct 27 16:44:21 2010
Log: Fix some issues in the xsiframe linker
- Add support for including <stylesheet> tags
- Fix a bug in computeScriptBase.js
Review at http://gwt-code-reviews.appspot.com/1057801
Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=9158
Added:
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/loadExternalStylesheets.js
Modified:
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/ResourceInjectionUtil.java
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/computeScriptBase.js
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptAlreadyIncluded.js
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptDirect.js
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptNull.js
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/waitForBodyLoaded.js
/trunk/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeLinker.java
/trunk/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeTemplate.js
=======================================
--- /dev/null
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/loadExternalStylesheets.js
Wed Oct 27 16:44:21 2010
@@ -0,0 +1,24 @@
+function loadExternalStylesheets() {
+ // Setup for loading of external stylesheets. 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 = {}; }
+
+ function installOneStylesheet(stylesheetUrl, hrefExpr) {
+ if (!__gwt_stylesLoaded[stylesheetUrl]) {
+ if (isBodyLoaded()) {
+ var l = $doc.createElement('link');
+ l.setAttribute('rel', 'stylesheet');
+ l.setAttribute('href', hrefExpr);
+ $doc.getElementsByTagName('head')[0].appendChild(l);
+ } else {
+ $doc.write("<link id='' rel='stylesheet' href='" + hrefExpr
+ "'></li" + "nk>");
+ }
+ __gwt_stylesLoaded[stylesheetUrl] = true;
+ }
+ }
+
+ sendStats('loadExternalRefs', 'begin');
+ // __MODULE_STYLES__
+ sendStats('loadExternalRefs', 'end');
+}
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/ResourceInjectionUtil.java
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/ResourceInjectionUtil.java
Wed Oct 27 16:44:21 2010
@@ -27,6 +27,9 @@
* Utility class to help linkers do resource injection.
*/
public class ResourceInjectionUtil {
+ /**
+ * Installs stylesheets and scripts
+ */
public static StringBuffer injectResources(StringBuffer selectionScript,
ArtifactSet artifacts) {
// Add external dependencies
@@ -49,6 +52,40 @@
}
return selectionScript;
}
+
+ /**
+ * Installs stylesheets using the installOneStylesheet method, which is
+ * assumed to be defined on the page.
+ */
+ public static StringBuffer injectStylesheets(StringBuffer
selectionScript,
+ ArtifactSet artifacts) {
+ int startPos = selectionScript.indexOf("// __MODULE_STYLES__");
+ if (startPos != -1) {
+ for (StylesheetReference resource :
artifacts.find(StylesheetReference.class)) {
+ String text = generateNewStylesheetInjector(resource.getSrc());
+ selectionScript.insert(startPos, text);
+ startPos += text.length();
+ }
+ }
+ return selectionScript;
+ }
+
+ /**
+ * Generate a Snippet of JavaScript to inject an external stylesheet
using
+ * the installOneStylesheet helper function (which is assumed to already
+ * be defined on the page.
+ *
+ * <pre>
+ * installOneStylesheet(URL, HREF_EXPR);
+ * </pre>
+ */
+ private static String generateNewStylesheetInjector(String
stylesheetUrl) {
+ String hrefExpr = "'" + stylesheetUrl + "'";
+ if (isRelativeURL(stylesheetUrl)) {
+ hrefExpr = "__MODULE_FUNC__.__moduleBase + " + hrefExpr;
+ }
+ return "installOneStylesheet('" + stylesheetUrl + "', " + hrefExpr
+ ");\n";
+ }
private static String generateScriptInjector(String scriptUrl) {
if (isRelativeURL(scriptUrl)) {
@@ -67,7 +104,7 @@
+ scriptUrl + "\\\"></script>');\n" + " }\n";
}
}
-
+
/**
* Generate a Snippet of JavaScript to inject an external stylesheet.
*
@@ -95,7 +132,7 @@
+ "
$doc.getElementsByTagName('head')[0].appendChild(l);\n "
+ "}\n";
}
-
+
/**
* Determines whether or not the URL is relative.
*
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/computeScriptBase.js
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/computeScriptBase.js
Wed Oct 27 13:37:45 2010
@@ -15,11 +15,13 @@
*/
/**
- * Determine our own script's URL via magic :)
- * This function produces one side-effect, it sets base to the module's
- * base url. Note: although this script returns the module's base url, it
- * also sets the global 'base' variable for backwards compatability with
older
- * linkers.
+ * Determine our own script's URL by trying various things
+ *
+ * First - use the baseUrl meta tag if it exists
+ * Second - look for a script tag with the src set to
MODULE_NAME.nocache.js and
+ * if it's found, use it to determine the baseUrl
+ * Third - if the page is not already loaded, try to use some
document.write
+ * magic to install a temporary tag and use that to determine the
baseUrl.
*
* This is included into the selection scripts
* wherever COMPUTE_SCRIPT_BASE appears with underlines
@@ -32,10 +34,15 @@
// Note: the base variable should not be defined in this function
because in
// the older templates (like IFrameTemplate.js), base is defined outside
this
// function, and they rely on the fact that calling computeScriptBase
will set
- // that base variable rather than using the return value.
+ // that base variable rather than using the return value. Instead, we
define
+ // a tempBase variable, and then right before we return, we also set the
+ // base variable for backwards compatability
+ var tempBase = '';
+
if (metaVal != null) {
- base = metaVal;
- return base;
+ tempBase = metaVal;
+ base = tempBase;
+ return tempBase;
}
// The baseUrl will be similar to the URL for this script's URL
@@ -54,16 +61,18 @@
// it. Note that this will not work in the Late Loading case due to the
// document.write call.
if (!thisScript) {
- // Put in a marker script element which should be the first script tag
after
- // the tag we're looking for. To find it, we start at the marker and
walk
- // backwards until we find a script.
- var markerId = "__gwt_marker___MODULE_NAME__";
- var markerScript;
- $doc.write('<script id="' + markerId + '"></script>');
- markerScript = $doc.getElementById(markerId);
- thisScript = markerScript && markerScript.previousSibling;
- while (thisScript && thisScript.tagName != 'SCRIPT') {
- thisScript = thisScript.previousSibling;
+ if (typeof isBodyLoaded == 'undefined' || !isBodyLoaded()) {
+ // Put in a marker script element which should be the first script
tag after
+ // the tag we're looking for. To find it, we start at the marker and
walk
+ // backwards until we find a script.
+ var markerId = "__gwt_marker___MODULE_NAME__";
+ var markerScript;
+ $doc.write('<script id="' + markerId + '"></script>');
+ markerScript = $doc.getElementById(markerId);
+ thisScript = markerScript && markerScript.previousSibling;
+ while (thisScript && thisScript.tagName != 'SCRIPT') {
+ thisScript = thisScript.previousSibling;
+ }
}
}
@@ -84,21 +93,21 @@
if (thisScript && thisScript.src) {
// Compute our base url
- base = getDirectoryOfFile(thisScript.src);
+ tempBase = getDirectoryOfFile(thisScript.src);
}
// Make the base URL absolute
- if (base == '') {
+ if (tempBase == '') {
// If there's a base tag, use it.
var baseElements = $doc.getElementsByTagName('base');
if (baseElements.length > 0) {
// It's always the last parsed base tag that will apply to this
script.
- base = baseElements[baseElements.length - 1].href;
+ tempBase = baseElements[baseElements.length - 1].href;
} else {
// No base tag; the base must be the same as the document location.
- base = getDirectoryOfFile($doc.location.href);
- }
- } else if ((base.match(/^\w+:\/\//))) {
+ tempBase = getDirectoryOfFile($doc.location.href);
+ }
+ } else if ((tempBase.match(/^\w+:\/\//))) {
// If the URL is obviously absolute, do nothing.
} else {
// Probably a relative URL; use magic to make the browser absolutify
it.
@@ -106,8 +115,8 @@
// sure way! (A side benefit is it preloads clear.cache.gif)
// Note: this trick is harmless if the URL was really already absolute.
var img = $doc.createElement("img");
- img.src = base + 'clear.cache.gif';
- base = getDirectoryOfFile(img.src);
+ img.src = tempBase + 'clear.cache.gif';
+ tempBase = getDirectoryOfFile(img.src);
}
if (markerScript) {
@@ -115,5 +124,6 @@
markerScript.parentNode.removeChild(markerScript);
}
- return base;
-}
+ base = tempBase;
+ return tempBase;
+}
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptAlreadyIncluded.js
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptAlreadyIncluded.js
Wed Oct 27 13:37:45 2010
@@ -1,8 +1,13 @@
+// Installs a script which has already been downloaded (usually because the
+// script contents are combined with the bootstrap script in cases like
SSSS).
+// Since the script contents are wrapped in a call to onScriptDownloaded,
all
+// we do here is set up that function, which will install the contents in
+// a script tag appended to the install location.
function installScript(filename) {
// Provides the getInstallLocation() and getInstallLocationDoc()
functions
__INSTALL_LOCATION__
- // Provides the setupWaitForBodyLoad() and isBodyLoaded() functions
+ // Provides the setupWaitForBodyLoad() function
__WAIT_FOR_BODY_LOADED__
function installCode(code) {
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptDirect.js
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptDirect.js
Wed Oct 27 13:37:45 2010
@@ -1,8 +1,10 @@
+// Installs the script directly, by simply appending a script tag with the
+// src set to the correct location to the install location.
function installScript(filename) {
// Provides the getInstallLocation() and getInstallLocationDoc()
functions
__INSTALL_LOCATION__
- // Provides the setupWaitForBodyLoad() and isBodyLoaded() functions
+ // Provides the setupWaitForBodyLoad()function
__WAIT_FOR_BODY_LOADED__
function installCode(code) {
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js
Wed Oct 27 13:37:45 2010
@@ -1,8 +1,12 @@
+// Installs the script by immediately appending a script tag to the body
head
+// with the src set, to get the script contents. The script contents are
then
+// installed into a script tag which is added to the install location
(because
+// the script contents will be wrapped in a call to onScriptDownloaded()).
function installScript(filename) {
// Provides the getInstallLocation() and getInstallLocationDoc()
functions
__INSTALL_LOCATION__
- // Provides the setupWaitForBodyLoad() and isBodyLoaded() functions
+ // Provides the setupWaitForBodyLoad() function
__WAIT_FOR_BODY_LOADED__
function installCode(code) {
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptNull.js
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/installScriptNull.js
Wed Oct 27 13:37:45 2010
@@ -1,3 +1,5 @@
+// Assumes that the script contents are directly part of the bootstrap
script
+// and do not need to be installed anywhere.
function installScript(filename) {
// Does nothing
}
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/waitForBodyLoaded.js
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/waitForBodyLoaded.js
Wed Oct 27 13:37:45 2010
@@ -1,8 +1,3 @@
-// Check whether the body is loaded.
-function isBodyLoaded() {
- return (/loaded|complete/.test($doc.readyState));
-}
-
// Setup code which waits for the body to be loaded and then calls the
// callback function
function setupWaitForBodyLoad(callback) {
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeLinker.java
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeLinker.java
Wed Oct 27 13:37:45 2010
@@ -25,6 +25,7 @@
import com.google.gwt.core.ext.linker.LinkerOrder.Order;
import com.google.gwt.core.ext.linker.Shardable;
import com.google.gwt.core.ext.linker.impl.PropertiesMappingArtifact;
+import com.google.gwt.core.ext.linker.impl.ResourceInjectionUtil;
import com.google.gwt.core.ext.linker.impl.SelectionScriptLinker;
import com.google.gwt.dev.About;
import com.google.gwt.dev.js.JsToStringGenerationVisitor;
@@ -65,13 +66,15 @@
includeJs(ss, logger, getJsProperties(context), "__PROPERTIES__");
includeJs(ss, logger, getJsProcessMetas(context), "__PROCESS_METAS__");
includeJs(ss, logger,
getJsComputeScriptBase(context), "__COMPUTE_SCRIPT_BASE__");
-
+ includeJs(ss, logger,
getJsLoadExternalStylesheets(context), "__LOAD_STYLESHEETS__");
+
+ ss = ResourceInjectionUtil.injectStylesheets(ss, artifacts);
+ ss = permutationsUtil.addPermutationsJs(ss, logger, context);
+
replaceAll(ss, "__MODULE_FUNC__", context.getModuleFunctionName());
replaceAll(ss, "__MODULE_NAME__", context.getModuleName());
replaceAll(ss, "__HOSTED_FILENAME__", getHostedFilename());
- permutationsUtil.addPermutationsJs(ss, logger, context);
-
return ss.toString();
}
@@ -99,6 +102,10 @@
protected String getJsInstallScript(LinkerContext context) {
return "com/google/gwt/core/ext/linker/impl/installScriptEarlyDownload.js";
}
+
+ protected String getJsLoadExternalStylesheets(LinkerContext context) {
+
return "com/google/gwt/core/ext/linker/impl/loadExternalStylesheets.js";
+ }
protected String getJsPermutations(LinkerContext context) {
return "com/google/gwt/core/ext/linker/impl/permutations.js";
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeTemplate.js
Tue Oct 12 16:00:43 2010
+++
/trunk/dev/core/src/com/google/gwt/core/linker/CrossSiteIframeTemplate.js
Wed Oct 27 13:37:45 2010
@@ -22,6 +22,10 @@
* Internal Helper Functions
***************************************************************************/
+ function isBodyLoaded() {
+ return (/loaded|complete/.test($doc.readyState));
+ }
+
function isHostedMode() {
var query = $wnd.location.search;
return (query.indexOf('gwt.codesvr=') != -1);
@@ -90,6 +94,8 @@
// __MODULE_FUNC__.__softPermutationId variables if needed
__PERMUTATIONS__
+ // Provides the loadExternalStylesheets() function
+ __LOAD_STYLESHEETS__
/****************************************************************************
* Bootstrap startup code
@@ -103,11 +109,9 @@
// Must be done right before the "bootstrap" "end" stat is sent
var filename = getCompiledCodeFilename();
+ loadExternalStylesheets();
+
sendStats('bootstrap', 'end');
- // For now, send this dummy statistic since some people are depending on
it
- // being present. TODO(unnurg): remove this statistic soon
- sendStats('loadExternalRefs', 'begin');
- sendStats('loadExternalRefs', 'end');
installScript(filename);
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors