diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp
index b5947bc7150..8a9522982f4 100644
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1961,7 +1961,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
mWillReparent = PR_TRUE;
#endif
- rv = window->SetNewDocument(this, nsnull, PR_FALSE);
+ rv = window->SetNewDocument(this, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index 3cfe130ddbc..2e3817c7266 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1568,39 +1568,18 @@ NS_IMPL_ISUPPORTS1(WindowStateHolder, WindowStateHolder)
nsresult
nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
- nsISupports* aState,
- PRBool aClearScopeHint)
+ nsISupports* aState)
{
- return SetNewDocument(aDocument, aState, aClearScopeHint, PR_FALSE);
-}
+ NS_PRECONDITION(mDocumentPrincipal == nsnull,
+ "mDocumentPrincipal prematurely set!");
-nsresult
-nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
- nsISupports* aState,
- PRBool aClearScopeHint,
- PRBool aIsInternalCall)
-{
- NS_ASSERTION(mDocumentPrincipal == nsnull,
- "mDocumentPrincipal prematurely set!");
-#ifdef PR_LOGGING
- if (IsInnerWindow() && aDocument && gDOMLeakPRLog &&
- PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
- nsIURI *uri = aDocument->GetDocumentURI();
- nsCAutoString spec;
- if (uri)
- uri->GetSpec(spec);
- PR_LogPrint("DOMWINDOW %p SetNewDocument %s", this, spec.get());
- }
-#endif
+ if (!aDocument) {
+ NS_ERROR("SetNewDocument(null) called!");
- if (IsOuterWindow() && IsFrozen()) {
- // This outer is now getting its first inner, thaw the outer now
- // that it's ready and is getting an inner window.
-
- Thaw();
+ return NS_ERROR_INVALID_ARG;
}
- if (!aIsInternalCall && IsInnerWindow()) {
+ if (IsInnerWindow()) {
if (!mOuterWindow) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -1611,15 +1590,15 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
return NS_ERROR_NOT_AVAILABLE;
}
- return GetOuterWindowInternal()->SetNewDocument(aDocument,
- aState,
- aClearScopeHint, PR_TRUE);
+ return GetOuterWindowInternal()->SetNewDocument(aDocument, aState);
}
- if (!aDocument) {
- NS_ERROR("SetNewDocument(null) called!");
+ NS_PRECONDITION(IsOuterWindow(), "Must only be called on outer windows");
- return NS_ERROR_INVALID_ARG;
+ if (IsFrozen()) {
+ // This outer is now getting its first inner, thaw the outer now
+ // that it's ready and is getting an inner window.
+ Thaw();
}
NS_ASSERTION(!GetCurrentInnerWindow() ||
@@ -1667,16 +1646,10 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
SetStatus(EmptyString());
SetDefaultStatus(EmptyString());
- // This code should not be called during shutdown any more (now that
- // we don't ever call SetNewDocument(nsnull), so no need to null
- // check xpc here.
- nsIXPConnect *xpc = nsContentUtils::XPConnect();
-
PRBool reUseInnerWindow = WouldReuseInnerWindow(aDocument);
// Remember the old document's principal.
nsIPrincipal *oldPrincipal = nsnull;
-
if (oldDoc) {
oldPrincipal = oldDoc->NodePrincipal();
}
@@ -1707,11 +1680,405 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
mNavigator->LoadingNewDocument();
}
- PRUint32 st_id, st_ndx; // we loop over all our context/globs lots!
-
// Set mDocument even if this is an outer window to avoid
// having to *always* reach into the inner window to find the
// document.
+ mDocument = do_QueryInterface(aDocument);
+ mDoc = aDocument;
+
+#ifdef DEBUG
+ mLastOpenedURI = aDocument->GetDocumentURI();
+#endif
+
+ PRUint32 st_id; // we loop over all our context/globs lots!
+ NS_STID_FOR_ID(st_id) {
+ nsIScriptContext *langContext = GetScriptContextInternal(st_id);
+ if (langContext)
+ langContext->WillInitializeContext();
+ }
+
+ nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
+
+ nsRefPtr newInnerWindow;
+
+ nsCOMPtr thisChrome =
+ do_QueryInterface(static_cast(this));
+ nsCOMPtr navigatorHolder;
+ jsval nav;
+
+ PRBool isChrome = PR_FALSE;
+
+ nsCxPusher cxPusher;
+ if (!cxPusher.Push(cx)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ JSAutoRequest ar(cx);
+
+ // Make sure to clear scope on the outer window *before* we
+ // initialize the new inner window. If we don't, things
+ // (Object.prototype etc) could leak from the old outer to the new
+ // inner scope.
+ NS_STID_FOR_ID(st_id) {
+ nsIScriptContext *langContext = GetScriptContextInternal(st_id);
+ if (langContext)
+ langContext->ClearScope(mScriptGlobals[NS_STID_INDEX(st_id)],
+ PR_FALSE);
+ }
+
+ if (reUseInnerWindow) {
+ // We're reusing the current inner window.
+ NS_ASSERTION(!currentInner->IsFrozen(),
+ "We should never be reusing a shared inner window");
+ newInnerWindow = currentInner;
+
+ if (aDocument != oldDoc) {
+ nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
+ }
+ } else {
+ if (aState) {
+ nsCOMPtr wsh = do_QueryInterface(aState);
+ NS_ASSERTION(wsh, "What kind of weird state are you giving me here?");
+
+ newInnerWindow = wsh->GetInnerWindow();
+ NS_STID_FOR_ID(st_id) {
+ mInnerWindowHolders[NS_STID_INDEX(st_id)] = wsh->GetInnerWindowHolder(st_id);
+ }
+
+ // These assignments addref.
+ mNavigator = wsh->GetNavigator();
+ mLocation = wsh->GetLocation();
+
+ if (mNavigator) {
+ // Update mNavigator's docshell pointer now.
+ mNavigator->SetDocShell(mDocShell);
+ mNavigator->LoadingNewDocument();
+ }
+ } else {
+ if (thisChrome) {
+ newInnerWindow = new nsGlobalChromeWindow(this);
+
+ isChrome = PR_TRUE;
+ } else {
+ if (mIsModalContentWindow) {
+ newInnerWindow = new nsGlobalModalWindow(this);
+ } else {
+ newInnerWindow = new nsGlobalWindow(this);
+ }
+ }
+
+ mLocation = nsnull;
+ }
+
+ if (!newInnerWindow) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (currentInner && currentInner->mJSObject) {
+ if (mNavigator && !aState) {
+ // Hold on to the navigator wrapper so that we can set
+ // window.navigator in the new window to point to the same
+ // object (assuming we didn't change origins etc). See bug
+ // 163645 for more on why we need this.
+
+ nsIDOMNavigator* navigator =
+ static_cast(mNavigator.get());
+ nsContentUtils::WrapNative(cx, currentInner->mJSObject, navigator,
+ &NS_GET_IID(nsIDOMNavigator), &nav,
+ getter_AddRefs(navigatorHolder));
+ }
+ }
+
+ if (!aState) {
+ // This is redundant if we're restoring from a previous inner window.
+ nsIScriptGlobalObject *sgo =
+ (nsIScriptGlobalObject *)newInnerWindow.get();
+
+ // Freeze the outer window and null out the inner window so
+ // that initializing classes on the new inner doesn't end up
+ // reaching into the old inner window for classes etc.
+ //
+ // [This happens with Object.prototype when XPConnect creates
+ // a temporary global while initializing classes; the reason
+ // being that xpconnect creates the temp global w/o a parent
+ // and proto, which makes the JS engine look up classes in
+ // cx->globalObject, i.e. this outer window].
+
+ mInnerWindow = nsnull;
+
+ Freeze();
+ mCreatingInnerWindow = PR_TRUE;
+ // Every script context we are initialized with must create a
+ // new global.
+ rv = NS_OK;
+ NS_STID_FOR_ID(st_id) {
+ PRUint32 st_ndx = NS_STID_INDEX(st_id);
+ nsIScriptContext *this_ctx = GetScriptContextInternal(st_id);
+ if (this_ctx) {
+ void *&newGlobal = newInnerWindow->mScriptGlobals[st_ndx];
+ nsCOMPtr &holder = mInnerWindowHolders[st_ndx];
+ rv |= this_ctx->CreateNativeGlobalForInner(sgo, isChrome,
+ &newGlobal,
+ getter_AddRefs(holder));
+ NS_ASSERTION(NS_SUCCEEDED(rv) && newGlobal && holder,
+ "Failed to get script global and holder");
+ if (st_id == nsIProgrammingLanguage::JAVASCRIPT) {
+ newInnerWindow->mJSObject = (JSObject *)newGlobal;
+ }
+ }
+ }
+ mCreatingInnerWindow = PR_FALSE;
+ Thaw();
+
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ if (currentInner && currentInner->mJSObject) {
+ PRBool termFuncSet = PR_FALSE;
+
+ if (oldDoc == aDocument) {
+ // Suspend the current context's request before Pop() resumes the old
+ // context's request.
+ JSAutoSuspendRequest asr(cx);
+
+ // Pop our context here so that we get the correct one for the
+ // termination function.
+ cxPusher.Pop();
+
+ JSContext *oldCx = nsContentUtils::GetCurrentJSContext();
+
+ nsIScriptContext *callerScx;
+ if (oldCx && (callerScx = GetScriptContextFromJSContext(oldCx))) {
+ // We're called from document.open() (and document.open() is
+ // called from JS), clear the scope etc in a termination
+ // function on the calling context to prevent clearing the
+ // calling scope.
+ NS_ASSERTION(!currentInner->IsFrozen(),
+ "How does this opened window get into session history");
+
+ JSAutoRequest ar(oldCx);
+
+ callerScx->SetTerminationFunction(ClearWindowScope,
+ static_cast
+ (currentInner));
+
+ termFuncSet = PR_TRUE;
+ }
+
+ // Re-push our context.
+ cxPusher.Push(cx);
+ }
+
+ // Don't clear scope on our current inner window if it's going to be
+ // held in the bfcache.
+ if (!currentInner->IsFrozen()) {
+ // Skip the ClearScope if we set a termination function to do
+ // it ourselves, later.
+ currentInner->FreeInnerObjects(!termFuncSet);
+ }
+ }
+
+ mInnerWindow = newInnerWindow;
+ }
+
+ if (!aState && !reUseInnerWindow) {
+ // Loading a new page and creating a new inner window, *not*
+ // restoring from session history.
+
+ // InitClassesWithNewWrappedGlobal() (via CreateNativeGlobalForInner)
+ // for the new inner window
+ // sets the global object in cx to be the new wrapped global. We
+ // don't want that, but re-initializing the outer window will
+ // fix that for us. And perhaps more importantly, this will
+ // ensure that the outer window gets a new prototype so we don't
+ // leak prototype properties from the old inner window to the
+ // new one.
+ NS_STID_FOR_ID(st_id) {
+ nsIScriptContext *this_ctx = GetScriptContextInternal(st_id);
+ if (st_id == nsIProgrammingLanguage::JAVASCRIPT)
+ JS_BeginRequest((JSContext *)this_ctx->GetNativeContext());
+ if (this_ctx) {
+ this_ctx->InitContext(this);
+ // Now that both the the inner and outer windows are initialized
+ // let each script context do its magic to hook them together.
+ void *glob = mScriptGlobals[NS_STID_INDEX(st_id)];
+ this_ctx->ConnectToInner(newInnerWindow, glob);
+ }
+ if (st_id == nsIProgrammingLanguage::JAVASCRIPT)
+ JS_EndRequest((JSContext *)this_ctx->GetNativeContext());
+ }
+
+ nsCOMPtr frame = do_QueryInterface(GetFrameElementInternal());
+ if (frame && frame->GetOwnerDoc()) {
+ nsPIDOMWindow* parentWindow = frame->GetOwnerDoc()->GetWindow();
+ if (parentWindow && parentWindow->TimeoutSuspendCount()) {
+ SuspendTimeouts(parentWindow->TimeoutSuspendCount());
+ }
+ }
+ }
+ // Tell the contexts we have completed setting up the doc.
+ NS_STID_FOR_ID(st_id) {
+ // Add an extra ref in case we release mContext during GC.
+ nsCOMPtr this_ctx =
+ GetScriptContextInternal(st_id);
+ if (this_ctx) {
+ nsCOMPtr dd(do_QueryInterface(aDocument));
+ this_ctx->DidSetDocument(dd, newInnerWindow->GetScriptGlobal(st_id));
+ }
+ }
+
+ // Now that the prototype is all set up, install the global scope
+ // polluter. This must happen after the above prototype fixup. If
+ // the GSP was to be installed on the inner window's real
+ // prototype (as it would be if this was done before the prototype
+ // fixup above) we would end up holding the GSP alive (through
+ // XPConnect's internal marking of wrapper prototypes) as long as
+ // the inner window was around, and if the GSP had properties on
+ // it that held an element alive we'd hold the document alive,
+ // which could hold event handlers alive, which hold the context
+ // alive etc.
+
+ if ((!reUseInnerWindow || aDocument != oldDoc) && !aState) {
+ nsCOMPtr html_doc(do_QueryInterface(mDocument));
+ nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
+ html_doc);
+ }
+
+ // This code should not be called during shutdown any more (now that
+ // we don't ever call SetNewDocument(nsnull), so no need to null
+ // check xpc here.
+ nsIXPConnect *xpc = nsContentUtils::XPConnect();
+
+ if (aState) {
+ // Restoring from session history.
+
+ nsCOMPtr wsh = do_QueryInterface(aState);
+ NS_ASSERTION(wsh, "What kind of weird state are you giving me here?");
+
+ // Restore the prototype for the Window/ChromeWindow class in
+ // the outer window scope.
+ nsCOMPtr ci =
+ do_QueryInterface((nsIScriptGlobalObject *)this);
+
+ rv = xpc->RestoreWrappedNativePrototype(cx, mJSObject, ci,
+ wsh->GetOuterProto());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Refresh the outer window's prototype to what it was when the
+ // window state was saved. This will make the outer window
+ // object (and wrapper) pick up the prototype it had when the
+ // window state was saved. This means Object.prototype etc from
+ // the old inner will again be on the outer window's prototype
+ // chain.
+
+ nsCOMPtr wrapper;
+ rv = xpc->GetWrappedNativeOfJSObject(cx, mJSObject,
+ getter_AddRefs(wrapper));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = wrapper->RefreshPrototype();
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ if (aDocument) {
+ aDocument->SetScriptGlobalObject(newInnerWindow);
+ }
+
+ if (!aState) {
+ if (reUseInnerWindow) {
+ if (newInnerWindow->mDoc != aDocument) {
+ newInnerWindow->mDocument = do_QueryInterface(aDocument);
+ newInnerWindow->mDoc = aDocument;
+
+ // We're reusing the inner window for a new document. In this
+ // case we don't clear the inner window's scope, but we must
+ // make sure the cached document property gets updated.
+
+ // XXXmarkh - tell other languages about this?
+ JSAutoRequest ar(cx);
+ ::JS_DeleteProperty(cx, currentInner->mJSObject, "document");
+ }
+ } else {
+ rv = newInnerWindow->InnerWindowSetNewDocument(aDocument);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_STID_FOR_ID(st_id) {
+ nsIScriptContext *this_ctx = GetScriptContextInternal(st_id);
+ if (this_ctx) {
+ // Initialize DOM classes etc on the inner window.
+ void *glob = newInnerWindow->mScriptGlobals[NS_STID_INDEX(st_id)];
+ rv = this_ctx->InitClasses(glob);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (navigatorHolder &&
+ st_id == nsIProgrammingLanguage::JAVASCRIPT) {
+ // Restore window.navigator onto the new inner window.
+ JSAutoRequest ar(cx);
+
+ ::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
+ nav, nsnull, nsnull,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
+ JSPROP_READONLY);
+
+ // The Navigator's prototype object keeps a reference to the
+ // window in which it was first created and can thus cause that
+ // window to stay alive for too long. Reparenting it here allows
+ // the window to be collected sooner.
+ nsIDOMNavigator* navigator =
+ static_cast(mNavigator);
+
+ xpc->
+ ReparentWrappedNativeIfFound(cx, JSVAL_TO_OBJECT(nav),
+ newInnerWindow->mJSObject,
+ navigator,
+ getter_AddRefs(navigatorHolder));
+ }
+ }
+ }
+ }
+
+ if (mArguments) {
+ newInnerWindow->DefineArgumentsProperty(mArguments);
+ newInnerWindow->mArguments = mArguments;
+ newInnerWindow->mArgumentsOrigin = mArgumentsOrigin;
+
+ mArguments = nsnull;
+ mArgumentsOrigin = nsnull;
+ }
+
+ // Give the new inner window our chrome event handler (since it
+ // doesn't have one).
+ newInnerWindow->mChromeEventHandler = mChromeEventHandler;
+ }
+
+ NS_STID_FOR_ID(st_id) {
+ // Add an extra ref in case we release mContext during GC.
+ nsCOMPtr this_ctx =
+ GetScriptContextInternal(st_id);
+ if (this_ctx) {
+ this_ctx->GC();
+ this_ctx->DidInitializeContext();
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsGlobalWindow::InnerWindowSetNewDocument(nsIDocument* aDocument)
+{
+ NS_PRECONDITION(IsInnerWindow(), "Must only be called on inner windows");
+
+#ifdef PR_LOGGING
+ if (aDocument && gDOMLeakPRLog &&
+ PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
+ nsIURI *uri = aDocument->GetDocumentURI();
+ nsCAutoString spec;
+ if (uri)
+ uri->GetSpec(spec);
+ PR_LogPrint("DOMWINDOW %p SetNewDocument %s", this, spec.get());
+ }
+#endif
mDocument = do_QueryInterface(aDocument);
mDoc = aDocument;
@@ -1722,374 +2089,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
mLastOpenedURI = aDocument->GetDocumentURI();
#endif
- if (IsOuterWindow()) {
- NS_STID_FOR_ID(st_id) {
- nsIScriptContext *langContext = GetScriptContextInternal(st_id);
- if (langContext)
- langContext->WillInitializeContext();
- }
-
- nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
-
- nsRefPtr newInnerWindow;
-
- nsCOMPtr thisChrome =
- do_QueryInterface(static_cast(this));
- nsCOMPtr navigatorHolder;
- jsval nav;
-
- PRBool isChrome = PR_FALSE;
-
- nsCxPusher cxPusher;
- if (!cxPusher.Push(cx)) {
- return NS_ERROR_FAILURE;
- }
-
- JSAutoRequest ar(cx);
-
- // Make sure to clear scope on the outer window *before* we
- // initialize the new inner window. If we don't, things
- // (Object.prototype etc) could leak from the old outer to the new
- // inner scope.
- NS_STID_FOR_ID(st_id) {
- nsIScriptContext *langContext = GetScriptContextInternal(st_id);
- if (langContext)
- langContext->ClearScope(mScriptGlobals[NS_STID_INDEX(st_id)],
- PR_FALSE);
- }
-
- if (reUseInnerWindow) {
- // We're reusing the current inner window.
- NS_ASSERTION(!currentInner->IsFrozen(),
- "We should never be reusing a shared inner window");
- newInnerWindow = currentInner;
-
- if (aDocument != oldDoc) {
- nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
- }
- } else {
- if (aState) {
- nsCOMPtr wsh = do_QueryInterface(aState);
- NS_ASSERTION(wsh, "What kind of weird state are you giving me here?");
-
- newInnerWindow = wsh->GetInnerWindow();
- NS_STID_FOR_ID(st_id) {
- mInnerWindowHolders[NS_STID_INDEX(st_id)] = wsh->GetInnerWindowHolder(st_id);
- }
-
- // These assignments addref.
- mNavigator = wsh->GetNavigator();
- mLocation = wsh->GetLocation();
-
- if (mNavigator) {
- // Update mNavigator's docshell pointer now.
- mNavigator->SetDocShell(mDocShell);
- mNavigator->LoadingNewDocument();
- }
- } else {
- if (thisChrome) {
- newInnerWindow = new nsGlobalChromeWindow(this);
-
- isChrome = PR_TRUE;
- } else {
- if (mIsModalContentWindow) {
- newInnerWindow = new nsGlobalModalWindow(this);
- } else {
- newInnerWindow = new nsGlobalWindow(this);
- }
- }
-
- mLocation = nsnull;
- }
-
- if (!newInnerWindow) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- if (currentInner && currentInner->mJSObject) {
- if (mNavigator && !aState) {
- // Hold on to the navigator wrapper so that we can set
- // window.navigator in the new window to point to the same
- // object (assuming we didn't change origins etc). See bug
- // 163645 for more on why we need this.
-
- nsIDOMNavigator* navigator =
- static_cast(mNavigator.get());
- nsContentUtils::WrapNative(cx, currentInner->mJSObject, navigator,
- &NS_GET_IID(nsIDOMNavigator), &nav,
- getter_AddRefs(navigatorHolder));
- }
- }
-
- if (!aState) {
- // This is redundant if we're restoring from a previous inner window.
- nsIScriptGlobalObject *sgo =
- (nsIScriptGlobalObject *)newInnerWindow.get();
-
- // Freeze the outer window and null out the inner window so
- // that initializing classes on the new inner doesn't end up
- // reaching into the old inner window for classes etc.
- //
- // [This happens with Object.prototype when XPConnect creates
- // a temporary global while initializing classes; the reason
- // being that xpconnect creates the temp global w/o a parent
- // and proto, which makes the JS engine look up classes in
- // cx->globalObject, i.e. this outer window].
-
- mInnerWindow = nsnull;
-
- Freeze();
- mCreatingInnerWindow = PR_TRUE;
- // Every script context we are initialized with must create a
- // new global.
- rv = NS_OK;
- NS_STID_FOR_ID(st_id) {
- st_ndx = NS_STID_INDEX(st_id);
- nsIScriptContext *this_ctx = GetScriptContextInternal(st_id);
- if (this_ctx) {
- void *&newGlobal = newInnerWindow->mScriptGlobals[st_ndx];
- nsCOMPtr &holder = mInnerWindowHolders[st_ndx];
- rv |= this_ctx->CreateNativeGlobalForInner(sgo, isChrome,
- &newGlobal,
- getter_AddRefs(holder));
- NS_ASSERTION(NS_SUCCEEDED(rv) && newGlobal && holder,
- "Failed to get script global and holder");
- if (st_id == nsIProgrammingLanguage::JAVASCRIPT) {
- newInnerWindow->mJSObject = (JSObject *)newGlobal;
- }
- }
- }
- mCreatingInnerWindow = PR_FALSE;
- Thaw();
-
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (currentInner && currentInner->mJSObject) {
- PRBool termFuncSet = PR_FALSE;
-
- if (oldDoc == aDocument) {
- // Suspend the current context's request before Pop() resumes the old
- // context's request.
- JSAutoSuspendRequest asr(cx);
-
- // Pop our context here so that we get the correct one for the
- // termination function.
- cxPusher.Pop();
-
- JSContext *oldCx = nsContentUtils::GetCurrentJSContext();
-
- nsIScriptContext *callerScx;
- if (oldCx && (callerScx = GetScriptContextFromJSContext(oldCx))) {
- // We're called from document.open() (and document.open() is
- // called from JS), clear the scope etc in a termination
- // function on the calling context to prevent clearing the
- // calling scope.
- NS_ASSERTION(!currentInner->IsFrozen(),
- "How does this opened window get into session history");
-
- JSAutoRequest ar(oldCx);
-
- callerScx->SetTerminationFunction(ClearWindowScope,
- static_cast
- (currentInner));
-
- termFuncSet = PR_TRUE;
- }
-
- // Re-push our context.
- cxPusher.Push(cx);
- }
-
- // Don't clear scope on our current inner window if it's going to be
- // held in the bfcache.
- if (!currentInner->IsFrozen()) {
- // Skip the ClearScope if we set a termination function to do
- // it ourselves, later.
- currentInner->FreeInnerObjects(!termFuncSet);
- }
- }
-
- mInnerWindow = newInnerWindow;
- }
-
- if (!aState && !reUseInnerWindow) {
- // Loading a new page and creating a new inner window, *not*
- // restoring from session history.
-
- // InitClassesWithNewWrappedGlobal() (via CreateNativeGlobalForInner)
- // for the new inner window
- // sets the global object in cx to be the new wrapped global. We
- // don't want that, but re-initializing the outer window will
- // fix that for us. And perhaps more importantly, this will
- // ensure that the outer window gets a new prototype so we don't
- // leak prototype properties from the old inner window to the
- // new one.
- NS_STID_FOR_ID(st_id) {
- nsIScriptContext *this_ctx = GetScriptContextInternal(st_id);
- if (st_id == nsIProgrammingLanguage::JAVASCRIPT)
- JS_BeginRequest((JSContext *)this_ctx->GetNativeContext());
- if (this_ctx) {
- this_ctx->InitContext(this);
- // Now that both the the inner and outer windows are initialized
- // let each script context do its magic to hook them together.
- void *glob = mScriptGlobals[NS_STID_INDEX(st_id)];
- this_ctx->ConnectToInner(newInnerWindow, glob);
- }
- if (st_id == nsIProgrammingLanguage::JAVASCRIPT)
- JS_EndRequest((JSContext *)this_ctx->GetNativeContext());
- }
-
- nsCOMPtr frame = do_QueryInterface(GetFrameElementInternal());
- if (frame && frame->GetOwnerDoc()) {
- nsPIDOMWindow* parentWindow = frame->GetOwnerDoc()->GetWindow();
- if (parentWindow && parentWindow->TimeoutSuspendCount()) {
- SuspendTimeouts(parentWindow->TimeoutSuspendCount());
- }
- }
- }
- // Tell the contexts we have completed setting up the doc.
- NS_STID_FOR_ID(st_id) {
- // Add an extra ref in case we release mContext during GC.
- nsCOMPtr this_ctx =
- GetScriptContextInternal(st_id);
- if (this_ctx) {
- nsCOMPtr dd(do_QueryInterface(aDocument));
- this_ctx->DidSetDocument(dd, newInnerWindow->GetScriptGlobal(st_id));
- }
- }
-
- // Now that the prototype is all set up, install the global scope
- // polluter. This must happen after the above prototype fixup. If
- // the GSP was to be installed on the inner window's real
- // prototype (as it would be if this was done before the prototype
- // fixup above) we would end up holding the GSP alive (through
- // XPConnect's internal marking of wrapper prototypes) as long as
- // the inner window was around, and if the GSP had properties on
- // it that held an element alive we'd hold the document alive,
- // which could hold event handlers alive, which hold the context
- // alive etc.
-
- if ((!reUseInnerWindow || aDocument != oldDoc) && !aState) {
- nsCOMPtr html_doc(do_QueryInterface(mDocument));
- nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
- html_doc);
- }
-
- if (aState) {
- // Restoring from session history.
-
- nsCOMPtr wsh = do_QueryInterface(aState);
- NS_ASSERTION(wsh, "What kind of weird state are you giving me here?");
-
- // Restore the prototype for the Window/ChromeWindow class in
- // the outer window scope.
- nsCOMPtr ci =
- do_QueryInterface((nsIScriptGlobalObject *)this);
-
- rv = xpc->RestoreWrappedNativePrototype(cx, mJSObject, ci,
- wsh->GetOuterProto());
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Refresh the outer window's prototype to what it was when the
- // window state was saved. This will make the outer window
- // object (and wrapper) pick up the prototype it had when the
- // window state was saved. This means Object.prototype etc from
- // the old inner will again be on the outer window's prototype
- // chain.
-
- nsCOMPtr wrapper;
- rv = xpc->GetWrappedNativeOfJSObject(cx, mJSObject,
- getter_AddRefs(wrapper));
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = wrapper->RefreshPrototype();
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- if (aDocument) {
- aDocument->SetScriptGlobalObject(newInnerWindow);
- }
-
- if (!aState) {
- if (reUseInnerWindow) {
- if (newInnerWindow->mDoc != aDocument) {
- newInnerWindow->mDocument = do_QueryInterface(aDocument);
- newInnerWindow->mDoc = aDocument;
-
- // We're reusing the inner window for a new document. In this
- // case we don't clear the inner window's scope, but we must
- // make sure the cached document property gets updated.
-
- // XXXmarkh - tell other languages about this?
- JSAutoRequest ar(cx);
- ::JS_DeleteProperty(cx, currentInner->mJSObject, "document");
- }
- } else {
- rv = newInnerWindow->SetNewDocument(aDocument, nsnull,
- aClearScopeHint, PR_TRUE);
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_STID_FOR_ID(st_id) {
- nsIScriptContext *this_ctx = GetScriptContextInternal(st_id);
- if (this_ctx) {
- // Initialize DOM classes etc on the inner window.
- void *glob = newInnerWindow->mScriptGlobals[NS_STID_INDEX(st_id)];
- rv = this_ctx->InitClasses(glob);
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (navigatorHolder &&
- st_id == nsIProgrammingLanguage::JAVASCRIPT) {
- // Restore window.navigator onto the new inner window.
- JSAutoRequest ar(cx);
-
- ::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
- nav, nsnull, nsnull,
- JSPROP_ENUMERATE | JSPROP_PERMANENT |
- JSPROP_READONLY);
-
- // The Navigator's prototype object keeps a reference to the
- // window in which it was first created and can thus cause that
- // window to stay alive for too long. Reparenting it here allows
- // the window to be collected sooner.
- nsIDOMNavigator* navigator =
- static_cast(mNavigator);
-
- xpc->
- ReparentWrappedNativeIfFound(cx, JSVAL_TO_OBJECT(nav),
- newInnerWindow->mJSObject,
- navigator,
- getter_AddRefs(navigatorHolder));
- }
- }
- }
- }
-
- if (mArguments) {
- newInnerWindow->DefineArgumentsProperty(mArguments);
- newInnerWindow->mArguments = mArguments;
- newInnerWindow->mArgumentsOrigin = mArgumentsOrigin;
-
- mArguments = nsnull;
- mArgumentsOrigin = nsnull;
- }
-
- // Give the new inner window our chrome event handler (since it
- // doesn't have one).
- newInnerWindow->mChromeEventHandler = mChromeEventHandler;
- }
-
- NS_STID_FOR_ID(st_id) {
- // Add an extra ref in case we release mContext during GC.
- nsCOMPtr this_ctx =
- GetScriptContextInternal(st_id);
- if (this_ctx) {
- this_ctx->GC();
- this_ctx->DidInitializeContext();
- }
- }
- }
-
// Clear our mutation bitfield.
mMutationBits = 0;
@@ -9445,8 +9444,7 @@ nsGlobalModalWindow::SetReturnValue(nsIVariant *aRetVal)
nsresult
nsGlobalModalWindow::SetNewDocument(nsIDocument *aDocument,
- nsISupports *aState,
- PRBool aClearScopeHint)
+ nsISupports *aState)
{
// If we're loading a new document into a modal dialog, clear the
// return value that was set, if any, by the current document.
@@ -9454,7 +9452,7 @@ nsGlobalModalWindow::SetNewDocument(nsIDocument *aDocument,
mReturnValue = nsnull;
}
- return nsGlobalWindow::SetNewDocument(aDocument, aState, aClearScopeHint);
+ return nsGlobalWindow::SetNewDocument(aDocument, aState);
}
//*****************************************************************************
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index 8d89e7aa3da..86c4873164c 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -335,8 +335,7 @@ public:
virtual NS_HIDDEN_(void) SetDocShell(nsIDocShell* aDocShell);
virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument,
- nsISupports *aState,
- PRBool aClearScopeHint);
+ nsISupports *aState);
virtual NS_HIDDEN_(void) SetOpenerWindow(nsIDOMWindowInternal *aOpener,
PRBool aOriginalOpener);
virtual NS_HIDDEN_(void) EnsureSizeUpToDate();
@@ -463,10 +462,8 @@ protected:
void FreeInnerObjects(PRBool aClearScope);
nsGlobalWindow *CallerInnerWindow();
- nsresult SetNewDocument(nsIDocument *aDocument,
- nsISupports *aState,
- PRBool aClearScopeHint,
- PRBool aIsInternalCall);
+ nsresult InnerWindowSetNewDocument(nsIDocument* aDocument);
+
nsresult DefineArgumentsProperty(nsIArray *aArguments);
// Get the parent, returns null if this is a toplevel window
@@ -848,8 +845,7 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument,
- nsISupports *aState,
- PRBool aClearScopeHint);
+ nsISupports *aState);
protected:
nsCOMPtr mReturnValue;
diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h
index 02d0f887dcc..faa28ee7fd5 100644
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -78,8 +78,8 @@ class nsIArray;
class nsPIWindowRoot;
#define NS_PIDOMWINDOW_IID \
-{ 0x2962cfa4, 0x13f9, 0x4606, \
- { 0x84, 0x64, 0xef, 0x4c, 0xfa, 0x33, 0xcc, 0xce } }
+{ 0x81cdf500, 0x2183, 0x4af6, \
+ { 0xa4, 0x56, 0x35, 0x1f, 0x4a, 0x0d, 0x1a, 0x0b } }
class nsPIDOMWindow : public nsIDOMWindowInternal
{
@@ -353,8 +353,7 @@ public:
* created.
*/
virtual nsresult SetNewDocument(nsIDocument *aDocument,
- nsISupports *aState,
- PRBool aClearScope) = 0;
+ nsISupports *aState) = 0;
/**
* Set the opener window. aOriginalOpener is true if and only if this is the
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
index f8a59e338b3..b0048b268df 100644
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -946,7 +946,7 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
getter_AddRefs(window));
if (window) {
- window->SetNewDocument(mDocument, aState, PR_TRUE);
+ window->SetNewDocument(mDocument, aState);
nsJSContext::LoadStart();
}
@@ -1695,7 +1695,7 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
// Set the script global object on the new document
nsCOMPtr window = do_GetInterface(container);
if (window) {
- window->SetNewDocument(newDoc, nsnull, PR_TRUE);
+ window->SetNewDocument(newDoc, nsnull);
}
// Clear the list of old child docshells. CChild docshells for the new