Merge mozilla-central into mozilla-inbound
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 15 Jan 2013 09:10:19 -0500
changeset 118889 a319e28420a311e58e71b88fc21e1109e8d87ba3
parent 118888 762779b020dbb807fdb31ea74d75be4beebbd3cb (current diff)
parent 118768 b695e94363b5600ead241172c7d2a1a1f36c9e47 (diff)
child 118890 0348a30c19b4b7d2921819f87d466309b08df57a
push id24180
push useremorley@mozilla.com
push dateTue, 15 Jan 2013 22:58:27 +0000
treeherdermozilla-central@72e34ce7fd92 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central into mozilla-inbound
docshell/base/nsDocShell.cpp
docshell/test/browser/browser_bug808035.js
docshell/test/chrome/bug754029_window.xul
docshell/test/chrome/test_bug754029.xul
docshell/test/navigation/file_bug754029.html
dom/base/nsJSEnvironment.cpp
--- a/browser/base/content/test/browser_tab_dragdrop.js
+++ b/browser/base/content/test/browser_tab_dragdrop.js
@@ -9,17 +9,17 @@ function test()
     gBrowser.tabs[0],
     gBrowser.addTab("about:blank", {skipAnimation: true}),
     gBrowser.addTab("about:blank", {skipAnimation: true}),
     gBrowser.addTab("about:blank", {skipAnimation: true}),
     gBrowser.addTab("about:blank", {skipAnimation: true})
   ];
 
   function setLocation(i, url) {
-    gBrowser.getBrowserForTab(tabs[i]).contentWindow.location.assign(url);
+    gBrowser.getBrowserForTab(tabs[i]).contentWindow.location = url;
   }
   function moveTabTo(a, b) {
     gBrowser.swapBrowsersAndCloseOther(gBrowser.tabs[b], gBrowser.tabs[a]);
   }
   function clickTest(doc, win) {
     var clicks = doc.defaultView.clicks;
     EventUtils.synthesizeMouseAtCenter(doc.body, {}, win);
     is(doc.defaultView.clicks, clicks+1, "adding 1 more click on BODY");
--- a/browser/base/content/test/browser_tabfocus.js
+++ b/browser/base/content/test/browser_tabfocus.js
@@ -161,23 +161,23 @@ function test() {
 
     window.removeEventListener("focus", _browser_tabfocus_test_eventOccured, true);
     window.removeEventListener("blur", _browser_tabfocus_test_eventOccured, true);
 
     // next, check whether navigating forward, focusing the urlbar and then
     // navigating back maintains the focus in the urlbar.
     browser1.addEventListener("pageshow", _browser_tabfocus_navigation_test_eventOccured, true);
     button1.focus();
-    browser1.contentWindow.location.assign(testPage3);
+    browser1.contentWindow.location = testPage3;
   }
 
   browser1.addEventListener("load", check, true);
   browser2.addEventListener("load", check, true);
-  browser1.contentWindow.location.assign(testPage1);
-  browser2.contentWindow.location.assign(testPage2);
+  browser1.contentWindow.location = testPage1;
+  browser2.contentWindow.location = testPage2;
 }
 
 var _browser_tabfocus_test_lastfocus;
 var _browser_tabfocus_test_lastfocuswindow = null;
 var _browser_tabfocus_test_events = "";
 
 function _browser_tabfocus_test_eventOccured(event)
 {
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -3051,19 +3051,17 @@ let SessionStoreInternal = {
 
       // Make sure that set/getTabValue will set/read the correct data by
       // wiping out any current value in tab.__SS_extdata.
       delete tab.__SS_extdata;
 
       if (!tabData.entries || tabData.entries.length == 0) {
         // make sure to blank out this tab's content
         // (just purging the tab's history won't be enough)
-        browser.loadURIWithFlags("about:blank",
-                                 Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY,
-                                 null, null, null);
+        browser.contentDocument.location = "about:blank";
         continue;
       }
 
       browser.stop(); // in case about:blank isn't done yet
 
       // wall-paper fix for bug 439675: make sure that the URL to be loaded
       // is always visible in the address bar
       let activeIndex = (tabData.index || tabData.entries.length) - 1;
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -838,16 +838,19 @@ nsScriptLoader::EvaluateScript(nsScriptL
   // Make sure context is a strong reference since we access it after
   // we've executed a script, which may cause all other references to
   // the context to go away.
   nsCOMPtr<nsIScriptContext> context = globalObject->GetScriptContext();
   if (!context) {
     return NS_ERROR_FAILURE;
   }
 
+  bool oldProcessingScriptTag = context->GetProcessingScriptTag();
+  context->SetProcessingScriptTag(true);
+
   // Update our current script.
   nsCOMPtr<nsIScriptElement> oldCurrent = mCurrentScript;
   mCurrentScript = aRequest->mElement;
 
   // It's very important to use aRequest->mURI, not the final URI of the channel
   // aRequest ended up getting script data from, as the script filename.
   nsAutoCString url;
   nsContentUtils::GetWrapperSafeScriptFilename(mDocument, aRequest->mURI, url);
@@ -858,16 +861,20 @@ nsScriptLoader::EvaluateScript(nsScriptL
                                aRequest->mOriginPrincipal,
                                url.get(), aRequest->mLineNo,
                                JSVersion(aRequest->mJSVersion), nullptr,
                                &isUndefined);
 
   // Put the old script back in case it wants to do anything else.
   mCurrentScript = oldCurrent;
 
+  JSContext *cx = nullptr; // Initialize this to keep GCC happy.
+  cx = context->GetNativeContext();
+  JSAutoRequest ar(cx);
+  context->SetProcessingScriptTag(oldProcessingScriptTag);
   return rv;
 }
 
 void
 nsScriptLoader::ProcessPendingRequestsAsync()
 {
   if (mParserBlockingRequest || !mPendingChildLoaders.IsEmpty()) {
     nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this,
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1410,16 +1410,26 @@ nsDocShell::LoadURI(nsIURI * aURI,
                     if (parentBusy & BUSY_FLAGS_BUSY ||
                         selfBusy & BUSY_FLAGS_BUSY) {
                         loadType = LOAD_NORMAL_REPLACE;
                         shEntry = nullptr; 
                     }
                 }
             } // parent
         } //parentDS
+        else {  
+            // This is the root docshell. If we got here while  
+            // executing an onLoad Handler,this load will not go 
+            // into session history.
+            bool inOnLoadHandler=false;
+            GetIsExecutingOnLoadHandler(&inOnLoadHandler);
+            if (inOnLoadHandler) {
+                loadType = LOAD_NORMAL_REPLACE;
+            }
+        } 
     } // !shEntry
 
     if (shEntry) {
 #ifdef DEBUG
         PR_LOG(gDocShellLog, PR_LOG_DEBUG,
               ("nsDocShell[%p]: loading from session history", this));
 #endif
 
@@ -6515,17 +6525,17 @@ nsDocShell::EndPageLoad(nsIWebProgress *
     //
     // one of many safeguards that prevent death and destruction if
     // someone is so very very rude as to bring this window down
     // during this load handler.
     //
     nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
 
     // Notify the ContentViewer that the Document has finished loading.  This
-    // will cause any OnLoad(...) handlers to fire.
+    // will cause any OnLoad(...) and PopState(...) handlers to fire.
     if (!mEODForCurrentDocument && mContentViewer) {
         mIsExecutingOnLoadHandler = true;
         mContentViewer->LoadComplete(aStatus);
         mIsExecutingOnLoadHandler = false;
 
         mEODForCurrentDocument = true;
 
         // If all documents have completed their loading
@@ -10488,34 +10498,32 @@ nsDocShell::AddToSessionHistory(nsIURI *
         if (aCloneChildren && mOSHE) {
             uint32_t cloneID;
             mOSHE->GetID(&cloneID);
             nsCOMPtr<nsISHEntry> newEntry;
             CloneAndReplace(mOSHE, this, cloneID, entry, true, getter_AddRefs(newEntry));
             NS_ASSERTION(entry == newEntry, "The new session history should be in the new entry");
         }
 
-        int32_t index = 0;   
-        mSessionHistory->GetIndex(&index);
-
         // This is the root docshell
-        if (-1 != index &&
-            LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {            
+        if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {            
             // Replace current entry in session history.
+            int32_t  index = 0;   
+            mSessionHistory->GetIndex(&index);
             nsCOMPtr<nsISHistoryInternal>   shPrivate(do_QueryInterface(mSessionHistory));
             // Replace the current entry with the new entry
             if (shPrivate)
                 rv = shPrivate->ReplaceEntry(index, entry);          
         }
         else {
             // Add to session history
             nsCOMPtr<nsISHistoryInternal>
                 shPrivate(do_QueryInterface(mSessionHistory));
             NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
-            mPreviousTransIndex = index;
+            mSessionHistory->GetIndex(&mPreviousTransIndex);
             rv = shPrivate->AddEntry(entry, shouldPersist);
             mSessionHistory->GetIndex(&mLoadedTransIndex);
 #ifdef DEBUG_PAGE_CACHE
             printf("Previous index: %d, Loaded index: %d\n\n",
                    mPreviousTransIndex, mLoadedTransIndex);
 #endif
         }
     }
--- a/docshell/test/browser/Makefile.in
+++ b/docshell/test/browser/Makefile.in
@@ -27,12 +27,11 @@ MOCHITEST_BROWSER_FILES =	\
 		browser_bug554155.js \
 		browser_bug655273.js \
 		browser_bug655270.js \
 		file_bug655270.html \
 		favicon_bug655270.ico \
 		browser_bug670318.js \
 		file_bug670318.html \
 		browser_bug673467.js \
-		browser_bug808035.js \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/docshell/test/browser/browser_bug808035.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Test for bug 808035.
-// When we open a new tab, the initial URI is the transient <about:blank> and 
-// then requested URI would be loaded. When the URI's shceme is "javascript:",
-// we can *replace* the transient <about:blank> with an actual requet
-// through <javascript:location.replace("http://example.org/")>.
-//
-// There's no session history entry corresponding to the transient
-// <about:blank>. But we should make sure there exists a session history entry
-// for <http://example.org>.
-
-function test() {
-  const NEW_URI = "http://test1.example.org/";
-  const REQUESTED_URI = "javascript:void(location.replace('" + NEW_URI +
-                        "'))";
-
-  waitForExplicitFinish();
-
-  let tab = gBrowser.addTab(REQUESTED_URI);
-  let browser = tab.linkedBrowser;
-
-  browser.addEventListener('load', function(aEvent) {
-    browser.removeEventListener('load', arguments.callee, true);
-
-    is(browser.contentWindow.location.href, NEW_URI, "The URI is OK.");
-    is(browser.contentWindow.history.length, 1, "There exists a SH entry.");
-
-    gBrowser.removeTab(tab);
-    finish();
-  }, true);
-}
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -89,18 +89,16 @@ MOCHITEST_CHROME_FILES =	\
 		test_bug690056.xul \
 		bug690056_window.xul \
 		test_bug311007.xul \
 		bug311007_window.xul \
 		test_principalInherit.xul \
 		test_mozFrameType.xul \
 		mozFrameType_window.xul \
 		test_bug789773.xul \
-		test_bug754029.xul \
-		bug754029_window.xul \
     docshell_helpers.js \
     generic.html \
     $(NULL)
 
 ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 MOCHITEST_CHROME_FILES += \
 		test_bug454235.xul \
 		$(NULL)
--- a/docshell/test/chrome/bug311007_window.xul
+++ b/docshell/test/chrome/bug311007_window.xul
@@ -104,17 +104,17 @@ function step1B(aWebProgress, aRequest, 
 }
 
 /******************************************************************************
  * Step 2: Load a HTTPS page, and confirm it's secure. 
  ******************************************************************************/
 
 function step2A() {
   gListener.callback = step2B;
-  content.location.assign(kSecureURI);
+  content.location = kSecureURI;
 }
 
 function step2B(aWebProgress, aRequest, aLocation, aFlags) {
   is(aLocation.spec, kSecureURI, "A URI on HTTPS (2)");
 
   ok(!(aFlags & Components.interfaces.nsIWebProgressListener
                           .LOCATION_CHANGE_SAME_DOCUMENT),
      "DocShell loaded a document (2)");
@@ -134,17 +134,17 @@ function step2B(aWebProgress, aRequest, 
 
 /*****************************************************************************
  * Step 3: Trigger hashchange within a secure page, and confirm UA knows
  *         it's secure. (Bug 283733)
  *****************************************************************************/
 
 function step3A() {
   gListener.callback = step3B;
-  content.location.assign("#foo");
+  content.location += "#foo";
 }
 
 function step3B(aWebProgress, aRequest, aLocation, aFlags) {
   is(aLocation.spec, kSecureURI + "#foo", "hashchange on HTTPS (3)");
 
   ok((aFlags & Components.interfaces.nsIWebProgressListener
                          .LOCATION_CHANGE_SAME_DOCUMENT),
      "We are in the same document as before (3)");
deleted file mode 100644
--- a/docshell/test/chrome/bug754029_window.xul
+++ /dev/null
@@ -1,307 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window id="754029Test"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        width="600"
-        height="600"
-        onload="startup();"
-        title="bug 754029 test">
-
-  <script type="application/javascript" src="docshell_helpers.js"></script>
-  <script type="application/javascript"><![CDATA[
-
-const _kDocshellTestNavURI =
-  "http://test1.example.org:80/tests/docshell/test/navigation/";
-
-const kBlankURI = _kDocshellTestNavURI + "blank.html";
-const kRedirectURI = _kDocshellTestNavURI + "file_bug754029.html";
-
-function startup() {
-  var browser = document.getElementById("content");
-  browser.addEventListener("load", contentOnLoad, true);
-  content.location.href = kBlankURI + "?start";
-}
-
-function contentOnLoad(aEvent) {
-  is(aEvent.originalTarget.nodeName, "#document", "Loading a document.");
-  var browser = document.getElementById("content");
-  var sessionHistory = browser.sessionHistory;
-
-  var _contentLoadURI = function (aHref) {content.location.href = aHref;}
-
-  function contentLoadURI(aHref) {
-    setTimeout(_contentLoadURI, 0, aHref);
-  }
-
-  function indexToSearch(aSessionHistory, aIndex) {
-    return "?" + aSessionHistory.getEntryAtIndex(aIndex, false)
-                                .URI
-                                .QueryInterface(Components.interfaces.nsIURL)
-                                .query;
-  }
-
-  switch(content.location.search) {
-  case "?start":
-    // Expected SH entries are:
-    // 1  * <blank.html          ?start>
-    is(content.history.length, 1, "Initial <about:blank> is replaced.");
-
-    // Requesting <file_bug754029.html?test1>
-    contentLoadURI(kRedirectURI + "?test1");
-    break;
-
-  /*****************************************************************************
-   * Test 1: Load a JS redirecting page; |location.href = ...| is directly in
-   *         <script></script> tag.
-   *
-   * Expected Result: The redirected page should replace the redirecting page's
-   *                  session history.
-   ****************************************************************************/
-  case "?test1":
-    // We can't catch this onload, because redirection is earlier than
-    // firing load event. That is OK.
-
-    // Expected SH entries are:
-    // 0    <?start>
-    // 1  * <?test1>
-    break;
-
-  case "?result1":
-    // Expected SH entries are:
-    // 0    <?start>
-    // x    <?test1>    // replaced.
-    // 1  * <?result1>
-
-    is(sessionHistory.count, 2, "<?result1>: SH's length");
-    is(sessionHistory.index, 1, "<?result1>: Current entry's index");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?result1",
-       "Check if the current SH entry is <?result1>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?start",
-       "Check if the previous SH entry is not <?test1> but <?start>");
-
-    // Requesting <file_bug754029.html?test2>
-    contentLoadURI(kRedirectURI + "?test2");
-    break;
-
-  /*****************************************************************************
-   * Test 2: Load a JS redirecting page; |location.href = ...| is in
-   *         "load" event handler.
-   *
-   * Expected Result: Replace
-   ****************************************************************************/
-  case "?test2":
-    // Expected SH entries are:
-    // 0    <?start>
-    // x    <?test1>    // replaced.
-    // 1    <?result1>
-    // 2  * <?test2>
-
-    is(sessionHistory.count, 3, "<?test2>: SH's length");
-    is(sessionHistory.index, 2, "<?test2>: Current entry's index");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?test2",
-       "Check if the current SH entry is <?test2>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?result1",
-       "Check if the previous SH entry is <?result1>");
-    break;
-
-  case "?result2":
-    // Expected SH entries are:
-    // 0    <?start>
-    // x    <?test1>    // replaced.
-    // 1    <?result1>
-    // x    <?test2>    // replaced.
-    // 2  * <?result2>
-
-    is(sessionHistory.count, 3, "<?result2>: SH's length");
-    is(sessionHistory.index, 2, "<?result2>: Current entry's index");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?result2",
-       "Check if the current SH entry is <?result2>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?result1",
-       "Check if the previous SH entry is not <?test2> but <?resutl1>");
-
-    contentLoadURI(kRedirectURI + "?test3");
-    break;
-
-  /*****************************************************************************
-   * Test 3: Load a JS redirecting page; |location.href = ...| is in
-   *         setTimeout(...)'s call back.
-   *
-   * Expected Result: Not replace
-   ****************************************************************************/
-  case "?test3":
-    // Expected SH entries are:
-    // 0    <?start>
-    // x    <?test1>    // replaced.
-    // 1    <?result1>
-    // x    <?test2>    // replaced.
-    // 2    <?result2>
-    // 3  * <?test3>
-
-    is(sessionHistory.count, 4, "<?test3>: SH's length");
-    is(sessionHistory.index, 3, "<?test3>: Current entry's index");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?test3",
-       "Check if the current SH entry is <?test3>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?result2",
-       "Check if the previous SH entry is <?result2>");
-    break;
-
-  case "?result3":
-    // Expected SH entries are:
-    // 0    <?start>
-    // x    <?test1>    // replaced.
-    // 1    <?result1>
-    // x    <?test2>    // replaced.
-    // 2    <?result2>
-    // 3    <?test3>    // not replaced.
-    // 4  * <?result3>
-
-    is(sessionHistory.count, 5, "<?result3>: SH's length");
-    is(sessionHistory.index, 4, "<?result3>: Current entry's index");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?result3",
-       "Check if the current SH entry is <?result3>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?test3",
-       "Check if <?test3> exists.");
-
-    contentLoadURI(kRedirectURI + "?test4");
-    break;
-
-  /*****************************************************************************
-   * Test 4: Load a JS redirecting page; setTimeout(...)'s callback
-   *         is inserting a new script element into the document. And the
-   *         inserted script contains |location.href = ...|.
-   *
-   *         See also:
-   *         https://bugzilla.mozilla.org/attachment.cgi?id=622899
-   *
-   * Expected Result: Not replace
-   ****************************************************************************/
-  case "?test4":
-    // Expected SH entries are:
-    // 0    <?start>
-    // x    <?test1>    // replaced.
-    // 1    <?result1>
-    // x    <?test2>    // replaced.
-    // 2    <?result2>
-    // 3    <?test3>    // not replaced
-    // 4    <?result3>
-    // 5  * <?test4>
-
-    is(sessionHistory.count, 6, "<?test4>: SH's length");
-    is(sessionHistory.index, 5, "<?test4>: Current entry's index");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?test4",
-       "Check if the current SH entry is <?test4>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?result3",
-       "Check if the previous SH entry is <?result3>");
-
-    break;
-
-  case "?result4":
-    // Expected SH entries are:
-    // 0    <?start>
-    // x    <?test1>    // replaced.
-    // 1    <?result1>
-    // x    <?test2>    // replaced.
-    // 2    <?result2>
-    // 3    <?test3>    // not replaced.
-    // 4    <?result3>
-    // 5    <?test4>    // not replaced.
-    // 6  * <?result4>
-
-    is(sessionHistory.count, 7, "<?test4>: SH's length");
-    is(sessionHistory.index, 6, "<?test4>: Current entry's index");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?result4",
-       "Check if the current SH entry is <?test4>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?test4",
-       "Check if <?test4> exists.");
-
-    contentLoadURI(kRedirectURI + "?testDOMContentLoaded");
-    break;
-
-  /*****************************************************************************
-   * Test 5: Setting location.href in onDOMContentLoaded() should REPLACE.
-   ****************************************************************************/
-  case "?testDOMContentLoaded":
-    break;
-  case "?resultDOMContentLoaded":
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?resultDOMContentLoaded",
-       "Check if the current SH entry is <?resultDOMContentLoaded>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?result4",
-       "Check if the perevious entry is not <?testDOMContentLoaded> but " +
-       "<?result4>.");
-
-    contentLoadURI(kRedirectURI + "?testPageshow");
-    break;
-
-  /*****************************************************************************
-   * Test 6: Setting location.href in onpageshow() should REPLACE.
-   ****************************************************************************/
-  case "?testPageshow":
-    break;
-  case "?resultPageshow":
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?resultPageshow",
-       "Check if the current SH entry is <?resultPageshow>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?resultDOMContentLoaded",
-       "Check if the perevious entry is not <?testPageshow> but " +
-       "<?resultDOMContentLoaded>.");
-
-    contentLoadURI(kRedirectURI + "?testReadystatechange");
-    break;
-
-  /*****************************************************************************
-   * Test 7: Setting location.href in onreadystatechange() should REPLACE.
-   ****************************************************************************/
-  case "?testReadystatechange":
-    break;
-  case "?resultReadystatechange":
-    is(indexToSearch(sessionHistory, sessionHistory.index),
-       "?resultReadystatechange",
-       "Check if the current SH entry is <?resultReadystatechange>");
-
-    is(indexToSearch(sessionHistory, sessionHistory.index - 1),
-       "?resultPageshow",
-       "Check if the perevious entry is not <?testReadystatechange> but " +
-       "<?resultPageshow>.");
-
-    finish();
-    break;
-  }
-}
-  ]]></script>
-
-  <browser type="content-primary" flex="1" id="content" src="about:blank"/>
-</window>
deleted file mode 100644
--- a/docshell/test/chrome/test_bug754029.xul
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet
-  href="chrome://mochikit/content/tests/SimpleTest/test.css"
-  type="text/css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=754029.xul
--->
-<window title="Mozilla Bug 754029"
-  xmlns:html="http://www.w3.org/1999/xhtml"
-  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-  <title>Test for Bug 754029</title>
-  <script type="application/javascript"
-    src="chrome://mochikit/content/MochiKit/packed.js"></script>
-  <script type="application/javascript"
-    src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-
-<body  xmlns="http://www.w3.org/1999/xhtml">
-<a target="_blank"
-   href="https://bugzilla.mozilla.org/show_bug.cgi?id=754029">
-   Mozilla Bug 754029</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-</body>
-
-<script class="testbody" type="application/javascript">
-<![CDATA[
-
-/** Test for Bug 754029 **/
-
-SimpleTest.waitForExplicitFinish();
-window.open("bug754029_window.xul", "bug754029",
-            "chrome,width=600,height=600");
-
-]]>
-</script>
-
-</window>
--- a/docshell/test/navigation/Makefile.in
+++ b/docshell/test/navigation/Makefile.in
@@ -41,17 +41,16 @@ MOCHITEST_FILES = \
 		file_document_write_1.html \
 		file_static_and_dynamic_1.html \
 		frame0.html \
 		frame1.html \
 		frame2.html \
 		frame3.html \
 		goback.html \
 		file_bug534178.html \
-		file_bug754029.html \
 		$(NULL)
 
 ifneq (mobile/android,$(MOZ_BUILD_APP))
 MOCHITEST_FILES += \
 		test_bug270414.html \
 		$(NULL)
 endif
 
--- a/docshell/test/navigation/browser_bug343515.js
+++ b/docshell/test/navigation/browser_bug343515.js
@@ -7,23 +7,61 @@ var ctx = {};
 // Helper function to check if a window is active
 function isActive(aWindow) {
   var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                         .getInterface(Ci.nsIWebNavigation)
                         .QueryInterface(Ci.nsIDocShell);
   return docshell.isActive;
 }
 
-function oneShotListener(aBrowser, aType, aCallback) {
-  aBrowser.addEventListener(aType, function (evt) {
-    if (evt.target != aBrowser.contentDocument)
+function oneShotListener(aElem, aType, aCallback) {
+  aElem.addEventListener(aType, function () {
+    aElem.removeEventListener(aType, arguments.callee, true);
+
+    // aCallback is executed asynchronously, which is handy because load
+    // events fire before mIsDocumentLoaded is actually set to true. :(
+    executeSoon(aCallback);
+  }, true);
+}
+
+// Returns a closure that iteratively (BFS) waits for all
+// of the descendant frames of aInitialWindow to finish loading,
+// then calls aFinalCallback.
+function frameLoadWaiter(aInitialWindow, aFinalCallback) {
+
+  // The window we're currently waiting on
+  var curr = aInitialWindow;
+
+  // The windows we need to wait for
+  var waitQueue = [];
+
+  // The callback to call when we're all done
+  var finalCallback = aFinalCallback;
+
+  function frameLoadCallback() {
+
+    // Push any subframes of what we just got
+    for (var i = 0; i < curr.frames.length; ++i)
+      waitQueue.push(curr.frames[i]);
+
+    // Handle the next window in the queue
+    if (waitQueue.length >= 1) {
+      curr = waitQueue.shift();
+      if (curr.document.readyState == "complete")
+        frameLoadCallback();
+      else
+        oneShotListener(curr, "load", frameLoadCallback);
       return;
-    aBrowser.removeEventListener(aType, arguments.callee, true);
-    aCallback();
-  }, true);
+    }
+
+    // Otherwise, we're all done. Call the final callback
+    finalCallback();
+  }
+
+  return frameLoadCallback;
 }
 
 // Entry point from Mochikit
 function test() {
 
   // Lots of callbacks going on here
   waitForExplicitFinish();
 
@@ -60,38 +98,34 @@ function step2() {
   // Tab 1 should now be active
   ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
   ok(isActive(ctx.tab1Window), "Tab 1 should be active");
 
   // Open another tab
   ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
   ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
   ctx.tab2Window = ctx.tab2Browser.contentWindow;
-  oneShotListener(ctx.tab2Browser, "load", step3);
+  oneShotListener(ctx.tab2Browser, "load", frameLoadWaiter(ctx.tab2Window, step3));
 }
 
 function step3() {
 
   // Tab 0 should be inactive, Tab 1 should be active
   ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
   ok(isActive(ctx.tab1Window), "Tab 1 should be active");
 
   // Tab 2's window _and_ its iframes should be inactive
   ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
   is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
   ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
   ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
 
   // Navigate tab 2 to a different page
-  // Note that we need to use setAttribute('src', ...) here rather than setting
-  // window.location, because this function gets called in an onload handler, and
-  // per spec setting window.location during onload is equivalent to calling
-  // window.replace.
-  ctx.tab2Browser.setAttribute('src', testPath + "bug343515_pg3.html");
-  oneShotListener(ctx.tab2Browser, "load", step4);
+  ctx.tab2Window.location = testPath + "bug343515_pg3.html";
+  oneShotListener(ctx.tab2Browser, "load", frameLoadWaiter(ctx.tab2Window, step4));
 }
 
 function step4() {
 
   // Tab 0 should be inactive, Tab 1 should be active
   ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
   ok(isActive(ctx.tab1Window), "Tab 1 should be active");
 
@@ -110,53 +144,55 @@ function step4() {
   ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
   ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
   ok(isActive(ctx.tab2Window), "Tab 2 should be active");
   ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
   ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active");
   ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
 
   // Go back
-  oneShotListener(ctx.tab2Browser, "pageshow", step5);
-  SimpleTest.executeSoon(function() {ctx.tab2Browser.goBack();});
+  oneShotListener(ctx.tab2Browser, "pageshow", frameLoadWaiter(ctx.tab2Window, step5));
+  ctx.tab2Browser.goBack();
 
 }
 
 function step5() {
 
   // Check everything
   ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
   ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
   ok(isActive(ctx.tab2Window), "Tab 2 should be active");
   ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
   ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
 
   // Switch to tab 1
   gBrowser.selectedTab = ctx.tab1;
 
   // Navigate to page 3
-  ctx.tab1Browser.setAttribute('src', testPath + "bug343515_pg3.html");
-  oneShotListener(ctx.tab1Browser, "load", step6);
+  ctx.tab1Window.location = testPath + "bug343515_pg3.html";
+  oneShotListener(ctx.tab1Browser, "load", frameLoadWaiter(ctx.tab1Window, step6));
 }
 
 function step6() {
 
   // Check everything
   ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
   ok(isActive(ctx.tab1Window), "Tab 1 should be active");
   ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
   ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
   ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
   ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
   ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
   ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
 
   // Go forward on tab 2
-  oneShotListener(ctx.tab2Browser, "pageshow",  step7);
-  SimpleTest.executeSoon(function() {ctx.tab2Browser.goForward();});
+  oneShotListener(ctx.tab2Browser, "pageshow", frameLoadWaiter(ctx.tab2Window, step7));
+  var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor)
+                                   .getInterface(Ci.nsIWebNavigation);
+  tab2docshell.goForward();
 }
 
 function step7() {
 
   ctx.tab2Window = ctx.tab2Browser.contentWindow;
 
   // Check everything
   ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
deleted file mode 100644
--- a/docshell/test/navigation/file_bug754029.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<html>
-<head>
-<meta http-equiv="content-type" Content="text/html; charset=utf-8">
-</head>
-<body>
-<script>
-
-// inline <script> tag redirection.
-function test1() {
-  location.href = "blank.html?result1";
-}
-
-// onload() handler redirection.
-function test2() {
-  addEventListener("load", 
-                   function(aEvent) {
-                     location.href = "blank.html?result2";
-                   },
-                   false);
-}
-
-// setTimeout() 100 milisec redirection.
-function test3() {
-  setTimeout(function() {
-               location.href = "blank.html?result3";
-             },
-             100);
-}
-
-// setTimeout() 100 milisec + inline <script> tag redirection.
-function test4() {
-  setTimeout(function() {
-               var ns = document.createElement("script");
-               var nt = document.createTextNode(
-                          "location = 'blank.html?result4'"
-                        );
-               ns.appendChild(nt);
-               document.documentElement.appendChild(ns);
-             },
-             100);
-}
-
-// DOMContentLoaded
-function testDOMContentLoaded() {
-  addEventListener("DOMContentLoaded", 
-                   function(aEvent) {
-                     location.href = "blank.html?resultDOMContentLoaded";
-                   },
-                   false);
-}
-
-// pageshow
-function testPageshow() {
-  addEventListener("pageshow", 
-                   function(aEvent) {
-                     location.href = "blank.html?resultPageshow";
-                   },
-                   false);
-}
-
-// readystatechange for "complete"
-function testReadystatechange() {
-  document.onreadystatechange =
-    function() {
-      if ("complete" == document.readyState) {
-        location.href = "blank.html?resultReadystatechange";
-      }
-    };
-}
-
-switch(location.search) {
-case "?test1": test1(); break;
-case "?test2": test2(); break;
-case "?test3": test3(); break;
-case "?test4": test4(); break;
-case "?testDOMContentLoaded": testDOMContentLoaded(); break;
-case "?testPageshow"        : testPageshow();         break;
-case "?testReadystatechange": testReadystatechange(); break;
-default: throw "Unexpected!";
-}
-
-</script>
-</body>
-</html>
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -40,18 +40,18 @@ public:
 
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
                               NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0x95870c91, 0xe21d, 0x4499, \
-  { 0x9b, 0x61, 0x45, 0x79, 0x5f, 0x12, 0x0c, 0x98 } }
+{ 0xa842337f, 0x4332, 0x4221, \
+  { 0xa3, 0x8f, 0xca, 0x47, 0x0b, 0x78, 0xd0, 0x6d } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 /**
  * It is used by the application to initialize a runtime and run scripts.
  * A script runtime would implement this interface.
@@ -323,16 +323,22 @@ public:
    * Called to disable/enable script execution in this context.
    */
   virtual bool GetScriptsEnabled() = 0;
   virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts) = 0;
 
   // SetProperty is suspect and jst believes should not be needed.  Currenly
   // used only for "arguments".
   virtual nsresult SetProperty(JSObject* aTarget, const char* aPropName, nsISupports* aVal) = 0;
+  /** 
+   * Called to set/get information if the script context is
+   * currently processing a script tag
+   */
+  virtual bool GetProcessingScriptTag() = 0;
+  virtual void SetProcessingScriptTag(bool aResult) = 0;
 
   /**
    * Called to find out if this script context might be executing script.
    */
   virtual bool GetExecutingScript() = 0;
 
   /**
    * Initialize DOM classes on aGlobalObj, always call
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1112,16 +1112,17 @@ nsJSContext::nsJSContext(JSRuntime *aRun
     xpc_LocalizeContext(mContext);
   }
   mIsInitialized = false;
   mTerminations = nullptr;
   mScriptsEnabled = true;
   mOperationCallbackTime = 0;
   mModalStateTime = 0;
   mModalStateDepth = 0;
+  mProcessingScriptTag = false;
 }
 
 nsJSContext::~nsJSContext()
 {
 #ifdef DEBUG
   nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptContext*>(this));
 #endif
 
@@ -2865,16 +2866,28 @@ nsJSContext::SetScriptsEnabled(bool aEna
 
   if (global) {
     global->SetScriptsEnabled(aEnabled, aFireTimeouts);
   }
 }
 
 
 bool
+nsJSContext::GetProcessingScriptTag()
+{
+  return mProcessingScriptTag;
+}
+
+void
+nsJSContext::SetProcessingScriptTag(bool aFlag)
+{
+  mProcessingScriptTag = aFlag;
+}
+
+bool
 nsJSContext::GetExecutingScript()
 {
   return JS_IsRunning(mContext) || mExecuteDepth > 0;
 }
 
 NS_IMETHODIMP
 nsJSContext::ScriptExecuted()
 {
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -114,16 +114,19 @@ public:
   virtual void ScriptEvaluated(bool aTerminated);
   virtual void SetTerminationFunction(nsScriptTerminationFunc aFunc,
                                       nsIDOMWindow* aRef);
   virtual bool GetScriptsEnabled();
   virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts);
 
   virtual nsresult SetProperty(JSObject* aTarget, const char* aPropName, nsISupports* aVal);
 
+  virtual bool GetProcessingScriptTag();
+  virtual void SetProcessingScriptTag(bool aResult);
+
   virtual bool GetExecutingScript();
 
   virtual nsresult InitClasses(JSObject* aGlobalObj);
 
   virtual void WillInitializeContext();
   virtual void DidInitializeContext();
 
   virtual nsresult Serialize(nsIObjectOutputStream* aStream, JSScript* aScriptObject);
@@ -277,16 +280,17 @@ public:
 
 protected:
   TerminationFuncClosure* mTerminations;
 
 private:
   bool mIsInitialized;
   bool mScriptsEnabled;
   bool mGCOnDestruction;
+  bool mProcessingScriptTag;
 
   uint32_t mExecuteDepth;
   uint32_t mDefaultJSOptions;
   PRTime mOperationCallbackTime;
 
   PRTime mModalStateTime;
   uint32_t mModalStateDepth;
 
--- a/dom/base/nsLocation.cpp
+++ b/dom/base/nsLocation.cpp
@@ -31,17 +31,16 @@
 #include "nsDOMClassInfoID.h"
 #include "nsCRT.h"
 #include "nsIProtocolHandler.h"
 #include "nsReadableUtils.h"
 #include "nsITextToSubURI.h"
 #include "nsJSUtils.h"
 #include "jsfriendapi.h"
 #include "nsContentUtils.h"
-#include "nsEventStateManager.h"
 #include "mozilla/Likely.h"
 #include "nsCycleCollectionParticipant.h"
 
 static nsresult
 GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
 {
   aCharset.Truncate();
 
@@ -456,92 +455,28 @@ nsLocation::GetHref(nsAString& aHref)
 
 NS_IMETHODIMP
 nsLocation::SetHref(const nsAString& aHref)
 {
   nsAutoString oldHref;
   nsresult rv = NS_OK;
 
   JSContext *cx = nsContentUtils::GetCurrentJSContext();
-
-  // According to HTML5 spec, |location.href = ...| must act as if
-  // it were |location.replace(...)| before the page load finishes.
-  //
-  // http://www.w3.org/TR/2011/WD-html5-20110113/history.html#location
-  //
-  // > The href attribute must return the current address of the
-  // > associated Document object, as an absolute URL.
-  // >
-  // > On setting, if the Location object's associated Document
-  // > object has completely loaded, then the user agent must act
-  // > as if the assign() method had been called with the new value
-  // > as its argument. Otherwise, the user agent must act as if
-  // > the replace() method had been called with the new value as its
-  // > argument.
-  //
-  // Note: The spec says the condition is "Document object has completely
-  //       loaded", but that may break some websites. If the user was
-  //       willing to move from one page to another, and was able to do
-  //       so, we should not overwrite the session history entry even
-  //       if the loading has not finished yet.
-  //
-  //       https://www.w3.org/Bugs/Public/show_bug.cgi?id=17041 
-  //
-  // See bug 39938, bug 72197, bug 178729 and bug 754029.
-  // About other browsers:
-  // http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2010-July/027372.html
-
-  bool replace = false;
-  if (!nsEventStateManager::IsHandlingUserInput()) {
-    // "completely loaded" is defined at:
-    //
-    // http://www.w3.org/TR/2012/WD-html5-20120329/the-end.html#completely-loaded
-    //
-    // > 7.  document readiness to "complete", and fire "load".
-    // >
-    // > 8.  "pageshow"
-    // >
-    // > 9.  ApplicationCache
-    // >
-    // > 10. Print in the pending list.
-    // >
-    // > 12. Queue a task to mark the Document as completely loaded.
-    //
-    // Since Gecko doesn't (yet) have a flag corresponding to no. "12.
-    // ... completely loaded", here the logic is a little tricky.
-
-    nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
-    nsCOMPtr<nsIDocument> document(do_GetInterface(docShell));
-    if (document) {
-      replace =
-        nsIDocument::READYSTATE_COMPLETE != document->GetReadyStateEnum();
-
-      // nsIDocShell::isExecutingOnLoadHandler is true while
-      // the document is handling "load", "pageshow",
-      // "readystatechange" for "complete" and "beforeprint"/"afterprint".
-      //
-      // Maybe this API property needs a better name.
-      if (!replace) {
-        docShell->GetIsExecutingOnLoadHandler(&replace);
-      }
-    }
-  }
-
   if (cx) {
-    rv = SetHrefWithContext(cx, aHref, replace);
+    rv = SetHrefWithContext(cx, aHref, false);
   } else {
     rv = GetHref(oldHref);
 
     if (NS_SUCCEEDED(rv)) {
       nsCOMPtr<nsIURI> oldUri;
 
       rv = NS_NewURI(getter_AddRefs(oldUri), oldHref);
 
       if (oldUri) {
-        rv = SetHrefWithBase(aHref, oldUri, replace);
+        rv = SetHrefWithBase(aHref, oldUri, false);
       }
     }
   }
 
   return rv;
 }
 
 nsresult
@@ -562,24 +497,53 @@ nsLocation::SetHrefWithContext(JSContext
 
 nsresult
 nsLocation::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
                             bool aReplace)
 {
   nsresult result;
   nsCOMPtr<nsIURI> newUri;
 
+  nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
+
   nsAutoCString docCharset;
   if (NS_SUCCEEDED(GetDocumentCharacterSetForURI(aHref, docCharset)))
     result = NS_NewURI(getter_AddRefs(newUri), aHref, docCharset.get(), aBase);
   else
     result = NS_NewURI(getter_AddRefs(newUri), aHref, nullptr, aBase);
 
   if (newUri) {
-    return SetURI(newUri, aReplace);
+    /* Check with the scriptContext if it is currently processing a script tag.
+     * If so, this must be a <script> tag with a location.href in it.
+     * we want to do a replace load, in such a situation. 
+     * In other cases, for example if a event handler or a JS timer
+     * had a location.href in it, we want to do a normal load,
+     * so that the new url will be appended to Session History.
+     * This solution is tricky. Hopefully it isn't going to bite
+     * anywhere else. This is part of solution for bug # 39938, 72197
+     * 
+     */
+    bool inScriptTag=false;
+    JSContext *cx = nsContentUtils::GetCurrentJSContext();
+    if (cx) {
+      nsIScriptContext *scriptContext =
+        nsJSUtils::GetDynamicScriptContext(cx);
+
+      if (scriptContext) {
+        if (scriptContext->GetProcessingScriptTag()) {
+          // Now check to make sure that the script is running in our window,
+          // since we only want to replace if the location is set by a
+          // <script> tag in the same window.  See bug 178729.
+          nsCOMPtr<nsIScriptGlobalObject> ourGlobal(do_GetInterface(docShell));
+          inScriptTag = (ourGlobal == scriptContext->GetGlobalObject());
+        }
+      }  
+    } //cx
+
+    return SetURI(newUri, aReplace || inScriptTag);
   }
 
   return result;
 }
 
 NS_IMETHODIMP
 nsLocation::GetOrigin(nsAString& aOrigin)
 {