Fix for 106153, don't build a content model for XBL's implementation. r=bryner, sr=ben

This commit is contained in:
hyatt%netscape.com 2001-11-13 04:09:56 +00:00
Родитель ee9c51654a
Коммит 465e6e150b
29 изменённых файлов: 1785 добавлений и 250 удалений

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

@ -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;