зеркало из https://github.com/mozilla/gecko-dev.git
Bugs 18127, 20677, 23905. Partial fix. Give the nsXULPrototypeDocument it's own JSContext to use for compiling scripts and event handlers. Modify script and event handler code to compile shared scripts using this context, if appropriate. r=brendan
This commit is contained in:
Родитель
146f7bdd8e
Коммит
d100985675
|
@ -553,13 +553,17 @@ nsEventListenerManager::AddScriptEventListener(nsIScriptContext* aContext,
|
|||
}
|
||||
|
||||
if (!done) {
|
||||
if (handlerOwner) {
|
||||
// Always let the handler owner compile the event handler, as
|
||||
// it may want to use a special context or scope object.
|
||||
rv = handlerOwner->CompileEventHandler(aContext, scriptObject, aName, aBody, &handler);
|
||||
}
|
||||
else {
|
||||
rv = aContext->CompileEventHandler(scriptObject, aName, aBody,
|
||||
(handlerOwner != nsnull),
|
||||
&handler);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (handlerOwner)
|
||||
handlerOwner->SetCompiledEventHandler(aName, handler);
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
return SetJSEventListener(aContext, aScriptObjectOwner, aName, aIID, aDeferCompilation);
|
||||
|
@ -621,12 +625,19 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
|
|||
nsAutoString handlerBody;
|
||||
result = content->GetAttribute(kNameSpaceID_None, atom, handlerBody);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (handlerOwner) {
|
||||
// Always let the handler owner compile the event
|
||||
// handler, as it may want to use a special
|
||||
// context or scope object.
|
||||
result = handlerOwner->CompileEventHandler(scriptCX, jsobj, atom, handlerBody, &handler);
|
||||
}
|
||||
else {
|
||||
result = scriptCX->CompileEventHandler(jsobj, atom, handlerBody,
|
||||
(handlerOwner != nsnull),
|
||||
&handler);
|
||||
}
|
||||
if (NS_SUCCEEDED(result))
|
||||
aListenerStruct->mHandlerIsString &= ~aSubType;
|
||||
if (handlerOwner)
|
||||
handlerOwner->SetCompiledEventHandler(atom, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1594,14 +1594,18 @@ nsXULElement::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject)
|
|||
// tag...
|
||||
nsresult (*fn)(nsIScriptContext* aContext, nsISupports* aSupports, nsISupports* aParent, void** aReturn);
|
||||
|
||||
const char* rootname;
|
||||
if (Tag() == kTreeAtom) {
|
||||
fn = NS_NewScriptXULTreeElement;
|
||||
rootname = "nsXULTreeElement::mScriptObject";
|
||||
}
|
||||
else if (Tag() == kEditorAtom) {
|
||||
fn = NS_NewScriptXULEditorElement;
|
||||
rootname = "nsXULEditorElement::mScriptObject";
|
||||
}
|
||||
else {
|
||||
fn = NS_NewScriptXULElement;
|
||||
rootname = "nsXULElement::mScriptObject";
|
||||
}
|
||||
|
||||
// Create the script object; N.B. that if |mDocument| is null,
|
||||
|
@ -1611,7 +1615,7 @@ nsXULElement::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject)
|
|||
rv = fn(aContext, (nsIDOMXULElement*) this, mDocument, (void**) &mScriptObject);
|
||||
|
||||
// Ensure that a reference exists to this element
|
||||
aContext->AddNamedReference((void*) &mScriptObject, mScriptObject, "nsXULElement::mScriptObject");
|
||||
aContext->AddNamedReference((void*) &mScriptObject, mScriptObject, rootname);
|
||||
}
|
||||
|
||||
*aScriptObject = mScriptObject;
|
||||
|
@ -1651,29 +1655,85 @@ nsXULElement::GetCompiledEventHandler(nsIAtom *aName, void** aHandler)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::SetCompiledEventHandler(nsIAtom *aName, void* aHandler)
|
||||
nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
|
||||
void* aTarget,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aHandler)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets);
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
JSObject* scopeObject;
|
||||
PRBool shared;
|
||||
|
||||
if (mPrototype) {
|
||||
// It'll be shared amonst the instances of the prototype
|
||||
shared = PR_TRUE;
|
||||
|
||||
// Use the prototype document's special context
|
||||
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mDocument);
|
||||
NS_ASSERTION(xuldoc != nsnull, "mDocument is not an nsIXULDocument");
|
||||
if (! xuldoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIXULPrototypeDocument> protodoc;
|
||||
rv = xuldoc->GetMasterPrototype(getter_AddRefs(protodoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ASSERTION(protodoc != nsnull, "xul document has no prototype");
|
||||
if (! protodoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(protodoc);
|
||||
NS_ASSERTION(global != nsnull, "prototype doc is not a script global");
|
||||
if (! global)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = global->GetContext(getter_AddRefs(context));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Use the prototype script's special scope object
|
||||
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(protodoc);
|
||||
if (! owner)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = owner->GetScriptObject(context, (void**) &scopeObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
// We don't have a prototype; do a one-off compile.
|
||||
shared = PR_FALSE;
|
||||
context = aContext;
|
||||
scopeObject = NS_STATIC_CAST(JSObject*, aTarget);
|
||||
}
|
||||
|
||||
NS_ASSERTION(context != nsnull, "no script context");
|
||||
if (! context)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// Compile the event handler
|
||||
rv = context->CompileEventHandler(scopeObject, aName, aBody, shared, aHandler);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (shared) {
|
||||
// If it's a shared handler, we need to bind the shared
|
||||
// function object to the real target.
|
||||
rv = aContext->BindCompiledEventHandler(aTarget, aName, *aHandler);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
if (mPrototype) {
|
||||
// Remember the compiled event handler
|
||||
for (PRInt32 i = 0; i < mPrototype->mNumAttributes; ++i) {
|
||||
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
|
||||
|
||||
if ((attr->mNameSpaceID == kNameSpaceID_None) &&
|
||||
(attr->mName.get() == aName)) {
|
||||
nsresult rv;
|
||||
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
|
||||
attr->mEventHandler = aHandler;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
mDocument->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
NS_ASSERTION(global != nsnull, "no script global object");
|
||||
if (! global)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
rv = global->GetContext(getter_AddRefs(context));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
attr->mEventHandler = *aHandler;
|
||||
|
||||
JSContext *cx = (JSContext*) context->GetNativeContext();
|
||||
if (!cx)
|
||||
|
@ -1686,6 +1746,7 @@ nsXULElement::SetCompiledEventHandler(nsIAtom *aName, void* aHandler)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1926,7 +1987,10 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
|
|||
if (insertOk) {
|
||||
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
|
||||
//nsRange::OwnerChildInserted(this, aIndex);
|
||||
|
||||
//XXXwaterson this should be shallow
|
||||
aKid->SetDocument(mDocument, PR_TRUE);
|
||||
|
||||
if (aNotify && ElementIsInDocument()) {
|
||||
mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex);
|
||||
}
|
||||
|
@ -1965,10 +2029,21 @@ nsXULElement::ReplaceChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
|
|||
if (replaceOk) {
|
||||
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
|
||||
//nsRange::OwnerChildReplaced(this, aIndex, oldKid);
|
||||
|
||||
//XXXwaterson this should be shallow
|
||||
aKid->SetDocument(mDocument, PR_TRUE);
|
||||
|
||||
if (aNotify && ElementIsInDocument()) {
|
||||
mDocument->ContentReplaced(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aKid, aIndex);
|
||||
}
|
||||
|
||||
#if 0 //XXXwaterson put this in eventually.
|
||||
// This will cause the script object to be unrooted for each
|
||||
// element in the subtree.
|
||||
oldKid->SetDocument(nsnull, PR_TRUE);
|
||||
#endif
|
||||
|
||||
// We've got no mo' parent.
|
||||
oldKid->SetParent(nsnull);
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -1992,7 +2067,10 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
|||
if (appendOk) {
|
||||
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
|
||||
// ranges don't need adjustment since new child is at end of list
|
||||
|
||||
//XXXwaterson this should be shallow
|
||||
aKid->SetDocument(mDocument, PR_TRUE);
|
||||
|
||||
if (aNotify && ElementIsInDocument()) {
|
||||
PRUint32 cnt;
|
||||
rv = mChildren->Count(&cnt);
|
||||
|
@ -2097,6 +2175,14 @@ nsXULElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|||
if (aNotify && removeOk && ElementIsInDocument()) {
|
||||
doc->ContentRemoved(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aIndex);
|
||||
}
|
||||
|
||||
#if 0 //XXXwaterson put this in eventually
|
||||
// This will cause the script object to be unrooted for each
|
||||
// element in the subtree.
|
||||
oldKid->SetDocument(nsnull, PR_TRUE);
|
||||
#endif
|
||||
|
||||
// We've got no mo' parent.
|
||||
oldKid->SetParent(nsnull);
|
||||
}
|
||||
|
||||
|
@ -3921,33 +4007,13 @@ nsXULPrototypeScript::~nsXULPrototypeScript()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsXULPrototypeScript::Compile(const PRUnichar* aText, PRInt32 aTextLength,
|
||||
nsIURI* aURI, PRInt32 aLineNo,
|
||||
nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
||||
PRInt32 aTextLength,
|
||||
nsIURI* aURI,
|
||||
PRInt32 aLineNo,
|
||||
nsIDocument* aDocument,
|
||||
nsIXULPrototypeDocument* aPrototypeDocument)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
aDocument->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
NS_ASSERTION(global != nsnull, "no script global object");
|
||||
if (! global)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
rv = global->GetContext(getter_AddRefs(context));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
JSContext *cx = (JSContext*) context->GetNativeContext();
|
||||
if (!cx)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
dont_AddRef(aDocument->GetDocumentPrincipal());
|
||||
|
||||
nsXPIDLCString urlspec;
|
||||
aURI->GetSpec(getter_Copies(urlspec));
|
||||
|
||||
// We'll compile the script using the prototype document's special
|
||||
// script object as the parent. This ensures that we won't end up
|
||||
// with an uncollectable reference.
|
||||
|
@ -3959,18 +4025,62 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, PRInt32 aTextLength,
|
|||
// and the first document would indirectly reference the prototype
|
||||
// document because it keeps the prototype cache
|
||||
// alive. Circularity!
|
||||
void * scopeObject;
|
||||
nsCOMPtr<nsIScriptObjectOwner> owner= do_QueryInterface(aPrototypeDocument, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsresult rv;
|
||||
|
||||
rv = owner->GetScriptObject(context, &scopeObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// Use the prototype document's special context
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
|
||||
rv = context->CompileScript(aText, aTextLength, (JSObject *)scopeObject,
|
||||
principal, urlspec, aLineNo, mLangVersion,
|
||||
{
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(aPrototypeDocument);
|
||||
NS_ASSERTION(global != nsnull, "prototype doc is not a 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;
|
||||
|
||||
// Use the prototype script's special scope object
|
||||
JSObject* scopeObject;
|
||||
|
||||
{
|
||||
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(aPrototypeDocument);
|
||||
if (! owner)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = owner->GetScriptObject(context, (void**) &scopeObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Use the enclosing document's principal
|
||||
// XXX is this right? or should we use the protodoc's?
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
dont_AddRef(aDocument->GetDocumentPrincipal());
|
||||
|
||||
nsXPIDLCString urlspec;
|
||||
aURI->GetSpec(getter_Copies(urlspec));
|
||||
|
||||
// Ok, compile it to create a prototype script object!
|
||||
rv = context->CompileScript(aText,
|
||||
aTextLength,
|
||||
scopeObject,
|
||||
principal,
|
||||
urlspec,
|
||||
aLineNo,
|
||||
mLangVersion,
|
||||
(void**) &mScriptObject);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Root the compiled prototype script object.
|
||||
JSContext* cx = NS_STATIC_CAST(JSContext*, context->GetNativeContext());
|
||||
if (!cx)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = AddJSGCRoot(cx, &mScriptObject, "nsXULPrototypeScript::mScriptObject");
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -463,8 +463,12 @@ public:
|
|||
NS_IMETHOD SetScriptObject(void *aScriptObject);
|
||||
|
||||
// nsIScriptEventHandlerOwner
|
||||
NS_IMETHOD CompileEventHandler(nsIScriptContext* aContext,
|
||||
void* aTarget,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aHandler);
|
||||
NS_IMETHOD GetCompiledEventHandler(nsIAtom *aName, void** aHandler);
|
||||
NS_IMETHOD SetCompiledEventHandler(nsIAtom *aName, void* aHandler);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool AddProperty(JSContext *aContext, JSObject *aObj,
|
||||
|
|
|
@ -113,6 +113,11 @@ public:
|
|||
*/
|
||||
NS_IMETHOD SetMasterPrototype(nsIXULPrototypeDocument* aDocument) = 0;
|
||||
|
||||
/**
|
||||
* Get the master prototype.
|
||||
*/
|
||||
NS_IMETHOD GetMasterPrototype(nsIXULPrototypeDocument** aPrototypeDocument) = 0;
|
||||
|
||||
/**
|
||||
* Set the current prototype
|
||||
*/
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
|
||||
class nsIAtom;
|
||||
class nsIPrincipal;
|
||||
class nsIURI;
|
||||
class nsIStyleSheet;
|
||||
class nsIURI;
|
||||
class nsString;
|
||||
class nsVoidArray;
|
||||
class nsXULPrototypeElement;
|
||||
|
|
|
@ -2108,6 +2108,14 @@ nsXULDocument::SetMasterPrototype(nsIXULPrototypeDocument* aDocument)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::GetMasterPrototype(nsIXULPrototypeDocument** aDocument)
|
||||
{
|
||||
*aDocument = mMasterPrototype;
|
||||
NS_IF_ADDREF(*aDocument);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::SetCurrentPrototype(nsIXULPrototypeDocument* aDocument)
|
||||
{
|
||||
|
@ -2683,7 +2691,7 @@ nsXULDocument::AddSubtreeToDocument(nsIContent* aElement)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Finally, recurse to children.
|
||||
// 4. Recurse to children.
|
||||
PRInt32 count;
|
||||
nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(aElement);
|
||||
rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count);
|
||||
|
@ -2708,6 +2716,7 @@ nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement)
|
|||
// document.
|
||||
nsresult rv;
|
||||
|
||||
// 1. Remove any children from the document.
|
||||
PRInt32 count;
|
||||
nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(aElement);
|
||||
rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count);
|
||||
|
@ -2722,11 +2731,11 @@ nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// 1. Remove the element from the resource-to-element map
|
||||
// 2. Remove the element from the resource-to-element map
|
||||
rv = RemoveElementFromMap(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// 2. If the element is a 'command updater', then remove the
|
||||
// 3. If the element is a 'command updater', then remove the
|
||||
// element from the document's command dispatcher.
|
||||
nsAutoString value;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, kCommandUpdaterAtom, value);
|
||||
|
@ -3951,10 +3960,9 @@ nsXULDocument::CreateElement(PRInt32 aNameSpaceID,
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv = result->SetDocument(this, PR_FALSE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to set element's document");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#if 1 // XXXwaterson remove this eventually
|
||||
result->SetDocument(this, PR_FALSE);
|
||||
#endif
|
||||
result->SetContentID(mNextContentID++);
|
||||
|
||||
*aResult = result;
|
||||
|
|
|
@ -285,6 +285,7 @@ public:
|
|||
NS_IMETHOD AddForwardReference(nsForwardReference* aRef);
|
||||
NS_IMETHOD ResolveForwardReferences();
|
||||
NS_IMETHOD SetMasterPrototype(nsIXULPrototypeDocument* aDocument);
|
||||
NS_IMETHOD GetMasterPrototype(nsIXULPrototypeDocument** aDocument);
|
||||
NS_IMETHOD SetCurrentPrototype(nsIXULPrototypeDocument* aDocument);
|
||||
NS_IMETHOD SetDocumentURL(nsIURI* anURL);
|
||||
NS_IMETHOD PrepareStyleSheets(nsIURI* anURL);
|
||||
|
|
|
@ -27,19 +27,23 @@
|
|||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString2.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptGlobalObjectData.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIXULPrototypeDocument.h"
|
||||
#include "nsString2.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsXULElement.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
|
||||
|
||||
class nsXULPrototypeDocument : public nsIXULPrototypeDocument,
|
||||
public nsIScriptObjectOwner
|
||||
public nsIScriptObjectOwner,
|
||||
public nsIScriptGlobalObject,
|
||||
public nsIScriptGlobalObjectData
|
||||
{
|
||||
public:
|
||||
static nsresult
|
||||
|
@ -71,12 +75,33 @@ public:
|
|||
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 SetWebShell(nsIWebShell *aWebShell);
|
||||
NS_IMETHOD GetWebShell(nsIWebShell **aWebShell);
|
||||
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);
|
||||
|
||||
// nsIScriptGlobalObjectData methods
|
||||
NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal);
|
||||
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsXULPrototypeElement* mRoot;
|
||||
nsCOMPtr<nsISupportsArray> mStyleSheetReferences;
|
||||
nsCOMPtr<nsISupportsArray> mOverlayReferences;
|
||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mScriptContext;
|
||||
JSObject *mScriptObject; // XXX JS language rabies bigotry badness
|
||||
|
||||
nsXULPrototypeDocument();
|
||||
|
@ -85,13 +110,30 @@ protected:
|
|||
|
||||
friend NS_IMETHODIMP
|
||||
NS_NewXULPrototypeDocument(nsISupports* aOuter, REFNSIID aIID, void** aResult);
|
||||
|
||||
static JSClass gSharedGlobalClass;
|
||||
|
||||
static void PR_CALLBACK
|
||||
FinalizeScriptObject(JSContext* cx, JSObject* obj);
|
||||
};
|
||||
|
||||
JSClass nsXULPrototypeDocument::gSharedGlobalClass = {
|
||||
"nsXULPrototypeScript compilation scope",
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nsXULPrototypeDocument::FinalizeScriptObject
|
||||
};
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// ctors, dtors, n' stuff
|
||||
//
|
||||
|
||||
nsXULPrototypeDocument::nsXULPrototypeDocument()
|
||||
: mRoot(nsnull), mScriptObject(nsnull)
|
||||
: mRoot(nsnull),
|
||||
mScriptObject(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
@ -115,19 +157,14 @@ nsXULPrototypeDocument::Init()
|
|||
nsXULPrototypeDocument::~nsXULPrototypeDocument()
|
||||
{
|
||||
delete mRoot;
|
||||
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSRuntimeService, rtsvc, "nsJSRuntimeService", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
JSRuntime *rt;
|
||||
rv = rtsvc->GetRuntime(&rt);
|
||||
if (NS_SUCCEEDED(rv) && rt)
|
||||
JS_RemoveRootRT(rt, &mScriptObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsXULPrototypeDocument, nsIXULPrototypeDocument, nsIScriptObjectOwner);
|
||||
NS_IMPL_ISUPPORTS4(nsXULPrototypeDocument,
|
||||
nsIXULPrototypeDocument,
|
||||
nsIScriptObjectOwner,
|
||||
nsIScriptGlobalObject,
|
||||
nsIScriptGlobalObjectData);
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_NewXULPrototypeDocument(nsISupports* aOuter, REFNSIID aIID, void** aResult)
|
||||
|
@ -156,6 +193,9 @@ NS_NewXULPrototypeDocument(nsISupports* aOuter, REFNSIID aIID, void** aResult)
|
|||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIXULPrototypeDocument methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::GetURI(nsIURI** aResult)
|
||||
|
@ -169,7 +209,7 @@ nsXULPrototypeDocument::GetURI(nsIURI** aResult)
|
|||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::SetURI(nsIURI* aURI)
|
||||
{
|
||||
mURI = aURI;
|
||||
mURI = dont_QueryInterface(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -257,14 +297,20 @@ nsXULPrototypeDocument::GetDocumentPrincipal(nsIPrincipal** aResult)
|
|||
{
|
||||
if (!mDocumentPrincipal) {
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
|
||||
NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
|
||||
NS_WITH_SERVICE(nsIScriptSecurityManager,
|
||||
securityManager,
|
||||
NS_SCRIPTSECURITYMANAGER_PROGID,
|
||||
&rv);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rv = securityManager->GetCodebasePrincipal(mURI, getter_AddRefs(mDocumentPrincipal));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aResult = mDocumentPrincipal;
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
|
@ -278,40 +324,43 @@ nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
JSClass null_class = {
|
||||
"nsXULPrototypeScript compilation scope", 0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIScriptObjectOwner methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::GetScriptObject(nsIScriptContext *aContext, void **aObject)
|
||||
{
|
||||
// The prototype document will have its own special secret script
|
||||
// object that can be used to compile scripts and event handlers.
|
||||
if (!mScriptObject) {
|
||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||
if (!cx)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
// The prototype document has its own special secret script object
|
||||
// that can be used to compile scripts and event handlers.
|
||||
nsresult rv;
|
||||
|
||||
mScriptObject = JS_NewObject(cx, &null_class, nsnull, nsnull);
|
||||
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_STATIC_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;
|
||||
|
||||
// Be sure to unlink the script object from the parent global
|
||||
// object. This ensures that we don't end up with a circular
|
||||
// reference back to the first document.
|
||||
JS_SetPrototype(cx, mScriptObject, nsnull);
|
||||
JS_SetParent(cx, mScriptObject, nsnull);
|
||||
|
||||
JS_AddNamedRoot(cx, &mScriptObject, "nsXULPrototypeDocument::mScriptObject");
|
||||
|
||||
// We need standard classes, in particular RegExp, to compile JS.
|
||||
if (!JS_InitStandardClasses(cx, mScriptObject))
|
||||
return NS_ERROR_FAILURE;
|
||||
// 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;
|
||||
}
|
||||
|
@ -322,3 +371,120 @@ 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)
|
||||
{
|
||||
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::SetWebShell(nsIWebShell *aWebShell)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::GetWebShell(nsIWebShell **aWebShell)
|
||||
{
|
||||
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)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::HandleDOMEvent(nsIPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIScriptGlobalObjectData methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::GetPrincipal(nsIPrincipal** aPrincipal)
|
||||
{
|
||||
return GetDocumentPrincipal(aPrincipal);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// Implementation methods
|
||||
//
|
||||
|
||||
void PR_CALLBACK
|
||||
nsXULPrototypeDocument::FinalizeScriptObject(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
nsXULPrototypeDocument* native =
|
||||
NS_STATIC_CAST(nsXULPrototypeDocument*, ::JS_GetPrivate(cx, obj));
|
||||
|
||||
if (native) {
|
||||
// Clear the native object's reference back to us, and release
|
||||
// our ownership of it.
|
||||
native->SetScriptObject(nsnull);
|
||||
NS_RELEASE(native);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,9 +90,30 @@ class nsIScriptEventHandlerOwner : public nsISupports
|
|||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCRIPTEVENTHANDLEROWNER_IID)
|
||||
|
||||
NS_IMETHOD GetCompiledEventHandler(nsIAtom *aName, void** aHandler) = 0;
|
||||
/**
|
||||
* Compile the specified event handler, and bind it to aTarget using
|
||||
* aContext.
|
||||
*
|
||||
* @param aContext the context to use when creating event handler
|
||||
* @param aTarget the object to which to bind the event handler
|
||||
* @param aName the name of the handler
|
||||
* @param aBody the handler script body
|
||||
* @param aHandler the compiled, bound handler object
|
||||
*/
|
||||
NS_IMETHOD CompileEventHandler(nsIScriptContext* aContext,
|
||||
void* aTarget,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aHandler) = 0;
|
||||
|
||||
NS_IMETHOD SetCompiledEventHandler(nsIAtom *aName, void* aHandler) = 0;
|
||||
/**
|
||||
* Retrieve an already-compiled event handler that can be bound to a
|
||||
* target object using a script context.
|
||||
*
|
||||
* @param aName the name of the event handler to retrieve
|
||||
* @param aHandler the compiled event handler
|
||||
*/
|
||||
NS_IMETHOD GetCompiledEventHandler(nsIAtom *aName, void** aHandler) = 0;
|
||||
};
|
||||
|
||||
#endif // nsIScriptObjectOwner_h__
|
||||
|
|
|
@ -553,13 +553,17 @@ nsEventListenerManager::AddScriptEventListener(nsIScriptContext* aContext,
|
|||
}
|
||||
|
||||
if (!done) {
|
||||
if (handlerOwner) {
|
||||
// Always let the handler owner compile the event handler, as
|
||||
// it may want to use a special context or scope object.
|
||||
rv = handlerOwner->CompileEventHandler(aContext, scriptObject, aName, aBody, &handler);
|
||||
}
|
||||
else {
|
||||
rv = aContext->CompileEventHandler(scriptObject, aName, aBody,
|
||||
(handlerOwner != nsnull),
|
||||
&handler);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (handlerOwner)
|
||||
handlerOwner->SetCompiledEventHandler(aName, handler);
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
return SetJSEventListener(aContext, aScriptObjectOwner, aName, aIID, aDeferCompilation);
|
||||
|
@ -621,12 +625,19 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
|
|||
nsAutoString handlerBody;
|
||||
result = content->GetAttribute(kNameSpaceID_None, atom, handlerBody);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (handlerOwner) {
|
||||
// Always let the handler owner compile the event
|
||||
// handler, as it may want to use a special
|
||||
// context or scope object.
|
||||
result = handlerOwner->CompileEventHandler(scriptCX, jsobj, atom, handlerBody, &handler);
|
||||
}
|
||||
else {
|
||||
result = scriptCX->CompileEventHandler(jsobj, atom, handlerBody,
|
||||
(handlerOwner != nsnull),
|
||||
&handler);
|
||||
}
|
||||
if (NS_SUCCEEDED(result))
|
||||
aListenerStruct->mHandlerIsString &= ~aSubType;
|
||||
if (handlerOwner)
|
||||
handlerOwner->SetCompiledEventHandler(atom, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,11 @@ public:
|
|||
*/
|
||||
NS_IMETHOD SetMasterPrototype(nsIXULPrototypeDocument* aDocument) = 0;
|
||||
|
||||
/**
|
||||
* Get the master prototype.
|
||||
*/
|
||||
NS_IMETHOD GetMasterPrototype(nsIXULPrototypeDocument** aPrototypeDocument) = 0;
|
||||
|
||||
/**
|
||||
* Set the current prototype
|
||||
*/
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
|
||||
class nsIAtom;
|
||||
class nsIPrincipal;
|
||||
class nsIURI;
|
||||
class nsIStyleSheet;
|
||||
class nsIURI;
|
||||
class nsString;
|
||||
class nsVoidArray;
|
||||
class nsXULPrototypeElement;
|
||||
|
|
|
@ -2108,6 +2108,14 @@ nsXULDocument::SetMasterPrototype(nsIXULPrototypeDocument* aDocument)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::GetMasterPrototype(nsIXULPrototypeDocument** aDocument)
|
||||
{
|
||||
*aDocument = mMasterPrototype;
|
||||
NS_IF_ADDREF(*aDocument);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::SetCurrentPrototype(nsIXULPrototypeDocument* aDocument)
|
||||
{
|
||||
|
@ -2683,7 +2691,7 @@ nsXULDocument::AddSubtreeToDocument(nsIContent* aElement)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Finally, recurse to children.
|
||||
// 4. Recurse to children.
|
||||
PRInt32 count;
|
||||
nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(aElement);
|
||||
rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count);
|
||||
|
@ -2708,6 +2716,7 @@ nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement)
|
|||
// document.
|
||||
nsresult rv;
|
||||
|
||||
// 1. Remove any children from the document.
|
||||
PRInt32 count;
|
||||
nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(aElement);
|
||||
rv = xulcontent ? xulcontent->PeekChildCount(count) : aElement->ChildCount(count);
|
||||
|
@ -2722,11 +2731,11 @@ nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// 1. Remove the element from the resource-to-element map
|
||||
// 2. Remove the element from the resource-to-element map
|
||||
rv = RemoveElementFromMap(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// 2. If the element is a 'command updater', then remove the
|
||||
// 3. If the element is a 'command updater', then remove the
|
||||
// element from the document's command dispatcher.
|
||||
nsAutoString value;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, kCommandUpdaterAtom, value);
|
||||
|
@ -3951,10 +3960,9 @@ nsXULDocument::CreateElement(PRInt32 aNameSpaceID,
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv = result->SetDocument(this, PR_FALSE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to set element's document");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#if 1 // XXXwaterson remove this eventually
|
||||
result->SetDocument(this, PR_FALSE);
|
||||
#endif
|
||||
result->SetContentID(mNextContentID++);
|
||||
|
||||
*aResult = result;
|
||||
|
|
|
@ -285,6 +285,7 @@ public:
|
|||
NS_IMETHOD AddForwardReference(nsForwardReference* aRef);
|
||||
NS_IMETHOD ResolveForwardReferences();
|
||||
NS_IMETHOD SetMasterPrototype(nsIXULPrototypeDocument* aDocument);
|
||||
NS_IMETHOD GetMasterPrototype(nsIXULPrototypeDocument** aDocument);
|
||||
NS_IMETHOD SetCurrentPrototype(nsIXULPrototypeDocument* aDocument);
|
||||
NS_IMETHOD SetDocumentURL(nsIURI* anURL);
|
||||
NS_IMETHOD PrepareStyleSheets(nsIURI* anURL);
|
||||
|
|
|
@ -1594,14 +1594,18 @@ nsXULElement::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject)
|
|||
// tag...
|
||||
nsresult (*fn)(nsIScriptContext* aContext, nsISupports* aSupports, nsISupports* aParent, void** aReturn);
|
||||
|
||||
const char* rootname;
|
||||
if (Tag() == kTreeAtom) {
|
||||
fn = NS_NewScriptXULTreeElement;
|
||||
rootname = "nsXULTreeElement::mScriptObject";
|
||||
}
|
||||
else if (Tag() == kEditorAtom) {
|
||||
fn = NS_NewScriptXULEditorElement;
|
||||
rootname = "nsXULEditorElement::mScriptObject";
|
||||
}
|
||||
else {
|
||||
fn = NS_NewScriptXULElement;
|
||||
rootname = "nsXULElement::mScriptObject";
|
||||
}
|
||||
|
||||
// Create the script object; N.B. that if |mDocument| is null,
|
||||
|
@ -1611,7 +1615,7 @@ nsXULElement::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject)
|
|||
rv = fn(aContext, (nsIDOMXULElement*) this, mDocument, (void**) &mScriptObject);
|
||||
|
||||
// Ensure that a reference exists to this element
|
||||
aContext->AddNamedReference((void*) &mScriptObject, mScriptObject, "nsXULElement::mScriptObject");
|
||||
aContext->AddNamedReference((void*) &mScriptObject, mScriptObject, rootname);
|
||||
}
|
||||
|
||||
*aScriptObject = mScriptObject;
|
||||
|
@ -1651,29 +1655,85 @@ nsXULElement::GetCompiledEventHandler(nsIAtom *aName, void** aHandler)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::SetCompiledEventHandler(nsIAtom *aName, void* aHandler)
|
||||
nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
|
||||
void* aTarget,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aHandler)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets);
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
JSObject* scopeObject;
|
||||
PRBool shared;
|
||||
|
||||
if (mPrototype) {
|
||||
// It'll be shared amonst the instances of the prototype
|
||||
shared = PR_TRUE;
|
||||
|
||||
// Use the prototype document's special context
|
||||
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mDocument);
|
||||
NS_ASSERTION(xuldoc != nsnull, "mDocument is not an nsIXULDocument");
|
||||
if (! xuldoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIXULPrototypeDocument> protodoc;
|
||||
rv = xuldoc->GetMasterPrototype(getter_AddRefs(protodoc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ASSERTION(protodoc != nsnull, "xul document has no prototype");
|
||||
if (! protodoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(protodoc);
|
||||
NS_ASSERTION(global != nsnull, "prototype doc is not a script global");
|
||||
if (! global)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = global->GetContext(getter_AddRefs(context));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Use the prototype script's special scope object
|
||||
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(protodoc);
|
||||
if (! owner)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = owner->GetScriptObject(context, (void**) &scopeObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
// We don't have a prototype; do a one-off compile.
|
||||
shared = PR_FALSE;
|
||||
context = aContext;
|
||||
scopeObject = NS_STATIC_CAST(JSObject*, aTarget);
|
||||
}
|
||||
|
||||
NS_ASSERTION(context != nsnull, "no script context");
|
||||
if (! context)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// Compile the event handler
|
||||
rv = context->CompileEventHandler(scopeObject, aName, aBody, shared, aHandler);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (shared) {
|
||||
// If it's a shared handler, we need to bind the shared
|
||||
// function object to the real target.
|
||||
rv = aContext->BindCompiledEventHandler(aTarget, aName, *aHandler);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
if (mPrototype) {
|
||||
// Remember the compiled event handler
|
||||
for (PRInt32 i = 0; i < mPrototype->mNumAttributes; ++i) {
|
||||
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
|
||||
|
||||
if ((attr->mNameSpaceID == kNameSpaceID_None) &&
|
||||
(attr->mName.get() == aName)) {
|
||||
nsresult rv;
|
||||
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
|
||||
attr->mEventHandler = aHandler;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
mDocument->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
NS_ASSERTION(global != nsnull, "no script global object");
|
||||
if (! global)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
rv = global->GetContext(getter_AddRefs(context));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
attr->mEventHandler = *aHandler;
|
||||
|
||||
JSContext *cx = (JSContext*) context->GetNativeContext();
|
||||
if (!cx)
|
||||
|
@ -1686,6 +1746,7 @@ nsXULElement::SetCompiledEventHandler(nsIAtom *aName, void* aHandler)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1926,7 +1987,10 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
|
|||
if (insertOk) {
|
||||
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
|
||||
//nsRange::OwnerChildInserted(this, aIndex);
|
||||
|
||||
//XXXwaterson this should be shallow
|
||||
aKid->SetDocument(mDocument, PR_TRUE);
|
||||
|
||||
if (aNotify && ElementIsInDocument()) {
|
||||
mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex);
|
||||
}
|
||||
|
@ -1965,10 +2029,21 @@ nsXULElement::ReplaceChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
|
|||
if (replaceOk) {
|
||||
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
|
||||
//nsRange::OwnerChildReplaced(this, aIndex, oldKid);
|
||||
|
||||
//XXXwaterson this should be shallow
|
||||
aKid->SetDocument(mDocument, PR_TRUE);
|
||||
|
||||
if (aNotify && ElementIsInDocument()) {
|
||||
mDocument->ContentReplaced(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aKid, aIndex);
|
||||
}
|
||||
|
||||
#if 0 //XXXwaterson put this in eventually.
|
||||
// This will cause the script object to be unrooted for each
|
||||
// element in the subtree.
|
||||
oldKid->SetDocument(nsnull, PR_TRUE);
|
||||
#endif
|
||||
|
||||
// We've got no mo' parent.
|
||||
oldKid->SetParent(nsnull);
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -1992,7 +2067,10 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
|||
if (appendOk) {
|
||||
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
|
||||
// ranges don't need adjustment since new child is at end of list
|
||||
|
||||
//XXXwaterson this should be shallow
|
||||
aKid->SetDocument(mDocument, PR_TRUE);
|
||||
|
||||
if (aNotify && ElementIsInDocument()) {
|
||||
PRUint32 cnt;
|
||||
rv = mChildren->Count(&cnt);
|
||||
|
@ -2097,6 +2175,14 @@ nsXULElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|||
if (aNotify && removeOk && ElementIsInDocument()) {
|
||||
doc->ContentRemoved(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aIndex);
|
||||
}
|
||||
|
||||
#if 0 //XXXwaterson put this in eventually
|
||||
// This will cause the script object to be unrooted for each
|
||||
// element in the subtree.
|
||||
oldKid->SetDocument(nsnull, PR_TRUE);
|
||||
#endif
|
||||
|
||||
// We've got no mo' parent.
|
||||
oldKid->SetParent(nsnull);
|
||||
}
|
||||
|
||||
|
@ -3921,33 +4007,13 @@ nsXULPrototypeScript::~nsXULPrototypeScript()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsXULPrototypeScript::Compile(const PRUnichar* aText, PRInt32 aTextLength,
|
||||
nsIURI* aURI, PRInt32 aLineNo,
|
||||
nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
||||
PRInt32 aTextLength,
|
||||
nsIURI* aURI,
|
||||
PRInt32 aLineNo,
|
||||
nsIDocument* aDocument,
|
||||
nsIXULPrototypeDocument* aPrototypeDocument)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
aDocument->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
NS_ASSERTION(global != nsnull, "no script global object");
|
||||
if (! global)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
rv = global->GetContext(getter_AddRefs(context));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
JSContext *cx = (JSContext*) context->GetNativeContext();
|
||||
if (!cx)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
dont_AddRef(aDocument->GetDocumentPrincipal());
|
||||
|
||||
nsXPIDLCString urlspec;
|
||||
aURI->GetSpec(getter_Copies(urlspec));
|
||||
|
||||
// We'll compile the script using the prototype document's special
|
||||
// script object as the parent. This ensures that we won't end up
|
||||
// with an uncollectable reference.
|
||||
|
@ -3959,18 +4025,62 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, PRInt32 aTextLength,
|
|||
// and the first document would indirectly reference the prototype
|
||||
// document because it keeps the prototype cache
|
||||
// alive. Circularity!
|
||||
void * scopeObject;
|
||||
nsCOMPtr<nsIScriptObjectOwner> owner= do_QueryInterface(aPrototypeDocument, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsresult rv;
|
||||
|
||||
rv = owner->GetScriptObject(context, &scopeObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// Use the prototype document's special context
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
|
||||
rv = context->CompileScript(aText, aTextLength, (JSObject *)scopeObject,
|
||||
principal, urlspec, aLineNo, mLangVersion,
|
||||
{
|
||||
nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(aPrototypeDocument);
|
||||
NS_ASSERTION(global != nsnull, "prototype doc is not a 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;
|
||||
|
||||
// Use the prototype script's special scope object
|
||||
JSObject* scopeObject;
|
||||
|
||||
{
|
||||
nsCOMPtr<nsIScriptObjectOwner> owner = do_QueryInterface(aPrototypeDocument);
|
||||
if (! owner)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = owner->GetScriptObject(context, (void**) &scopeObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Use the enclosing document's principal
|
||||
// XXX is this right? or should we use the protodoc's?
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
dont_AddRef(aDocument->GetDocumentPrincipal());
|
||||
|
||||
nsXPIDLCString urlspec;
|
||||
aURI->GetSpec(getter_Copies(urlspec));
|
||||
|
||||
// Ok, compile it to create a prototype script object!
|
||||
rv = context->CompileScript(aText,
|
||||
aTextLength,
|
||||
scopeObject,
|
||||
principal,
|
||||
urlspec,
|
||||
aLineNo,
|
||||
mLangVersion,
|
||||
(void**) &mScriptObject);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Root the compiled prototype script object.
|
||||
JSContext* cx = NS_STATIC_CAST(JSContext*, context->GetNativeContext());
|
||||
if (!cx)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = AddJSGCRoot(cx, &mScriptObject, "nsXULPrototypeScript::mScriptObject");
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -463,8 +463,12 @@ public:
|
|||
NS_IMETHOD SetScriptObject(void *aScriptObject);
|
||||
|
||||
// nsIScriptEventHandlerOwner
|
||||
NS_IMETHOD CompileEventHandler(nsIScriptContext* aContext,
|
||||
void* aTarget,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aHandler);
|
||||
NS_IMETHOD GetCompiledEventHandler(nsIAtom *aName, void** aHandler);
|
||||
NS_IMETHOD SetCompiledEventHandler(nsIAtom *aName, void* aHandler);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool AddProperty(JSContext *aContext, JSObject *aObj,
|
||||
|
|
|
@ -403,7 +403,6 @@ nsXULKeyListenerImpl::Init(
|
|||
nsIDOMElement * aElement,
|
||||
nsIDOMDocument * aDocument)
|
||||
{
|
||||
printf("nsXULKeyListenerImpl::Init()\n");
|
||||
element = aElement; // Weak reference. Don't addref it.
|
||||
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc = do_QueryInterface(aDocument);
|
||||
|
@ -1552,12 +1551,14 @@ nsXULKeyListenerImpl::HandleEventUsingKeyset(nsIDOMElement* aKeysetElement, nsID
|
|||
nsAutoString value;
|
||||
keyContent->GetAttribute(kNameSpaceID_None, eventName, value);
|
||||
if (value != "") {
|
||||
if (handlerOwner) {
|
||||
handlerOwner->CompileEventHandler(context, scriptObject, eventName, value, &handler);
|
||||
}
|
||||
else {
|
||||
context->CompileEventHandler(scriptObject, eventName, value,
|
||||
PR_TRUE, &handler);
|
||||
}
|
||||
|
||||
if (handler)
|
||||
handlerOwner->SetCompiledEventHandler(eventName, handler);
|
||||
}
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
|
|
|
@ -27,19 +27,23 @@
|
|||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString2.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptGlobalObjectData.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIXULPrototypeDocument.h"
|
||||
#include "nsString2.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsXULElement.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
|
||||
|
||||
class nsXULPrototypeDocument : public nsIXULPrototypeDocument,
|
||||
public nsIScriptObjectOwner
|
||||
public nsIScriptObjectOwner,
|
||||
public nsIScriptGlobalObject,
|
||||
public nsIScriptGlobalObjectData
|
||||
{
|
||||
public:
|
||||
static nsresult
|
||||
|
@ -71,12 +75,33 @@ public:
|
|||
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 SetWebShell(nsIWebShell *aWebShell);
|
||||
NS_IMETHOD GetWebShell(nsIWebShell **aWebShell);
|
||||
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);
|
||||
|
||||
// nsIScriptGlobalObjectData methods
|
||||
NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal);
|
||||
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsXULPrototypeElement* mRoot;
|
||||
nsCOMPtr<nsISupportsArray> mStyleSheetReferences;
|
||||
nsCOMPtr<nsISupportsArray> mOverlayReferences;
|
||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mScriptContext;
|
||||
JSObject *mScriptObject; // XXX JS language rabies bigotry badness
|
||||
|
||||
nsXULPrototypeDocument();
|
||||
|
@ -85,13 +110,30 @@ protected:
|
|||
|
||||
friend NS_IMETHODIMP
|
||||
NS_NewXULPrototypeDocument(nsISupports* aOuter, REFNSIID aIID, void** aResult);
|
||||
|
||||
static JSClass gSharedGlobalClass;
|
||||
|
||||
static void PR_CALLBACK
|
||||
FinalizeScriptObject(JSContext* cx, JSObject* obj);
|
||||
};
|
||||
|
||||
JSClass nsXULPrototypeDocument::gSharedGlobalClass = {
|
||||
"nsXULPrototypeScript compilation scope",
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nsXULPrototypeDocument::FinalizeScriptObject
|
||||
};
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// ctors, dtors, n' stuff
|
||||
//
|
||||
|
||||
nsXULPrototypeDocument::nsXULPrototypeDocument()
|
||||
: mRoot(nsnull), mScriptObject(nsnull)
|
||||
: mRoot(nsnull),
|
||||
mScriptObject(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
@ -115,19 +157,14 @@ nsXULPrototypeDocument::Init()
|
|||
nsXULPrototypeDocument::~nsXULPrototypeDocument()
|
||||
{
|
||||
delete mRoot;
|
||||
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIJSRuntimeService, rtsvc, "nsJSRuntimeService", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
JSRuntime *rt;
|
||||
rv = rtsvc->GetRuntime(&rt);
|
||||
if (NS_SUCCEEDED(rv) && rt)
|
||||
JS_RemoveRootRT(rt, &mScriptObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsXULPrototypeDocument, nsIXULPrototypeDocument, nsIScriptObjectOwner);
|
||||
NS_IMPL_ISUPPORTS4(nsXULPrototypeDocument,
|
||||
nsIXULPrototypeDocument,
|
||||
nsIScriptObjectOwner,
|
||||
nsIScriptGlobalObject,
|
||||
nsIScriptGlobalObjectData);
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_NewXULPrototypeDocument(nsISupports* aOuter, REFNSIID aIID, void** aResult)
|
||||
|
@ -156,6 +193,9 @@ NS_NewXULPrototypeDocument(nsISupports* aOuter, REFNSIID aIID, void** aResult)
|
|||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIXULPrototypeDocument methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::GetURI(nsIURI** aResult)
|
||||
|
@ -169,7 +209,7 @@ nsXULPrototypeDocument::GetURI(nsIURI** aResult)
|
|||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::SetURI(nsIURI* aURI)
|
||||
{
|
||||
mURI = aURI;
|
||||
mURI = dont_QueryInterface(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -257,14 +297,20 @@ nsXULPrototypeDocument::GetDocumentPrincipal(nsIPrincipal** aResult)
|
|||
{
|
||||
if (!mDocumentPrincipal) {
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
|
||||
NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
|
||||
NS_WITH_SERVICE(nsIScriptSecurityManager,
|
||||
securityManager,
|
||||
NS_SCRIPTSECURITYMANAGER_PROGID,
|
||||
&rv);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rv = securityManager->GetCodebasePrincipal(mURI, getter_AddRefs(mDocumentPrincipal));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aResult = mDocumentPrincipal;
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
|
@ -278,40 +324,43 @@ nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
JSClass null_class = {
|
||||
"nsXULPrototypeScript compilation scope", 0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIScriptObjectOwner methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::GetScriptObject(nsIScriptContext *aContext, void **aObject)
|
||||
{
|
||||
// The prototype document will have its own special secret script
|
||||
// object that can be used to compile scripts and event handlers.
|
||||
if (!mScriptObject) {
|
||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||
if (!cx)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
// The prototype document has its own special secret script object
|
||||
// that can be used to compile scripts and event handlers.
|
||||
nsresult rv;
|
||||
|
||||
mScriptObject = JS_NewObject(cx, &null_class, nsnull, nsnull);
|
||||
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_STATIC_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;
|
||||
|
||||
// Be sure to unlink the script object from the parent global
|
||||
// object. This ensures that we don't end up with a circular
|
||||
// reference back to the first document.
|
||||
JS_SetPrototype(cx, mScriptObject, nsnull);
|
||||
JS_SetParent(cx, mScriptObject, nsnull);
|
||||
|
||||
JS_AddNamedRoot(cx, &mScriptObject, "nsXULPrototypeDocument::mScriptObject");
|
||||
|
||||
// We need standard classes, in particular RegExp, to compile JS.
|
||||
if (!JS_InitStandardClasses(cx, mScriptObject))
|
||||
return NS_ERROR_FAILURE;
|
||||
// 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;
|
||||
}
|
||||
|
@ -322,3 +371,120 @@ 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)
|
||||
{
|
||||
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::SetWebShell(nsIWebShell *aWebShell)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::GetWebShell(nsIWebShell **aWebShell)
|
||||
{
|
||||
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)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::HandleDOMEvent(nsIPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIScriptGlobalObjectData methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeDocument::GetPrincipal(nsIPrincipal** aPrincipal)
|
||||
{
|
||||
return GetDocumentPrincipal(aPrincipal);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// Implementation methods
|
||||
//
|
||||
|
||||
void PR_CALLBACK
|
||||
nsXULPrototypeDocument::FinalizeScriptObject(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
nsXULPrototypeDocument* native =
|
||||
NS_STATIC_CAST(nsXULPrototypeDocument*, ::JS_GetPrivate(cx, obj));
|
||||
|
||||
if (native) {
|
||||
// Clear the native object's reference back to us, and release
|
||||
// our ownership of it.
|
||||
native->SetScriptObject(nsnull);
|
||||
NS_RELEASE(native);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче