зеркало из https://github.com/mozilla/gecko-dev.git
Landing XBL brutal sharing from mscott's machine. This is hyatt. The bug has r/sr=hyatt,brendan.
This commit is contained in:
Родитель
23272e1972
Коммит
f6cc8b51fd
|
@ -36,6 +36,7 @@ EXPORTS = \
|
|||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLPrototypeBinding.h \
|
||||
nsIXBLPrototypeHandler.h \
|
||||
nsIXBLPrototypeProperty.h \
|
||||
nsIXBLService.h \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -26,10 +26,11 @@ EXPORTS = \
|
|||
nsIXBLBinding.h \
|
||||
nsIXBLBindingAttachedHandler.h \
|
||||
nsIXBLDocumentInfo.h \
|
||||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLPrototypeBinding.h \
|
||||
nsIXBLPrototypeHandler.h \
|
||||
nsIXBLService.h \
|
||||
nsIXBLPrototypeProperty.h \
|
||||
$(NULL)
|
||||
|
||||
MODULE=raptor
|
||||
|
|
|
@ -32,8 +32,11 @@ class nsIDocument;
|
|||
class nsIDOMEventReceiver;
|
||||
class nsIXBLDocumentInfo;
|
||||
class nsIXBLPrototypeHandler;
|
||||
class nsIXBLPrototypeProperty;
|
||||
class nsIXBLBinding;
|
||||
class nsISupportsArray;
|
||||
class nsCString;
|
||||
class nsIScriptContext;
|
||||
|
||||
// {34D700F5-C1A2-4408-A0B1-DD8F891DD1FE}
|
||||
#define NS_IXBLPROTOTYPEBINDING_IID \
|
||||
|
@ -63,6 +66,12 @@ public:
|
|||
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler)=0;
|
||||
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler)=0;
|
||||
|
||||
NS_IMETHOD GetPrototypeProperties(nsIXBLPrototypeProperty** aResult) = 0;
|
||||
NS_IMETHOD SetProtoTypeProperties(nsIXBLPrototypeProperty* aResult) = 0;
|
||||
NS_IMETHOD GetCompiledClassObject(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject) = 0;
|
||||
|
||||
NS_IMETHOD InitClass(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject) = 0;
|
||||
|
||||
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
|
||||
nsIContent* aChangedElement, nsIContent* aAnonymousContent)=0;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ REQUIRES = xpcom string js dom widget caps htmlparser necko xpconnect pref docsh
|
|||
CPPSRCS = \
|
||||
nsXBLBinding.cpp \
|
||||
nsXBLPrototypeBinding.cpp \
|
||||
nsXBLPrototypeProperty.cpp \
|
||||
nsXBLEventHandler.cpp \
|
||||
nsXBLWindowHandler.cpp \
|
||||
nsXBLWindowKeyHandler.cpp \
|
||||
|
|
|
@ -48,6 +48,7 @@ CPPSRCS= \
|
|||
nsXBLPrototypeHandler.cpp \
|
||||
nsBindingManager.cpp \
|
||||
nsXBLInsertionPoint.cpp \
|
||||
nsXBLPrototypeProperty.cpp \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS= \
|
||||
|
@ -72,6 +73,7 @@ CPP_OBJS= \
|
|||
.\$(OBJDIR)\nsXBLService.obj \
|
||||
.\$(OBJDIR)\nsBindingManager.obj \
|
||||
.\$(OBJDIR)\nsXBLInsertionPoint.obj \
|
||||
.\$(OBJDIR)\nsXBLPrototypeProperty.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
|
|
@ -66,6 +66,15 @@
|
|||
|
||||
#include "jsapi.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsDOMCID.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptGlobalObjectOwner.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIScriptError.h"
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
// Static IIDs/CIDs. Try to minimize these.
|
||||
|
@ -73,7 +82,260 @@ static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
|||
static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
|
||||
static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
|
||||
|
||||
class nsXBLDocumentInfo : public nsIXBLDocumentInfo, public nsSupportsWeakReference
|
||||
// an XBLDocumentInfo object has a special context associated with it which we can use to pre-compile properties and methods
|
||||
// of XBL widgets against.....
|
||||
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
|
||||
class nsXBLDocGlobalObject : public nsIScriptGlobalObject,
|
||||
public nsIScriptObjectPrincipal
|
||||
{
|
||||
public:
|
||||
nsXBLDocGlobalObject();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// 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(nsIDOMWindowInternal *aOpener);
|
||||
NS_IMETHOD SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner);
|
||||
NS_IMETHOD GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner);
|
||||
NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus);
|
||||
NS_IMETHOD_(JSObject *) GetGlobalJSObject();
|
||||
NS_IMETHOD OnFinalize(JSObject *aObject);
|
||||
|
||||
// nsIScriptObjectPrincipal methods
|
||||
NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal);
|
||||
|
||||
protected:
|
||||
virtual ~nsXBLDocGlobalObject();
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mScriptContext;
|
||||
JSObject *mJSObject; // XXX JS language rabies bigotry badness
|
||||
|
||||
nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // weak reference
|
||||
static JSClass gSharedGlobalClass;
|
||||
};
|
||||
|
||||
void PR_CALLBACK nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(cx, obj);
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
|
||||
|
||||
if (sgo)
|
||||
sgo->OnFinalize(obj);
|
||||
|
||||
// The addref was part of JSObject construction
|
||||
NS_RELEASE(nativeThis);
|
||||
}
|
||||
|
||||
|
||||
JSBool PR_CALLBACK nsXBLDocGlobalObject_resolve(JSContext *cx, JSObject *obj, jsval id)
|
||||
{
|
||||
JSBool did_resolve = JS_FALSE;
|
||||
return JS_ResolveStandardClass(cx, obj, id, &did_resolve);
|
||||
}
|
||||
|
||||
|
||||
JSClass nsXBLDocGlobalObject::gSharedGlobalClass = {
|
||||
"nsXBLPrototypeScript compilation scope",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, nsXBLDocGlobalObject_resolve, JS_ConvertStub,
|
||||
nsXBLDocGlobalObject_finalize
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXBLDocGlobalObject
|
||||
//
|
||||
|
||||
nsXBLDocGlobalObject::nsXBLDocGlobalObject()
|
||||
: mJSObject(nsnull),
|
||||
mGlobalObjectOwner(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
|
||||
nsXBLDocGlobalObject::~nsXBLDocGlobalObject()
|
||||
{}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsXBLDocGlobalObject, nsIScriptGlobalObject, nsIScriptObjectPrincipal)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIScriptGlobalObject methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::SetContext(nsIScriptContext *aContext)
|
||||
{
|
||||
mScriptContext = aContext;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::GetContext(nsIScriptContext **aContext)
|
||||
{
|
||||
// This whole fragile mess is predicated on the fact that
|
||||
// GetContext() will be called before GetScriptObject() is.
|
||||
if (! mScriptContext) {
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(kDOMScriptObjectFactoryCID);
|
||||
NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = factory->NewScriptContext(nsnull, getter_AddRefs(mScriptContext));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
JSContext *cx = (JSContext *)mScriptContext->GetNativeContext();
|
||||
|
||||
mJSObject = ::JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
|
||||
if (!mJSObject)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
::JS_SetGlobalObject(cx, mJSObject);
|
||||
|
||||
// Add an owning reference from JS back to us. This'll be
|
||||
// released when the JSObject is finalized.
|
||||
::JS_SetPrivate(cx, mJSObject, this);
|
||||
NS_ADDREF(this);
|
||||
}
|
||||
|
||||
*aContext = mScriptContext;
|
||||
NS_IF_ADDREF(*aContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::SetNewDocument(nsIDOMDocument *aDocument)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::SetDocShell(nsIDocShell *aDocShell)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::GetDocShell(nsIDocShell **aDocShell)
|
||||
{
|
||||
NS_WARNING("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::SetOpenerWindow(nsIDOMWindowInternal *aOpener)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner)
|
||||
{
|
||||
mGlobalObjectOwner = aOwner; // weak reference
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner)
|
||||
{
|
||||
*aOwner = mGlobalObjectOwner;
|
||||
NS_IF_ADDREF(*aOwner);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::HandleDOMEvent(nsIPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIDOMEvent** aDOMEvent,
|
||||
PRUint32 aFlags,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(JSObject *)
|
||||
nsXBLDocGlobalObject::GetGlobalJSObject()
|
||||
{
|
||||
// The prototype document has its own special secret script object
|
||||
// that can be used to compile scripts and event handlers.
|
||||
|
||||
if (!mScriptContext)
|
||||
return nsnull;
|
||||
|
||||
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||
mScriptContext->GetNativeContext());
|
||||
if (!cx)
|
||||
return nsnull;
|
||||
|
||||
return ::JS_GetGlobalObject(cx);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::OnFinalize(JSObject *aObject)
|
||||
{
|
||||
NS_ASSERTION(aObject == mJSObject, "Wrong object finalized!");
|
||||
|
||||
mJSObject = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIScriptObjectPrincipal methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocGlobalObject::GetPrincipal(nsIPrincipal** aPrincipal)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (!mGlobalObjectOwner) {
|
||||
*aPrincipal = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXBLDocumentInfo> docInfo = do_QueryInterface(mGlobalObjectOwner, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
rv = docInfo->GetDocument(getter_AddRefs(document));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
return document->GetPrincipal(aPrincipal);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class nsXBLDocumentInfo : public nsIXBLDocumentInfo, public nsIScriptGlobalObjectOwner, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -91,15 +353,20 @@ public:
|
|||
NS_IMETHOD GetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding** aResult);
|
||||
NS_IMETHOD SetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding* aBinding);
|
||||
|
||||
// nsIScriptGlobalObjectOwner methods
|
||||
NS_DECL_NSISCRIPTGLOBALOBJECTOWNER
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCString mDocURI;
|
||||
PRBool mScriptAccess;
|
||||
nsSupportsHashtable* mBindingTable;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> mGlobalObject;
|
||||
};
|
||||
|
||||
/* Implementation file */
|
||||
NS_IMPL_ISUPPORTS2(nsXBLDocumentInfo, nsIXBLDocumentInfo, nsISupportsWeakReference)
|
||||
NS_IMPL_ISUPPORTS3(nsXBLDocumentInfo, nsIXBLDocumentInfo, nsIScriptGlobalObjectOwner, nsISupportsWeakReference)
|
||||
|
||||
nsXBLDocumentInfo::nsXBLDocumentInfo(const char* aDocURI, nsIDocument* aDocument)
|
||||
{
|
||||
|
@ -114,6 +381,10 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(const char* aDocURI, nsIDocument* aDocument
|
|||
nsXBLDocumentInfo::~nsXBLDocumentInfo()
|
||||
{
|
||||
/* destructor code */
|
||||
if (mGlobalObject) {
|
||||
mGlobalObject->SetContext(nsnull); // remove circular reference
|
||||
mGlobalObject->SetGlobalObjectOwner(nsnull); // just in case
|
||||
}
|
||||
delete mBindingTable;
|
||||
}
|
||||
|
||||
|
@ -144,6 +415,45 @@ nsXBLDocumentInfo::SetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPro
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIScriptGlobalObjectOwner methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocumentInfo::GetScriptGlobalObject(nsIScriptGlobalObject** _result)
|
||||
{
|
||||
if (!mGlobalObject) {
|
||||
|
||||
mGlobalObject = new nsXBLDocGlobalObject();
|
||||
|
||||
if (!mGlobalObject) {
|
||||
*_result = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mGlobalObject->SetGlobalObjectOwner(this); // does not refcount
|
||||
}
|
||||
|
||||
*_result = mGlobalObject;
|
||||
NS_ADDREF(*_result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLDocumentInfo::ReportScriptError(nsIScriptError *errorObject)
|
||||
{
|
||||
if (errorObject == nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Get the console service, where we're going to register the error.
|
||||
nsCOMPtr<nsIConsoleService> consoleService (do_GetService("@mozilla.org/consoleservice;1"));
|
||||
|
||||
if (!consoleService)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
return consoleService->LogMessage(errorObject);
|
||||
}
|
||||
|
||||
nsresult NS_NewXBLDocumentInfo(nsIDocument* aDocument, nsIXBLDocumentInfo** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIURI> url;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
||||
*
|
||||
* Contributor(s): Brendan Eich (brendan@mozilla.org)
|
||||
* Scott MacGregor (mscott@netscape.com)
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -53,6 +54,7 @@
|
|||
#include "nsXBLService.h"
|
||||
#include "nsIXBLInsertionPoint.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIScriptGlobalObjectOwner.h"
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
// Event listeners
|
||||
|
@ -73,6 +75,7 @@
|
|||
#include "nsIDOMNamedNodeMap.h"
|
||||
|
||||
#include "nsIXBLPrototypeHandler.h"
|
||||
#include "nsIXBLPrototypeProperty.h"
|
||||
|
||||
#include "nsXBLKeyHandler.h"
|
||||
#include "nsXBLFocusHandler.h"
|
||||
|
@ -1054,281 +1057,47 @@ nsXBLBinding::InstallEventHandlers()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
const char* gPropertyArg[] = { "val" };
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::InstallProperties()
|
||||
{
|
||||
// Always install the base class properties first, so that
|
||||
// derived classes can reference the base class properties.
|
||||
|
||||
if (mNextBinding)
|
||||
mNextBinding->InstallProperties();
|
||||
|
||||
// Fetch the interface element for this binding.
|
||||
nsCOMPtr<nsIContent> interfaceElement;
|
||||
GetImmediateChild(kImplementationAtom, getter_AddRefs(interfaceElement));
|
||||
// iterate through each property in the prototype's list and install the property.
|
||||
if (AllowScripts()) {
|
||||
nsCOMPtr<nsIXBLPrototypeProperty> propertyChain;
|
||||
mPrototypeBinding->GetPrototypeProperties(getter_AddRefs(propertyChain));
|
||||
|
||||
if (!propertyChain) return NS_OK; // kick out if our list is empty
|
||||
|
||||
if (interfaceElement && AllowScripts()) {
|
||||
// Get our bound element's script context.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(document));
|
||||
if (!document)
|
||||
return NS_OK;
|
||||
if (!document) return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
document->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
|
||||
if (!global)
|
||||
return NS_OK;
|
||||
if (!global) return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
rv = global->GetContext(getter_AddRefs(context));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsresult rv = global->GetContext(getter_AddRefs(context));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!context) return NS_OK;
|
||||
|
||||
// Init our class and insert it into the prototype chain.
|
||||
nsAutoString className;
|
||||
nsCAutoString classStr;
|
||||
interfaceElement->GetAttr(kNameSpaceID_None, kNameAtom, className);
|
||||
if (!className.IsEmpty()) {
|
||||
classStr.AssignWithConversion(className);
|
||||
}
|
||||
else {
|
||||
GetBindingURI(classStr);
|
||||
}
|
||||
void * targetScriptObject = nsnull;
|
||||
void * targetClassObject = nsnull;
|
||||
rv = propertyChain->InitTargetObjects(context, mBoundElement, &targetScriptObject, &targetClassObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv); // kick out if we were unable to properly intialize our target objects
|
||||
|
||||
JSObject* scriptObject;
|
||||
JSObject* classObject;
|
||||
if (NS_FAILED(rv = InitClass(classStr, context, document, (void**)&scriptObject, (void**)&classObject)))
|
||||
return rv;
|
||||
|
||||
JSContext* cx = (JSContext*)context->GetNativeContext();
|
||||
|
||||
// Do a walk.
|
||||
PRInt32 childCount;
|
||||
interfaceElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
interfaceElement->ChildAt(i, *getter_AddRefs(child));
|
||||
|
||||
// See if we're a property or a method.
|
||||
nsCOMPtr<nsIAtom> tagName;
|
||||
child->GetTag(*getter_AddRefs(tagName));
|
||||
|
||||
if (tagName.get() == kMethodAtom && classObject) {
|
||||
// Obtain our name attribute.
|
||||
nsAutoString name, body;
|
||||
child->GetAttr(kNameSpaceID_None, kNameAtom, name);
|
||||
|
||||
// Now walk all of our args.
|
||||
// XXX I'm lame. 32 max args allowed.
|
||||
char* args[32];
|
||||
PRUint32 argCount = 0;
|
||||
PRInt32 kidCount;
|
||||
child->ChildCount(kidCount);
|
||||
for (PRInt32 j = 0; j < kidCount; j++)
|
||||
{
|
||||
nsCOMPtr<nsIContent> arg;
|
||||
child->ChildAt(j, *getter_AddRefs(arg));
|
||||
nsCOMPtr<nsIAtom> kidTagName;
|
||||
arg->GetTag(*getter_AddRefs(kidTagName));
|
||||
if (kidTagName.get() == kParameterAtom) {
|
||||
// Get the argname and add it to the array.
|
||||
nsAutoString argName;
|
||||
arg->GetAttr(kNameSpaceID_None, kNameAtom, argName);
|
||||
char* argStr = argName.ToNewCString();
|
||||
args[argCount] = argStr;
|
||||
argCount++;
|
||||
}
|
||||
else if (kidTagName.get() == kBodyAtom) {
|
||||
PRInt32 textCount;
|
||||
arg->ChildCount(textCount);
|
||||
|
||||
for (PRInt32 k = 0; k < textCount; k++) {
|
||||
// Get the child.
|
||||
nsCOMPtr<nsIContent> textChild;
|
||||
arg->ChildAt(k, *getter_AddRefs(textChild));
|
||||
nsCOMPtr<nsIDOMText> text(do_QueryInterface(textChild));
|
||||
if (text) {
|
||||
nsAutoString data;
|
||||
text->GetData(data);
|
||||
body += data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have a body and args, compile the function
|
||||
// and then define it as a property.
|
||||
if (!body.IsEmpty()) {
|
||||
void* myFunc;
|
||||
nsCAutoString cname; cname.AssignWithConversion(name.get());
|
||||
nsCAutoString functionUri = classStr;
|
||||
functionUri += ".";
|
||||
functionUri += cname;
|
||||
functionUri += "()";
|
||||
|
||||
rv = context->CompileFunction(classObject,
|
||||
cname,
|
||||
argCount,
|
||||
(const char**)args,
|
||||
body,
|
||||
functionUri.get(),
|
||||
0,
|
||||
PR_FALSE,
|
||||
&myFunc);
|
||||
}
|
||||
for (PRUint32 l = 0; l < argCount; l++) {
|
||||
nsMemory::Free(args[l]);
|
||||
}
|
||||
}
|
||||
else if (tagName.get() == kPropertyAtom) {
|
||||
// Obtain our name attribute.
|
||||
nsAutoString name;
|
||||
child->GetAttr(kNameSpaceID_None, kNameAtom, name);
|
||||
|
||||
if (!name.IsEmpty()) {
|
||||
// We have a property.
|
||||
nsAutoString getter, setter, readOnly;
|
||||
child->GetAttr(kNameSpaceID_None, kOnGetAtom, getter);
|
||||
child->GetAttr(kNameSpaceID_None, kOnSetAtom, setter);
|
||||
child->GetAttr(kNameSpaceID_None, kReadOnlyAtom, readOnly);
|
||||
|
||||
void* getFunc = nsnull;
|
||||
void* setFunc = nsnull;
|
||||
uintN attrs = JSPROP_ENUMERATE;
|
||||
|
||||
if (readOnly == NS_LITERAL_STRING("true"))
|
||||
attrs |= JSPROP_READONLY;
|
||||
|
||||
// try for first <getter> tag
|
||||
if (getter.IsEmpty()) {
|
||||
PRInt32 childCount;
|
||||
child->ChildCount(childCount);
|
||||
|
||||
nsCOMPtr<nsIContent> getterElement;
|
||||
for (PRInt32 j=0; j<childCount; j++) {
|
||||
child->ChildAt(j, *getter_AddRefs(getterElement));
|
||||
|
||||
if (!getterElement) continue;
|
||||
|
||||
nsCOMPtr<nsIAtom> getterTag;
|
||||
getterElement->GetTag(*getter_AddRefs(getterTag));
|
||||
|
||||
if (getterTag.get() == kGetterAtom) {
|
||||
GetTextData(getterElement, getter);
|
||||
break; // stop at first tag
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!getter.IsEmpty() && classObject) {
|
||||
nsCAutoString functionUri = classStr;
|
||||
functionUri += ".";
|
||||
functionUri.AppendWithConversion(name.get());
|
||||
functionUri += " (getter)";
|
||||
rv = context->CompileFunction(classObject,
|
||||
nsCAutoString("onget"),
|
||||
0,
|
||||
nsnull,
|
||||
getter,
|
||||
functionUri.get(),
|
||||
0,
|
||||
PR_FALSE,
|
||||
&getFunc);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
attrs |= JSPROP_GETTER | JSPROP_SHARED;
|
||||
}
|
||||
|
||||
// try for first <setter> tag
|
||||
if (setter.IsEmpty()) {
|
||||
PRInt32 childCount;
|
||||
child->ChildCount(childCount);
|
||||
|
||||
nsCOMPtr<nsIContent> setterElement;
|
||||
for (PRInt32 j=0; j<childCount; j++) {
|
||||
child->ChildAt(j, *getter_AddRefs(setterElement));
|
||||
|
||||
if (!setterElement) continue;
|
||||
|
||||
nsCOMPtr<nsIAtom> setterTag;
|
||||
setterElement->GetTag(*getter_AddRefs(setterTag));
|
||||
if (setterTag.get() == kSetterAtom) {
|
||||
GetTextData(setterElement, setter);
|
||||
break; // stop at first tag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!setter.IsEmpty() && classObject) {
|
||||
nsCAutoString functionUri = classStr;
|
||||
functionUri += ".";
|
||||
functionUri.AppendWithConversion(name.get());
|
||||
functionUri += " (setter)";
|
||||
rv = context->CompileFunction(classObject,
|
||||
nsCAutoString("onset"),
|
||||
1,
|
||||
gPropertyArg,
|
||||
setter,
|
||||
functionUri.get(),
|
||||
0,
|
||||
PR_FALSE,
|
||||
&setFunc);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
attrs |= JSPROP_SETTER | JSPROP_SHARED;
|
||||
}
|
||||
|
||||
if ((getFunc || setFunc) && classObject) {
|
||||
// Having either a getter or setter results in the
|
||||
// destruction of any initial value that might be set.
|
||||
// This means we only have to worry about defining the getter
|
||||
// or setter.
|
||||
::JS_DefineUCProperty(cx, (JSObject*)classObject, NS_REINTERPRET_CAST(const jschar*, name.get()),
|
||||
name.Length(), JSVAL_VOID,
|
||||
(JSPropertyOp) getFunc,
|
||||
(JSPropertyOp) setFunc,
|
||||
attrs);
|
||||
} else {
|
||||
// Look for a normal value and just define that.
|
||||
nsCOMPtr<nsIContent> textChild;
|
||||
PRInt32 textCount;
|
||||
child->ChildCount(textCount);
|
||||
nsAutoString answer;
|
||||
for (PRInt32 j = 0; j < textCount; j++) {
|
||||
// Get the child.
|
||||
child->ChildAt(j, *getter_AddRefs(textChild));
|
||||
nsCOMPtr<nsIDOMText> text(do_QueryInterface(textChild));
|
||||
if (text) {
|
||||
nsAutoString data;
|
||||
text->GetData(data);
|
||||
answer += data;
|
||||
}
|
||||
}
|
||||
|
||||
if (!answer.IsEmpty()) {
|
||||
// Evaluate our script and obtain a value.
|
||||
jsval result = nsnull;
|
||||
PRBool undefined;
|
||||
rv = context->EvaluateStringWithValue(answer,
|
||||
scriptObject,
|
||||
nsnull, nsnull, 0, nsnull,
|
||||
(void*) &result, &undefined);
|
||||
|
||||
if (!undefined) {
|
||||
// Define that value as a property
|
||||
::JS_DefineUCProperty(cx, (JSObject*)scriptObject, NS_REINTERPRET_CAST(const jschar*, name.get()),
|
||||
name.Length(), result,
|
||||
nsnull, nsnull,
|
||||
attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIXBLPrototypeProperty> curr = propertyChain;
|
||||
do {
|
||||
curr->InstallProperty(context, mBoundElement, targetScriptObject, targetClassObject);
|
||||
curr->GetNextProperty(getter_AddRefs(propertyChain));
|
||||
curr = propertyChain;
|
||||
} while (curr);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1441,8 +1210,11 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
|
|||
// XXX Sanity check to make sure our class name matches
|
||||
// Pull ourselves out of the proto chain.
|
||||
JSObject* ourProto = ::JS_GetPrototype(jscontext, scriptObject);
|
||||
JSObject* grandProto = ::JS_GetPrototype(jscontext, ourProto);
|
||||
::JS_SetPrototype(jscontext, scriptObject, grandProto);
|
||||
if (ourProto)
|
||||
{
|
||||
JSObject* grandProto = ::JS_GetPrototype(jscontext, ourProto);
|
||||
::JS_SetPrototype(jscontext, scriptObject, grandProto);
|
||||
}
|
||||
|
||||
// Don't remove the reference from the document to the
|
||||
// wrapper here since it'll be removed by the element
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
#include "nsHTMLAtoms.h"
|
||||
#include "nsXULAtoms.h"
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
#include "nsICSSLoader.h"
|
||||
#include "nsIStyleRuleProcessor.h"
|
||||
|
||||
|
@ -250,11 +252,10 @@ static const PRInt32 kInsInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLInsertionPoi
|
|||
// Implementation /////////////////////////////////////////////////////////////////
|
||||
|
||||
// Implement our nsISupports methods
|
||||
NS_IMPL_ISUPPORTS2(nsXBLPrototypeBinding, nsIXBLPrototypeBinding, nsICSSLoaderObserver)
|
||||
NS_IMPL_ISUPPORTS3(nsXBLPrototypeBinding, nsIXBLPrototypeBinding, nsICSSLoaderObserver, nsISupportsWeakReference)
|
||||
|
||||
// Constructors/Destructors
|
||||
nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIContent* aElement,
|
||||
nsIXBLDocumentInfo* aInfo)
|
||||
nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIXBLDocumentInfo* aInfo)
|
||||
: mID(aID),
|
||||
mInheritStyle(PR_TRUE),
|
||||
mHasBaseProto(PR_TRUE),
|
||||
|
@ -264,7 +265,8 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
|||
mAttributeTable(nsnull),
|
||||
mInsertionPointTable(nsnull),
|
||||
mInterfaceTable(nsnull),
|
||||
mStyleSheetList(nsnull)
|
||||
mStyleSheetList(nsnull),
|
||||
mClassObject(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
|
@ -297,7 +299,10 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
|||
kImplementationAtom = NS_NewAtom("implementation");
|
||||
kImplementsAtom = NS_NewAtom("implements");
|
||||
}
|
||||
}
|
||||
|
||||
void nsXBLPrototypeBinding::Initialize(nsIContent * aElement, nsIXBLDocumentInfo* aInfo)
|
||||
{
|
||||
// These all use atoms, so we have to do these ops last to ensure
|
||||
// the atoms exist.
|
||||
SetBindingElement(aElement);
|
||||
|
@ -306,6 +311,7 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
|||
aInfo->GetScriptAccess(&allowScripts);
|
||||
if (allowScripts) {
|
||||
ConstructHandlers();
|
||||
ConstructProperties();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
|
@ -321,7 +327,6 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
|||
ConstructInterfaceTable(impl);
|
||||
}
|
||||
|
||||
|
||||
nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
||||
{
|
||||
delete mAttributeTable;
|
||||
|
@ -617,6 +622,21 @@ nsXBLPrototypeBinding::SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::GetPrototypeProperties(nsIXBLPrototypeProperty ** aResult)
|
||||
{
|
||||
*aResult = mPrototypeProperty;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::SetProtoTypeProperties(nsIXBLPrototypeProperty* aResult)
|
||||
{
|
||||
mPrototypeProperty = aResult;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
|
||||
nsIContent* aChangedElement, nsIContent* aAnonymousContent)
|
||||
|
@ -933,6 +953,120 @@ nsXBLPrototypeBinding::GetImmediateChild(nsIAtom* aTag, nsIContent** aResult)
|
|||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::ConstructProperties()
|
||||
{
|
||||
nsCOMPtr<nsIContent> properties;
|
||||
GetImmediateChild(kImplementationAtom, getter_AddRefs(properties));
|
||||
if (properties && mBinding) {
|
||||
nsXBLService::BuildPropertyChain(this, properties, getter_AddRefs(mPrototypeProperty));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::GetCompiledClassObject(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject)
|
||||
{
|
||||
if (mClassObject) {
|
||||
*aClassObject = mClassObject;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
InitClass(aClassName, aContext, aScriptObject, &mClassObject);
|
||||
*aClassObject = mClassObject;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER (aClassObject);
|
||||
|
||||
*aClassObject = nsnull;
|
||||
|
||||
JSContext* jscontext = (JSContext*)aContext->GetNativeContext();
|
||||
JSObject* global = ::JS_GetGlobalObject(jscontext);
|
||||
JSObject* scriptObject = (JSObject*) aScriptObject;
|
||||
|
||||
// First ensure our JS class is initialized.
|
||||
jsval vp;
|
||||
JSObject* proto;
|
||||
|
||||
if ((! ::JS_LookupProperty(jscontext, global, aClassName, &vp)) || JSVAL_IS_PRIMITIVE(vp)) {
|
||||
// We need to initialize the class.
|
||||
nsXBLJSClass* c;
|
||||
void* classObject;
|
||||
nsCStringKey key(aClassName);
|
||||
classObject = (nsXBLService::gClassTable)->Get(&key);
|
||||
|
||||
if (classObject) {
|
||||
c = NS_STATIC_CAST(nsXBLJSClass*, classObject);
|
||||
// If c is on the LRU list (i.e., not linked to itself), remove it now!
|
||||
JSCList* link = NS_STATIC_CAST(JSCList*, c);
|
||||
if (c->next != link) {
|
||||
JS_REMOVE_AND_INIT_LINK(link);
|
||||
nsXBLService::gClassLRUListLength--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (JS_CLIST_IS_EMPTY(&nsXBLService::gClassLRUList)) {
|
||||
// We need to create a struct for this class.
|
||||
c = new nsXBLJSClass(aClassName);
|
||||
if (!c)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
// Pull the least recently used class struct off the list.
|
||||
JSCList* lru = (nsXBLService::gClassLRUList).next;
|
||||
JS_REMOVE_AND_INIT_LINK(lru);
|
||||
nsXBLService::gClassLRUListLength--;
|
||||
|
||||
// Remove any mapping from the old name to the class struct.
|
||||
c = NS_STATIC_CAST(nsXBLJSClass*, lru);
|
||||
nsCStringKey oldKey(c->name);
|
||||
(nsXBLService::gClassTable)->Remove(&oldKey);
|
||||
|
||||
// Change the class name and we're done.
|
||||
nsMemory::Free((void*) c->name);
|
||||
c->name = aClassName.ToNewCString();
|
||||
}
|
||||
|
||||
// Add c to our table.
|
||||
(nsXBLService::gClassTable)->Put(&key, (void*)c);
|
||||
}
|
||||
|
||||
// Retrieve the current prototype of the JS object.
|
||||
JSObject* parent_proto = ::JS_GetPrototype(jscontext, scriptObject);
|
||||
|
||||
// Make a new object prototyped by parent_proto and parented by global.
|
||||
proto = ::JS_InitClass(jscontext, // context
|
||||
global, // global object
|
||||
parent_proto, // parent proto
|
||||
c, // JSClass
|
||||
NULL, // JSNative ctor
|
||||
0, // ctor args
|
||||
nsnull, // proto props
|
||||
nsnull, // proto funcs
|
||||
nsnull, // ctor props (static)
|
||||
nsnull); // ctor funcs (static)
|
||||
if (!proto) {
|
||||
(nsXBLService::gClassTable)->Remove(&key);
|
||||
delete c;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// The prototype holds a strong reference to its class struct.
|
||||
c->Hold();
|
||||
*aClassObject = (void *) proto;
|
||||
}
|
||||
else
|
||||
proto = JSVAL_TO_OBJECT(vp);
|
||||
|
||||
::JS_SetPrototype(jscontext, scriptObject, proto);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::ConstructHandlers()
|
||||
{
|
||||
|
@ -1520,10 +1654,13 @@ nsresult
|
|||
NS_NewXBLPrototypeBinding(const nsAReadableCString& aRef, nsIContent* aElement,
|
||||
nsIXBLDocumentInfo* aInfo, nsIXBLPrototypeBinding** aResult)
|
||||
{
|
||||
*aResult = new nsXBLPrototypeBinding(aRef, aElement, aInfo);
|
||||
if (!*aResult)
|
||||
nsXBLPrototypeBinding * binding = new nsXBLPrototypeBinding(aRef, aInfo);
|
||||
if (!binding)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
binding->QueryInterface(NS_GET_IID(nsIXBLPrototypeBinding), (void **) aResult);
|
||||
binding->Initialize(aElement, aInfo);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIXBLPrototypeBinding.h"
|
||||
#include "nsIXBLPrototypeHandler.h"
|
||||
#include "nsIXBLPrototypeProperty.h"
|
||||
#include "nsICSSStyleSheet.h"
|
||||
#include "nsICSSLoaderObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIAtom;
|
||||
|
@ -40,7 +42,7 @@ class nsFixedSizeAllocator;
|
|||
// *********************************************************************/
|
||||
// The XBLPrototypeBinding class
|
||||
|
||||
class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsICSSLoaderObserver
|
||||
class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsICSSLoaderObserver, public nsSupportsWeakReference
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
|
@ -67,6 +69,11 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsICSSLoaderO
|
|||
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler);
|
||||
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler);
|
||||
|
||||
NS_IMETHOD GetPrototypeProperties(nsIXBLPrototypeProperty** aResult);
|
||||
NS_IMETHOD SetProtoTypeProperties(nsIXBLPrototypeProperty* aResult);
|
||||
NS_IMETHOD GetCompiledClassObject(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject);
|
||||
NS_IMETHOD InitClass(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject);
|
||||
|
||||
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
|
||||
nsIContent* aChangedElement, nsIContent* aAnonymousContent);
|
||||
|
||||
|
@ -108,10 +115,11 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsICSSLoaderO
|
|||
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult) { *aResult = mConstructor; NS_IF_ADDREF(*aResult); return NS_OK; };
|
||||
|
||||
public:
|
||||
nsXBLPrototypeBinding(const nsAReadableCString& aRef, nsIContent* aElement,
|
||||
nsIXBLDocumentInfo* aInfo);
|
||||
nsXBLPrototypeBinding(const nsAReadableCString& aRef, nsIXBLDocumentInfo* aInfo);
|
||||
virtual ~nsXBLPrototypeBinding();
|
||||
|
||||
void Initialize(nsIContent * aElement, nsIXBLDocumentInfo* aInfo);
|
||||
|
||||
// Static members
|
||||
static PRUint32 gRefCnt;
|
||||
static nsIAtom* kInheritStyleAtom;
|
||||
|
@ -143,6 +151,7 @@ public:
|
|||
|
||||
protected:
|
||||
void ConstructHandlers();
|
||||
void ConstructProperties();
|
||||
void ConstructAttributeTable(nsIContent* aElement);
|
||||
void ConstructInsertionTable(nsIContent* aElement);
|
||||
void ConstructInterfaceTable(nsIContent* aElement);
|
||||
|
@ -182,6 +191,8 @@ protected:
|
|||
nsCOMPtr<nsIXBLPrototypeHandler> mConstructor; // Strong. Our constructor.
|
||||
nsCOMPtr<nsIXBLPrototypeHandler> mDestructor; // Strong. Our destructor.
|
||||
|
||||
nsCOMPtr<nsIXBLPrototypeProperty> mPrototypeProperty;
|
||||
|
||||
nsCOMPtr<nsIXBLPrototypeBinding> mBaseBinding; // Strong. We own the base binding in our explicit inheritance chain.
|
||||
PRPackedBool mInheritStyle;
|
||||
PRPackedBool mHasBaseProto;
|
||||
|
@ -206,4 +217,6 @@ protected:
|
|||
|
||||
PRInt32 mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will
|
||||
nsCOMPtr<nsIAtom> mBaseTag; // be stored in here.
|
||||
|
||||
void * mClassObject; // the class object for the binding. We'll use this to pre-compile properties and methods for the binding.
|
||||
};
|
||||
|
|
|
@ -107,7 +107,7 @@ RemoveJSGCRoot(void* aScriptObjectRef)
|
|||
}
|
||||
|
||||
nsXBLPrototypeProperty::nsXBLPrototypeProperty(nsIXBLPrototypeBinding * aPrototypeBinding)
|
||||
: mJSMethod(nsnull), mJSGetterObject(nsnull), mJSSetterObject(nsnull), mPropertyIsCompiled(PR_FALSE)
|
||||
: mJSMethodObject(nsnull), mJSGetterObject(nsnull), mJSSetterObject(nsnull), mPropertyIsCompiled(PR_FALSE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mClassObject = nsnull;
|
||||
|
@ -132,8 +132,8 @@ nsXBLPrototypeProperty::nsXBLPrototypeProperty(nsIXBLPrototypeBinding * aPrototy
|
|||
|
||||
nsXBLPrototypeProperty::~nsXBLPrototypeProperty()
|
||||
{
|
||||
if (mJSMethod)
|
||||
RemoveJSGCRoot(&mJSMethod);
|
||||
if (mJSMethodObject)
|
||||
RemoveJSGCRoot(&mJSMethodObject);
|
||||
if (mJSGetterObject)
|
||||
RemoveJSGCRoot(&mJSGetterObject);
|
||||
if (mJSSetterObject)
|
||||
|
@ -232,13 +232,16 @@ nsXBLPrototypeProperty::InstallProperty(nsIScriptContext * aContext, nsIContent
|
|||
|
||||
JSContext* cx = (JSContext*) aContext->GetNativeContext();
|
||||
JSObject * scriptObject = (JSObject *) aScriptObject;
|
||||
NS_ASSERTION(scriptObject, "uhoh, script Object should NOT be null or bad things will happen");
|
||||
|
||||
JSObject * targetClassObject = (JSObject *) aTargetClassObject;
|
||||
JSObject * globalObject = ::JS_GetGlobalObject(cx);
|
||||
|
||||
// now we want to re-evaluate our property using aContext and the script object for this window...
|
||||
|
||||
if (mJSMethod && targetClassObject)
|
||||
if (mJSMethodObject && targetClassObject)
|
||||
{
|
||||
JSObject * method = ::JS_CloneFunctionObject(cx, (JSObject *) mJSMethod, JS_GetGlobalObject(cx));
|
||||
JSObject * method = ::JS_CloneFunctionObject(cx, mJSMethodObject, globalObject);
|
||||
::JS_DefineUCProperty(cx, targetClassObject, NS_REINTERPRET_CAST(const jschar*, mName.get()), mName.Length(), OBJECT_TO_JSVAL(method),
|
||||
NULL, NULL, JSPROP_ENUMERATE);
|
||||
|
||||
|
@ -253,11 +256,11 @@ nsXBLPrototypeProperty::InstallProperty(nsIScriptContext * aContext, nsIContent
|
|||
|
||||
JSObject * getter = nsnull;
|
||||
if (mJSGetterObject)
|
||||
getter = ::JS_CloneFunctionObject(cx, (JSObject *) mJSGetterObject, JS_GetGlobalObject(cx));
|
||||
getter = ::JS_CloneFunctionObject(cx, mJSGetterObject, globalObject);
|
||||
|
||||
JSObject * setter = nsnull;
|
||||
if (mJSSetterObject)
|
||||
setter = ::JS_CloneFunctionObject(cx, (JSObject *) mJSSetterObject, JS_GetGlobalObject(cx));
|
||||
setter = ::JS_CloneFunctionObject(cx, mJSSetterObject, globalObject);
|
||||
|
||||
::JS_DefineUCProperty(cx, targetClassObject, NS_REINTERPRET_CAST(const jschar*, mName.get()),
|
||||
mName.Length(), JSVAL_VOID, (JSPropertyOp) getter,
|
||||
|
@ -269,9 +272,9 @@ nsXBLPrototypeProperty::InstallProperty(nsIScriptContext * aContext, nsIContent
|
|||
jsval result = nsnull;
|
||||
PRBool undefined;
|
||||
aContext->EvaluateStringWithValue(mLiteralPropertyString,
|
||||
scriptObject,
|
||||
nsnull, nsnull, 0, nsnull,
|
||||
(void*) &result, &undefined);
|
||||
scriptObject,
|
||||
nsnull, nsnull, 0, nsnull,
|
||||
(void*) &result, &undefined);
|
||||
|
||||
if (!undefined)
|
||||
{
|
||||
|
@ -419,7 +422,7 @@ nsresult nsXBLPrototypeProperty::ParseProperty(nsIScriptContext * aContext, nsIC
|
|||
functionUri.get(),
|
||||
0,
|
||||
PR_FALSE,
|
||||
&mJSGetterObject);
|
||||
(void **) &mJSGetterObject);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
|
||||
if (mJSGetterObject)
|
||||
|
@ -471,7 +474,7 @@ nsresult nsXBLPrototypeProperty::ParseProperty(nsIScriptContext * aContext, nsIC
|
|||
functionUri.get(),
|
||||
0,
|
||||
PR_FALSE,
|
||||
&mJSSetterObject);
|
||||
(void **) &mJSSetterObject);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
|
||||
if (mJSSetterObject)
|
||||
|
@ -589,17 +592,16 @@ nsresult nsXBLPrototypeProperty::ParseMethod(nsIScriptContext * aContext, nsICon
|
|||
functionUri.get(),
|
||||
0,
|
||||
PR_FALSE,
|
||||
&mJSMethod);
|
||||
(void **) &mJSMethodObject);
|
||||
|
||||
if (mJSMethod)
|
||||
if (mJSMethodObject)
|
||||
{
|
||||
// Root the compiled prototype script object.
|
||||
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||
aContext->GetNativeContext());
|
||||
if (!cx) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = AddJSGCRoot(&mJSMethod, "nsXBLPrototypeProperty::mJSMethod");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = AddJSGCRoot(&mJSMethodObject, "nsXBLPrototypeProperty::mJSMethod");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,9 +68,9 @@ protected:
|
|||
static nsIAtom* kNameAtom;
|
||||
static nsIAtom* kReadOnlyAtom;
|
||||
|
||||
void * mJSMethod; // precompiled JS for a method
|
||||
void * mJSGetterObject; // precompiled JS for a getter property
|
||||
void * mJSSetterObject; // precompiled JS for a setter property
|
||||
JSObject * mJSMethodObject; // precompiled JS for a method
|
||||
JSObject * mJSGetterObject; // precompiled JS for a getter property
|
||||
JSObject * mJSSetterObject; // precompiled JS for a setter property
|
||||
nsString mLiteralPropertyString; // the property is just a literal string
|
||||
|
||||
JSObject* mClassObject;
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "nsIXBLDocumentInfo.h"
|
||||
|
||||
#include "nsIXBLPrototypeHandler.h"
|
||||
#include "nsIXBLPrototypeProperty.h"
|
||||
|
||||
#include "nsIChromeRegistry.h"
|
||||
#include "nsIPref.h"
|
||||
|
@ -1398,6 +1399,40 @@ static void GetImmediateChild(nsIAtom* aTag, nsIContent* aParent, nsIContent** a
|
|||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLService::BuildPropertyChain(nsIXBLPrototypeBinding * aPrototypeBinding, nsIContent * aContent, nsIXBLPrototypeProperty ** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIXBLPrototypeProperty> firstProperty;
|
||||
nsCOMPtr<nsIXBLPrototypeProperty> currProperty;
|
||||
PRInt32 propertyCount = 0;
|
||||
aContent->ChildCount(propertyCount);
|
||||
|
||||
for (PRInt32 j = 0; j < propertyCount; j++) {
|
||||
nsCOMPtr<nsIContent> property;
|
||||
aContent->ChildAt(j, *getter_AddRefs(property));
|
||||
|
||||
nsCOMPtr<nsIXBLPrototypeProperty> newProperty;
|
||||
NS_NewXBLPrototypeProperty(aPrototypeBinding, getter_AddRefs(newProperty));
|
||||
|
||||
if (!newProperty) return NS_ERROR_FAILURE;
|
||||
|
||||
newProperty->ConstructProperty(aContent, property);
|
||||
|
||||
if (newProperty) {
|
||||
if (currProperty)
|
||||
currProperty->SetNextProperty(newProperty);
|
||||
else
|
||||
firstProperty = newProperty;
|
||||
currProperty = newProperty;
|
||||
}
|
||||
}
|
||||
|
||||
*aResult = firstProperty;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLService::BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult)
|
||||
{
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
class nsIXBLBinding;
|
||||
class nsIXBLDocumentInfo;
|
||||
class nsIXBLPrototypeHandler;
|
||||
class nsIXBLPrototypeBinding;
|
||||
class nsIXBLPrototypeProperty;
|
||||
class nsINameSpaceManager;
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
|
@ -102,6 +104,7 @@ public:
|
|||
// that contain only whitespace.
|
||||
static nsresult StripWhitespaceNodes(nsIContent* aContent);
|
||||
static nsresult BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult);
|
||||
static nsresult BuildPropertyChain(nsIXBLPrototypeBinding * aPrototypeBinding, nsIContent * aContent, nsIXBLPrototypeProperty ** aResult);
|
||||
|
||||
// MEMBER VARIABLES
|
||||
public:
|
||||
|
|
Загрузка…
Ссылка в новой задаче