Author: j...@google.com Date: Thu Jul 9 09:30:45 2009 New Revision: 5699 Modified: branches/snapshot-2009.06.16-r5570/dev/core/src/com/google/gwt/core/ext/linker/impl/hosted.html branches/snapshot-2009.06.16-r5570/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js branches/snapshot-2009.06.16-r5570/user/src/com/google/gwt/user/client/impl/HistoryImpl.java branches/snapshot-2009.06.16-r5570/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
Log: Merging /trunk c5691, c5696 into this branch. Modified: branches/snapshot-2009.06.16-r5570/dev/core/src/com/google/gwt/core/ext/linker/impl/hosted.html ============================================================================== --- branches/snapshot-2009.06.16-r5570/dev/core/src/com/google/gwt/core/ext/linker/impl/hosted.html (original) +++ branches/snapshot-2009.06.16-r5570/dev/core/src/com/google/gwt/core/ext/linker/impl/hosted.html Thu Jul 9 09:30:45 2009 @@ -4,21 +4,11 @@ var $doc = $wnd.document; var $moduleName, $moduleBase ,$stats = $wnd.__gwtStatsEvent ? function(a) {return $wnd.__gwtStatsEvent(a);} : null; - -// The module to be loaded can be specified either through the url query -// parameter (as done by the legacy HostedModeTemplate.js), or by specifying -// window.name (as done by IFrameTemplate.js). When the former approach -// is removed, we can drop the window.location.search part of this logic. -var moduleFuncName = window.location.search.substring(1); -if (!moduleFuncName || !$wnd[moduleFuncName]) { - moduleFuncName = window.name; -} - -var moduleFunc = $wnd[moduleFuncName]; -var moduleName = moduleFunc ? moduleFunc.moduleName : "unknown"; - // Lightweight metrics if ($stats) { + var moduleFuncName = location.search.substr(1); + var moduleFunc = $wnd[moduleFuncName]; + var moduleName = moduleFunc ? moduleFunc.moduleName : "unknown"; $stats({moduleName:moduleName,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalStart'}); } @@ -248,8 +238,13 @@ } else { $hosted = query.substring(idx + 11); } + + // According to RFC 3986, some of this component's characters (e.g., ':') + // are reserved and *may* be escaped. + $hosted = decodeURIComponent($hosted); } } -setTimeout($wnd[moduleFuncName].onScriptLoad, 1); +query = window.location.search.substring(1); +if (query && $wnd[query]) setTimeout($wnd[query].onScriptLoad, 1); --></script></body></html> Modified: branches/snapshot-2009.06.16-r5570/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js ============================================================================== --- branches/snapshot-2009.06.16-r5570/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js (original) +++ branches/snapshot-2009.06.16-r5570/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js Thu Jul 9 09:30:45 2009 @@ -23,7 +23,7 @@ ,$stats = $wnd.__gwtStatsEvent ? function(a) {return $wnd.__gwtStatsEvent(a);} : null // These variables gate calling gwtOnLoad; all must be true to start - ,injectedScriptsDone, gwtCodeEvaluated, bodyDone, scriptRequestCompleted, gwtFrameCreated + ,scriptsDone, loadDone, bodyDone // If non-empty, an alternate base url for this module ,base = '' @@ -41,16 +41,9 @@ // the strong name of the cache.js file to load. ,answers = [] - // Error functions. Default unset in compiled mode, may be set by meta props + // Error functions. Default unset in compiled mode, may be set by meta props. ,onLoadErrorFunc, propertyErrorFunc - // The frame that will contain the compiled script (created in - // maybeCreateGwtFrame()) - ,scriptFrame - - // Holds the compiled script retreived via XHR until the body is loaded - ,compiledScript = "" - ; // end of global vars $stats && $stats({ @@ -86,16 +79,13 @@ return result; } - // Called by onScriptLoad(), onScriptInjectionDone(), maybeCreateGwtFrame(), - // and onBodyDone(). It causes the specified module to be cranked up. + // Called by onScriptLoad(), onInjectionDone(), and onload(). It causes + // the specified module to be cranked up. // - var moduleStarted = false; function maybeStartModule() { - if (bodyDone && injectedScriptsDone && gwtCodeEvaluated && gwtFrameCreated && !moduleStarted) { - moduleStarted = true; - - var frameWnd = scriptFrame.contentWindow; - + if (scriptsDone && loadDone) { + var iframe = $doc.getElementById('__MODULE_NAME__'); + var frameWnd = iframe.contentWindow; // inject hosted mode property evaluation function if (isHostedMode()) { frameWnd.__gwt_getProperty = function(name) { @@ -284,83 +274,32 @@ throw null; } - // Creates a new XMLHttpRequest object. Used by fetchCompiledScript(). - // - function newXhr() { - // This is the same logic as in GWT's XMLHttpRequest wrapper. The 'else' - // case is needed primarily for old IEs. - if (window.XMLHttpRequest) { - return new XMLHttpRequest(); - } else { - try { - return new ActiveXObject('MSXML2.XMLHTTP.3.0'); - } catch (e) { - return new ActiveXObject("Microsoft.XMLHTTP"); - } - } - } - - // Fetches the compiled script via XHR, saving it to 'compiledScript' - // to be added to the page later. - // - function fetchCompiledScript() { - $stats && $stats({ - moduleName:'__MODULE_NAME__', - subSystem:'startup', - evtGroup: 'moduleStartup', - millis:(new Date()).getTime(), - type: 'moduleRequested' - }); - - // Fetch the contents via XHR. - var xhr = newXhr(); - xhr.open('GET', base + initialHtml); - xhr.onreadystatechange = function() { - // 4 == DONE - if (xhr.readyState == 4) { - compiledScript = xhr.responseText; - xhr = null; - scriptRequestCompleted = true; - maybeCreateGwtFrame(); - } - }; - xhr.send(null); - } - - // This is gated by bodyDone because we can't add elements to the - // page until the body is ready. It's also gated by 'scriptRequestCompleted' - // so it will not fire until the XHR returns, in case onBodyDone happens - // first. - function maybeCreateGwtFrame() { - if (bodyDone && scriptRequestCompleted && !gwtFrameCreated) { - // Create the script frame, making sure it's invisible, but not - // "display:none", which keeps some browsers from running code in it. - scriptFrame = document.createElement('iframe'); - scriptFrame.src = 'javascript:""'; - scriptFrame.id = '__MODULE_NAME__'; - scriptFrame.style.cssText = 'position:absolute; width:0; height:0; border:none'; - scriptFrame.tabIndex = -1; - document.body.appendChild(scriptFrame); - - // Expose the module function via the iframe's window.name property - // (this is needed for the compiled script to call back into - // onScriptLoad()). - var win = scriptFrame.contentWindow; - if (isHostedMode()) { - win.name = '__MODULE_FUNC__'; - } - - // Set this *before* calling doc.write(), because the linux hosted-mode - // browser sometimes doesn't properly return from doc.write() if there are - // a large number of script blocks (even though it works fine). Go figure. - gwtFrameCreated = true; - - // Inject the fetched script into the script frame. - // (this script will call onScriptLoad()) - var doc = win.document; - doc.open(); - doc.write(compiledScript); - doc.close(); + var frameInjected; + function maybeInjectFrame() { + if (!frameInjected) { + frameInjected = true; + var iframe = $doc.createElement('iframe'); + // Prevents mixed mode security in IE6/7. + iframe.src = "javascript:''"; + iframe.id = "__MODULE_NAME__"; + iframe.style.cssText = "position:absolute;width:0;height:0;border:none"; + iframe.tabIndex = -1; + // Due to an IE6/7 refresh quirk, this must be an appendChild. + $doc.body.appendChild(iframe); + + /* + * The src has to be set after the iframe is attached to the DOM to avoid + * refresh quirks in Safari. We have to use the location.replace trick to + * avoid FF2 refresh quirks. + */ + $stats && $stats({ + moduleName:'__MODULE_NAME__', + subSystem:'startup', + evtGroup: 'moduleStartup', + millis:(new Date()).getTime(), + type: 'moduleRequested' + }); + iframe.contentWindow.location.replace(base + initialHtml); } } @@ -374,17 +313,21 @@ // 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. - gwtCodeEvaluated = true; - maybeStartModule(); + // IE7 bookmark bug. A phantom (presumably cached) version of our compiled iframe + // can call onScriptLoad before we even properly inject the iframe. So if this is + // called before the frame was injected ... it is completely bogus. + if (frameInjected) { + // Mark this module's script as done loading and (possibly) start the module. + loadDone = true; + maybeStartModule(); + } } // Called when the script injection is complete. // - __MODULE_FUNC__.onScriptInjectionDone = function() { + __MODULE_FUNC__.onInjectionDone = function() { // Mark this module's script injection done and (possibly) start the module. - injectedScriptsDone = true; + scriptsDone = true; $stats && $stats({ moduleName:'__MODULE_NAME__', subSystem:'startup', @@ -408,14 +351,13 @@ $wnd.location.reload(); return; } - - initialHtml = "hosted.html"; + initialHtml = "hosted.html?__MODULE_FUNC__"; strongName = ""; } processMetas(); - // ------- SELECT PERMUTATION AND FETCH SCRIPT ------- + // --------------- WINDOW ONLOAD HOOK --------------- $stats && $stats({ moduleName:'__MODULE_NAME__', @@ -437,16 +379,10 @@ } } - // Start the request for the compiled script. - fetchCompiledScript(); - - // --------------- WINDOW ONLOAD HOOK --------------- - var onBodyDoneTimerId; function onBodyDone() { if (!bodyDone) { bodyDone = true; - maybeCreateGwtFrame(); // __MODULE_STYLES_BEGIN__ // Style resources are injected here to prevent operation aborted errors on ie // __MODULE_STYLES_END__ @@ -464,6 +400,7 @@ // For everyone that supports DOMContentLoaded. if ($doc.addEventListener) { $doc.addEventListener("DOMContentLoaded", function() { + maybeInjectFrame(); onBodyDone(); }, false); } @@ -471,6 +408,7 @@ // Fallback. If onBodyDone() gets fired twice, it's not a big deal. var onBodyDoneTimerId = setInterval(function() { if (/loaded|complete/.test($doc.readyState)) { + maybeInjectFrame(); onBodyDone(); } }, 50); @@ -498,7 +436,7 @@ // The 'defer' attribute here is a workaround for strange IE behavior where // <script> tags that are doc.writ()en execute *immediately*, rather than // in document-order, as they should. It has no effect on other browsers. - $doc.write('<script defer="defer">__MODULE_FUNC__.onScriptInjectionDone(\'__MODULE_NAME__\')</script>'); + $doc.write('<script defer="defer">__MODULE_FUNC__.onInjectionDone(\'__MODULE_NAME__\')</script>'); } __MODULE_FUNC__(); Modified: branches/snapshot-2009.06.16-r5570/user/src/com/google/gwt/user/client/impl/HistoryImpl.java ============================================================================== --- branches/snapshot-2009.06.16-r5570/user/src/com/google/gwt/user/client/impl/HistoryImpl.java (original) +++ branches/snapshot-2009.06.16-r5570/user/src/com/google/gwt/user/client/impl/HistoryImpl.java Thu Jul 9 09:30:45 2009 @@ -38,16 +38,17 @@ public class HistoryImpl implements HasValueChangeHandlers<String>, HasHandlers { - static boolean updateHashOnIE6 = true; - /** * Sets whether the IE6 history implementation will update the URL hash when * creating a new item. This should be used only for applications with large * DOM structures that are suffering from performance problems when creating * a new history item on IE6 and 7. + * + * @deprecated This is no longer necessary, as the underlying performance + * problem has been solved. It is now a no-op. */ + @Deprecated public static void setUpdateHashOnIE6(boolean updateHash) { - HistoryImpl.updateHashOnIE6 = updateHash; } public static native String getToken() /*-{ Modified: branches/snapshot-2009.06.16-r5570/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java ============================================================================== --- branches/snapshot-2009.06.16-r5570/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java (original) +++ branches/snapshot-2009.06.16-r5570/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java Thu Jul 9 09:30:45 2009 @@ -199,13 +199,7 @@ Location.reload(); } - private void updateHash(String token) { - if (HistoryImpl.updateHashOnIE6) { - updateHashInternal(token); - } - } - - private native void updateHashInternal(String token) /*-{ + private native void updateHash(String token) /*-{ $wnd.location.hash = th...@com.google.gwt.user.client.impl.historyimpl::encodeFragment(Ljava/lang/String;)(token); }-*/; } --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---