зеркало из 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 \
|
||||
nsIXBLBindingAttachedHandler.h \
|
||||
nsIXBLDocumentInfo.h \
|
||||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLInsertionPoint.h \
|
||||
nsIXBLPrototypeBinding.h \
|
||||
nsIXBLPrototypeHandler.h \
|
||||
nsIXBLPrototypeProperty.h \
|
||||
nsIXBLService.h \
|
||||
$(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 InstallEventHandlers() = 0;
|
||||
NS_IMETHOD InstallProperties() = 0;
|
||||
NS_IMETHOD InstallImplementation() = 0;
|
||||
|
||||
NS_IMETHOD HasStyleSheets(PRBool* aResolveStyle) = 0;
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ class nsIXBLBinding;
|
|||
class nsISupportsArray;
|
||||
class nsCString;
|
||||
class nsIScriptContext;
|
||||
class nsXBLProtoImpl;
|
||||
|
||||
// {34D700F5-C1A2-4408-A0B1-DD8F891DD1FE}
|
||||
#define NS_IXBLPROTOTYPEBINDING_IID \
|
||||
|
@ -82,12 +83,18 @@ public:
|
|||
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler)=0;
|
||||
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler)=0;
|
||||
|
||||
NS_IMETHOD GetPrototypeProperties(nsIXBLPrototypeProperty** aResult) = 0;
|
||||
NS_IMETHOD SetProtoTypeProperties(nsIXBLPrototypeProperty* aResult) = 0;
|
||||
NS_IMETHOD GetCompiledClassObject(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject) = 0;
|
||||
|
||||
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult)=0;
|
||||
NS_IMETHOD SetConstructor(nsIXBLPrototypeHandler* aConstructor)=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 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,
|
||||
nsIContent* aChangedElement, nsIContent* aAnonymousContent)=0;
|
||||
|
||||
|
@ -126,8 +133,6 @@ public:
|
|||
|
||||
NS_IMETHOD AddResourceListener(nsIContent* aBoundElement)=0;
|
||||
|
||||
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult)=0;
|
||||
|
||||
NS_IMETHOD Initialize()=0;
|
||||
};
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
NS_IMETHOD KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aEvent, PRBool* 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;
|
||||
|
||||
|
|
|
@ -62,7 +62,10 @@ CPPSRCS = \
|
|||
nsXBLResourceLoader.cpp \
|
||||
nsXBLDocumentInfo.cpp \
|
||||
nsXBLContentSink.cpp \
|
||||
nsXBLPrototypeProperty.cpp \
|
||||
nsXBLProtoImplProperty.cpp \
|
||||
nsXBLProtoImplMethod.cpp \
|
||||
nsXBLProtoImplField.cpp \
|
||||
nsXBLProtoImpl.cpp \
|
||||
nsXBLEventHandler.cpp \
|
||||
nsXBLWindowHandler.cpp \
|
||||
nsXBLWindowKeyHandler.cpp \
|
||||
|
|
|
@ -76,7 +76,10 @@ CPPSRCS= \
|
|||
nsXBLPrototypeHandler.cpp \
|
||||
nsBindingManager.cpp \
|
||||
nsXBLInsertionPoint.cpp \
|
||||
nsXBLPrototypeProperty.cpp \
|
||||
nsXBLProtoImplProperty.cpp \
|
||||
nsXBLProtoImplMethod.cpp \
|
||||
nsXBLProtoImplField.cpp \
|
||||
nsXBLProtoImpl.cpp \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS= \
|
||||
|
@ -105,7 +108,10 @@ CPP_OBJS= \
|
|||
.\$(OBJDIR)\nsXBLService.obj \
|
||||
.\$(OBJDIR)\nsBindingManager.obj \
|
||||
.\$(OBJDIR)\nsXBLInsertionPoint.obj \
|
||||
.\$(OBJDIR)\nsXBLPrototypeProperty.obj \
|
||||
.\$(OBJDIR)\nsXBLProtoImplProperty.obj \
|
||||
.\$(OBJDIR)\nsXBLProtoImplMethod.obj \
|
||||
.\$(OBJDIR)\nsXBLProtoImplField.obj \
|
||||
.\$(OBJDIR)\nsXBLProtoImpl.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
|
|
@ -94,7 +94,6 @@
|
|||
#include "nsIDOMAttr.h"
|
||||
#include "nsIDOMNamedNodeMap.h"
|
||||
|
||||
#include "nsIXBLPrototypeProperty.h"
|
||||
#include "nsXBLPrototypeHandler.h"
|
||||
|
||||
#include "nsXBLKeyHandler.h"
|
||||
|
@ -994,47 +993,17 @@ nsXBLBinding::InstallEventHandlers()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::InstallProperties()
|
||||
nsXBLBinding::InstallImplementation()
|
||||
{
|
||||
// Always install the base class properties first, so that
|
||||
// derived classes can reference the base class properties.
|
||||
|
||||
if (mNextBinding)
|
||||
mNextBinding->InstallProperties();
|
||||
mNextBinding->InstallImplementation();
|
||||
|
||||
// iterate through each property in the prototype's list and install the property.
|
||||
if (AllowScripts()) {
|
||||
nsCOMPtr<nsIXBLPrototypeProperty> propertyChain;
|
||||
mPrototypeBinding->GetPrototypeProperties(getter_AddRefs(propertyChain));
|
||||
|
||||
if (!propertyChain) return NS_OK; // kick out if our list is empty
|
||||
|
||||
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);
|
||||
}
|
||||
if (AllowScripts())
|
||||
mPrototypeBinding->InstallImplementation(mBoundElement);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ class nsXBLBinding: public nsIXBLBinding
|
|||
|
||||
NS_IMETHOD GenerateAnonymousContent();
|
||||
NS_IMETHOD InstallEventHandlers();
|
||||
NS_IMETHOD InstallProperties();
|
||||
NS_IMETHOD InstallImplementation();
|
||||
|
||||
NS_IMETHOD HasStyleSheets(PRBool* aResolveStyle);
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
#include "nsTextFragment.h"
|
||||
#include "nsXULElement.h"
|
||||
#include "nsXULAtoms.h"
|
||||
#include "nsXBLProtoImplProperty.h"
|
||||
#include "nsXBLProtoImplMethod.h"
|
||||
#include "nsXBLProtoImplField.h"
|
||||
|
||||
static NS_DEFINE_CID(kCSSParserCID, NS_CSSPARSER_CID);
|
||||
|
||||
|
@ -79,6 +82,11 @@ nsXBLContentSink::nsXBLContentSink()
|
|||
mSecondaryState = eXBL_None;
|
||||
mDocInfo = nsnull;
|
||||
mIsChromeOrResource = PR_FALSE;
|
||||
mImplementation = nsnull;
|
||||
mImplMember = nsnull;
|
||||
mProperty = nsnull;
|
||||
mMethod = nsnull;
|
||||
mField = nsnull;
|
||||
}
|
||||
|
||||
nsXBLContentSink::~nsXBLContentSink()
|
||||
|
@ -137,13 +145,57 @@ nsXBLContentSink::OnOpenContainer(const nsIParserNode& aNode, PRInt32 aNameSpace
|
|||
mState = eXBL_InResources;
|
||||
ret = PR_FALSE; // The XML content sink should ignore all <resources>.
|
||||
}
|
||||
else if (mState == eXBL_InResources && (aTagName == nsXBLAtoms::stylesheet || aTagName == nsXBLAtoms::image)) {
|
||||
ConstructResource(aNode, aTagName);
|
||||
ret = PR_FALSE; // The XML content sink should ignore all <resources>.
|
||||
else if (mState == eXBL_InResources) {
|
||||
if (aTagName == nsXBLAtoms::stylesheet || aTagName == nsXBLAtoms::image)
|
||||
ConstructResource(aNode, aTagName);
|
||||
ret = PR_FALSE; // The XML content sink should ignore everything within a <resources> block.
|
||||
}
|
||||
else if (aTagName == nsXBLAtoms::implementation) {
|
||||
// mState = eXBL_InImplementation;
|
||||
// ret = PR_FALSE; // The XML content sink should ignore the <implementation>.
|
||||
mState = eXBL_InImplementation;
|
||||
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;
|
||||
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);
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -243,21 +321,125 @@ nsXBLContentSink::AddLeaf(const nsIParserNode& aNode)
|
|||
// Get the text and add it to the event handler.
|
||||
switch (aNode.GetTokenType()) {
|
||||
case eToken_text:
|
||||
case eToken_whitespace:
|
||||
case eToken_newline:
|
||||
case eToken_cdatasection:
|
||||
mHandler->SetHandlerText(aNode.GetText());
|
||||
mHandler->AppendHandlerText(aNode.GetText());
|
||||
break;
|
||||
case eToken_entity:
|
||||
{
|
||||
nsAutoString tmp;
|
||||
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
|
||||
if (unicode < 0)
|
||||
mHandler->SetHandlerText(aNode.GetText());
|
||||
mHandler->AppendHandlerText(aNode.GetText());
|
||||
else
|
||||
mHandler->SetHandlerText(aNode.GetText());
|
||||
mHandler->AppendHandlerText(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -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 "nsIXBLPrototypeBinding.h"
|
||||
#include "nsIXBLPrototypeHandler.h"
|
||||
#include "nsXBLProtoImpl.h"
|
||||
#include "nsICSSParser.h"
|
||||
#include "nsLayoutCID.h"
|
||||
|
||||
|
@ -62,10 +63,16 @@ typedef enum {
|
|||
eXBL_InField,
|
||||
eXBL_InBody,
|
||||
eXBL_InGetter,
|
||||
eXBL_InSetter
|
||||
eXBL_InSetter,
|
||||
eXBL_InConstructor,
|
||||
eXBL_InDestructor
|
||||
} XBLSecondaryState;
|
||||
|
||||
class nsXULPrototypeElement;
|
||||
class nsXBLProtoImplMember;
|
||||
class nsXBLProtoImplProperty;
|
||||
class nsXBLProtoImplMethod;
|
||||
class nsXBLProtoImplField;
|
||||
|
||||
// The XBL content sink overrides the XML content sink to
|
||||
// builds its own lightweight data structures for the <resources>,
|
||||
|
@ -100,6 +107,12 @@ protected:
|
|||
void ConstructBinding();
|
||||
void ConstructHandler(const nsIParserNode& aNode);
|
||||
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);
|
||||
|
||||
protected:
|
||||
|
@ -112,6 +125,11 @@ protected:
|
|||
|
||||
nsCOMPtr<nsIXBLPrototypeBinding> mBinding;
|
||||
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 "nsXULAtoms.h"
|
||||
#include "nsXBLAtoms.h"
|
||||
#include "nsXBLProtoImpl.h"
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
|
@ -255,17 +256,18 @@ NS_IMPL_ISUPPORTS2(nsXBLPrototypeBinding, nsIXBLPrototypeBinding, nsISupportsWea
|
|||
// Constructors/Destructors
|
||||
nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIXBLDocumentInfo* aInfo,
|
||||
nsIContent* aElement)
|
||||
: mID(aID),
|
||||
mInheritStyle(PR_TRUE),
|
||||
: mInheritStyle(PR_TRUE),
|
||||
mHasBaseProto(PR_TRUE),
|
||||
mResources(nsnull),
|
||||
mImplementation(nsnull),
|
||||
mAttributeTable(nsnull),
|
||||
mInsertionPointTable(nsnull),
|
||||
mInterfaceTable(nsnull),
|
||||
mClassObject(nsnull)
|
||||
mInterfaceTable(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mID = ToNewCString(aID);
|
||||
|
||||
mXBLDocInfoWeak = getter_AddRefs(NS_GetWeakReference(aInfo));
|
||||
|
||||
gRefCnt++;
|
||||
|
@ -284,15 +286,6 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIX
|
|||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::Initialize()
|
||||
{
|
||||
nsCOMPtr<nsIXBLDocumentInfo> info(do_QueryReferent(mXBLDocInfoWeak));
|
||||
|
||||
PRBool allowScripts;
|
||||
info->GetScriptAccess(&allowScripts);
|
||||
if (allowScripts) {
|
||||
BuildConstructorAndDestructor();
|
||||
ConstructProperties();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(content));
|
||||
if (content) {
|
||||
|
@ -300,20 +293,17 @@ nsXBLPrototypeBinding::Initialize()
|
|||
ConstructInsertionTable(content);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> impl;
|
||||
GetImmediateChild(nsXBLAtoms::implementation, getter_AddRefs(impl));
|
||||
if (impl)
|
||||
ConstructInterfaceTable(impl);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
||||
{
|
||||
nsMemory::Free(mID);
|
||||
delete mResources;
|
||||
delete mAttributeTable;
|
||||
delete mInsertionPointTable;
|
||||
delete mInterfaceTable;
|
||||
delete mImplementation;
|
||||
gRefCnt--;
|
||||
if (gRefCnt == 0) {
|
||||
delete kAttrPool;
|
||||
|
@ -437,16 +427,16 @@ nsXBLPrototypeBinding::AddResource(nsIAtom* aResourceType, const nsAReadableStri
|
|||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::BindingAttached(nsIDOMEventReceiver* aReceiver)
|
||||
{
|
||||
if (mConstructor)
|
||||
return mConstructor->BindingAttached(aReceiver);
|
||||
if (mImplementation && mImplementation->mConstructor)
|
||||
return mImplementation->mConstructor->BindingAttached(aReceiver);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::BindingDetached(nsIDOMEventReceiver* aReceiver)
|
||||
{
|
||||
if (mDestructor)
|
||||
return mDestructor->BindingDetached(aReceiver);
|
||||
if (mImplementation && mImplementation->mDestructor)
|
||||
return mImplementation->mDestructor->BindingDetached(aReceiver);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -500,17 +490,52 @@ nsXBLPrototypeBinding::SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::GetPrototypeProperties(nsIXBLPrototypeProperty ** aResult)
|
||||
nsXBLPrototypeBinding::GetConstructor(nsIXBLPrototypeHandler** aResult)
|
||||
{
|
||||
*aResult = mPrototypeProperty;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
if (mImplementation && mImplementation->mConstructor) {
|
||||
*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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -829,30 +854,6 @@ nsXBLPrototypeBinding::GetImmediateChild(nsIAtom* aTag, nsIContent** aResult)
|
|||
|
||||
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
|
||||
nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject)
|
||||
|
@ -944,38 +945,6 @@ nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, nsIScriptContext *
|
|||
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
|
||||
nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement, nsIContent* aTemplRoot, nsIContent* aCopyRoot,
|
||||
nsIContent* aTemplChild, nsIContent** aCopyResult)
|
||||
|
@ -1365,24 +1334,22 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent* aElement)
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::ConstructInterfaceTable(const nsAReadableString& aImpls)
|
||||
{
|
||||
nsAutoString impls;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::implements, impls);
|
||||
if (!impls.IsEmpty()) {
|
||||
if (!aImpls.IsEmpty()) {
|
||||
// Obtain the interface info manager that can tell us the IID
|
||||
// for a given interface name.
|
||||
nsCOMPtr<nsIInterfaceInfoManager> infoManager = getter_AddRefs(XPTI_GetInterfaceInfoManager());
|
||||
if (!infoManager)
|
||||
return;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Create the table.
|
||||
if (!mInterfaceTable)
|
||||
mInterfaceTable = new nsSupportsHashtable(4);
|
||||
|
||||
// The user specified at least one attribute.
|
||||
char* str = ToNewCString(impls);
|
||||
char* str = ToNewCString(aImpls);
|
||||
char* newStr;
|
||||
// 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
|
||||
|
@ -1404,6 +1371,8 @@ nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent* aElement)
|
|||
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIXBLPrototypeBinding.h"
|
||||
#include "nsIXBLPrototypeHandler.h"
|
||||
#include "nsIXBLPrototypeProperty.h"
|
||||
#include "nsXBLPrototypeResources.h"
|
||||
#include "nsICSSStyleSheet.h"
|
||||
#include "nsICSSLoaderObserver.h"
|
||||
|
@ -82,12 +81,19 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsSupportsWea
|
|||
|
||||
NS_IMETHOD GetPrototypeHandlers(nsIXBLPrototypeHandler** aHandler);
|
||||
NS_IMETHOD SetPrototypeHandlers(nsIXBLPrototypeHandler* aHandler);
|
||||
|
||||
NS_IMETHOD GetPrototypeProperties(nsIXBLPrototypeProperty** aResult);
|
||||
NS_IMETHOD SetProtoTypeProperties(nsIXBLPrototypeProperty* aResult);
|
||||
NS_IMETHOD GetCompiledClassObject(const nsCString& aClassName, nsIScriptContext * aContext, void * aScriptObject, void ** aClassObject);
|
||||
|
||||
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult);
|
||||
NS_IMETHOD SetConstructor(nsIXBLPrototypeHandler* aConstructor);
|
||||
NS_IMETHOD GetDestructor(nsIXBLPrototypeHandler** aResult);
|
||||
NS_IMETHOD SetDestructor(nsIXBLPrototypeHandler* aDestructor);
|
||||
|
||||
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,
|
||||
nsIContent* aChangedElement, nsIContent* aAnonymousContent);
|
||||
|
||||
|
@ -127,8 +133,6 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsSupportsWea
|
|||
|
||||
NS_IMETHOD AddResourceListener(nsIContent* aBoundElement);
|
||||
|
||||
NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult) { *aResult = mConstructor; NS_IF_ADDREF(*aResult); return NS_OK; };
|
||||
|
||||
NS_IMETHOD Initialize();
|
||||
|
||||
public:
|
||||
|
@ -149,11 +153,8 @@ public:
|
|||
nsIContent* aTemplChild, nsIContent** aCopyResult);
|
||||
|
||||
protected:
|
||||
void BuildConstructorAndDestructor();
|
||||
void ConstructProperties();
|
||||
void ConstructAttributeTable(nsIContent* aElement);
|
||||
void ConstructInsertionTable(nsIContent* aElement);
|
||||
void ConstructInterfaceTable(nsIContent* aElement);
|
||||
void GetNestedChildren(nsIAtom* aTag, nsIContent* aContent, nsISupportsArray** aList);
|
||||
|
||||
protected:
|
||||
|
@ -182,14 +183,13 @@ protected:
|
|||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsCString mID;
|
||||
char* mID;
|
||||
|
||||
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> mConstructor; // Strong. Our constructor.
|
||||
nsCOMPtr<nsIXBLPrototypeHandler> mDestructor; // Strong. Our destructor.
|
||||
|
||||
nsCOMPtr<nsIXBLPrototypeProperty> mPrototypeProperty;
|
||||
|
||||
nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
|
||||
// the constructor, and the destructor).
|
||||
|
||||
nsCOMPtr<nsIXBLPrototypeBinding> mBaseBinding; // Strong. We own the base binding in our explicit inheritance chain.
|
||||
PRPackedBool mInheritStyle;
|
||||
|
@ -209,6 +209,4 @@ protected:
|
|||
|
||||
PRInt32 mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will
|
||||
nsCOMPtr<nsIAtom> mBaseTag; // be stored in here.
|
||||
|
||||
void * mClassObject; // the class object for the binding. We'll use this to pre-compile properties and methods for the binding.
|
||||
};
|
||||
|
|
|
@ -146,11 +146,17 @@ nsXBLPrototypeHandler::GetHandlerElement(nsIContent** aResult)
|
|||
}
|
||||
|
||||
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);
|
||||
mHandlerText = ToNewUnicode(aText);
|
||||
mHandlerText = ToNewUnicode(currText);
|
||||
}
|
||||
else
|
||||
mHandlerText = ToNewUnicode(aText);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
|
||||
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; };
|
||||
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
#include "nsXBLAtoms.h"
|
||||
|
||||
#include "nsIXBLPrototypeHandler.h"
|
||||
#include "nsIXBLPrototypeProperty.h"
|
||||
|
||||
#include "nsIChromeRegistry.h"
|
||||
#include "nsIPref.h"
|
||||
|
@ -308,7 +307,6 @@ nsXBLStreamListener::OnStopRequest(nsIRequest* request, nsISupports* aCtxt, nsre
|
|||
|
||||
if (NS_FAILED(rv) || NS_FAILED(aStatus))
|
||||
{
|
||||
|
||||
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
|
||||
if (aChannel)
|
||||
{
|
||||
|
@ -685,7 +683,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsAReadableString& aURL,
|
|||
} while (nextBinding);
|
||||
|
||||
// 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.
|
||||
bindingManager->SetBinding(aContent, newBinding);
|
||||
baseBinding->SetBaseBinding(binding);
|
||||
|
@ -714,7 +712,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsAReadableString& aURL,
|
|||
newBinding->InstallEventHandlers();
|
||||
|
||||
// Set up our properties
|
||||
newBinding->InstallProperties();
|
||||
newBinding->InstallImplementation();
|
||||
|
||||
// Figure out if we need to execute a constructor.
|
||||
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 ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult NS_NewXBLService(nsIXBLService** aResult);
|
||||
|
|
|
@ -52,7 +52,6 @@ class nsIXBLBinding;
|
|||
class nsIXBLDocumentInfo;
|
||||
class nsIXBLPrototypeHandler;
|
||||
class nsIXBLPrototypeBinding;
|
||||
class nsIXBLPrototypeProperty;
|
||||
class nsINameSpaceManager;
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
|
@ -115,10 +114,6 @@ public:
|
|||
NS_IMETHOD GetBindingInternal(nsIContent* aBoundElement, const nsCString& aURLStr,
|
||||
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
|
||||
public:
|
||||
static nsIXULContentUtils* gXULUtils;
|
||||
|
|
Загрузка…
Ссылка в новой задаче