[XFORMS] Bug 391586, bind on an insert changes the in-scope evaluation context, p=msterlin@us.ibm.com, r=aaronr+me, NPOTB

git-svn-id: svn://10.0.0.236/trunk@234039 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
Olli.Pettay%helsinki.fi
2007-09-06 18:26:26 +00:00
parent 0209f0a444
commit f02f6aaf97
3 changed files with 77 additions and 76 deletions

View File

@@ -124,89 +124,74 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
return NS_OK;
nsresult rv;
nsCOMPtr<nsIModelElementPrivate> 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<nsIDOMXPathResult> contextNodeset;
nsCOMPtr<nsIDOMNode> 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<nsIModelElementPrivate> model;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIXFormsControl> 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<nsIDOMElement> bindElement;
nsCOMPtr<nsIXFormsControl> 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<nsIDOMXPathResult> 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;
}
//