зеркало из https://github.com/mozilla/pjs.git
Fix for 106153, don't build a content model for XBL's implementation. r=bryner, sr=ben
This commit is contained in:
Родитель
ee9c51654a
Коммит
465e6e150b
|
@ -33,10 +33,9 @@ EXPORTS = \
|
||||||
nsIXBLBinding.h \
|
nsIXBLBinding.h \
|
||||||
nsIXBLBindingAttachedHandler.h \
|
nsIXBLBindingAttachedHandler.h \
|
||||||
nsIXBLDocumentInfo.h \
|
nsIXBLDocumentInfo.h \
|
||||||
nsIXBLInsertionPoint.h \
|
nsIXBLInsertionPoint.h \
|
||||||
nsIXBLPrototypeBinding.h \
|
nsIXBLPrototypeBinding.h \
|
||||||
nsIXBLPrototypeHandler.h \
|
nsIXBLPrototypeHandler.h \
|
||||||
nsIXBLPrototypeProperty.h \
|
|
||||||
nsIXBLService.h \
|
nsIXBLService.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
#!nmake
|
|
||||||
#
|
|
||||||
# The contents of this file are subject to the Netscape Public
|
|
||||||
# License Version 1.1 (the "License"); you may not use this file
|
|
||||||
# except in compliance with the License. You may obtain a copy of
|
|
||||||
# the License at http://www.mozilla.org/NPL/
|
|
||||||
#
|
|
||||||
# Software distributed under the License is distributed on an "AS
|
|
||||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
||||||
# implied. See the License for the specific language governing
|
|
||||||
# rights and limitations under the License.
|
|
||||||
#
|
|
||||||
# The Original Code is mozilla.org code.
|
|
||||||
#
|
|
||||||
# The Initial Developer of the Original Code is Netscape
|
|
||||||
# Communications Corporation. Portions created by Netscape are
|
|
||||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
|
||||||
# Rights Reserved.
|
|
||||||
#
|
|
||||||
# Contributor(s):
|
|
||||||
|
|
||||||
DEPTH=..\..\..
|
|
||||||
|
|
||||||
EXPORTS = \
|
|
||||||
nsIBindingManager.h \
|
|
||||||
nsIXBLBinding.h \
|
|
||||||
nsIXBLBindingAttachedHandler.h \
|
|
||||||
nsIXBLDocumentInfo.h \
|
|
||||||
nsIXBLInsertionPoint.h \
|
|
||||||
nsIXBLPrototypeBinding.h \
|
|
||||||
nsIXBLPrototypeHandler.h \
|
|
||||||
nsIXBLService.h \
|
|
||||||
nsIXBLPrototypeProperty.h \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
MODULE=content
|
|
||||||
|
|
||||||
include <$(DEPTH)\config\rules.mak>
|
|
|
@ -82,7 +82,7 @@ public:
|
||||||
|
|
||||||
NS_IMETHOD GenerateAnonymousContent() = 0;
|
NS_IMETHOD GenerateAnonymousContent() = 0;
|
||||||
NS_IMETHOD InstallEventHandlers() = 0;
|
NS_IMETHOD InstallEventHandlers() = 0;
|
||||||
NS_IMETHOD InstallProperties() = 0;
|
NS_IMETHOD InstallImplementation() = 0;
|
||||||
|
|
||||||
NS_IMETHOD HasStyleSheets(PRBool* aResolveStyle) = 0;
|
NS_IMETHOD HasStyleSheets(PRBool* aResolveStyle) = 0;
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ class nsIXBLBinding;
|
||||||
class nsISupportsArray;
|
class nsISupportsArray;
|
||||||
class nsCString;
|
class nsCString;
|
||||||
class nsIScriptContext;
|
class nsIScriptContext;
|
||||||
|
class nsXBLProtoImpl;
|
||||||
|
|
||||||
// {34D700F5-C1A2-4408-A0B1-DD8F891DD1FE}
|
// {34D700F5-C1A2-4408-A0B1-DD8F891DD1FE}
|
||||||
#define NS_IXBLPROTOTYPEBINDING_IID \
|
#define NS_IXBLPROTOTYPEBINDING_IID \
|
||||||
|
@ -82,12 +83,18 @@ public:
|
||||||
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler)=0;
|
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler)=0;
|
||||||
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler)=0;
|
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler)=0;
|
||||||
|
|
||||||
NS_IMETHOD GetPrototypeProperties(nsIXBLPrototypeProperty** aResult) = 0;
|
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult)=0;
|
||||||
NS_IMETHOD SetProtoTypeProperties(nsIXBLPrototypeProperty* aResult) = 0;
|
NS_IMETHOD SetConstructor(nsIXBLPrototypeHandler* aConstructor)=0;
|
||||||
NS_IMETHOD GetCompiledClassObject(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject) = 0;
|
NS_IMETHOD GetDestructor(nsIXBLPrototypeHandler** aResult)=0;
|
||||||
|
NS_IMETHOD SetDestructor(nsIXBLPrototypeHandler* aDestructor)=0;
|
||||||
|
|
||||||
NS_IMETHOD InitClass(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 SetImplementation(nsXBLProtoImpl* aImpl)=0;
|
||||||
|
NS_IMETHOD InstallImplementation(nsIContent* aBoundElement)=0;
|
||||||
|
|
||||||
|
NS_IMETHOD ConstructInterfaceTable(const nsAReadableString& aImpls)=0;
|
||||||
|
|
||||||
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
|
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
|
||||||
nsIContent* aChangedElement, nsIContent* aAnonymousContent)=0;
|
nsIContent* aChangedElement, nsIContent* aAnonymousContent)=0;
|
||||||
|
|
||||||
|
@ -126,8 +133,6 @@ public:
|
||||||
|
|
||||||
NS_IMETHOD AddResourceListener(nsIContent* aBoundElement)=0;
|
NS_IMETHOD AddResourceListener(nsIContent* aBoundElement)=0;
|
||||||
|
|
||||||
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult)=0;
|
|
||||||
|
|
||||||
NS_IMETHOD Initialize()=0;
|
NS_IMETHOD Initialize()=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ public:
|
||||||
NS_IMETHOD KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aEvent, PRBool* aResult) = 0;
|
NS_IMETHOD KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aEvent, PRBool* aResult) = 0;
|
||||||
|
|
||||||
NS_IMETHOD GetHandlerElement(nsIContent** aResult) = 0;
|
NS_IMETHOD GetHandlerElement(nsIContent** aResult) = 0;
|
||||||
NS_IMETHOD SetHandlerText(const nsAReadableString& aText) = 0;
|
NS_IMETHOD AppendHandlerText(const nsAReadableString& aText) = 0;
|
||||||
|
|
||||||
NS_IMETHOD GetPhase(PRUint8* aPhase) = 0;
|
NS_IMETHOD GetPhase(PRUint8* aPhase) = 0;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,10 @@ CPPSRCS = \
|
||||||
nsXBLResourceLoader.cpp \
|
nsXBLResourceLoader.cpp \
|
||||||
nsXBLDocumentInfo.cpp \
|
nsXBLDocumentInfo.cpp \
|
||||||
nsXBLContentSink.cpp \
|
nsXBLContentSink.cpp \
|
||||||
nsXBLPrototypeProperty.cpp \
|
nsXBLProtoImplProperty.cpp \
|
||||||
|
nsXBLProtoImplMethod.cpp \
|
||||||
|
nsXBLProtoImplField.cpp \
|
||||||
|
nsXBLProtoImpl.cpp \
|
||||||
nsXBLEventHandler.cpp \
|
nsXBLEventHandler.cpp \
|
||||||
nsXBLWindowHandler.cpp \
|
nsXBLWindowHandler.cpp \
|
||||||
nsXBLWindowKeyHandler.cpp \
|
nsXBLWindowKeyHandler.cpp \
|
||||||
|
|
|
@ -76,7 +76,10 @@ CPPSRCS= \
|
||||||
nsXBLPrototypeHandler.cpp \
|
nsXBLPrototypeHandler.cpp \
|
||||||
nsBindingManager.cpp \
|
nsBindingManager.cpp \
|
||||||
nsXBLInsertionPoint.cpp \
|
nsXBLInsertionPoint.cpp \
|
||||||
nsXBLPrototypeProperty.cpp \
|
nsXBLProtoImplProperty.cpp \
|
||||||
|
nsXBLProtoImplMethod.cpp \
|
||||||
|
nsXBLProtoImplField.cpp \
|
||||||
|
nsXBLProtoImpl.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
CPP_OBJS= \
|
CPP_OBJS= \
|
||||||
|
@ -105,7 +108,10 @@ CPP_OBJS= \
|
||||||
.\$(OBJDIR)\nsXBLService.obj \
|
.\$(OBJDIR)\nsXBLService.obj \
|
||||||
.\$(OBJDIR)\nsBindingManager.obj \
|
.\$(OBJDIR)\nsBindingManager.obj \
|
||||||
.\$(OBJDIR)\nsXBLInsertionPoint.obj \
|
.\$(OBJDIR)\nsXBLInsertionPoint.obj \
|
||||||
.\$(OBJDIR)\nsXBLPrototypeProperty.obj \
|
.\$(OBJDIR)\nsXBLProtoImplProperty.obj \
|
||||||
|
.\$(OBJDIR)\nsXBLProtoImplMethod.obj \
|
||||||
|
.\$(OBJDIR)\nsXBLProtoImplField.obj \
|
||||||
|
.\$(OBJDIR)\nsXBLProtoImpl.obj \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXPORTS = \
|
EXPORTS = \
|
||||||
|
|
|
@ -94,7 +94,6 @@
|
||||||
#include "nsIDOMAttr.h"
|
#include "nsIDOMAttr.h"
|
||||||
#include "nsIDOMNamedNodeMap.h"
|
#include "nsIDOMNamedNodeMap.h"
|
||||||
|
|
||||||
#include "nsIXBLPrototypeProperty.h"
|
|
||||||
#include "nsXBLPrototypeHandler.h"
|
#include "nsXBLPrototypeHandler.h"
|
||||||
|
|
||||||
#include "nsXBLKeyHandler.h"
|
#include "nsXBLKeyHandler.h"
|
||||||
|
@ -994,47 +993,17 @@ nsXBLBinding::InstallEventHandlers()
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLBinding::InstallProperties()
|
nsXBLBinding::InstallImplementation()
|
||||||
{
|
{
|
||||||
// Always install the base class properties first, so that
|
// Always install the base class properties first, so that
|
||||||
// derived classes can reference the base class properties.
|
// derived classes can reference the base class properties.
|
||||||
|
|
||||||
if (mNextBinding)
|
if (mNextBinding)
|
||||||
mNextBinding->InstallProperties();
|
mNextBinding->InstallImplementation();
|
||||||
|
|
||||||
// iterate through each property in the prototype's list and install the property.
|
// iterate through each property in the prototype's list and install the property.
|
||||||
if (AllowScripts()) {
|
if (AllowScripts())
|
||||||
nsCOMPtr<nsIXBLPrototypeProperty> propertyChain;
|
mPrototypeBinding->InstallImplementation(mBoundElement);
|
||||||
mPrototypeBinding->GetPrototypeProperties(getter_AddRefs(propertyChain));
|
|
||||||
|
|
||||||
if (!propertyChain) return NS_OK; // kick out if our list is empty
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> document;
|
|
||||||
mBoundElement->GetDocument(*getter_AddRefs(document));
|
|
||||||
if (!document) return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
|
||||||
document->GetScriptGlobalObject(getter_AddRefs(global));
|
|
||||||
if (!global) return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptContext> context;
|
|
||||||
nsresult rv = global->GetContext(getter_AddRefs(context));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (!context) return NS_OK;
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
nsCOMPtr<nsIXBLPrototypeProperty> curr = propertyChain;
|
|
||||||
do {
|
|
||||||
curr->InstallProperty(context, mBoundElement, targetScriptObject, targetClassObject);
|
|
||||||
curr->GetNextProperty(getter_AddRefs(propertyChain));
|
|
||||||
curr = propertyChain;
|
|
||||||
} while (curr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ class nsXBLBinding: public nsIXBLBinding
|
||||||
|
|
||||||
NS_IMETHOD GenerateAnonymousContent();
|
NS_IMETHOD GenerateAnonymousContent();
|
||||||
NS_IMETHOD InstallEventHandlers();
|
NS_IMETHOD InstallEventHandlers();
|
||||||
NS_IMETHOD InstallProperties();
|
NS_IMETHOD InstallImplementation();
|
||||||
|
|
||||||
NS_IMETHOD HasStyleSheets(PRBool* aResolveStyle);
|
NS_IMETHOD HasStyleSheets(PRBool* aResolveStyle);
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,9 @@
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
#include "nsXULElement.h"
|
#include "nsXULElement.h"
|
||||||
#include "nsXULAtoms.h"
|
#include "nsXULAtoms.h"
|
||||||
|
#include "nsXBLProtoImplProperty.h"
|
||||||
|
#include "nsXBLProtoImplMethod.h"
|
||||||
|
#include "nsXBLProtoImplField.h"
|
||||||
|
|
||||||
static NS_DEFINE_CID(kCSSParserCID, NS_CSSPARSER_CID);
|
static NS_DEFINE_CID(kCSSParserCID, NS_CSSPARSER_CID);
|
||||||
|
|
||||||
|
@ -79,6 +82,11 @@ nsXBLContentSink::nsXBLContentSink()
|
||||||
mSecondaryState = eXBL_None;
|
mSecondaryState = eXBL_None;
|
||||||
mDocInfo = nsnull;
|
mDocInfo = nsnull;
|
||||||
mIsChromeOrResource = PR_FALSE;
|
mIsChromeOrResource = PR_FALSE;
|
||||||
|
mImplementation = nsnull;
|
||||||
|
mImplMember = nsnull;
|
||||||
|
mProperty = nsnull;
|
||||||
|
mMethod = nsnull;
|
||||||
|
mField = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsXBLContentSink::~nsXBLContentSink()
|
nsXBLContentSink::~nsXBLContentSink()
|
||||||
|
@ -137,13 +145,57 @@ nsXBLContentSink::OnOpenContainer(const nsIParserNode& aNode, PRInt32 aNameSpace
|
||||||
mState = eXBL_InResources;
|
mState = eXBL_InResources;
|
||||||
ret = PR_FALSE; // The XML content sink should ignore all <resources>.
|
ret = PR_FALSE; // The XML content sink should ignore all <resources>.
|
||||||
}
|
}
|
||||||
else if (mState == eXBL_InResources && (aTagName == nsXBLAtoms::stylesheet || aTagName == nsXBLAtoms::image)) {
|
else if (mState == eXBL_InResources) {
|
||||||
ConstructResource(aNode, aTagName);
|
if (aTagName == nsXBLAtoms::stylesheet || aTagName == nsXBLAtoms::image)
|
||||||
ret = PR_FALSE; // The XML content sink should ignore all <resources>.
|
ConstructResource(aNode, aTagName);
|
||||||
|
ret = PR_FALSE; // The XML content sink should ignore everything within a <resources> block.
|
||||||
}
|
}
|
||||||
else if (aTagName == nsXBLAtoms::implementation) {
|
else if (aTagName == nsXBLAtoms::implementation) {
|
||||||
// mState = eXBL_InImplementation;
|
mState = eXBL_InImplementation;
|
||||||
// ret = PR_FALSE; // The XML content sink should ignore the <implementation>.
|
ConstructImplementation(aNode);
|
||||||
|
ret = PR_FALSE; // The XML content sink should ignore the <implementation>.
|
||||||
|
}
|
||||||
|
else if (mState == eXBL_InImplementation) {
|
||||||
|
if (aTagName == nsXBLAtoms::constructor) {
|
||||||
|
mSecondaryState = eXBL_InConstructor;
|
||||||
|
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
|
||||||
|
NS_NewXBLPrototypeHandler(nsnull, nsnull, nsnull, nsnull,
|
||||||
|
nsnull, nsnull, nsnull, nsnull, nsnull,
|
||||||
|
getter_AddRefs(newHandler));
|
||||||
|
newHandler->SetEventName(nsXBLAtoms::constructor);
|
||||||
|
mBinding->SetConstructor(newHandler);
|
||||||
|
}
|
||||||
|
else if (aTagName == nsXBLAtoms::destructor) {
|
||||||
|
mSecondaryState = eXBL_InDestructor;
|
||||||
|
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
|
||||||
|
NS_NewXBLPrototypeHandler(nsnull, nsnull, nsnull, nsnull,
|
||||||
|
nsnull, nsnull, nsnull, nsnull, nsnull,
|
||||||
|
getter_AddRefs(newHandler));
|
||||||
|
newHandler->SetEventName(nsXBLAtoms::destructor);
|
||||||
|
mBinding->SetDestructor(newHandler);
|
||||||
|
}
|
||||||
|
else if (aTagName == nsXBLAtoms::field) {
|
||||||
|
mSecondaryState = eXBL_InField;
|
||||||
|
ConstructField(aNode);
|
||||||
|
}
|
||||||
|
else if (aTagName == nsXBLAtoms::property) {
|
||||||
|
mSecondaryState = eXBL_InProperty;
|
||||||
|
ConstructProperty(aNode);
|
||||||
|
}
|
||||||
|
else if (aTagName == nsXBLAtoms::getter)
|
||||||
|
mSecondaryState = eXBL_InGetter;
|
||||||
|
else if (aTagName == nsXBLAtoms::setter)
|
||||||
|
mSecondaryState = eXBL_InSetter;
|
||||||
|
else if (aTagName == nsXBLAtoms::method) {
|
||||||
|
mSecondaryState = eXBL_InMethod;
|
||||||
|
ConstructMethod(aNode);
|
||||||
|
}
|
||||||
|
else if (aTagName == nsXBLAtoms::parameter)
|
||||||
|
ConstructParameter(aNode);
|
||||||
|
else if (aTagName == nsXBLAtoms::body)
|
||||||
|
mSecondaryState = eXBL_InBody;
|
||||||
|
|
||||||
|
ret = PR_FALSE; // Ignore everything we encounter inside an <implementation> block.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +240,32 @@ nsXBLContentSink::CloseContainer(const nsIParserNode& aNode)
|
||||||
mState = eXBL_InBinding;
|
mState = eXBL_InBinding;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
else if (mState == eXBL_InImplementation) {
|
||||||
|
if (tagAtom == nsXBLAtoms::implementation)
|
||||||
|
mState = eXBL_InBinding;
|
||||||
|
else if (tagAtom == nsXBLAtoms::property) {
|
||||||
|
mSecondaryState = eXBL_None;
|
||||||
|
mProperty = nsnull;
|
||||||
|
}
|
||||||
|
else if (tagAtom == nsXBLAtoms::method) {
|
||||||
|
mSecondaryState = eXBL_None;
|
||||||
|
mMethod = nsnull;
|
||||||
|
}
|
||||||
|
else if (tagAtom == nsXBLAtoms::field) {
|
||||||
|
mSecondaryState = eXBL_None;
|
||||||
|
mField = nsnull;
|
||||||
|
}
|
||||||
|
else if (tagAtom == nsXBLAtoms::constructor ||
|
||||||
|
tagAtom == nsXBLAtoms::destructor)
|
||||||
|
mSecondaryState = eXBL_None;
|
||||||
|
else if (tagAtom == nsXBLAtoms::getter ||
|
||||||
|
tagAtom == nsXBLAtoms::setter)
|
||||||
|
mSecondaryState = eXBL_InProperty;
|
||||||
|
else if (tagAtom == nsXBLAtoms::parameter ||
|
||||||
|
tagAtom == nsXBLAtoms::body)
|
||||||
|
mSecondaryState = eXBL_InMethod;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult rv = nsXMLContentSink::CloseContainer(aNode);
|
nsresult rv = nsXMLContentSink::CloseContainer(aNode);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
|
@ -243,21 +321,125 @@ nsXBLContentSink::AddLeaf(const nsIParserNode& aNode)
|
||||||
// Get the text and add it to the event handler.
|
// Get the text and add it to the event handler.
|
||||||
switch (aNode.GetTokenType()) {
|
switch (aNode.GetTokenType()) {
|
||||||
case eToken_text:
|
case eToken_text:
|
||||||
|
case eToken_whitespace:
|
||||||
|
case eToken_newline:
|
||||||
case eToken_cdatasection:
|
case eToken_cdatasection:
|
||||||
mHandler->SetHandlerText(aNode.GetText());
|
mHandler->AppendHandlerText(aNode.GetText());
|
||||||
|
break;
|
||||||
case eToken_entity:
|
case eToken_entity:
|
||||||
{
|
{
|
||||||
nsAutoString tmp;
|
nsAutoString tmp;
|
||||||
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
|
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
|
||||||
if (unicode < 0)
|
if (unicode < 0)
|
||||||
mHandler->SetHandlerText(aNode.GetText());
|
mHandler->AppendHandlerText(aNode.GetText());
|
||||||
else
|
else
|
||||||
mHandler->SetHandlerText(aNode.GetText());
|
mHandler->AppendHandlerText(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
else if (mState == eXBL_InImplementation) {
|
||||||
|
if (mSecondaryState == eXBL_InConstructor ||
|
||||||
|
mSecondaryState == eXBL_InDestructor) {
|
||||||
|
// Construct a handler for the constructor/destructor.
|
||||||
|
// XXXdwh This is just awful. These used to be handlers called
|
||||||
|
// BindingAttached and BindingDetached, and they're still implemented
|
||||||
|
// using handlers. At some point, we need to change these to just
|
||||||
|
// be special functions on the class instead.
|
||||||
|
nsCOMPtr<nsIXBLPrototypeHandler> handler;
|
||||||
|
if (mSecondaryState == eXBL_InConstructor)
|
||||||
|
mBinding->GetConstructor(getter_AddRefs(handler));
|
||||||
|
else
|
||||||
|
mBinding->GetDestructor(getter_AddRefs(handler));
|
||||||
|
|
||||||
|
// Get the text and add it to the constructor/destructor.
|
||||||
|
switch (aNode.GetTokenType()) {
|
||||||
|
case eToken_text:
|
||||||
|
case eToken_whitespace:
|
||||||
|
case eToken_newline:
|
||||||
|
case eToken_cdatasection:
|
||||||
|
handler->AppendHandlerText(aNode.GetText());
|
||||||
|
break;
|
||||||
|
case eToken_entity:
|
||||||
|
{
|
||||||
|
nsAutoString tmp;
|
||||||
|
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
|
||||||
|
if (unicode < 0)
|
||||||
|
handler->AppendHandlerText(aNode.GetText());
|
||||||
|
else
|
||||||
|
handler->AppendHandlerText(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mSecondaryState == eXBL_InGetter ||
|
||||||
|
mSecondaryState == eXBL_InSetter) {
|
||||||
|
// Get the text and add it to the constructor/destructor.
|
||||||
|
PRBool getter = mSecondaryState == eXBL_InGetter;
|
||||||
|
switch (aNode.GetTokenType()) {
|
||||||
|
case eToken_text:
|
||||||
|
case eToken_whitespace:
|
||||||
|
case eToken_newline:
|
||||||
|
case eToken_cdatasection:
|
||||||
|
getter ? mProperty->AppendGetterText(aNode.GetText()) :
|
||||||
|
mProperty->AppendSetterText(aNode.GetText());
|
||||||
|
break;
|
||||||
|
case eToken_entity:
|
||||||
|
{
|
||||||
|
nsAutoString tmp;
|
||||||
|
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
|
||||||
|
if (unicode < 0)
|
||||||
|
getter ? mProperty->AppendGetterText(aNode.GetText()) :
|
||||||
|
mProperty->AppendSetterText(aNode.GetText());
|
||||||
|
else
|
||||||
|
getter ? mProperty->AppendGetterText(tmp) :
|
||||||
|
mProperty->AppendSetterText(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mSecondaryState == eXBL_InBody) {
|
||||||
|
// Get the text and add it to the method
|
||||||
|
switch (aNode.GetTokenType()) {
|
||||||
|
case eToken_text:
|
||||||
|
case eToken_whitespace:
|
||||||
|
case eToken_newline:
|
||||||
|
case eToken_cdatasection:
|
||||||
|
mMethod->AppendBodyText(aNode.GetText());
|
||||||
|
break;
|
||||||
|
case eToken_entity:
|
||||||
|
{
|
||||||
|
nsAutoString tmp;
|
||||||
|
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
|
||||||
|
if (unicode < 0)
|
||||||
|
mMethod->AppendBodyText(aNode.GetText());
|
||||||
|
else
|
||||||
|
mMethod->AppendBodyText(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mSecondaryState == eXBL_InField) {
|
||||||
|
// Get the text and add it to the method
|
||||||
|
switch (aNode.GetTokenType()) {
|
||||||
|
case eToken_text:
|
||||||
|
case eToken_whitespace:
|
||||||
|
case eToken_newline:
|
||||||
|
case eToken_cdatasection:
|
||||||
|
mField->AppendFieldText(aNode.GetText());
|
||||||
|
break;
|
||||||
|
case eToken_entity:
|
||||||
|
{
|
||||||
|
nsAutoString tmp;
|
||||||
|
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
|
||||||
|
if (unicode < 0)
|
||||||
|
mField->AppendFieldText(aNode.GetText());
|
||||||
|
else
|
||||||
|
mField->AppendFieldText(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return nsXMLContentSink::AddLeaf(aNode);
|
return nsXMLContentSink::AddLeaf(aNode);
|
||||||
}
|
}
|
||||||
|
@ -504,3 +686,184 @@ nsXBLContentSink::ConstructResource(const nsIParserNode& aNode, nsIAtom* aResour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLContentSink::ConstructImplementation(const nsIParserNode& aNode)
|
||||||
|
{
|
||||||
|
mImplementation = nsnull;
|
||||||
|
mImplMember = nsnull;
|
||||||
|
|
||||||
|
if (!mBinding)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsAReadableString* name = nsnull;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
||||||
|
PRInt32 ac = aNode.GetAttributeCount();
|
||||||
|
for (PRInt32 i = 0; i < ac; i++) {
|
||||||
|
// Get upper-cased key
|
||||||
|
const nsAReadableString& key = aNode.GetKeyAt(i);
|
||||||
|
|
||||||
|
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
|
||||||
|
getter_AddRefs(nameAtom));
|
||||||
|
|
||||||
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Is this attribute one of the ones we care about?
|
||||||
|
if (key.Equals(NS_LITERAL_STRING("name")))
|
||||||
|
name = &(aNode.GetValueAt(i));
|
||||||
|
else if (key.Equals(NS_LITERAL_STRING("implements")))
|
||||||
|
mBinding->ConstructInterfaceTable(aNode.GetValueAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_NewXBLProtoImpl(mBinding, name, &mImplementation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLContentSink::ConstructField(const nsIParserNode& aNode)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
||||||
|
PRInt32 ac = aNode.GetAttributeCount();
|
||||||
|
|
||||||
|
nsAReadableString* name = nsnull;
|
||||||
|
nsAReadableString* readonly = nsnull;
|
||||||
|
|
||||||
|
for (PRInt32 i = 0; i < ac; i++) {
|
||||||
|
// Get upper-cased key
|
||||||
|
const nsAReadableString& key = aNode.GetKeyAt(i);
|
||||||
|
|
||||||
|
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
|
||||||
|
getter_AddRefs(nameAtom));
|
||||||
|
|
||||||
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Is this attribute one of the ones we care about?
|
||||||
|
if (key.Equals(NS_LITERAL_STRING("name")))
|
||||||
|
name = &(aNode.GetValueAt(i));
|
||||||
|
else if (key.Equals(NS_LITERAL_STRING("readonly")))
|
||||||
|
readonly = &(aNode.GetValueAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// All of our pointers are now filled in. Construct our field with all of these
|
||||||
|
// parameters.
|
||||||
|
mField = new nsXBLProtoImplField(name, readonly);
|
||||||
|
if (mField) {
|
||||||
|
// Add this member to our chain.
|
||||||
|
if (mImplMember)
|
||||||
|
mImplMember->SetNext(mField); // Already have a chain. Just append to the end.
|
||||||
|
else
|
||||||
|
mImplementation->SetMemberList(mField); // We're the first member in the chain.
|
||||||
|
|
||||||
|
mImplMember = mField; // Adjust our pointer to point to the new last member in the chain.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLContentSink::ConstructProperty(const nsIParserNode& aNode)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
||||||
|
PRInt32 ac = aNode.GetAttributeCount();
|
||||||
|
|
||||||
|
nsAReadableString* name = nsnull;
|
||||||
|
nsAReadableString* readonly = nsnull;
|
||||||
|
nsAReadableString* onget = nsnull;
|
||||||
|
nsAReadableString* onset = nsnull;
|
||||||
|
|
||||||
|
for (PRInt32 i = 0; i < ac; i++) {
|
||||||
|
// Get upper-cased key
|
||||||
|
const nsAReadableString& key = aNode.GetKeyAt(i);
|
||||||
|
|
||||||
|
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
|
||||||
|
getter_AddRefs(nameAtom));
|
||||||
|
|
||||||
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Is this attribute one of the ones we care about?
|
||||||
|
if (key.Equals(NS_LITERAL_STRING("name")))
|
||||||
|
name = &(aNode.GetValueAt(i));
|
||||||
|
else if (key.Equals(NS_LITERAL_STRING("readonly")))
|
||||||
|
readonly = &(aNode.GetValueAt(i));
|
||||||
|
else if (key.Equals(NS_LITERAL_STRING("onget")))
|
||||||
|
onget = &(aNode.GetValueAt(i));
|
||||||
|
else if (key.Equals(NS_LITERAL_STRING("onset")))
|
||||||
|
onset = &(aNode.GetValueAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// All of our pointers are now filled in. Construct our property with all of these
|
||||||
|
// parameters.
|
||||||
|
mProperty = new nsXBLProtoImplProperty(name, onget, onset, readonly);
|
||||||
|
if (mProperty) {
|
||||||
|
// Add this member to our chain.
|
||||||
|
if (mImplMember)
|
||||||
|
mImplMember->SetNext(mProperty); // Already have a chain. Just append to the end.
|
||||||
|
else
|
||||||
|
mImplementation->SetMemberList(mProperty); // We're the first member in the chain.
|
||||||
|
|
||||||
|
mImplMember = mProperty; // Adjust our pointer to point to the new last member in the chain.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLContentSink::ConstructMethod(const nsIParserNode& aNode)
|
||||||
|
{
|
||||||
|
mMethod = nsnull;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
||||||
|
PRInt32 ac = aNode.GetAttributeCount();
|
||||||
|
|
||||||
|
for (PRInt32 i = 0; i < ac; i++) {
|
||||||
|
// Get upper-cased key
|
||||||
|
const nsAReadableString& key = aNode.GetKeyAt(i);
|
||||||
|
|
||||||
|
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
|
||||||
|
getter_AddRefs(nameAtom));
|
||||||
|
|
||||||
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Is this attribute one of the ones we care about?
|
||||||
|
if (key.Equals(NS_LITERAL_STRING("name"))) {
|
||||||
|
mMethod = new nsXBLProtoImplMethod(aNode.GetValueAt(i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMethod) {
|
||||||
|
// Add this member to our chain.
|
||||||
|
if (mImplMember)
|
||||||
|
mImplMember->SetNext(mMethod); // Already have a chain. Just append to the end.
|
||||||
|
else
|
||||||
|
mImplementation->SetMemberList(mMethod); // We're the first member in the chain.
|
||||||
|
|
||||||
|
mImplMember = mMethod; // Adjust our pointer to point to the new last member in the chain.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLContentSink::ConstructParameter(const nsIParserNode& aNode)
|
||||||
|
{
|
||||||
|
if (!mMethod)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
||||||
|
PRInt32 ac = aNode.GetAttributeCount();
|
||||||
|
for (PRInt32 i = 0; i < ac; i++) {
|
||||||
|
// Get upper-cased key
|
||||||
|
const nsAReadableString& key = aNode.GetKeyAt(i);
|
||||||
|
|
||||||
|
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
|
||||||
|
getter_AddRefs(nameAtom));
|
||||||
|
|
||||||
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Is this attribute one of the ones we care about?
|
||||||
|
if (key.Equals(NS_LITERAL_STRING("name"))) {
|
||||||
|
mMethod->AddParameter(aNode.GetValueAt(i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "nsXBLDocumentInfo.h"
|
#include "nsXBLDocumentInfo.h"
|
||||||
#include "nsIXBLPrototypeBinding.h"
|
#include "nsIXBLPrototypeBinding.h"
|
||||||
#include "nsIXBLPrototypeHandler.h"
|
#include "nsIXBLPrototypeHandler.h"
|
||||||
|
#include "nsXBLProtoImpl.h"
|
||||||
#include "nsICSSParser.h"
|
#include "nsICSSParser.h"
|
||||||
#include "nsLayoutCID.h"
|
#include "nsLayoutCID.h"
|
||||||
|
|
||||||
|
@ -62,10 +63,16 @@ typedef enum {
|
||||||
eXBL_InField,
|
eXBL_InField,
|
||||||
eXBL_InBody,
|
eXBL_InBody,
|
||||||
eXBL_InGetter,
|
eXBL_InGetter,
|
||||||
eXBL_InSetter
|
eXBL_InSetter,
|
||||||
|
eXBL_InConstructor,
|
||||||
|
eXBL_InDestructor
|
||||||
} XBLSecondaryState;
|
} XBLSecondaryState;
|
||||||
|
|
||||||
class nsXULPrototypeElement;
|
class nsXULPrototypeElement;
|
||||||
|
class nsXBLProtoImplMember;
|
||||||
|
class nsXBLProtoImplProperty;
|
||||||
|
class nsXBLProtoImplMethod;
|
||||||
|
class nsXBLProtoImplField;
|
||||||
|
|
||||||
// The XBL content sink overrides the XML content sink to
|
// The XBL content sink overrides the XML content sink to
|
||||||
// builds its own lightweight data structures for the <resources>,
|
// builds its own lightweight data structures for the <resources>,
|
||||||
|
@ -100,6 +107,12 @@ protected:
|
||||||
void ConstructBinding();
|
void ConstructBinding();
|
||||||
void ConstructHandler(const nsIParserNode& aNode);
|
void ConstructHandler(const nsIParserNode& aNode);
|
||||||
void ConstructResource(const nsIParserNode& aNode, nsIAtom* aResourceType);
|
void ConstructResource(const nsIParserNode& aNode, nsIAtom* aResourceType);
|
||||||
|
void ConstructImplementation(const nsIParserNode& aNode);
|
||||||
|
void ConstructProperty(const nsIParserNode& aNode);
|
||||||
|
void ConstructMethod(const nsIParserNode& aNode);
|
||||||
|
void ConstructParameter(const nsIParserNode& aNode);
|
||||||
|
void ConstructField(const nsIParserNode& aNode);
|
||||||
|
|
||||||
nsresult AddAttributesToXULPrototype(const nsIParserNode& aNode, nsXULPrototypeElement* aElement);
|
nsresult AddAttributesToXULPrototype(const nsIParserNode& aNode, nsXULPrototypeElement* aElement);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -112,6 +125,11 @@ protected:
|
||||||
|
|
||||||
nsCOMPtr<nsIXBLPrototypeBinding> mBinding;
|
nsCOMPtr<nsIXBLPrototypeBinding> mBinding;
|
||||||
nsCOMPtr<nsIXBLPrototypeHandler> mHandler;
|
nsCOMPtr<nsIXBLPrototypeHandler> mHandler;
|
||||||
|
nsXBLProtoImpl* mImplementation;
|
||||||
|
nsXBLProtoImplMember* mImplMember;
|
||||||
|
nsXBLProtoImplProperty* mProperty;
|
||||||
|
nsXBLProtoImplMethod* mMethod;
|
||||||
|
nsXBLProtoImplField* mField;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsXBLProtoImpl.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
#include "nsIScriptGlobalObject.h"
|
||||||
|
#include "nsIScriptGlobalObjectOwner.h"
|
||||||
|
#include "nsIScriptContext.h"
|
||||||
|
#include "nsIXPConnect.h"
|
||||||
|
#include "nsIServiceManager.h"
|
||||||
|
#include "nsIXBLDocumentInfo.h"
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImpl::InstallImplementation(nsIXBLPrototypeBinding* aBinding, nsIContent* aBoundElement)
|
||||||
|
{
|
||||||
|
// This function is called to install a concrete implementation on a bound element using
|
||||||
|
// this prototype implementation as a guide. The prototype implementation is compiled lazily,
|
||||||
|
// so for the first bound element that needs a concrete implementation, we also build the
|
||||||
|
// prototype implementation.
|
||||||
|
if (!mMembers)
|
||||||
|
return NS_OK; // Nothing to do, so let's not waste time.
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocument> document;
|
||||||
|
aBoundElement->GetDocument(*getter_AddRefs(document));
|
||||||
|
if (!document) return NS_OK;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||||
|
document->GetScriptGlobalObject(getter_AddRefs(global));
|
||||||
|
if (!global) return NS_OK;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScriptContext> context;
|
||||||
|
nsresult rv = global->GetContext(getter_AddRefs(context));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (!context) return NS_OK;
|
||||||
|
|
||||||
|
// InitTarget objects gives us back the JS object that represents the bound element and the
|
||||||
|
// class object in the bound document that represents the concrete version of this implementation.
|
||||||
|
// This function also has the side effect of building up the prototype implementation if it has
|
||||||
|
// not been built already.
|
||||||
|
void * targetScriptObject = nsnull;
|
||||||
|
void * targetClassObject = nsnull;
|
||||||
|
rv = InitTargetObjects(aBinding, context, aBoundElement, &targetScriptObject, &targetClassObject);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv); // kick out if we were unable to properly intialize our target objects
|
||||||
|
|
||||||
|
// Walk our member list and install each one in turn.
|
||||||
|
for (nsXBLProtoImplMember* curr = mMembers;
|
||||||
|
curr;
|
||||||
|
curr = curr->GetNext())
|
||||||
|
curr->InstallMember(context, aBoundElement, targetScriptObject, targetClassObject);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImpl::InitTargetObjects(nsIXBLPrototypeBinding* aBinding,
|
||||||
|
nsIScriptContext* aContext,
|
||||||
|
nsIContent* aBoundElement,
|
||||||
|
void** aScriptObject,
|
||||||
|
void** aTargetClassObject)
|
||||||
|
{
|
||||||
|
if (!mClassObject)
|
||||||
|
CompilePrototypeMembers(aBinding); // This is the first time we've ever installed this binding on an element.
|
||||||
|
// We need to go ahead and compile all methods and properties on a class
|
||||||
|
// in our prototype binding.
|
||||||
|
|
||||||
|
if (!mClassObject)
|
||||||
|
return NS_OK; // This can be ok, if all we've got are fields (and no methods/properties).
|
||||||
|
|
||||||
|
// Because our prototype implementation has a class, we need to build up a corresponding
|
||||||
|
// class for the concrete implementation in the bound document.
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
JSContext* jscontext = (JSContext*)aContext->GetNativeContext();
|
||||||
|
JSObject* global = ::JS_GetGlobalObject(jscontext);
|
||||||
|
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
|
||||||
|
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
rv = xpc->WrapNative(jscontext, global, aBoundElement,
|
||||||
|
NS_GET_IID(nsISupports), getter_AddRefs(wrapper));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
JSObject * object = nsnull;
|
||||||
|
rv = wrapper->GetJSObject(&object);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// All of the above code was just obtaining the bound element's script object and its immediate
|
||||||
|
// concrete base class. We need to alter the object so that our concrete class is interposed
|
||||||
|
// between the object and its base class. We become the new base class of the object, and the
|
||||||
|
// object's old base class becomes the new class' base class.
|
||||||
|
*aScriptObject = object;
|
||||||
|
aBinding->InitClass(mClassName, aContext, (void *) object, aTargetClassObject);
|
||||||
|
|
||||||
|
// Root ourselves in the document.
|
||||||
|
nsCOMPtr<nsIDocument> doc;
|
||||||
|
aBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||||
|
if (doc) {
|
||||||
|
nsCOMPtr<nsIXPConnectWrappedNative> nativeWrapper(do_QueryInterface(wrapper));
|
||||||
|
if (nativeWrapper)
|
||||||
|
doc->AddReference(aBoundElement, nativeWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImpl::CompilePrototypeMembers(nsIXBLPrototypeBinding* aBinding)
|
||||||
|
{
|
||||||
|
// We want to pre-compile our implementation's members against a "prototype context". Then when we actually
|
||||||
|
// bind the prototype to a real xbl instance, we'll clone the pre-compiled JS into the real instance's
|
||||||
|
// context.
|
||||||
|
nsCOMPtr<nsIXBLDocumentInfo> docInfo;
|
||||||
|
aBinding->GetXBLDocumentInfo(nsnull, getter_AddRefs(docInfo));
|
||||||
|
if (!docInfo)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner(do_QueryInterface(docInfo));
|
||||||
|
nsCOMPtr<nsIScriptGlobalObject> globalObject;
|
||||||
|
globalOwner->GetScriptGlobalObject(getter_AddRefs(globalObject));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIScriptContext> context;
|
||||||
|
globalObject->GetContext(getter_AddRefs(context));
|
||||||
|
|
||||||
|
void* classObject;
|
||||||
|
JSObject* scopeObject = globalObject->GetGlobalJSObject();
|
||||||
|
aBinding->InitClass(mClassName, context, scopeObject, &classObject);
|
||||||
|
mClassObject = (JSObject*) classObject;
|
||||||
|
if (!mClassObject)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
// Now that we have a class object installed, we walk our member list and compile each of our
|
||||||
|
// properties and methods in turn.
|
||||||
|
for (nsXBLProtoImplMember* curr = mMembers;
|
||||||
|
curr;
|
||||||
|
curr = curr->GetNext()) {
|
||||||
|
curr->CompileMember(context, mClassName, mClassObject);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsXBLProtoImpl_h__
|
||||||
|
#define nsXBLProtoImpl_h__
|
||||||
|
|
||||||
|
#include "nsMemory.h"
|
||||||
|
#include "nsIXBLPrototypeBinding.h"
|
||||||
|
#include "nsIXBLPrototypeHandler.h"
|
||||||
|
#include "nsXBLProtoImplMember.h"
|
||||||
|
|
||||||
|
MOZ_DECL_CTOR_COUNTER(nsXBLProtoImpl);
|
||||||
|
|
||||||
|
class nsXBLProtoImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsXBLProtoImpl()
|
||||||
|
:mClassObject(nsnull)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(nsXBLProtoImpl);
|
||||||
|
mMembers = nsnull;
|
||||||
|
};
|
||||||
|
~nsXBLProtoImpl()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(nsXBLProtoImpl);
|
||||||
|
for (nsXBLProtoImplMember* curr = mMembers; curr; curr=curr->GetNext())
|
||||||
|
curr->Destroy(mClassObject != nsnull);
|
||||||
|
delete mMembers;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsresult InstallImplementation(nsIXBLPrototypeBinding* aBinding, nsIContent* aBoundElement);
|
||||||
|
nsresult InitTargetObjects(nsIXBLPrototypeBinding* aBinding, nsIScriptContext* aContext,
|
||||||
|
nsIContent* aBoundElement,
|
||||||
|
void** aScriptObject, void** aTargetClassObject);
|
||||||
|
nsresult CompilePrototypeMembers(nsIXBLPrototypeBinding* aBinding);
|
||||||
|
|
||||||
|
void SetMemberList(nsXBLProtoImplMember* aMemberList) { delete mMembers; mMembers = aMemberList; };
|
||||||
|
|
||||||
|
public:
|
||||||
|
nsCString mClassName; // The name of the class.
|
||||||
|
void* mClassObject; // The class object for the binding. We'll use this to pre-compile properties
|
||||||
|
// and methods for the binding.
|
||||||
|
|
||||||
|
nsXBLProtoImplMember* mMembers; // The members of an implementation are chained in this singly-linked list.
|
||||||
|
|
||||||
|
nsCOMPtr<nsIXBLPrototypeHandler> mConstructor; // Our class constructor.
|
||||||
|
nsCOMPtr<nsIXBLPrototypeHandler> mDestructor; // Our class destructor.
|
||||||
|
};
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
NS_NewXBLProtoImpl(nsIXBLPrototypeBinding* aBinding,
|
||||||
|
const nsAReadableString* aClassName,
|
||||||
|
nsXBLProtoImpl** aResult) {
|
||||||
|
nsXBLProtoImpl* impl = new nsXBLProtoImpl();
|
||||||
|
if (!impl)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
if (aClassName)
|
||||||
|
impl->mClassName.AssignWithConversion(*aClassName);
|
||||||
|
else
|
||||||
|
aBinding->GetBindingURI(impl->mClassName);
|
||||||
|
aBinding->SetImplementation(impl);
|
||||||
|
*aResult = impl;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // nsXBLProtoImpl_h__
|
|
@ -0,0 +1,116 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsUnicharUtils.h"
|
||||||
|
#include "nsReadableUtils.h"
|
||||||
|
#include "nsXBLProtoImplField.h"
|
||||||
|
#include "nsIScriptContext.h"
|
||||||
|
|
||||||
|
MOZ_DECL_CTOR_COUNTER(nsXBLProtoImplField);
|
||||||
|
|
||||||
|
nsXBLProtoImplField::nsXBLProtoImplField(const nsAReadableString* aName, const nsAReadableString* aReadOnly)
|
||||||
|
:nsXBLProtoImplMember(aName)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(nsXBLProtoImplField);
|
||||||
|
mJSAttributes = JSPROP_ENUMERATE;
|
||||||
|
if (aReadOnly) {
|
||||||
|
nsAutoString readOnly; readOnly.Assign(*aReadOnly);
|
||||||
|
if (readOnly.EqualsIgnoreCase("true"))
|
||||||
|
mJSAttributes |= JSPROP_READONLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXBLProtoImplField::~nsXBLProtoImplField()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(nsXBLProtoImplField);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLProtoImplField::Destroy(PRBool aIsCompiled)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLProtoImplField::AppendFieldText(const nsAReadableString& aText)
|
||||||
|
{
|
||||||
|
mFieldText += aText;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImplField::InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
|
||||||
|
void* aScriptObject, void* aTargetClassObject)
|
||||||
|
{
|
||||||
|
if (mFieldText.IsEmpty())
|
||||||
|
return NS_OK; // nothing to do.
|
||||||
|
|
||||||
|
JSContext* cx = (JSContext*) aContext->GetNativeContext();
|
||||||
|
JSObject * scriptObject = (JSObject *) aScriptObject;
|
||||||
|
NS_ASSERTION(scriptObject, "uh-oh, script Object should NOT be null or bad things will happen");
|
||||||
|
if (!scriptObject)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
// compile the literal string
|
||||||
|
jsval result = nsnull;
|
||||||
|
PRBool undefined;
|
||||||
|
aContext->EvaluateStringWithValue(mFieldText,
|
||||||
|
scriptObject,
|
||||||
|
nsnull, nsnull, 0, nsnull,
|
||||||
|
(void*) &result, &undefined);
|
||||||
|
|
||||||
|
if (!undefined) {
|
||||||
|
// Define the evaluated result as a JS property
|
||||||
|
nsDependentString name(mName);
|
||||||
|
::JS_DefineUCProperty(cx, scriptObject, NS_REINTERPRET_CAST(const jschar*, mName),
|
||||||
|
name.Length(), result,nsnull, nsnull, mJSAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImplField::CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr,
|
||||||
|
void* aClassObject)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsXBLProtoImplField_h__
|
||||||
|
#define nsXBLProtoImplField_h__
|
||||||
|
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsXBLProtoImplMember.h"
|
||||||
|
|
||||||
|
class nsXBLProtoImplField: public nsXBLProtoImplMember
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsXBLProtoImplField(const nsAReadableString* aName, const nsAReadableString* aReadOnly);
|
||||||
|
virtual ~nsXBLProtoImplField();
|
||||||
|
virtual void Destroy(PRBool aIsCompiled);
|
||||||
|
|
||||||
|
void AppendFieldText(const nsAReadableString& aText);
|
||||||
|
|
||||||
|
virtual nsresult InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
|
||||||
|
void* aScriptObject, void* aTargetClassObject);
|
||||||
|
virtual nsresult CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr, void* aClassObject);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsString mFieldText;
|
||||||
|
uintN mJSAttributes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // nsXBLProtoImplField_h__
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsXBLProtoImplMember_h__
|
||||||
|
#define nsXBLProtoImplMember_h__
|
||||||
|
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsIJSRuntimeService.h"
|
||||||
|
#include "nsIServiceManager.h"
|
||||||
|
#include "nsReadableUtils.h"
|
||||||
|
|
||||||
|
class nsIScriptContext;
|
||||||
|
|
||||||
|
class nsXBLProtoImplMember
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsXBLProtoImplMember(const nsAReadableString* aName) :mNext(nsnull) { mName = ToNewUnicode(*aName); };
|
||||||
|
virtual ~nsXBLProtoImplMember() { nsMemory::Free(mName); delete mNext; };
|
||||||
|
virtual void Destroy(PRBool aIsCompiled)=0;
|
||||||
|
|
||||||
|
nsXBLProtoImplMember* GetNext() { return mNext; };
|
||||||
|
void SetNext(nsXBLProtoImplMember* aNext) { mNext = aNext; };
|
||||||
|
|
||||||
|
virtual nsresult InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
|
||||||
|
void* aScriptObject, void* aTargetClassObject)=0;
|
||||||
|
virtual nsresult CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr, void* aClassObject)=0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsXBLProtoImplMember* mNext; // The members of an implementation are chained.
|
||||||
|
PRUnichar* mName; // The name of the field, method, or property.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // nsXBLProtoImplMember_h__
|
|
@ -0,0 +1,243 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsUnicharUtils.h"
|
||||||
|
#include "nsReadableUtils.h"
|
||||||
|
#include "nsXBLProtoImplMethod.h"
|
||||||
|
#include "nsIScriptContext.h"
|
||||||
|
|
||||||
|
static nsIJSRuntimeService* gJSRuntimeService = nsnull;
|
||||||
|
static JSRuntime* gScriptRuntime = nsnull;
|
||||||
|
static PRInt32 gScriptRuntimeRefcnt = 0;
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
AddJSGCRoot(void* aScriptObjectRef, const char* aName)
|
||||||
|
{
|
||||||
|
if (++gScriptRuntimeRefcnt == 1 || !gScriptRuntime) {
|
||||||
|
CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
|
||||||
|
&gJSRuntimeService);
|
||||||
|
if (! gJSRuntimeService) {
|
||||||
|
NS_NOTREACHED("couldn't add GC root");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gJSRuntimeService->GetRuntime(&gScriptRuntime);
|
||||||
|
if (! gScriptRuntime) {
|
||||||
|
NS_NOTREACHED("couldn't add GC root");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool ok;
|
||||||
|
ok = ::JS_AddNamedRootRT(gScriptRuntime, aScriptObjectRef, aName);
|
||||||
|
if (! ok) {
|
||||||
|
NS_NOTREACHED("couldn't add GC root");
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
RemoveJSGCRoot(void* aScriptObjectRef)
|
||||||
|
{
|
||||||
|
if (!gScriptRuntime) {
|
||||||
|
NS_NOTREACHED("couldn't remove GC root");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
::JS_RemoveRootRT(gScriptRuntime, aScriptObjectRef);
|
||||||
|
|
||||||
|
if (--gScriptRuntimeRefcnt == 0) {
|
||||||
|
NS_RELEASE(gJSRuntimeService);
|
||||||
|
gScriptRuntime = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_DECL_CTOR_COUNTER(nsXBLProtoImplMethod);
|
||||||
|
|
||||||
|
nsXBLProtoImplMethod::nsXBLProtoImplMethod(const nsAReadableString& aName)
|
||||||
|
:nsXBLProtoImplMember(&aName),
|
||||||
|
mUncompiledMethod(nsnull)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(nsXBLProtoImplMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXBLProtoImplMethod::~nsXBLProtoImplMethod()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(nsXBLProtoImplMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLProtoImplMethod::Destroy(PRBool aIsCompiled)
|
||||||
|
{
|
||||||
|
if (aIsCompiled) {
|
||||||
|
if (mJSMethodObject)
|
||||||
|
RemoveJSGCRoot(&mJSMethodObject);
|
||||||
|
mJSMethodObject = nsnull;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete mUncompiledMethod;
|
||||||
|
mUncompiledMethod = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLProtoImplMethod::AppendBodyText(const nsAReadableString& aText)
|
||||||
|
{
|
||||||
|
if (!mUncompiledMethod) {
|
||||||
|
mUncompiledMethod = new nsXBLUncompiledMethod();
|
||||||
|
if (!mUncompiledMethod)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mUncompiledMethod->AppendBodyText(aText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLProtoImplMethod::AddParameter(const nsAReadableString& aText)
|
||||||
|
{
|
||||||
|
if (!mUncompiledMethod) {
|
||||||
|
mUncompiledMethod = new nsXBLUncompiledMethod();
|
||||||
|
if (!mUncompiledMethod)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mUncompiledMethod->AddParameter(aText);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImplMethod::InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
|
||||||
|
void* aScriptObject, void* aTargetClassObject)
|
||||||
|
{
|
||||||
|
JSContext* cx = (JSContext*) aContext->GetNativeContext();
|
||||||
|
JSObject * scriptObject = (JSObject *) aScriptObject;
|
||||||
|
NS_ASSERTION(scriptObject, "uh-oh, script Object should NOT be null or bad things will happen");
|
||||||
|
if (!scriptObject)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
JSObject * targetClassObject = (JSObject *) aTargetClassObject;
|
||||||
|
JSObject * globalObject = ::JS_GetGlobalObject(cx);
|
||||||
|
|
||||||
|
// now we want to reevaluate our property using aContext and the script object for this window...
|
||||||
|
if (mJSMethodObject && targetClassObject) {
|
||||||
|
nsDependentString name(mName);
|
||||||
|
JSObject * method = ::JS_CloneFunctionObject(cx, mJSMethodObject, globalObject);
|
||||||
|
::JS_DefineUCProperty(cx, targetClassObject, NS_REINTERPRET_CAST(const jschar*, mName),
|
||||||
|
name.Length(), OBJECT_TO_JSVAL(method),
|
||||||
|
NULL, NULL, JSPROP_ENUMERATE);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr,
|
||||||
|
void* aClassObject)
|
||||||
|
{
|
||||||
|
if (!aClassObject)
|
||||||
|
return NS_OK; // Nothing to do.
|
||||||
|
|
||||||
|
if (!mName)
|
||||||
|
return NS_ERROR_FAILURE; // Without a valid name, we can't install the member.
|
||||||
|
|
||||||
|
// We have a method.
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
// Allocate an array for our arguments.
|
||||||
|
PRInt32 paramCount = mUncompiledMethod->GetParameterCount();
|
||||||
|
char** args = nsnull;
|
||||||
|
if (paramCount > 0) {
|
||||||
|
args = new char*[paramCount];
|
||||||
|
if (!args)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add our parameters to our args array.
|
||||||
|
PRInt32 argPos = 0;
|
||||||
|
for (nsXBLParameter* curr = mUncompiledMethod->mParameters;
|
||||||
|
curr;
|
||||||
|
curr = curr->mNext) {
|
||||||
|
args[argPos] = curr->mName;
|
||||||
|
argPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we have a body and args, compile the function
|
||||||
|
// and then define it.
|
||||||
|
nsDependentString body(mUncompiledMethod->mBodyText);
|
||||||
|
if (!body.IsEmpty()) {
|
||||||
|
nsCAutoString cname; cname.AssignWithConversion(mName);
|
||||||
|
nsCAutoString functionUri(aClassStr);
|
||||||
|
functionUri += ".";
|
||||||
|
functionUri += cname;
|
||||||
|
functionUri += "()";
|
||||||
|
|
||||||
|
JSObject* methodObject = nsnull;
|
||||||
|
aContext->CompileFunction(aClassObject,
|
||||||
|
cname,
|
||||||
|
paramCount,
|
||||||
|
(const char**)args,
|
||||||
|
body,
|
||||||
|
functionUri.get(),
|
||||||
|
0,
|
||||||
|
PR_FALSE,
|
||||||
|
(void **) &methodObject);
|
||||||
|
|
||||||
|
// Destroy our uncompiled method and delete our arg list.
|
||||||
|
delete mUncompiledMethod;
|
||||||
|
delete [] args;
|
||||||
|
mJSMethodObject = methodObject;
|
||||||
|
|
||||||
|
if (methodObject) {
|
||||||
|
// Root the compiled prototype script object.
|
||||||
|
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||||
|
aContext->GetNativeContext());
|
||||||
|
if (!cx) return NS_ERROR_UNEXPECTED;
|
||||||
|
AddJSGCRoot(&mJSMethodObject, "nsXBLProtoImplMethod::mJSMethodObject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsXBLProtoImplMethod_h__
|
||||||
|
#define nsXBLProtoImplMethod_h__
|
||||||
|
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsXBLProtoImplMember.h"
|
||||||
|
|
||||||
|
MOZ_DECL_CTOR_COUNTER(nsXBLParameter);
|
||||||
|
|
||||||
|
struct nsXBLParameter {
|
||||||
|
nsXBLParameter* mNext;
|
||||||
|
char* mName;
|
||||||
|
|
||||||
|
nsXBLParameter(const nsAReadableString& aName) {
|
||||||
|
MOZ_COUNT_CTOR(nsXBLParameter);
|
||||||
|
mName = ToNewCString(aName);
|
||||||
|
mNext = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
~nsXBLParameter() {
|
||||||
|
MOZ_COUNT_DTOR(nsXBLParameter);
|
||||||
|
nsMemory::Free(mName);
|
||||||
|
delete mNext;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MOZ_DECL_CTOR_COUNTER(nsXBLUncompiledMethod);
|
||||||
|
|
||||||
|
struct nsXBLUncompiledMethod {
|
||||||
|
nsXBLParameter* mParameters;
|
||||||
|
nsXBLParameter* mLastParameter;
|
||||||
|
PRUnichar* mBodyText;
|
||||||
|
|
||||||
|
nsXBLUncompiledMethod() {
|
||||||
|
MOZ_COUNT_CTOR(nsXBLUncompiledMethod);
|
||||||
|
mBodyText = nsnull;
|
||||||
|
mParameters = nsnull;
|
||||||
|
mLastParameter = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
~nsXBLUncompiledMethod() {
|
||||||
|
MOZ_COUNT_DTOR(nsXBLUncompiledMethod);
|
||||||
|
nsMemory::Free(mBodyText);
|
||||||
|
delete mParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt32 GetParameterCount() {
|
||||||
|
PRInt32 result = 0;
|
||||||
|
for (nsXBLParameter* curr = mParameters; curr; curr=curr->mNext)
|
||||||
|
result++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppendBodyText(const nsAReadableString& aText) {
|
||||||
|
if (mBodyText) {
|
||||||
|
nsAutoString currText(mBodyText);
|
||||||
|
currText += aText;
|
||||||
|
nsMemory::Free(mBodyText);
|
||||||
|
mBodyText = ToNewUnicode(currText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mBodyText = ToNewUnicode(aText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddParameter(const nsAReadableString& aText) {
|
||||||
|
nsXBLParameter* param = new nsXBLParameter(aText);
|
||||||
|
if (!param)
|
||||||
|
return;
|
||||||
|
if (!mParameters)
|
||||||
|
mParameters = param;
|
||||||
|
else
|
||||||
|
mLastParameter->mNext = param;
|
||||||
|
mLastParameter = param;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class nsXBLProtoImplMethod: public nsXBLProtoImplMember
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsXBLProtoImplMethod(const nsAReadableString& aName);
|
||||||
|
virtual ~nsXBLProtoImplMethod();
|
||||||
|
virtual void Destroy(PRBool aIsCompiled);
|
||||||
|
|
||||||
|
void AppendBodyText(const nsAReadableString& aBody);
|
||||||
|
void AddParameter(const nsAReadableString& aName);
|
||||||
|
|
||||||
|
virtual nsresult InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
|
||||||
|
void* aScriptObject, void* aTargetClassObject);
|
||||||
|
virtual nsresult CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr, void* aClassObject);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
union {
|
||||||
|
nsXBLUncompiledMethod* mUncompiledMethod; // An object that represents the method before being compiled.
|
||||||
|
JSObject * mJSMethodObject; // The JS object for the method (after compilation)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // nsXBLProtoImplMethod_h__
|
|
@ -0,0 +1,281 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsXBLProtoImplProperty.h"
|
||||||
|
#include "nsUnicharUtils.h"
|
||||||
|
#include "nsReadableUtils.h"
|
||||||
|
#include "nsIScriptContext.h"
|
||||||
|
|
||||||
|
static nsIJSRuntimeService* gJSRuntimeService = nsnull;
|
||||||
|
static JSRuntime* gScriptRuntime = nsnull;
|
||||||
|
static PRInt32 gScriptRuntimeRefcnt = 0;
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
AddJSGCRoot(void* aScriptObjectRef, const char* aName)
|
||||||
|
{
|
||||||
|
if (++gScriptRuntimeRefcnt == 1 || !gScriptRuntime) {
|
||||||
|
CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
|
||||||
|
&gJSRuntimeService);
|
||||||
|
if (! gJSRuntimeService) {
|
||||||
|
NS_NOTREACHED("couldn't add GC root");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gJSRuntimeService->GetRuntime(&gScriptRuntime);
|
||||||
|
if (! gScriptRuntime) {
|
||||||
|
NS_NOTREACHED("couldn't add GC root");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool ok;
|
||||||
|
ok = ::JS_AddNamedRootRT(gScriptRuntime, aScriptObjectRef, aName);
|
||||||
|
if (! ok) {
|
||||||
|
NS_NOTREACHED("couldn't add GC root");
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
RemoveJSGCRoot(void* aScriptObjectRef)
|
||||||
|
{
|
||||||
|
if (!gScriptRuntime) {
|
||||||
|
NS_NOTREACHED("couldn't remove GC root");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
::JS_RemoveRootRT(gScriptRuntime, aScriptObjectRef);
|
||||||
|
|
||||||
|
if (--gScriptRuntimeRefcnt == 0) {
|
||||||
|
NS_RELEASE(gJSRuntimeService);
|
||||||
|
gScriptRuntime = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_DECL_CTOR_COUNTER(nsXBLProtoImplProperty);
|
||||||
|
|
||||||
|
nsXBLProtoImplProperty::nsXBLProtoImplProperty(const nsAReadableString* aName,
|
||||||
|
const nsAReadableString* aGetter,
|
||||||
|
const nsAReadableString* aSetter,
|
||||||
|
const nsAReadableString* aReadOnly)
|
||||||
|
:nsXBLProtoImplMember(aName),
|
||||||
|
mGetterText(nsnull),
|
||||||
|
mSetterText(nsnull)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(nsXBLProtoImplProperty);
|
||||||
|
|
||||||
|
mJSAttributes = JSPROP_ENUMERATE;
|
||||||
|
if (aReadOnly) {
|
||||||
|
nsAutoString readOnly; readOnly.Assign(*aReadOnly);
|
||||||
|
if (readOnly.EqualsIgnoreCase("true"))
|
||||||
|
mJSAttributes |= JSPROP_READONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aGetter)
|
||||||
|
AppendGetterText(*aGetter);
|
||||||
|
if (aSetter)
|
||||||
|
AppendSetterText(*aSetter);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXBLProtoImplProperty::~nsXBLProtoImplProperty()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(nsXBLProtoImplProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLProtoImplProperty::Destroy(PRBool aIsCompiled)
|
||||||
|
{
|
||||||
|
if (aIsCompiled) {
|
||||||
|
if (mJSGetterObject)
|
||||||
|
RemoveJSGCRoot(&mJSGetterObject);
|
||||||
|
if (mJSSetterObject)
|
||||||
|
RemoveJSGCRoot(&mJSSetterObject);
|
||||||
|
mJSGetterObject = mJSSetterObject = nsnull;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nsMemory::Free(mGetterText);
|
||||||
|
nsMemory::Free(mSetterText);
|
||||||
|
mGetterText = mSetterText = nsnull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLProtoImplProperty::AppendGetterText(const nsAReadableString& aText)
|
||||||
|
{
|
||||||
|
if (mGetterText) {
|
||||||
|
nsAutoString currText(mGetterText);
|
||||||
|
currText += aText;
|
||||||
|
nsMemory::Free(mGetterText);
|
||||||
|
mGetterText = ToNewUnicode(currText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mGetterText = ToNewUnicode(aText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXBLProtoImplProperty::AppendSetterText(const nsAReadableString& aText)
|
||||||
|
{
|
||||||
|
if (mSetterText) {
|
||||||
|
nsAutoString currText(mSetterText);
|
||||||
|
currText += aText;
|
||||||
|
nsMemory::Free(mSetterText);
|
||||||
|
mSetterText = ToNewUnicode(currText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mSetterText = ToNewUnicode(aText);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* gPropertyArgs[] = { "val" };
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImplProperty::InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
|
||||||
|
void* aScriptObject, void* aTargetClassObject)
|
||||||
|
{
|
||||||
|
JSContext* cx = (JSContext*) aContext->GetNativeContext();
|
||||||
|
JSObject * scriptObject = (JSObject *) aScriptObject;
|
||||||
|
NS_ASSERTION(scriptObject, "uh-oh, script Object should NOT be null or bad things will happen");
|
||||||
|
if (!scriptObject)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
JSObject * targetClassObject = (JSObject *) aTargetClassObject;
|
||||||
|
JSObject * globalObject = ::JS_GetGlobalObject(cx);
|
||||||
|
|
||||||
|
// now we want to reevaluate our property using aContext and the script object for this window...
|
||||||
|
if ((mJSGetterObject || mJSSetterObject) && targetClassObject) {
|
||||||
|
JSObject * getter = nsnull;
|
||||||
|
if (mJSGetterObject)
|
||||||
|
getter = ::JS_CloneFunctionObject(cx, mJSGetterObject, globalObject);
|
||||||
|
|
||||||
|
JSObject * setter = nsnull;
|
||||||
|
if (mJSSetterObject)
|
||||||
|
setter = ::JS_CloneFunctionObject(cx, mJSSetterObject, globalObject);
|
||||||
|
|
||||||
|
nsDependentString name(mName);
|
||||||
|
::JS_DefineUCProperty(cx, targetClassObject, NS_REINTERPRET_CAST(const jschar*, mName),
|
||||||
|
name.Length(), JSVAL_VOID, (JSPropertyOp) getter,
|
||||||
|
(JSPropertyOp) setter, mJSAttributes);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr,
|
||||||
|
void* aClassObject)
|
||||||
|
{
|
||||||
|
if (!aClassObject)
|
||||||
|
return NS_OK; // Nothing to do.
|
||||||
|
|
||||||
|
if (!mName)
|
||||||
|
return NS_ERROR_FAILURE; // Without a valid name, we can't install the member.
|
||||||
|
|
||||||
|
// We have a property.
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
// Do we have a getter?
|
||||||
|
nsAutoString getter(mGetterText);
|
||||||
|
nsMemory::Free(mGetterText);
|
||||||
|
mGetterText = nsnull;
|
||||||
|
if (!getter.IsEmpty() && aClassObject) {
|
||||||
|
nsCAutoString functionUri;
|
||||||
|
functionUri.Assign(aClassStr);
|
||||||
|
functionUri += ".";
|
||||||
|
functionUri.AppendWithConversion(mName);
|
||||||
|
functionUri += " (getter)";
|
||||||
|
rv = aContext->CompileFunction(aClassObject,
|
||||||
|
nsCAutoString("onget"),
|
||||||
|
0,
|
||||||
|
nsnull,
|
||||||
|
getter,
|
||||||
|
functionUri.get(),
|
||||||
|
0,
|
||||||
|
PR_FALSE,
|
||||||
|
(void **) &mJSGetterObject);
|
||||||
|
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||||
|
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
|
||||||
|
if (mJSGetterObject) {
|
||||||
|
// Root the compiled prototype script object.
|
||||||
|
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||||
|
aContext->GetNativeContext());
|
||||||
|
if (!cx) return NS_ERROR_UNEXPECTED;
|
||||||
|
rv = AddJSGCRoot(&mJSGetterObject, "nsXBLProtoImplProperty::mJSGetterObject");
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
} // if getter is not empty
|
||||||
|
|
||||||
|
// Do we have a setter?
|
||||||
|
nsAutoString setter(mSetterText);
|
||||||
|
nsMemory::Free(mSetterText);
|
||||||
|
mSetterText = nsnull;
|
||||||
|
if (!setter.IsEmpty() && aClassObject) {
|
||||||
|
nsCAutoString functionUri (aClassStr);
|
||||||
|
functionUri += ".";
|
||||||
|
functionUri.AppendWithConversion(mName);
|
||||||
|
functionUri += " (setter)";
|
||||||
|
rv = aContext->CompileFunction(aClassObject,
|
||||||
|
nsCAutoString("onset"),
|
||||||
|
1,
|
||||||
|
gPropertyArgs,
|
||||||
|
setter,
|
||||||
|
functionUri.get(),
|
||||||
|
0,
|
||||||
|
PR_FALSE,
|
||||||
|
(void **) &mJSSetterObject);
|
||||||
|
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||||
|
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
|
||||||
|
if (mJSSetterObject) {
|
||||||
|
// Root the compiled prototype script object.
|
||||||
|
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||||
|
aContext->GetNativeContext());
|
||||||
|
if (!cx) return NS_ERROR_UNEXPECTED;
|
||||||
|
rv = AddJSGCRoot(&mJSSetterObject, "nsXBLProtoImplProperty::mJSSetterObject");
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
} // if setter wasn't empty....
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the NPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsXBLProtoImplProperty_h__
|
||||||
|
#define nsXBLProtoImplProperty_h__
|
||||||
|
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsXBLProtoImplMember.h"
|
||||||
|
|
||||||
|
class nsXBLProtoImplProperty: public nsXBLProtoImplMember
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsXBLProtoImplProperty(const nsAReadableString* aName,
|
||||||
|
const nsAReadableString* aGetter,
|
||||||
|
const nsAReadableString* aSetter,
|
||||||
|
const nsAReadableString* aReadOnly);
|
||||||
|
|
||||||
|
virtual ~nsXBLProtoImplProperty();
|
||||||
|
virtual void Destroy(PRBool aIsCompiled);
|
||||||
|
|
||||||
|
void AppendGetterText(const nsAReadableString& aGetter);
|
||||||
|
void AppendSetterText(const nsAReadableString& aSetter);
|
||||||
|
|
||||||
|
virtual nsresult InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
|
||||||
|
void* aScriptObject, void* aTargetClassObject);
|
||||||
|
virtual nsresult CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr, void* aClassObject);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
union {
|
||||||
|
PRUnichar* mGetterText; // The raw text for the getter (prior to compilation).
|
||||||
|
JSObject * mJSGetterObject; // The JS object for the getter (after compilation)
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
PRUnichar* mSetterText; // The raw text for the setter (prior to compilation).
|
||||||
|
JSObject * mJSSetterObject; // The JS object for the setter (after compilation)
|
||||||
|
};
|
||||||
|
|
||||||
|
uintN mJSAttributes; // A flag for all our JS properties (getter/setter/readonly/shared/enum)
|
||||||
|
PRBool mCompiled; // Whether or not we are compiled.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // nsXBLProtoImplProperty_h__
|
|
@ -76,6 +76,7 @@
|
||||||
#include "nsHTMLAtoms.h"
|
#include "nsHTMLAtoms.h"
|
||||||
#include "nsXULAtoms.h"
|
#include "nsXULAtoms.h"
|
||||||
#include "nsXBLAtoms.h"
|
#include "nsXBLAtoms.h"
|
||||||
|
#include "nsXBLProtoImpl.h"
|
||||||
|
|
||||||
#include "nsIScriptContext.h"
|
#include "nsIScriptContext.h"
|
||||||
|
|
||||||
|
@ -255,17 +256,18 @@ NS_IMPL_ISUPPORTS2(nsXBLPrototypeBinding, nsIXBLPrototypeBinding, nsISupportsWea
|
||||||
// Constructors/Destructors
|
// Constructors/Destructors
|
||||||
nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIXBLDocumentInfo* aInfo,
|
nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIXBLDocumentInfo* aInfo,
|
||||||
nsIContent* aElement)
|
nsIContent* aElement)
|
||||||
: mID(aID),
|
: mInheritStyle(PR_TRUE),
|
||||||
mInheritStyle(PR_TRUE),
|
|
||||||
mHasBaseProto(PR_TRUE),
|
mHasBaseProto(PR_TRUE),
|
||||||
mResources(nsnull),
|
mResources(nsnull),
|
||||||
|
mImplementation(nsnull),
|
||||||
mAttributeTable(nsnull),
|
mAttributeTable(nsnull),
|
||||||
mInsertionPointTable(nsnull),
|
mInsertionPointTable(nsnull),
|
||||||
mInterfaceTable(nsnull),
|
mInterfaceTable(nsnull)
|
||||||
mClassObject(nsnull)
|
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
|
|
||||||
|
mID = ToNewCString(aID);
|
||||||
|
|
||||||
mXBLDocInfoWeak = getter_AddRefs(NS_GetWeakReference(aInfo));
|
mXBLDocInfoWeak = getter_AddRefs(NS_GetWeakReference(aInfo));
|
||||||
|
|
||||||
gRefCnt++;
|
gRefCnt++;
|
||||||
|
@ -284,15 +286,6 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIX
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLPrototypeBinding::Initialize()
|
nsXBLPrototypeBinding::Initialize()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIXBLDocumentInfo> info(do_QueryReferent(mXBLDocInfoWeak));
|
|
||||||
|
|
||||||
PRBool allowScripts;
|
|
||||||
info->GetScriptAccess(&allowScripts);
|
|
||||||
if (allowScripts) {
|
|
||||||
BuildConstructorAndDestructor();
|
|
||||||
ConstructProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> content;
|
nsCOMPtr<nsIContent> content;
|
||||||
GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(content));
|
GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(content));
|
||||||
if (content) {
|
if (content) {
|
||||||
|
@ -300,20 +293,17 @@ nsXBLPrototypeBinding::Initialize()
|
||||||
ConstructInsertionTable(content);
|
ConstructInsertionTable(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> impl;
|
|
||||||
GetImmediateChild(nsXBLAtoms::implementation, getter_AddRefs(impl));
|
|
||||||
if (impl)
|
|
||||||
ConstructInterfaceTable(impl);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
||||||
{
|
{
|
||||||
|
nsMemory::Free(mID);
|
||||||
delete mResources;
|
delete mResources;
|
||||||
delete mAttributeTable;
|
delete mAttributeTable;
|
||||||
delete mInsertionPointTable;
|
delete mInsertionPointTable;
|
||||||
delete mInterfaceTable;
|
delete mInterfaceTable;
|
||||||
|
delete mImplementation;
|
||||||
gRefCnt--;
|
gRefCnt--;
|
||||||
if (gRefCnt == 0) {
|
if (gRefCnt == 0) {
|
||||||
delete kAttrPool;
|
delete kAttrPool;
|
||||||
|
@ -437,16 +427,16 @@ nsXBLPrototypeBinding::AddResource(nsIAtom* aResourceType, const nsAReadableStri
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLPrototypeBinding::BindingAttached(nsIDOMEventReceiver* aReceiver)
|
nsXBLPrototypeBinding::BindingAttached(nsIDOMEventReceiver* aReceiver)
|
||||||
{
|
{
|
||||||
if (mConstructor)
|
if (mImplementation && mImplementation->mConstructor)
|
||||||
return mConstructor->BindingAttached(aReceiver);
|
return mImplementation->mConstructor->BindingAttached(aReceiver);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLPrototypeBinding::BindingDetached(nsIDOMEventReceiver* aReceiver)
|
nsXBLPrototypeBinding::BindingDetached(nsIDOMEventReceiver* aReceiver)
|
||||||
{
|
{
|
||||||
if (mDestructor)
|
if (mImplementation && mImplementation->mDestructor)
|
||||||
return mDestructor->BindingDetached(aReceiver);
|
return mImplementation->mDestructor->BindingDetached(aReceiver);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,17 +490,52 @@ nsXBLPrototypeBinding::SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLPrototypeBinding::GetPrototypeProperties(nsIXBLPrototypeProperty ** aResult)
|
nsXBLPrototypeBinding::GetConstructor(nsIXBLPrototypeHandler** aResult)
|
||||||
{
|
{
|
||||||
*aResult = mPrototypeProperty;
|
if (mImplementation && mImplementation->mConstructor) {
|
||||||
NS_IF_ADDREF(*aResult);
|
*aResult = mImplementation->mConstructor;
|
||||||
|
NS_ADDREF(*aResult);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*aResult = nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXBLPrototypeBinding::GetDestructor(nsIXBLPrototypeHandler** aResult)
|
||||||
|
{
|
||||||
|
if (mImplementation && mImplementation->mDestructor) {
|
||||||
|
*aResult = mImplementation->mDestructor;
|
||||||
|
NS_ADDREF(*aResult);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*aResult = nsnull;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXBLPrototypeBinding::SetConstructor(nsIXBLPrototypeHandler* aHandler)
|
||||||
|
{
|
||||||
|
if (!mImplementation)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
mImplementation->mConstructor = aHandler;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLPrototypeBinding::SetProtoTypeProperties(nsIXBLPrototypeProperty* aResult)
|
nsXBLPrototypeBinding::SetDestructor(nsIXBLPrototypeHandler* aHandler)
|
||||||
{
|
{
|
||||||
mPrototypeProperty = aResult;
|
if (!mImplementation)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
mImplementation->mDestructor = aHandler;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXBLPrototypeBinding::InstallImplementation(nsIContent* aBoundElement)
|
||||||
|
{
|
||||||
|
if (mImplementation)
|
||||||
|
return mImplementation->InstallImplementation(this, aBoundElement);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,30 +854,6 @@ nsXBLPrototypeBinding::GetImmediateChild(nsIAtom* aTag, nsIContent** aResult)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsXBLPrototypeBinding::ConstructProperties()
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIContent> properties;
|
|
||||||
GetImmediateChild(nsXBLAtoms::implementation, 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
|
NS_IMETHODIMP
|
||||||
nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject)
|
nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject)
|
||||||
|
@ -944,38 +945,6 @@ nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, nsIScriptContext *
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsXBLPrototypeBinding::BuildConstructorAndDestructor()
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIContent> impl;
|
|
||||||
GetImmediateChild(nsXBLAtoms::implementation, getter_AddRefs(impl));
|
|
||||||
if (impl) {
|
|
||||||
// Look for <constructor> and <destructor>.
|
|
||||||
PRInt32 count;
|
|
||||||
impl->ChildCount(count);
|
|
||||||
for (PRInt32 i = 0; i < count; i++) {
|
|
||||||
nsCOMPtr<nsIContent> child;
|
|
||||||
impl->ChildAt(i, *getter_AddRefs(child));
|
|
||||||
nsCOMPtr<nsIAtom> tag;
|
|
||||||
child->GetTag(*getter_AddRefs(tag));
|
|
||||||
if (tag == nsXBLAtoms::constructor) {
|
|
||||||
nsAutoString value;
|
|
||||||
nsXBLBinding::GetTextData(child, value);
|
|
||||||
NS_NewXBLPrototypeHandler(nsnull, nsnull, &value, nsnull, nsnull, nsnull, nsnull,
|
|
||||||
nsnull, nsnull, getter_AddRefs(mConstructor));
|
|
||||||
mConstructor->SetEventName(tag);
|
|
||||||
}
|
|
||||||
else if (tag == nsXBLAtoms::destructor) {
|
|
||||||
nsAutoString value;
|
|
||||||
nsXBLBinding::GetTextData(child, value);
|
|
||||||
NS_NewXBLPrototypeHandler(nsnull, nsnull, &value, nsnull, nsnull, nsnull, nsnull,
|
|
||||||
nsnull, nsnull, getter_AddRefs(mDestructor));
|
|
||||||
mDestructor->SetEventName(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement, nsIContent* aTemplRoot, nsIContent* aCopyRoot,
|
nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement, nsIContent* aTemplRoot, nsIContent* aCopyRoot,
|
||||||
nsIContent* aTemplChild, nsIContent** aCopyResult)
|
nsIContent* aTemplChild, nsIContent** aCopyResult)
|
||||||
|
@ -1365,24 +1334,22 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
NS_IMETHODIMP
|
||||||
nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent* aElement)
|
nsXBLPrototypeBinding::ConstructInterfaceTable(const nsAReadableString& aImpls)
|
||||||
{
|
{
|
||||||
nsAutoString impls;
|
if (!aImpls.IsEmpty()) {
|
||||||
aElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::implements, impls);
|
|
||||||
if (!impls.IsEmpty()) {
|
|
||||||
// Obtain the interface info manager that can tell us the IID
|
// Obtain the interface info manager that can tell us the IID
|
||||||
// for a given interface name.
|
// for a given interface name.
|
||||||
nsCOMPtr<nsIInterfaceInfoManager> infoManager = getter_AddRefs(XPTI_GetInterfaceInfoManager());
|
nsCOMPtr<nsIInterfaceInfoManager> infoManager = getter_AddRefs(XPTI_GetInterfaceInfoManager());
|
||||||
if (!infoManager)
|
if (!infoManager)
|
||||||
return;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
// Create the table.
|
// Create the table.
|
||||||
if (!mInterfaceTable)
|
if (!mInterfaceTable)
|
||||||
mInterfaceTable = new nsSupportsHashtable(4);
|
mInterfaceTable = new nsSupportsHashtable(4);
|
||||||
|
|
||||||
// The user specified at least one attribute.
|
// The user specified at least one attribute.
|
||||||
char* str = ToNewCString(impls);
|
char* str = ToNewCString(aImpls);
|
||||||
char* newStr;
|
char* newStr;
|
||||||
// XXX We should use a strtok function that tokenizes PRUnichars
|
// XXX We should use a strtok function that tokenizes PRUnichars
|
||||||
// so that we don't have to convert from Unicode to ASCII and then back
|
// so that we don't have to convert from Unicode to ASCII and then back
|
||||||
|
@ -1404,6 +1371,8 @@ nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent* aElement)
|
||||||
|
|
||||||
nsMemory::Free(str);
|
nsMemory::Free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIXBLPrototypeBinding.h"
|
#include "nsIXBLPrototypeBinding.h"
|
||||||
#include "nsIXBLPrototypeHandler.h"
|
#include "nsIXBLPrototypeHandler.h"
|
||||||
#include "nsIXBLPrototypeProperty.h"
|
|
||||||
#include "nsXBLPrototypeResources.h"
|
#include "nsXBLPrototypeResources.h"
|
||||||
#include "nsICSSStyleSheet.h"
|
#include "nsICSSStyleSheet.h"
|
||||||
#include "nsICSSLoaderObserver.h"
|
#include "nsICSSLoaderObserver.h"
|
||||||
|
@ -82,12 +81,19 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsSupportsWea
|
||||||
|
|
||||||
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler);
|
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler);
|
||||||
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler);
|
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler);
|
||||||
|
|
||||||
NS_IMETHOD GetPrototypeProperties(nsIXBLPrototypeProperty** aResult);
|
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult);
|
||||||
NS_IMETHOD SetProtoTypeProperties(nsIXBLPrototypeProperty* aResult);
|
NS_IMETHOD SetConstructor(nsIXBLPrototypeHandler* aConstructor);
|
||||||
NS_IMETHOD GetCompiledClassObject(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject);
|
NS_IMETHOD GetDestructor(nsIXBLPrototypeHandler** aResult);
|
||||||
|
NS_IMETHOD SetDestructor(nsIXBLPrototypeHandler* aDestructor);
|
||||||
|
|
||||||
NS_IMETHOD InitClass(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject);
|
NS_IMETHOD InitClass(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject);
|
||||||
|
|
||||||
|
NS_IMETHOD ConstructInterfaceTable(const nsAReadableString& aImpls);
|
||||||
|
|
||||||
|
NS_IMETHOD SetImplementation(nsXBLProtoImpl* aImpl) { mImplementation = aImpl; return NS_OK; };
|
||||||
|
NS_IMETHOD InstallImplementation(nsIContent* aBoundElement);
|
||||||
|
|
||||||
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
|
NS_IMETHOD AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool aRemoveFlag,
|
||||||
nsIContent* aChangedElement, nsIContent* aAnonymousContent);
|
nsIContent* aChangedElement, nsIContent* aAnonymousContent);
|
||||||
|
|
||||||
|
@ -127,8 +133,6 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsSupportsWea
|
||||||
|
|
||||||
NS_IMETHOD AddResourceListener(nsIContent* aBoundElement);
|
NS_IMETHOD AddResourceListener(nsIContent* aBoundElement);
|
||||||
|
|
||||||
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult) { *aResult = mConstructor; NS_IF_ADDREF(*aResult); return NS_OK; };
|
|
||||||
|
|
||||||
NS_IMETHOD Initialize();
|
NS_IMETHOD Initialize();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -149,11 +153,8 @@ public:
|
||||||
nsIContent* aTemplChild, nsIContent** aCopyResult);
|
nsIContent* aTemplChild, nsIContent** aCopyResult);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void BuildConstructorAndDestructor();
|
|
||||||
void ConstructProperties();
|
|
||||||
void ConstructAttributeTable(nsIContent* aElement);
|
void ConstructAttributeTable(nsIContent* aElement);
|
||||||
void ConstructInsertionTable(nsIContent* aElement);
|
void ConstructInsertionTable(nsIContent* aElement);
|
||||||
void ConstructInterfaceTable(nsIContent* aElement);
|
|
||||||
void GetNestedChildren(nsIAtom* aTag, nsIContent* aContent, nsISupportsArray** aList);
|
void GetNestedChildren(nsIAtom* aTag, nsIContent* aContent, nsISupportsArray** aList);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -182,14 +183,13 @@ protected:
|
||||||
|
|
||||||
// MEMBER VARIABLES
|
// MEMBER VARIABLES
|
||||||
protected:
|
protected:
|
||||||
nsCString mID;
|
char* mID;
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc.
|
nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc.
|
||||||
nsCOMPtr<nsIXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
|
nsCOMPtr<nsIXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.
|
||||||
nsCOMPtr<nsIXBLPrototypeHandler> mConstructor; // Strong. Our constructor.
|
|
||||||
nsCOMPtr<nsIXBLPrototypeHandler> mDestructor; // Strong. Our destructor.
|
nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
|
||||||
|
// the constructor, and the destructor).
|
||||||
nsCOMPtr<nsIXBLPrototypeProperty> mPrototypeProperty;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIXBLPrototypeBinding> mBaseBinding; // Strong. We own the base binding in our explicit inheritance chain.
|
nsCOMPtr<nsIXBLPrototypeBinding> mBaseBinding; // Strong. We own the base binding in our explicit inheritance chain.
|
||||||
PRPackedBool mInheritStyle;
|
PRPackedBool mInheritStyle;
|
||||||
|
@ -209,6 +209,4 @@ protected:
|
||||||
|
|
||||||
PRInt32 mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will
|
PRInt32 mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will
|
||||||
nsCOMPtr<nsIAtom> mBaseTag; // be stored in here.
|
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.
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -146,11 +146,17 @@ nsXBLPrototypeHandler::GetHandlerElement(nsIContent** aResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLPrototypeHandler::SetHandlerText(const nsAReadableString& aText)
|
nsXBLPrototypeHandler::AppendHandlerText(const nsAReadableString& aText)
|
||||||
{
|
{
|
||||||
if (mHandlerText)
|
if (mHandlerText) {
|
||||||
|
// Append our text to the existing text.
|
||||||
|
nsAutoString currText(mHandlerText);
|
||||||
|
currText += aText;
|
||||||
nsMemory::Free(mHandlerText);
|
nsMemory::Free(mHandlerText);
|
||||||
mHandlerText = ToNewUnicode(aText);
|
mHandlerText = ToNewUnicode(currText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mHandlerText = ToNewUnicode(aText);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ public:
|
||||||
|
|
||||||
NS_IMETHOD GetHandlerElement(nsIContent** aResult);
|
NS_IMETHOD GetHandlerElement(nsIContent** aResult);
|
||||||
|
|
||||||
NS_IMETHOD SetHandlerText(const nsAReadableString& aText);
|
NS_IMETHOD AppendHandlerText(const nsAReadableString& aText);
|
||||||
|
|
||||||
NS_IMETHOD GetPhase(PRUint8* aResult) { *aResult = mPhase; return NS_OK; };
|
NS_IMETHOD GetPhase(PRUint8* aResult) { *aResult = mPhase; return NS_OK; };
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,6 @@
|
||||||
#include "nsXBLAtoms.h"
|
#include "nsXBLAtoms.h"
|
||||||
|
|
||||||
#include "nsIXBLPrototypeHandler.h"
|
#include "nsIXBLPrototypeHandler.h"
|
||||||
#include "nsIXBLPrototypeProperty.h"
|
|
||||||
|
|
||||||
#include "nsIChromeRegistry.h"
|
#include "nsIChromeRegistry.h"
|
||||||
#include "nsIPref.h"
|
#include "nsIPref.h"
|
||||||
|
@ -308,7 +307,6 @@ nsXBLStreamListener::OnStopRequest(nsIRequest* request, nsISupports* aCtxt, nsre
|
||||||
|
|
||||||
if (NS_FAILED(rv) || NS_FAILED(aStatus))
|
if (NS_FAILED(rv) || NS_FAILED(aStatus))
|
||||||
{
|
{
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
|
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
|
||||||
if (aChannel)
|
if (aChannel)
|
||||||
{
|
{
|
||||||
|
@ -685,7 +683,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsAReadableString& aURL,
|
||||||
} while (nextBinding);
|
} while (nextBinding);
|
||||||
|
|
||||||
// XXX Handle adjusting the prototype chain! We need to somehow indicate to
|
// XXX Handle adjusting the prototype chain! We need to somehow indicate to
|
||||||
// InstallProperties that the whole chain should just be whacked and rebuilt.
|
// InstallImplementation that the whole chain should just be whacked and rebuilt.
|
||||||
// We are becoming the new binding.
|
// We are becoming the new binding.
|
||||||
bindingManager->SetBinding(aContent, newBinding);
|
bindingManager->SetBinding(aContent, newBinding);
|
||||||
baseBinding->SetBaseBinding(binding);
|
baseBinding->SetBaseBinding(binding);
|
||||||
|
@ -714,7 +712,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsAReadableString& aURL,
|
||||||
newBinding->InstallEventHandlers();
|
newBinding->InstallEventHandlers();
|
||||||
|
|
||||||
// Set up our properties
|
// Set up our properties
|
||||||
newBinding->InstallProperties();
|
newBinding->InstallImplementation();
|
||||||
|
|
||||||
// Figure out if we need to execute a constructor.
|
// Figure out if we need to execute a constructor.
|
||||||
newBinding->GetFirstBindingWithConstructor(aBinding);
|
newBinding->GetFirstBindingWithConstructor(aBinding);
|
||||||
|
@ -1345,40 +1343,6 @@ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
nsresult NS_NewXBLService(nsIXBLService** aResult);
|
nsresult NS_NewXBLService(nsIXBLService** aResult);
|
||||||
|
|
|
@ -52,7 +52,6 @@ class nsIXBLBinding;
|
||||||
class nsIXBLDocumentInfo;
|
class nsIXBLDocumentInfo;
|
||||||
class nsIXBLPrototypeHandler;
|
class nsIXBLPrototypeHandler;
|
||||||
class nsIXBLPrototypeBinding;
|
class nsIXBLPrototypeBinding;
|
||||||
class nsIXBLPrototypeProperty;
|
|
||||||
class nsINameSpaceManager;
|
class nsINameSpaceManager;
|
||||||
class nsIContent;
|
class nsIContent;
|
||||||
class nsIDocument;
|
class nsIDocument;
|
||||||
|
@ -115,10 +114,6 @@ public:
|
||||||
NS_IMETHOD GetBindingInternal(nsIContent* aBoundElement, const nsCString& aURLStr,
|
NS_IMETHOD GetBindingInternal(nsIContent* aBoundElement, const nsCString& aURLStr,
|
||||||
PRBool aPeekFlag, PRBool* aIsReady, nsIXBLBinding** aResult);
|
PRBool aPeekFlag, PRBool* aIsReady, nsIXBLBinding** aResult);
|
||||||
|
|
||||||
// This method walks a binding document and removes any text nodes
|
|
||||||
// that contain only whitespace.
|
|
||||||
static nsresult BuildPropertyChain(nsIXBLPrototypeBinding * aPrototypeBinding, nsIContent * aContent, nsIXBLPrototypeProperty ** aResult);
|
|
||||||
|
|
||||||
// MEMBER VARIABLES
|
// MEMBER VARIABLES
|
||||||
public:
|
public:
|
||||||
static nsIXULContentUtils* gXULUtils;
|
static nsIXULContentUtils* gXULUtils;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче