diff --git a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp index 51ccb667838..c5854b5f2e1 100644 --- a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp @@ -124,89 +124,74 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, return NS_OK; nsresult rv; - nsCOMPtr model; - PRBool usesModelBinding; // // Step 1 (Insert or Delete): Determine the insert/delete context. // - // If the bind attribute is present, it is evaluated to determine the - // in-scope evaluation context and the context attribute is ignored; - // otherwise, the context attribute is evaluated and overrides the - // in-scope evaluation context. - // - // A NodeSet binding attribute (@bind or @nodeset) is required unless - // the context attribute is present. + // If the bind attribute is present or if the context attribute is not given, + // the insert context is the in-scope evaluation context. Otherwise, the + // XPath expression provided by the context attribute is evaluated using the + // in-scope evaluation context, and the first node rule is applied to obtain + // the insert context. // nsCOMPtr contextNodeset; nsCOMPtr contextNode; PRUint32 contextNodesetSize = 0; + // Get the in-scope evaluation context. The last parameter to GetNodeContext + // indicates whether it should try to get the context using @bind. We want to + // ignore @bind because it should not change the in-scope evaluation context + // for insert. + nsCOMPtr model; + nsCOMPtr bindElement; + nsCOMPtr parentControl; + PRBool outerBind; + rv = nsXFormsUtils::GetNodeContext(mElement, + nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, + getter_AddRefs(model), + getter_AddRefs(bindElement), + &outerBind, + getter_AddRefs(parentControl), + getter_AddRefs(contextNode), + nsnull, nsnull, PR_FALSE); + + NS_ENSURE_SUCCESS(rv, rv); + + // Determine if the context node is specified via @context. + // If @bind is present, @context is ignored. nsAutoString bindExpr; nsAutoString contextExpr; - nsAutoString contextStr; - - // Determine if the context node is specified via @bind or @context. - // If @bind is present, @context is ignored. mElement->GetAttribute(NS_LITERAL_STRING("bind"), bindExpr); - if (!bindExpr.IsEmpty()) { - contextStr.AssignLiteral("bind"); - } else { - mElement->GetAttribute(NS_LITERAL_STRING("context"), contextExpr); - if (!contextExpr.IsEmpty()) { - contextStr.AssignLiteral("context"); - } - } + mElement->GetAttribute(NS_LITERAL_STRING("context"), contextExpr); - if (!contextStr.IsEmpty()) { - // Context node is specified via either @bind or @context. - rv = nsXFormsUtils::EvaluateNodeBinding(mElement, - nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, - contextStr, - EmptyString(), - nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, - getter_AddRefs(model), - getter_AddRefs(contextNodeset), - &usesModelBinding); + if (bindExpr.IsEmpty() && !contextExpr.IsEmpty()) { + // @context is specified and overrides the in-scope evaluation context. + // The insert context is the result of evaluating @context in the current + // in-scope evaluation context. + rv = nsXFormsUtils::EvaluateXPath(contextExpr, contextNode, mElement, + nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, + getter_AddRefs(contextNodeset)); NS_ENSURE_SUCCESS(rv, rv); - if (!model) - return NS_OK; - // The insert/delete action is terminated with no effect if the context // is the empty node-set. if (contextNodeset) { rv = contextNodeset->GetSnapshotLength(&contextNodesetSize); NS_ENSURE_SUCCESS(rv, rv); - + if (contextNodesetSize < 1) return NS_OK; - + // Context node is the first node in the nodeset. contextNodeset->SnapshotItem(0, getter_AddRefs(contextNode)); } - - } else { - // Neither @bind nor @context. Get the in-scope evaluation context. - nsCOMPtr bindElement; - nsCOMPtr parentControl; - PRBool outerBind; - rv = nsXFormsUtils::GetNodeContext(mElement, - nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, - getter_AddRefs(model), - getter_AddRefs(bindElement), - &outerBind, - getter_AddRefs(parentControl), - getter_AddRefs(contextNode)); - - NS_ENSURE_SUCCESS(rv, rv); - - // The insert/delete action is terminated with no effect if the context - // is the empty node-set. - if (!model || !contextNode) - return NS_OK; } + // The insert/delete action is terminated with no effect if the context + // is the empty node-set. + if (!contextNode) + return NS_OK; + // The insert action is terminated with no effect if the context attribute // is given and the insert context does not evaluate to an element node. if (mIsInsert && !contextExpr.IsEmpty()) { @@ -223,6 +208,9 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, // Binding node-set. If a nodeset attribute is present, it is evaluated // within the context to determine the Node Set Binding node-set. // + // A NodeSet binding attribute (@bind or @nodeset) is required unless + // the context attribute is present. + // nsCOMPtr nodeset; PRUint32 nodesetSize = 0; @@ -230,29 +218,39 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, nsAutoString nodesetExpr; mElement->GetAttribute(NS_LITERAL_STRING("nodeset"), nodesetExpr); if (!nodesetExpr.IsEmpty()) { - // Evaluate the nodeset attribute within the context. + // Evaluate the nodeset attribute within the insert context. rv = nsXFormsUtils::EvaluateXPath(nodesetExpr, contextNode, mElement, nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, getter_AddRefs(nodeset)); NS_ENSURE_SUCCESS(rv, rv); - - rv = nodeset->GetSnapshotLength(&nodesetSize); - NS_ENSURE_SUCCESS(rv, rv); - } - - // The insert action is terminated with no effect if the context attribute - // is not given and the Node Set Binding node-set is the empty node-set. - // - // The delete action is terminated with no effect if the Node Set Binding - // node-set is the empty node-set. - if (!nodeset || nodesetSize < 1) { - if (!mIsInsert || (mIsInsert && contextExpr.IsEmpty())) - return NS_OK; } } else { - // Nodeset was determined by @bind. - nodeset = contextNodeset; - nodesetSize = contextNodesetSize; + PRBool usesModelBinding; + rv = nsXFormsUtils::EvaluateNodeBinding(mElement, + nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, + EmptyString(), + EmptyString(), + nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, + getter_AddRefs(model), + getter_AddRefs(nodeset), + &usesModelBinding); + NS_ENSURE_SUCCESS(rv, rv); + + if (!model) + return NS_OK; + } + + rv = nodeset->GetSnapshotLength(&nodesetSize); + NS_ENSURE_SUCCESS(rv, rv); + + // The insert action is terminated with no effect if the context attribute + // is not given and the Node Set Binding node-set is the empty node-set. + // + // The delete action is terminated with no effect if the Node Set Binding + // node-set is the empty node-set. + if (!nodeset || nodesetSize < 1) { + if (!mIsInsert || (mIsInsert && contextExpr.IsEmpty())) + return NS_OK; } // diff --git a/mozilla/extensions/xforms/nsXFormsUtils.cpp b/mozilla/extensions/xforms/nsXFormsUtils.cpp index 382ddec5b38..d1e566b3fe7 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.cpp +++ b/mozilla/extensions/xforms/nsXFormsUtils.cpp @@ -351,7 +351,8 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement, nsIXFormsControl **aParentControl, nsIDOMNode **aContextNode, PRInt32 *aContextPosition, - PRInt32 *aContextSize) + PRInt32 *aContextSize, + PRBool aUseBindAttr) { NS_ENSURE_ARG(aElement); NS_ENSURE_ARG(aOuterBind); @@ -371,7 +372,7 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement, nsAutoString bindId; NS_NAMED_LITERAL_STRING(bindStr, "bind"); aElement->GetAttribute(bindStr, bindId); - if (!bindId.IsEmpty()) { + if (!bindId.IsEmpty() && aUseBindAttr) { // CASE 1: Use @bind GetElementByContextId(aElement, bindId, aBindElement); diff --git a/mozilla/extensions/xforms/nsXFormsUtils.h b/mozilla/extensions/xforms/nsXFormsUtils.h index d146ec33f1d..ec6b2109e1e 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.h +++ b/mozilla/extensions/xforms/nsXFormsUtils.h @@ -218,6 +218,7 @@ public: * @param aContextNode The context node for the element * @param aContextPosition The context position for the element * @param aContextSize The context size for the element + * @param aUseBindAttr Use @bind (if present) to determine context node? */ static NS_HIDDEN_(nsresult) GetNodeContext(nsIDOMElement *aElement, @@ -228,7 +229,8 @@ public: nsIXFormsControl **aParentControl, nsIDOMNode **aContextNode, PRInt32 *aContextPosition = nsnull, - PRInt32 *aContextSize = nsnull); + PRInt32 *aContextSize = nsnull, + PRBool aUseBindAttr = PR_TRUE); /** * Locate the model for an element.