Bug 308106, controls not bound to external instance data in xul, r=aaronr+allan

This commit is contained in:
Olli.Pettay%helsinki.fi 2005-10-28 18:52:56 +00:00
Родитель 8082f3a4a0
Коммит 24c4b2f21e
5 изменённых файлов: 114 добавлений и 105 удалений

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

@ -44,7 +44,7 @@ interface nsIDOMElement;
/** /**
* Private interface implemented by the instance element. * Private interface implemented by the instance element.
*/ */
[uuid(446dc7b6-91fc-4de5-b6de-5ac22538ee5e)] [uuid(debb24ef-7ba1-4e01-9f62-18106b25c993)]
interface nsIInstanceElementPrivate : nsISupports interface nsIInstanceElementPrivate : nsISupports
{ {
/** /**
@ -54,5 +54,5 @@ interface nsIInstanceElementPrivate : nsISupports
readonly attribute nsIDOMElement element; readonly attribute nsIDOMElement element;
void backupOriginalDocument(); void backupOriginalDocument();
void restoreOriginalDocument(); void restoreOriginalDocument();
void initializeLazyInstance(); void initialize();
}; };

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

@ -63,7 +63,7 @@ NS_IMPL_ISUPPORTS_INHERITED5(nsXFormsInstanceElement,
nsXFormsInstanceElement::nsXFormsInstanceElement() nsXFormsInstanceElement::nsXFormsInstanceElement()
: mElement(nsnull) : mElement(nsnull)
, mAddingChildren(PR_FALSE) , mInitialized(PR_FALSE)
, mLazy(PR_FALSE) , mLazy(PR_FALSE)
{ {
} }
@ -87,7 +87,7 @@ NS_IMETHODIMP
nsXFormsInstanceElement::AttributeSet(nsIAtom *aName, nsXFormsInstanceElement::AttributeSet(nsIAtom *aName,
const nsAString &aNewValue) const nsAString &aNewValue)
{ {
if (mAddingChildren || mLazy) if (!mInitialized || mLazy)
return NS_OK; return NS_OK;
if (aName == nsXFormsAtoms::src) { if (aName == nsXFormsAtoms::src) {
@ -100,7 +100,7 @@ nsXFormsInstanceElement::AttributeSet(nsIAtom *aName,
NS_IMETHODIMP NS_IMETHODIMP
nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName) nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName)
{ {
if (mAddingChildren || mLazy) if (!mInitialized || mLazy)
return NS_OK; return NS_OK;
if (aName == nsXFormsAtoms::src) { if (aName == nsXFormsAtoms::src) {
@ -135,51 +135,11 @@ nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsXFormsInstanceElement::BeginAddingChildren()
{
mAddingChildren = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::DoneAddingChildren()
{
mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY),
NS_LITERAL_STRING("lazy"), &mLazy);
if (!mLazy) {
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
NS_ENSURE_TRUE(model, NS_ERROR_FAILURE);
model->AddInstanceElement(this);
// By the time this is called, we should be inserted in the document and
// have all of our child elements, so this is our first opportunity to
// create the instance document.
nsAutoString src;
mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
if (src.IsEmpty()) {
// If we don't have a linked external instance, use our inline data.
CloneInlineInstance();
} else {
LoadExternalInstance(src);
}
}
mAddingChildren = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper) nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
{ {
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_ATTRIBUTE_SET | aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED | nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED);
nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
nsCOMPtr<nsIDOMElement> node; nsCOMPtr<nsIDOMElement> node;
aWrapper->GetElementNode(getter_AddRefs(node)); aWrapper->GetElementNode(getter_AddRefs(node));
@ -194,22 +154,6 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent)
{
if (!aNewParent || mAddingChildren || mLazy)
return NS_OK;
// Once we are set up in the DOM, can find the model and make sure that this
// instance is on the list of instance elements that model keeps
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
if (model) {
model->AddInstanceElement(this);
}
return NS_OK;
}
// nsIInterfaceRequestor // nsIInterfaceRequestor
NS_IMETHODIMP NS_IMETHODIMP
@ -445,49 +389,73 @@ nsXFormsInstanceElement::GetElement(nsIDOMElement **aElement)
} }
NS_IMETHODIMP NS_IMETHODIMP
nsXFormsInstanceElement::InitializeLazyInstance() nsXFormsInstanceElement::Initialize()
{ {
NS_ENSURE_STATE(mElement); if (mInitialized || !mElement) {
if (!mLazy) { return NS_OK;
mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY),
NS_LITERAL_STRING("lazy"), &mLazy);
} }
NS_ENSURE_STATE(mLazy); mInitialized = PR_TRUE;
nsCOMPtr<nsIDOMDocument> domDoc; nsCOMPtr<nsIModelElementPrivate> model = GetModel();
mElement->GetOwnerDocument(getter_AddRefs(domDoc)); NS_ENSURE_TRUE(model, NS_ERROR_FAILURE);
NS_ENSURE_STATE(domDoc); model->AddInstanceElement(this);
nsCOMPtr<nsIDOMDOMImplementation> domImpl; mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY),
nsresult rv = domDoc->GetImplementation(getter_AddRefs(domImpl)); NS_LITERAL_STRING("lazy"), &mLazy);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> newDoc; // Lazy instance
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull, if (mLazy) {
getter_AddRefs(newDoc)); nsCOMPtr<nsIDOMDocument> domDoc;
NS_ENSURE_SUCCESS(rv, rv); mElement->GetOwnerDocument(getter_AddRefs(domDoc));
NS_ENSURE_STATE(domDoc);
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
nsresult rv = domDoc->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> newDoc;
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(newDoc));
NS_ENSURE_SUCCESS(rv, rv);
rv = SetDocument(newDoc);
NS_ENSURE_SUCCESS(rv, rv);
// Lazy authored instance documents have a root named "instanceData"
nsCOMPtr<nsIDOMElement> instanceDataElement;
nsCOMPtr<nsIDOMNode> childReturn;
rv = mDocument->CreateElementNS(EmptyString(),
NS_LITERAL_STRING("instanceData"),
getter_AddRefs(instanceDataElement));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn));
NS_ENSURE_SUCCESS(rv, rv);
// I don't know if not being able to create a backup document is worth
// failing this function. Since it probably won't be used often, we'll
// let it slide. But it probably does mean that things are going south
// with the browser.
domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mOriginalDocument));
NS_WARN_IF_FALSE(mOriginalDocument, "Couldn't create mOriginalDocument!!");
} else {
// Normal instance
rv = SetDocument(newDoc); // By the time this is called, we should be inserted in the document and
NS_ENSURE_SUCCESS(rv, rv); // have all of our child elements, so this is our first opportunity to
// create the instance document.
// Lazy authored instance documents have a root named "instanceData"
nsCOMPtr<nsIDOMElement> instanceDataElement; nsAutoString src;
nsCOMPtr<nsIDOMNode> childReturn; mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
rv = mDocument->CreateElementNS(EmptyString(),
NS_LITERAL_STRING("instanceData"), if (src.IsEmpty()) {
getter_AddRefs(instanceDataElement)); // If we don't have a linked external instance, use our inline data.
NS_ENSURE_SUCCESS(rv, rv); CloneInlineInstance();
rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn)); } else {
NS_ENSURE_SUCCESS(rv, rv); LoadExternalInstance(src);
}
// I don't know if not being able to create a backup document is worth }
// failing this function. Since it probably won't be used often, we'll
// let it slide. But it probably does mean that things are going south
// with the browser.
domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mOriginalDocument));
NS_WARN_IF_FALSE(mOriginalDocument, "Couldn't create mOriginalDocument!!");
return NS_OK; return NS_OK;
} }

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

@ -75,10 +75,7 @@ public:
NS_IMETHOD OnDestroyed(); NS_IMETHOD OnDestroyed();
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aNewValue); NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aNewValue);
NS_IMETHOD AttributeRemoved(nsIAtom *aName); NS_IMETHOD AttributeRemoved(nsIAtom *aName);
NS_IMETHOD BeginAddingChildren();
NS_IMETHOD DoneAddingChildren();
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper); NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper);
NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
nsXFormsInstanceElement() NS_HIDDEN; nsXFormsInstanceElement() NS_HIDDEN;
@ -92,7 +89,7 @@ private:
nsCOMPtr<nsIDOMDocument> mOriginalDocument; nsCOMPtr<nsIDOMDocument> mOriginalDocument;
nsIDOMElement *mElement; nsIDOMElement *mElement;
nsCOMPtr<nsIStreamListener> mListener; nsCOMPtr<nsIStreamListener> mListener;
PRBool mAddingChildren; PRBool mInitialized;
PRBool mLazy; PRBool mLazy;
nsCOMPtr<nsIChannel> mChannel; nsCOMPtr<nsIChannel> mChannel;
}; };

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

@ -260,6 +260,7 @@ nsXFormsModelElement::nsXFormsModelElement()
mPendingInstanceCount(0), mPendingInstanceCount(0),
mDocumentLoaded(PR_FALSE), mDocumentLoaded(PR_FALSE),
mNeedsRefresh(PR_FALSE), mNeedsRefresh(PR_FALSE),
mInstancesInitialized(PR_FALSE),
mInstanceDocuments(nsnull), mInstanceDocuments(nsnull),
mLazyModel(PR_FALSE) mLazyModel(PR_FALSE)
{ {
@ -346,6 +347,36 @@ nsXFormsModelElement::DocumentChanged(nsIDOMDocument* aNewDocument)
NS_IMETHODIMP NS_IMETHODIMP
nsXFormsModelElement::DoneAddingChildren() nsXFormsModelElement::DoneAddingChildren()
{ {
return InitializeInstances();
}
nsresult
nsXFormsModelElement::InitializeInstances()
{
if (mInstancesInitialized || !mElement) {
return NS_OK;
}
mInstancesInitialized = PR_TRUE;
nsCOMPtr<nsIDOMNodeList> children;
mElement->GetChildNodes(getter_AddRefs(children));
PRUint32 childCount = 0;
if (children) {
children->GetLength(&childCount);
}
for (PRUint32 i = 0; i < childCount; ++i) {
nsCOMPtr<nsIDOMNode> child;
children->Item(i, getter_AddRefs(child));
if (nsXFormsUtils::IsXFormsElement(child, NS_LITERAL_STRING("instance"))) {
nsCOMPtr<nsIInstanceElementPrivate> instance(do_QueryInterface(child));
if (instance) {
instance->Initialize();
}
}
}
// (XForms 4.2.1) // (XForms 4.2.1)
// 1. load xml schemas // 1. load xml schemas
@ -427,6 +458,9 @@ nsXFormsModelElement::DoneAddingChildren()
PRUint32 instCount; PRUint32 instCount;
mInstanceDocuments->GetLength(&instCount); mInstanceDocuments->GetLength(&instCount);
if (!instCount) { if (!instCount) {
#ifdef DEBUG
printf("Creating lazy instance\n");
#endif
nsCOMPtr<nsIDOMDocument> domDoc; nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc)); mElement->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(domDoc)); nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(domDoc));
@ -437,8 +471,6 @@ nsXFormsModelElement::DoneAddingChildren()
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mInstanceDocuments->GetLength(&instCount); mInstanceDocuments->GetLength(&instCount);
NS_WARN_IF_FALSE(instCount == 1,
"Installing lazy instance didn't succeed!");
nsCOMPtr<nsIDOMNodeList> list; nsCOMPtr<nsIDOMNodeList> list;
xblDoc->GetAnonymousNodes(mElement, getter_AddRefs(list)); xblDoc->GetAnonymousNodes(mElement, getter_AddRefs(list));
@ -454,7 +486,7 @@ nsXFormsModelElement::DoneAddingChildren()
nsCOMPtr<nsIInstanceElementPrivate> instance = nsCOMPtr<nsIInstanceElementPrivate> instance =
do_QueryInterface(item); do_QueryInterface(item);
if (instance) { if (instance) {
rv = instance->InitializeLazyInstance(); rv = instance->Initialize();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mLazyModel = PR_TRUE; mLazyModel = PR_TRUE;
@ -463,6 +495,7 @@ nsXFormsModelElement::DoneAddingChildren()
} }
} }
} }
NS_WARN_IF_FALSE(mLazyModel, "Installing lazy instance didn't succeed!");
} }
// (XForms 4.2.1 - cont) // (XForms 4.2.1 - cont)
@ -893,6 +926,12 @@ nsXFormsModelElement::HandleEvent(nsIDOMEvent* aEvent)
if (!type.EqualsLiteral("DOMContentLoaded")) if (!type.EqualsLiteral("DOMContentLoaded"))
return NS_OK; return NS_OK;
if (!mInstancesInitialized) {
// XXX This is for Bug 308106. In Gecko 1.8 DoneAddingChildren is not
// called in XUL if the element doesn't have any child nodes.
InitializeInstances();
}
mDocumentLoaded = PR_TRUE; mDocumentLoaded = PR_TRUE;
// dispatch xforms-model-construct, xforms-rebuild, xforms-recalculate, // dispatch xforms-model-construct, xforms-rebuild, xforms-recalculate,

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

@ -178,6 +178,8 @@ private:
/** Initializes the MIPs on all form controls */ /** Initializes the MIPs on all form controls */
NS_HIDDEN_(nsresult) InitializeControls(); NS_HIDDEN_(nsresult) InitializeControls();
NS_HIDDEN_(nsresult) InitializeInstances();
NS_HIDDEN_(nsresult) ProcessBindElements(); NS_HIDDEN_(nsresult) ProcessBindElements();
NS_HIDDEN_(nsresult) FinishConstruction(); NS_HIDDEN_(nsresult) FinishConstruction();
NS_HIDDEN_(nsresult) ConstructDone(); NS_HIDDEN_(nsresult) ConstructDone();
@ -253,6 +255,9 @@ private:
// xforms-revalidate yet // xforms-revalidate yet
PRBool mNeedsRefresh; PRBool mNeedsRefresh;
// This flag indicates whether instance elements have been initialized
PRBool mInstancesInitialized;
/** /**
* All instance documents contained by this model, including lazy-authored * All instance documents contained by this model, including lazy-authored
* instance documents. * instance documents.