Bug 825544: backout Bug 825544, Bug 825544, Bug 765192 and Bug 808035 to bring back the old .location=val behavior, r=bz

This commit is contained in:
Olli Pettay 2013-01-15 13:46:35 +02:00
Родитель 18b2461321
Коммит 1defaa48e6
18 изменённых файлов: 141 добавлений и 576 удалений

Просмотреть файл

@ -14,7 +14,7 @@ function test()
];
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]);

Просмотреть файл

@ -166,13 +166,13 @@ function test() {
// 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;

Просмотреть файл

@ -3056,9 +3056,7 @@ let SessionStoreInternal = {
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;
}

Просмотреть файл

@ -843,6 +843,9 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
return NS_ERROR_FAILURE;
}
bool oldProcessingScriptTag = context->GetProcessingScriptTag();
context->SetProcessingScriptTag(true);
// Update our current script.
nsCOMPtr<nsIScriptElement> oldCurrent = mCurrentScript;
mCurrentScript = aRequest->mElement;
@ -863,6 +866,10 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
// 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;
}

Просмотреть файл

@ -1414,6 +1414,16 @@ nsDocShell::LoadURI(nsIURI * aURI,
}
} // 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) {
@ -6519,7 +6529,7 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
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);
@ -10492,13 +10502,11 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI, nsIChannel * aChannel,
NS_ASSERTION(entry == newEntry, "The new session history should be in the new entry");
}
// This is the root docshell
if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
// Replace current entry in session history.
int32_t index = 0;
mSessionHistory->GetIndex(&index);
// This is the root docshell
if (-1 != index &&
LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
// Replace current entry in session history.
nsCOMPtr<nsISHistoryInternal> shPrivate(do_QueryInterface(mSessionHistory));
// Replace the current entry with the new entry
if (shPrivate)
@ -10509,7 +10517,7 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI, nsIChannel * aChannel,
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

Просмотреть файл

@ -32,7 +32,6 @@ MOCHITEST_BROWSER_FILES = \
browser_bug670318.js \
file_bug670318.html \
browser_bug673467.js \
browser_bug808035.js \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -94,8 +94,6 @@ MOCHITEST_CHROME_FILES = \
test_mozFrameType.xul \
mozFrameType_window.xul \
test_bug789773.xul \
test_bug754029.xul \
bug754029_window.xul \
docshell_helpers.js \
generic.html \
$(NULL)

Просмотреть файл

@ -109,7 +109,7 @@ function step1B(aWebProgress, aRequest, aLocation, aFlags) {
function step2A() {
gListener.callback = step2B;
content.location.assign(kSecureURI);
content.location = kSecureURI;
}
function step2B(aWebProgress, aRequest, aLocation, aFlags) {
@ -139,7 +139,7 @@ function step2B(aWebProgress, aRequest, aLocation, aFlags) {
function step3A() {
gListener.callback = step3B;
content.location.assign("#foo");
content.location += "#foo";
}
function step3B(aWebProgress, aRequest, aLocation, aFlags) {

Просмотреть файл

@ -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>

Просмотреть файл

@ -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>

Просмотреть файл

@ -46,7 +46,6 @@ MOCHITEST_FILES = \
frame3.html \
goback.html \
file_bug534178.html \
file_bug754029.html \
$(NULL)
ifneq (mobile/android,$(MOZ_BUILD_APP))

Просмотреть файл

@ -12,15 +12,53 @@ function isActive(aWindow) {
return docshell.isActive;
}
function oneShotListener(aBrowser, aType, aCallback) {
aBrowser.addEventListener(aType, function (evt) {
if (evt.target != aBrowser.contentDocument)
return;
aBrowser.removeEventListener(aType, arguments.callee, true);
aCallback();
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;
}
// Otherwise, we're all done. Call the final callback
finalCallback();
}
return frameLoadCallback;
}
// Entry point from Mochikit
function test() {
@ -65,7 +103,7 @@ function step2() {
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() {
@ -81,12 +119,8 @@ function step3() {
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() {
@ -115,8 +149,8 @@ function step4() {
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();
}
@ -133,8 +167,8 @@ function step5() {
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() {
@ -150,8 +184,10 @@ function step6() {
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() {

Просмотреть файл

@ -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>

Просмотреть файл

@ -45,8 +45,8 @@ 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... */
@ -328,6 +328,12 @@ public:
// 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.

Просмотреть файл

@ -1135,6 +1135,7 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime, bool aGCOnDestruction,
mOperationCallbackTime = 0;
mModalStateTime = 0;
mModalStateDepth = 0;
mProcessingScriptTag = false;
}
nsJSContext::~nsJSContext()
@ -2887,6 +2888,18 @@ nsJSContext::SetScriptsEnabled(bool aEnabled, bool aFireTimeouts)
}
bool
nsJSContext::GetProcessingScriptTag()
{
return mProcessingScriptTag;
}
void
nsJSContext::SetProcessingScriptTag(bool aFlag)
{
mProcessingScriptTag = aFlag;
}
bool
nsJSContext::GetExecutingScript()
{

Просмотреть файл

@ -119,6 +119,9 @@ public:
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);
@ -282,6 +285,7 @@ private:
bool mIsInitialized;
bool mScriptsEnabled;
bool mGCOnDestruction;
bool mProcessingScriptTag;
uint32_t mExecuteDepth;
uint32_t mDefaultJSOptions;

Просмотреть файл

@ -36,7 +36,6 @@
#include "nsJSUtils.h"
#include "jsfriendapi.h"
#include "nsContentUtils.h"
#include "nsEventStateManager.h"
#include "mozilla/Likely.h"
#include "nsCycleCollectionParticipant.h"
@ -461,72 +460,8 @@ nsLocation::SetHref(const nsAString& aHref)
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);
@ -536,7 +471,7 @@ nsLocation::SetHref(const nsAString& aHref)
rv = NS_NewURI(getter_AddRefs(oldUri), oldHref);
if (oldUri) {
rv = SetHrefWithBase(aHref, oldUri, replace);
rv = SetHrefWithBase(aHref, oldUri, false);
}
}
}
@ -567,6 +502,8 @@ nsLocation::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
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);
@ -574,7 +511,34 @@ nsLocation::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
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;