Fixing leak introduced by the fix for bug 256932. Make sure we release the document pointer held by the global scope polluter holds as private data early enough to let the document do its cleanup before it's too late during shutdown. r=brendan@mozilla.org, sr=dbaron@dbaron.org

This commit is contained in:
jst%mozilla.jstenback.com 2004-08-27 21:06:19 +00:00
parent 78e6b08b52
commit 376c9e5ad7
3 changed files with 62 additions and 16 deletions

View File

@ -3470,20 +3470,49 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
return JS_TRUE;
}
// static
JSObject *
nsWindowSH::GetInvalidatedGlobalScopePolluter(JSContext *cx, JSObject *obj)
{
JSObject *proto;
while ((proto = ::JS_GetPrototype(cx, obj))) {
if (JS_GET_CLASS(cx, proto) == &sGlobalScopePolluterClass) {
nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(cx, proto);
NS_IF_RELEASE(doc);
::JS_SetPrivate(cx, proto, nsnull);
::JS_ClearScope(cx, proto);
break;
}
obj = proto;
}
return proto;
}
// static
nsresult
nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
JSObject *oldPolluter,
nsIHTMLDocument *doc)
{
// If we didn't get a document, don't bother setting up a global
// scope polluter.
if (!doc || sDisableGlobalScopePollutionSupport) {
// If global scope pollution is disabled, do nothing
if (sDisableGlobalScopePollutionSupport) {
return NS_OK;
}
JSObject *gsp = ::JS_NewObject(cx, &sGlobalScopePolluterClass, nsnull, obj);
JSObject *gsp = oldPolluter;
if (!gsp) {
return NS_ERROR_OUT_OF_MEMORY;
gsp = ::JS_NewObject(cx, &sGlobalScopePolluterClass, nsnull, obj);
if (!gsp) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
JSObject *o = obj, *proto;
@ -3504,7 +3533,7 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
o = proto;
}
// And then set the ptototype of the object whose prototype was
// And then set the prototype of the object whose prototype was
// Object.prototype to be the global scope polluter.
if (!::JS_SetPrototype(cx, o, gsp)) {
return NS_ERROR_UNEXPECTED;
@ -3516,7 +3545,7 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
// The global scope polluter will release doc on destruction (or
// reinitialzation).
NS_ADDREF(doc);
NS_IF_ADDREF(doc);
return NS_OK;
}
@ -4489,9 +4518,7 @@ nsWindowSH::OnDocumentChanged(JSContext *cx, JSObject *obj,
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIHTMLDocument> html_doc(do_QueryInterface(document));
return InstallGlobalScopePolluter(cx, obj, html_doc);
return NS_OK;
}
NS_IMETHODIMP

View File

@ -373,7 +373,10 @@ public:
static JSBool JS_DLL_CALLBACK SecurityCheckOnSetProp(JSContext *cx,
JSObject *obj, jsval id,
jsval *vp);
static JSObject *GetInvalidatedGlobalScopePolluter(JSContext *cx,
JSObject *obj);
static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
JSObject *oldPolluter,
nsIHTMLDocument *doc);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)

View File

@ -81,6 +81,7 @@
#include "nsIDocShellTreeNode.h"
#include "nsIDocCharset.h"
#include "nsIDocument.h"
#include "nsIHTMLDocument.h"
#include "nsIDOMCrypto.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentView.h"
@ -602,9 +603,19 @@ GlobalWindowImpl::SetNewDocument(nsIDOMDocument* aDocument,
getter_AddRefs(mNavigatorHolder));
}
JSObject *gsp =
nsWindowSH::GetInvalidatedGlobalScopePolluter(cx, mJSObject);
::JS_ClearScope(cx, mJSObject);
::JS_ClearRegExpStatics(cx);
if (gsp) {
nsCOMPtr<nsIHTMLDocument> html_doc(do_QueryInterface(mDocument));
nsWindowSH::InstallGlobalScopePolluter(cx, mJSObject, gsp,
html_doc);
}
mIsScopeClear = PR_TRUE;
}
}
@ -642,18 +653,23 @@ GlobalWindowImpl::SetNewDocument(nsIDOMDocument* aDocument,
mDocument = aDocument;
if (mDocument && mContext) {
JSObject *gsp =
nsWindowSH::GetInvalidatedGlobalScopePolluter(cx, mJSObject);
if (mIsScopeClear) {
mContext->InitContext(this);
} else {
// If we didn't clear the scope (i.e. the old document was
// about:blank) then we need to update the cached document
// property on the window to reflect the new document and not the
// old one.
nsWindowSH::OnDocumentChanged(cx, mJSObject, this);
}
// If we didn't clear the scope (i.e. the old document was
// about:blank) then we need to update the cached document
// property on the window to reflect the new document and not the
// old one. And even if we did clear the scope, we need to notify
// the scriptable helper about the document change.
nsCOMPtr<nsIHTMLDocument> html_doc(do_QueryInterface(mDocument));
nsWindowSH::OnDocumentChanged(cx, mJSObject, this);
nsWindowSH::InstallGlobalScopePolluter(cx, mJSObject, gsp, html_doc);
}
// Clear our mutation bitfield.