diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.cpp b/mozilla/extensions/xforms/nsXFormsControlStub.cpp index c19a7dd0a2a..2faee0fe9e1 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.cpp +++ b/mozilla/extensions/xforms/nsXFormsControlStub.cpp @@ -320,12 +320,18 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt } nsresult -nsXFormsControlStubBase::BindToModel() +nsXFormsControlStubBase::BindToModel(PRBool aSetBoundNode) { nsCOMPtr oldModel(mModel); nsCOMPtr parentControl; - mModel = nsXFormsUtils::GetModel(mElement, getter_AddRefs(parentControl)); + nsCOMPtr boundNode; + mModel = nsXFormsUtils::GetModel(mElement, getter_AddRefs(parentControl), + kElementFlags, + getter_AddRefs(boundNode)); + if (aSetBoundNode) { + mBoundNode.swap(boundNode); + } return MaybeAddToModel(oldModel, parentControl); } @@ -632,8 +638,7 @@ nsXFormsControlStubBase::GetContext(nsAString &aModelID, if (aContextNode) { if (mBoundNode) { // We are bound to a node: This is the context node - CallQueryInterface(mBoundNode, aContextNode); // addrefs - NS_ASSERTION(*aContextNode, "could not QI context node from bound node?"); + NS_ADDREF(*aContextNode = mBoundNode); } else if (mModel) { // We are bound to a model: The document element of its default instance // document is the context node diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.h b/mozilla/extensions/xforms/nsXFormsControlStub.h index 59e6b075d31..f0fd11f70c6 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.h +++ b/mozilla/extensions/xforms/nsXFormsControlStub.h @@ -240,11 +240,15 @@ protected: void RemoveIndexListeners(); /** - * Binds the control to the model. Does _not_ set mBoundNode, etc. Just sets - * mModel, and handle attaching to the model (including reattaching from any - * old model). + * Binds the control to the model. Just sets mModel, and handle attaching to + * the model (including reattaching from any old model). + * + * @note It can also set the mBoundNode, but does not do a proper node + * binding, as in setting up dependencies, attaching index() listeners, etc. + * + * @param aSetBoundNode Set mBoundNode too? */ - nsresult BindToModel(); + nsresult BindToModel(PRBool aSetBoundNode = PR_FALSE); /** * Forces a rebinding to the model. diff --git a/mozilla/extensions/xforms/nsXFormsOutputElement.cpp b/mozilla/extensions/xforms/nsXFormsOutputElement.cpp index 92b9d778548..76a011bd131 100755 --- a/mozilla/extensions/xforms/nsXFormsOutputElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsOutputElement.cpp @@ -75,20 +75,26 @@ public: // nsIXFormsControl NS_IMETHOD Bind(); NS_IMETHOD Refresh(); + NS_IMETHOD GetBoundNode(nsIDOMNode **aBoundNode); // nsIXFormsDelegate NS_IMETHOD GetValue(nsAString& aValue); + NS_IMETHOD GetHasBoundNode(PRBool *aHasBoundNode); - nsXFormsOutputElement() : - nsXFormsDelegateStub(NS_LITERAL_STRING("output")) {} - + nsXFormsOutputElement(); private: - PRBool mHasBinding; - nsString mValue; - PRBool mValueIsDirty; + PRPackedBool mHasBinding; + PRPackedBool mValueIsDirty; + nsString mValue; }; +nsXFormsOutputElement::nsXFormsOutputElement() + : nsXFormsDelegateStub(NS_LITERAL_STRING("output")), + mHasBinding(PR_FALSE), mValueIsDirty(PR_TRUE) +{ +} + // nsIXFormsControl nsresult @@ -101,21 +107,24 @@ nsXFormsOutputElement::Bind() if (!mHasParent) return NS_OK; - - nsresult rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &mHasBinding); + + PRBool tmp; + nsresult rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &tmp); NS_ENSURE_SUCCESS(rv, rv); + mHasBinding = tmp; if (!mHasBinding) { - rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &mHasBinding); + rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &tmp); NS_ENSURE_SUCCESS(rv, rv); + mHasBinding = tmp; if (!mHasBinding) { - // If output only has a value attribute, it can't have a bound node. - // In an effort to streamline this a bit, we'll just get mModel here and - // add output to the deferred bind list if necessary. This should be all - // that we need from the services that ProcessNodeBinding provides. - // ProcessNodeBinding is called during ::Refresh (via GetValue) so we just - // need a few things set up before ::Refresh gets called (usually right - // after ::Bind) + // If output only has a value attribute, it can't have a proper single + // node binding. In an effort to streamline this a bit, we'll just bind + // to the model here and add output to the deferred bind list if + // necessary. This should be all that we need from the services that + // ProcessNodeBinding provides. ProcessNodeBinding is called during + // ::Refresh (via GetValue) so we just need a few things set up before + // ::Refresh gets called (usually right after ::Bind) nsCOMPtr domDoc; mElement->GetOwnerDocument(getter_AddRefs(domDoc)); @@ -123,7 +132,7 @@ nsXFormsOutputElement::Bind() nsXFormsModelElement::DeferElementBind(domDoc, this); } - return BindToModel(); + return BindToModel(PR_TRUE); } } @@ -160,6 +169,20 @@ nsXFormsOutputElement::Refresh() return nsXFormsDelegateStub::Refresh(); } +NS_IMETHODIMP +nsXFormsOutputElement::GetBoundNode(nsIDOMNode **aBoundNode) +{ + return mHasBinding ? nsXFormsDelegateStub::GetBoundNode(aBoundNode) : NS_OK; +} + +NS_IMETHODIMP +nsXFormsOutputElement::GetHasBoundNode(PRBool *aHasBoundNode) +{ + NS_ENSURE_ARG_POINTER(aHasBoundNode); + *aHasBoundNode = (mBoundNode && mHasBinding) ? PR_TRUE : PR_FALSE; + return NS_OK; +} + NS_IMETHODIMP nsXFormsOutputElement::GetValue(nsAString& aValue) { diff --git a/mozilla/extensions/xforms/nsXFormsUtils.cpp b/mozilla/extensions/xforms/nsXFormsUtils.cpp index ea346817921..11e9f14b0de 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.cpp +++ b/mozilla/extensions/xforms/nsXFormsUtils.cpp @@ -367,7 +367,8 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement, /* static */ already_AddRefed nsXFormsUtils::GetModel(nsIDOMElement *aElement, nsIXFormsControl **aParentControl, - PRUint32 aElementFlags) + PRUint32 aElementFlags, + nsIDOMNode **aContextNode) { nsCOMPtr model; @@ -385,9 +386,13 @@ nsXFormsUtils::GetModel(nsIDOMElement *aElement, NS_ENSURE_TRUE(model, nsnull); + if (aContextNode) { + NS_IF_ADDREF(*aContextNode = contextNode); + } + nsIModelElementPrivate *result = nsnull; if (model) - CallQueryInterface(model, &result); // addrefs + NS_ADDREF(result = model); return result; } diff --git a/mozilla/extensions/xforms/nsXFormsUtils.h b/mozilla/extensions/xforms/nsXFormsUtils.h index 3205be16f4f..522026726f0 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.h +++ b/mozilla/extensions/xforms/nsXFormsUtils.h @@ -207,12 +207,15 @@ public: * @param aElement The element * @param aParentControl The parent control setting the context * @param aElementFlags Flags describing characteristics of aElement + * @param aContextNode The context node * @return The model */ static NS_HIDDEN_(already_AddRefed) GetModel(nsIDOMElement *aElement, nsIXFormsControl **aParentControl = nsnull, - PRUint32 aElementFlags = ELEMENT_WITH_MODEL_ATTR); + PRUint32 aElementFlags = ELEMENT_WITH_MODEL_ATTR, + nsIDOMNode **aContextNode = nsnull); + /** * Evaluate a 'bind' or |aBindingAttr| attribute on |aElement|.