Fix bug 28570, leak of nsXULPrototypeDocument and nsJSContext (and things they owned). r=waterson@netscape.com

This commit is contained in:
dbaron%fas.harvard.edu 2000-03-16 01:11:02 +00:00
Родитель 47956a0718
Коммит e3a2013a7e
4 изменённых файлов: 500 добавлений и 380 удалений

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

@ -68,6 +68,7 @@
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptGlobalObjectOwner.h"
#include "nsIServiceManager.h"
#include "nsIStyleContext.h"
#include "nsIStyleRule.h"
@ -1988,8 +1989,10 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
if (! protodoc)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(protodoc);
NS_ASSERTION(global != nsnull, "prototype doc is not a script global");
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner = do_QueryInterface(protodoc);
nsCOMPtr<nsIScriptGlobalObject> global;
globalOwner->GetScriptGlobalObject(getter_AddRefs(global));
NS_ASSERTION(global != nsnull, "prototype doc does not have a script global");
if (! global)
return NS_ERROR_UNEXPECTED;
@ -1997,7 +2000,7 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
if (NS_FAILED(rv)) return rv;
// Use the prototype script's special scope object
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(protodoc);
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(global);
if (! owner)
return NS_ERROR_UNEXPECTED;
@ -4435,25 +4438,26 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
// Use the prototype document's special context
nsCOMPtr<nsIScriptContext> context;
// Use the prototype script's special scope object
JSObject* scopeObject;
{
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(aPrototypeDocument);
NS_ASSERTION(global != nsnull, "prototype doc is not a script global");
nsCOMPtr<nsIScriptGlobalObject> global;
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner
= do_QueryInterface(aPrototypeDocument);
globalOwner->GetScriptGlobalObject(getter_AddRefs(global));
NS_ASSERTION(global != nsnull, "prototype doc has no script global");
if (! global)
return NS_ERROR_UNEXPECTED;
rv = global->GetContext(getter_AddRefs(context));
if (NS_FAILED(rv)) return rv;
}
NS_ASSERTION(context != nsnull, "no context for script global");
if (! context)
return NS_ERROR_UNEXPECTED;
NS_ASSERTION(context != nsnull, "no context for script global");
if (! context)
return NS_ERROR_UNEXPECTED;
// Use the prototype script's special scope object
JSObject* scopeObject;
{
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(aPrototypeDocument);
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(global);
if (! owner)
return NS_ERROR_UNEXPECTED;

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

@ -18,6 +18,7 @@
* Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@fas.harvard.edu>
*/
/*
@ -41,12 +42,51 @@
#include "nsVoidArray.h"
#include "nsXULElement.h"
class nsXULPDGlobalObject : public nsIScriptObjectOwner,
public nsIScriptGlobalObject,
public nsIScriptObjectPrincipal
{
public:
nsXULPDGlobalObject();
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIScriptObjectOwner methods
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void **aObject);
NS_IMETHOD SetScriptObject(void *aObject);
// nsIScriptGlobalObject methods
NS_IMETHOD SetContext(nsIScriptContext *aContext);
NS_IMETHOD GetContext(nsIScriptContext **aContext);
NS_IMETHOD SetNewDocument(nsIDOMDocument *aDocument);
NS_IMETHOD SetDocShell(nsIDocShell *aDocShell);
NS_IMETHOD GetDocShell(nsIDocShell **aDocShell);
NS_IMETHOD SetOpenerWindow(nsIDOMWindow *aOpener);
NS_IMETHOD SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner);
NS_IMETHOD GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner);
NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
// nsIScriptObjectPrincipal methods
NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal);
protected:
virtual ~nsXULPDGlobalObject();
nsCOMPtr<nsIScriptContext> mScriptContext;
JSObject *mScriptObject; // XXX JS language rabies bigotry badness
nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // weak reference
static JSClass gSharedGlobalClass;
};
class nsXULPrototypeDocument : public nsIXULPrototypeDocument,
public nsIScriptObjectOwner,
public nsIScriptGlobalObject,
public nsIScriptGlobalObjectOwner,
public nsIScriptObjectPrincipal
public nsIScriptGlobalObjectOwner
{
public:
static nsresult
@ -74,31 +114,9 @@ public:
NS_IMETHOD GetDocumentPrincipal(nsIPrincipal** aResult);
NS_IMETHOD SetDocumentPrincipal(nsIPrincipal* aPrincipal);
// nsIScriptObjectOwner methods
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void **aObject);
NS_IMETHOD SetScriptObject(void *aObject);
// nsIScriptGlobalObject methods
NS_IMETHOD SetContext(nsIScriptContext *aContext);
NS_IMETHOD GetContext(nsIScriptContext **aContext);
NS_IMETHOD SetNewDocument(nsIDOMDocument *aDocument);
NS_IMETHOD SetDocShell(nsIDocShell *aDocShell);
NS_IMETHOD GetDocShell(nsIDocShell **aDocShell);
NS_IMETHOD SetOpenerWindow(nsIDOMWindow *aOpener);
NS_IMETHOD SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner);
NS_IMETHOD GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner);
NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
// nsIScriptGlobalObjectOwner methods
NS_DECL_NSISCRIPTGLOBALOBJECTOWNER
// nsIScriptObjectPrincipal methods
NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal);
protected:
nsCOMPtr<nsIURI> mURI;
@ -107,8 +125,7 @@ protected:
nsCOMPtr<nsISupportsArray> mOverlayReferences;
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
nsCOMPtr<nsIScriptContext> mScriptContext;
JSObject *mScriptObject; // XXX JS language rabies bigotry badness
nsCOMPtr<nsIScriptGlobalObject> mGlobalObject;
nsXULPrototypeDocument();
virtual ~nsXULPrototypeDocument();
@ -116,11 +133,9 @@ protected:
friend NS_IMETHODIMP
NS_NewXULPrototypeDocument(nsISupports* aOuter, REFNSIID aIID, void** aResult);
static JSClass gSharedGlobalClass;
};
JSClass nsXULPrototypeDocument::gSharedGlobalClass = {
JSClass nsXULPDGlobalObject::gSharedGlobalClass = {
"nsXULPrototypeScript compilation scope",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
@ -136,7 +151,7 @@ JSClass nsXULPrototypeDocument::gSharedGlobalClass = {
nsXULPrototypeDocument::nsXULPrototypeDocument()
: mRoot(nsnull),
mScriptObject(nsnull)
mGlobalObject(nsnull)
{
NS_INIT_REFCNT();
}
@ -159,6 +174,10 @@ nsXULPrototypeDocument::Init()
nsXULPrototypeDocument::~nsXULPrototypeDocument()
{
if (mGlobalObject) {
mGlobalObject->SetContext(nsnull); // remove circular reference
mGlobalObject->SetGlobalObjectOwner(nsnull); // just in case
}
delete mRoot;
}
@ -167,10 +186,7 @@ NS_IMPL_RELEASE(nsXULPrototypeDocument)
NS_INTERFACE_MAP_BEGIN(nsXULPrototypeDocument)
NS_INTERFACE_MAP_ENTRY(nsIXULPrototypeDocument)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectOwner)
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObjectOwner)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
@ -331,144 +347,6 @@ nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsIScriptObjectOwner methods
//
NS_IMETHODIMP
nsXULPrototypeDocument::GetScriptObject(nsIScriptContext *aContext, void **aObject)
{
// The prototype document has its own special secret script object
// that can be used to compile scripts and event handlers.
nsresult rv;
nsCOMPtr<nsIScriptContext> context;
if (mScriptContext && aContext != mScriptContext.get()) {
rv = GetContext(getter_AddRefs(context));
if (NS_FAILED(rv)) return rv;
}
else {
context = aContext;
}
if (! mScriptObject) {
JSContext* cx = NS_REINTERPRET_CAST(JSContext*, context->GetNativeContext());
if (! cx)
return NS_ERROR_OUT_OF_MEMORY;
mScriptObject = JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
if (! mScriptObject)
return NS_ERROR_OUT_OF_MEMORY;
// Add an owning reference from JS back to us. This'll be
// released when the JSObject is finalized.
::JS_SetPrivate(cx, mScriptObject, this);
NS_ADDREF(this);
}
*aObject = mScriptObject;
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetScriptObject(void *aObject)
{
mScriptObject = (JSObject *)aObject;
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsIScriptGlobalObject methods
//
NS_IMETHODIMP
nsXULPrototypeDocument::SetContext(nsIScriptContext *aContext)
{
mScriptContext = aContext;
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::GetContext(nsIScriptContext **aContext)
{
// This whole fragile mess is predicated on the fact that
// GetContext() will be called before GetScriptObject() is.
if (! mScriptContext) {
nsresult rv;
rv = NS_CreateScriptContext(this, getter_AddRefs(mScriptContext));
if (NS_FAILED(rv)) return rv;
}
*aContext = mScriptContext;
NS_IF_ADDREF(*aContext);
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetNewDocument(nsIDOMDocument *aDocument)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetDocShell(nsIDocShell *aDocShell)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::GetDocShell(nsIDocShell **aDocShell)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetOpenerWindow(nsIDOMWindow *aOpener)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner)
{
*aOwner = NS_STATIC_CAST(nsIScriptGlobalObjectOwner*, this);
NS_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::HandleDOMEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
//----------------------------------------------------------------------
//
// nsIScriptGlobalObjectOwner methods
@ -477,7 +355,15 @@ nsXULPrototypeDocument::HandleDOMEvent(nsIPresContext* aPresContext,
NS_IMETHODIMP
nsXULPrototypeDocument::GetScriptGlobalObject(nsIScriptGlobalObject** _result)
{
*_result = NS_STATIC_CAST(nsIScriptGlobalObject*, this);
if (!mGlobalObject) {
mGlobalObject = new nsXULPDGlobalObject();
if (!mGlobalObject) {
*_result = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
mGlobalObject->SetGlobalObjectOwner(this); // does not refcount
}
*_result = mGlobalObject;
NS_ADDREF(*_result);
return NS_OK;
}
@ -513,14 +399,184 @@ nsXULPrototypeDocument::ReportScriptError(const char* aErrorString,
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsXULPDGlobalObject
//
nsXULPDGlobalObject::nsXULPDGlobalObject()
: mScriptObject(nsnull),
mGlobalObjectOwner(nsnull)
{
NS_INIT_REFCNT();
}
nsXULPDGlobalObject::~nsXULPDGlobalObject()
{
}
NS_IMPL_ADDREF(nsXULPDGlobalObject)
NS_IMPL_RELEASE(nsXULPDGlobalObject)
NS_INTERFACE_MAP_BEGIN(nsXULPDGlobalObject)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectOwner)
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
//
// nsIScriptObjectOwner methods
//
NS_IMETHODIMP
nsXULPDGlobalObject::GetScriptObject(nsIScriptContext *aContext, void **aObject)
{
// The prototype document has its own special secret script object
// that can be used to compile scripts and event handlers.
nsresult rv;
nsCOMPtr<nsIScriptContext> context;
if (mScriptContext && aContext != mScriptContext.get()) {
rv = GetContext(getter_AddRefs(context));
if (NS_FAILED(rv)) return rv;
}
else {
context = aContext;
}
if (! mScriptObject) {
JSContext* cx = NS_REINTERPRET_CAST(JSContext*, context->GetNativeContext());
if (! cx)
return NS_ERROR_OUT_OF_MEMORY;
mScriptObject = JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
if (! mScriptObject)
return NS_ERROR_OUT_OF_MEMORY;
// Add an owning reference from JS back to us. This'll be
// released when the JSObject is finalized.
::JS_SetPrivate(cx, mScriptObject, this);
NS_ADDREF(this);
}
*aObject = mScriptObject;
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetScriptObject(void *aObject)
{
mScriptObject = (JSObject *)aObject;
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsIScriptGlobalObject methods
//
NS_IMETHODIMP
nsXULPDGlobalObject::SetContext(nsIScriptContext *aContext)
{
mScriptContext = aContext;
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::GetContext(nsIScriptContext **aContext)
{
// This whole fragile mess is predicated on the fact that
// GetContext() will be called before GetScriptObject() is.
if (! mScriptContext) {
nsresult rv;
rv = NS_CreateScriptContext(this, getter_AddRefs(mScriptContext));
if (NS_FAILED(rv)) return rv;
}
*aContext = mScriptContext;
NS_IF_ADDREF(*aContext);
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetNewDocument(nsIDOMDocument *aDocument)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetDocShell(nsIDocShell *aDocShell)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPDGlobalObject::GetDocShell(nsIDocShell **aDocShell)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetOpenerWindow(nsIDOMWindow *aOpener)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner)
{
mGlobalObjectOwner = aOwner; // weak reference
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner)
{
*aOwner = mGlobalObjectOwner;
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::HandleDOMEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
//----------------------------------------------------------------------
//
// nsIScriptObjectPrincipal methods
//
NS_IMETHODIMP
nsXULPrototypeDocument::GetPrincipal(nsIPrincipal** aPrincipal)
nsXULPDGlobalObject::GetPrincipal(nsIPrincipal** aPrincipal)
{
return GetDocumentPrincipal(aPrincipal);
if (!mGlobalObjectOwner) {
*aPrincipal = nsnull;
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIXULPrototypeDocument> protoDoc
= do_QueryInterface(mGlobalObjectOwner);
return protoDoc->GetDocumentPrincipal(aPrincipal);
}

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

@ -68,6 +68,7 @@
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptGlobalObjectOwner.h"
#include "nsIServiceManager.h"
#include "nsIStyleContext.h"
#include "nsIStyleRule.h"
@ -1988,8 +1989,10 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
if (! protodoc)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(protodoc);
NS_ASSERTION(global != nsnull, "prototype doc is not a script global");
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner = do_QueryInterface(protodoc);
nsCOMPtr<nsIScriptGlobalObject> global;
globalOwner->GetScriptGlobalObject(getter_AddRefs(global));
NS_ASSERTION(global != nsnull, "prototype doc does not have a script global");
if (! global)
return NS_ERROR_UNEXPECTED;
@ -1997,7 +2000,7 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
if (NS_FAILED(rv)) return rv;
// Use the prototype script's special scope object
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(protodoc);
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(global);
if (! owner)
return NS_ERROR_UNEXPECTED;
@ -4435,25 +4438,26 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
// Use the prototype document's special context
nsCOMPtr<nsIScriptContext> context;
// Use the prototype script's special scope object
JSObject* scopeObject;
{
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(aPrototypeDocument);
NS_ASSERTION(global != nsnull, "prototype doc is not a script global");
nsCOMPtr<nsIScriptGlobalObject> global;
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner
= do_QueryInterface(aPrototypeDocument);
globalOwner->GetScriptGlobalObject(getter_AddRefs(global));
NS_ASSERTION(global != nsnull, "prototype doc has no script global");
if (! global)
return NS_ERROR_UNEXPECTED;
rv = global->GetContext(getter_AddRefs(context));
if (NS_FAILED(rv)) return rv;
}
NS_ASSERTION(context != nsnull, "no context for script global");
if (! context)
return NS_ERROR_UNEXPECTED;
NS_ASSERTION(context != nsnull, "no context for script global");
if (! context)
return NS_ERROR_UNEXPECTED;
// Use the prototype script's special scope object
JSObject* scopeObject;
{
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(aPrototypeDocument);
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(global);
if (! owner)
return NS_ERROR_UNEXPECTED;

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

@ -18,6 +18,7 @@
* Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@fas.harvard.edu>
*/
/*
@ -41,12 +42,51 @@
#include "nsVoidArray.h"
#include "nsXULElement.h"
class nsXULPDGlobalObject : public nsIScriptObjectOwner,
public nsIScriptGlobalObject,
public nsIScriptObjectPrincipal
{
public:
nsXULPDGlobalObject();
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIScriptObjectOwner methods
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void **aObject);
NS_IMETHOD SetScriptObject(void *aObject);
// nsIScriptGlobalObject methods
NS_IMETHOD SetContext(nsIScriptContext *aContext);
NS_IMETHOD GetContext(nsIScriptContext **aContext);
NS_IMETHOD SetNewDocument(nsIDOMDocument *aDocument);
NS_IMETHOD SetDocShell(nsIDocShell *aDocShell);
NS_IMETHOD GetDocShell(nsIDocShell **aDocShell);
NS_IMETHOD SetOpenerWindow(nsIDOMWindow *aOpener);
NS_IMETHOD SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner);
NS_IMETHOD GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner);
NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
// nsIScriptObjectPrincipal methods
NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal);
protected:
virtual ~nsXULPDGlobalObject();
nsCOMPtr<nsIScriptContext> mScriptContext;
JSObject *mScriptObject; // XXX JS language rabies bigotry badness
nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // weak reference
static JSClass gSharedGlobalClass;
};
class nsXULPrototypeDocument : public nsIXULPrototypeDocument,
public nsIScriptObjectOwner,
public nsIScriptGlobalObject,
public nsIScriptGlobalObjectOwner,
public nsIScriptObjectPrincipal
public nsIScriptGlobalObjectOwner
{
public:
static nsresult
@ -74,31 +114,9 @@ public:
NS_IMETHOD GetDocumentPrincipal(nsIPrincipal** aResult);
NS_IMETHOD SetDocumentPrincipal(nsIPrincipal* aPrincipal);
// nsIScriptObjectOwner methods
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void **aObject);
NS_IMETHOD SetScriptObject(void *aObject);
// nsIScriptGlobalObject methods
NS_IMETHOD SetContext(nsIScriptContext *aContext);
NS_IMETHOD GetContext(nsIScriptContext **aContext);
NS_IMETHOD SetNewDocument(nsIDOMDocument *aDocument);
NS_IMETHOD SetDocShell(nsIDocShell *aDocShell);
NS_IMETHOD GetDocShell(nsIDocShell **aDocShell);
NS_IMETHOD SetOpenerWindow(nsIDOMWindow *aOpener);
NS_IMETHOD SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner);
NS_IMETHOD GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner);
NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
// nsIScriptGlobalObjectOwner methods
NS_DECL_NSISCRIPTGLOBALOBJECTOWNER
// nsIScriptObjectPrincipal methods
NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal);
protected:
nsCOMPtr<nsIURI> mURI;
@ -107,8 +125,7 @@ protected:
nsCOMPtr<nsISupportsArray> mOverlayReferences;
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
nsCOMPtr<nsIScriptContext> mScriptContext;
JSObject *mScriptObject; // XXX JS language rabies bigotry badness
nsCOMPtr<nsIScriptGlobalObject> mGlobalObject;
nsXULPrototypeDocument();
virtual ~nsXULPrototypeDocument();
@ -116,11 +133,9 @@ protected:
friend NS_IMETHODIMP
NS_NewXULPrototypeDocument(nsISupports* aOuter, REFNSIID aIID, void** aResult);
static JSClass gSharedGlobalClass;
};
JSClass nsXULPrototypeDocument::gSharedGlobalClass = {
JSClass nsXULPDGlobalObject::gSharedGlobalClass = {
"nsXULPrototypeScript compilation scope",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
@ -136,7 +151,7 @@ JSClass nsXULPrototypeDocument::gSharedGlobalClass = {
nsXULPrototypeDocument::nsXULPrototypeDocument()
: mRoot(nsnull),
mScriptObject(nsnull)
mGlobalObject(nsnull)
{
NS_INIT_REFCNT();
}
@ -159,6 +174,10 @@ nsXULPrototypeDocument::Init()
nsXULPrototypeDocument::~nsXULPrototypeDocument()
{
if (mGlobalObject) {
mGlobalObject->SetContext(nsnull); // remove circular reference
mGlobalObject->SetGlobalObjectOwner(nsnull); // just in case
}
delete mRoot;
}
@ -167,10 +186,7 @@ NS_IMPL_RELEASE(nsXULPrototypeDocument)
NS_INTERFACE_MAP_BEGIN(nsXULPrototypeDocument)
NS_INTERFACE_MAP_ENTRY(nsIXULPrototypeDocument)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectOwner)
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObjectOwner)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
@ -331,144 +347,6 @@ nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsIScriptObjectOwner methods
//
NS_IMETHODIMP
nsXULPrototypeDocument::GetScriptObject(nsIScriptContext *aContext, void **aObject)
{
// The prototype document has its own special secret script object
// that can be used to compile scripts and event handlers.
nsresult rv;
nsCOMPtr<nsIScriptContext> context;
if (mScriptContext && aContext != mScriptContext.get()) {
rv = GetContext(getter_AddRefs(context));
if (NS_FAILED(rv)) return rv;
}
else {
context = aContext;
}
if (! mScriptObject) {
JSContext* cx = NS_REINTERPRET_CAST(JSContext*, context->GetNativeContext());
if (! cx)
return NS_ERROR_OUT_OF_MEMORY;
mScriptObject = JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
if (! mScriptObject)
return NS_ERROR_OUT_OF_MEMORY;
// Add an owning reference from JS back to us. This'll be
// released when the JSObject is finalized.
::JS_SetPrivate(cx, mScriptObject, this);
NS_ADDREF(this);
}
*aObject = mScriptObject;
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetScriptObject(void *aObject)
{
mScriptObject = (JSObject *)aObject;
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsIScriptGlobalObject methods
//
NS_IMETHODIMP
nsXULPrototypeDocument::SetContext(nsIScriptContext *aContext)
{
mScriptContext = aContext;
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::GetContext(nsIScriptContext **aContext)
{
// This whole fragile mess is predicated on the fact that
// GetContext() will be called before GetScriptObject() is.
if (! mScriptContext) {
nsresult rv;
rv = NS_CreateScriptContext(this, getter_AddRefs(mScriptContext));
if (NS_FAILED(rv)) return rv;
}
*aContext = mScriptContext;
NS_IF_ADDREF(*aContext);
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetNewDocument(nsIDOMDocument *aDocument)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetDocShell(nsIDocShell *aDocShell)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::GetDocShell(nsIDocShell **aDocShell)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetOpenerWindow(nsIDOMWindow *aOpener)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPrototypeDocument::GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner)
{
*aOwner = NS_STATIC_CAST(nsIScriptGlobalObjectOwner*, this);
NS_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP
nsXULPrototypeDocument::HandleDOMEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
//----------------------------------------------------------------------
//
// nsIScriptGlobalObjectOwner methods
@ -477,7 +355,15 @@ nsXULPrototypeDocument::HandleDOMEvent(nsIPresContext* aPresContext,
NS_IMETHODIMP
nsXULPrototypeDocument::GetScriptGlobalObject(nsIScriptGlobalObject** _result)
{
*_result = NS_STATIC_CAST(nsIScriptGlobalObject*, this);
if (!mGlobalObject) {
mGlobalObject = new nsXULPDGlobalObject();
if (!mGlobalObject) {
*_result = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
mGlobalObject->SetGlobalObjectOwner(this); // does not refcount
}
*_result = mGlobalObject;
NS_ADDREF(*_result);
return NS_OK;
}
@ -513,14 +399,184 @@ nsXULPrototypeDocument::ReportScriptError(const char* aErrorString,
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsXULPDGlobalObject
//
nsXULPDGlobalObject::nsXULPDGlobalObject()
: mScriptObject(nsnull),
mGlobalObjectOwner(nsnull)
{
NS_INIT_REFCNT();
}
nsXULPDGlobalObject::~nsXULPDGlobalObject()
{
}
NS_IMPL_ADDREF(nsXULPDGlobalObject)
NS_IMPL_RELEASE(nsXULPDGlobalObject)
NS_INTERFACE_MAP_BEGIN(nsXULPDGlobalObject)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectOwner)
NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
//
// nsIScriptObjectOwner methods
//
NS_IMETHODIMP
nsXULPDGlobalObject::GetScriptObject(nsIScriptContext *aContext, void **aObject)
{
// The prototype document has its own special secret script object
// that can be used to compile scripts and event handlers.
nsresult rv;
nsCOMPtr<nsIScriptContext> context;
if (mScriptContext && aContext != mScriptContext.get()) {
rv = GetContext(getter_AddRefs(context));
if (NS_FAILED(rv)) return rv;
}
else {
context = aContext;
}
if (! mScriptObject) {
JSContext* cx = NS_REINTERPRET_CAST(JSContext*, context->GetNativeContext());
if (! cx)
return NS_ERROR_OUT_OF_MEMORY;
mScriptObject = JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
if (! mScriptObject)
return NS_ERROR_OUT_OF_MEMORY;
// Add an owning reference from JS back to us. This'll be
// released when the JSObject is finalized.
::JS_SetPrivate(cx, mScriptObject, this);
NS_ADDREF(this);
}
*aObject = mScriptObject;
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetScriptObject(void *aObject)
{
mScriptObject = (JSObject *)aObject;
return NS_OK;
}
//----------------------------------------------------------------------
//
// nsIScriptGlobalObject methods
//
NS_IMETHODIMP
nsXULPDGlobalObject::SetContext(nsIScriptContext *aContext)
{
mScriptContext = aContext;
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::GetContext(nsIScriptContext **aContext)
{
// This whole fragile mess is predicated on the fact that
// GetContext() will be called before GetScriptObject() is.
if (! mScriptContext) {
nsresult rv;
rv = NS_CreateScriptContext(this, getter_AddRefs(mScriptContext));
if (NS_FAILED(rv)) return rv;
}
*aContext = mScriptContext;
NS_IF_ADDREF(*aContext);
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetNewDocument(nsIDOMDocument *aDocument)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetDocShell(nsIDocShell *aDocShell)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPDGlobalObject::GetDocShell(nsIDocShell **aDocShell)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetOpenerWindow(nsIDOMWindow *aOpener)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsXULPDGlobalObject::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner)
{
mGlobalObjectOwner = aOwner; // weak reference
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner)
{
*aOwner = mGlobalObjectOwner;
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP
nsXULPDGlobalObject::HandleDOMEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus)
{
NS_NOTREACHED("waaah!");
return NS_ERROR_UNEXPECTED;
}
//----------------------------------------------------------------------
//
// nsIScriptObjectPrincipal methods
//
NS_IMETHODIMP
nsXULPrototypeDocument::GetPrincipal(nsIPrincipal** aPrincipal)
nsXULPDGlobalObject::GetPrincipal(nsIPrincipal** aPrincipal)
{
return GetDocumentPrincipal(aPrincipal);
if (!mGlobalObjectOwner) {
*aPrincipal = nsnull;
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIXULPrototypeDocument> protoDoc
= do_QueryInterface(mGlobalObjectOwner);
return protoDoc->GetDocumentPrincipal(aPrincipal);
}