[XForms] XPath expression errors when expr spans mult instances. Bug 348993, r=doronr+olli

This commit is contained in:
aaronr%us.ibm.com 2006-08-20 20:46:15 +00:00
Родитель fc5f3cdea2
Коммит 6e115f0df7
3 изменённых файлов: 85 добавлений и 22 удалений

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

@ -2310,20 +2310,6 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
sModelPropsList[i]->ToString(attrStr);
aBindElement->GetAttribute(attrStr, propStrings[i]);
if (!propStrings[i].IsEmpty() &&
i != eModel_type &&
i != eModel_p3ptype) {
rv = nsXFormsUtils::CreateExpression(eval, propStrings[i], resolver,
aBindElement,
getter_AddRefs(props[i]));
if (NS_FAILED(rv)) {
const PRUnichar *strings[] = { propStrings[i].get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("mipParseError"),
strings, 1, aBindElement, aBindElement);
nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException);
return rv;
}
}
}
// Find the nodeset that this bind applies to.
@ -2382,16 +2368,47 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
// Iterate over resultset
nsCOMArray<nsIDOMNode> deps;
nsCOMPtr<nsIDOMNode> node;
PRUint32 snapItem;
for (snapItem = 0; snapItem < snapLen; ++snapItem) {
if (!snapLen) {
return NS_OK;
}
// We rightly assume that all the nodes in the nodeset came from the same
// document. So now we'll get the xpath evaluator from that document. We
// need to ensure that the context node for the evaluation of each MIP
// expression and the evaluator for those expressions came from the same
// document. It is a rule for xpath.
PRUint32 snapItem = 0;
for (; snapItem < snapLen; ++snapItem) {
rv = result->SnapshotItem(snapItem, getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
if (!node) {
if (node){
break;
} else {
NS_WARNING("nsXFormsModelElement::ProcessBind(): Empty node in result set.");
continue;
}
}
if (!node) {
return NS_OK;
}
nsCOMPtr<nsIDOMDocument> nodesetDoc;
node->GetOwnerDocument(getter_AddRefs(nodesetDoc));
nsCOMPtr<nsIDOMXPathEvaluator> nodesetEval = do_QueryInterface(nodesetDoc);
nsCOMPtr<nsIXPathEvaluatorInternal> nodesetEvalInternal =
do_QueryInterface(nodesetEval);
NS_ENSURE_STATE(nodesetEval && nodesetEvalInternal);
// Since we've already gotten the first node in the nodeset and verified it is
// good to go, we'll contine on. For this node and each subsequent node in
// the nodeset, we'll evaluate the MIP expressions attached to the bind
// element and add them to the MDG. And also process any binds that this
// bind contains (aka nested binds).
while (node && snapItem < snapLen) {
// Apply MIPs
nsXFormsXPathParser parser;
@ -2429,6 +2446,19 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
NS_ENSURE_SUCCESS(rv, rv);
}
} else {
rv = nsXFormsUtils::CreateExpression(nodesetEvalInternal,
propStrings[j], resolver,
aBindElement,
getter_AddRefs(props[j]));
if (NS_FAILED(rv)) {
const PRUnichar *strings[] = { propStrings[j].get() };
nsXFormsUtils::ReportError(NS_LITERAL_STRING("mipParseError"),
strings, 1, aBindElement, aBindElement);
nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException);
return rv;
}
// the rest of the MIPs are given to the MDG
nsCOMPtr<nsIDOMNSXPathExpression> expr = do_QueryInterface(props[j]);
@ -2501,6 +2531,19 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
}
}
}
++snapItem;
while (snapItem < snapLen) {
rv = result->SnapshotItem(snapItem, getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
if (node) {
break;
}
NS_WARNING("nsXFormsModelElement::ProcessBind(): Empty node in result set.");
snapItem++;
}
}
return NS_OK;

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

@ -439,6 +439,8 @@ nsXFormsUtils::CreateExpression(nsIXPathEvaluatorInternal *aEvaluator,
contractid.AppendCString(NS_LITERAL_CSTRING("@mozilla.org/xforms-xpath-functions;1"));
state.AppendObject(aState);
// if somehow the contextNode and the evaluator weren't spawned from the same
// document, this could fail with NS_ERROR_DOM_WRONG_DOCUMENT_ERR
nsCOMPtr<nsIDOMXPathExpression> expression;
return aEvaluator->CreateExpression(aExpression, aResolver, &ns, &contractid,
&state, aResult);
@ -561,6 +563,8 @@ nsXFormsUtils::EvaluateXPath(nsIXPathEvaluatorInternal *aEvaluator,
do_QueryInterface(expression, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// if somehow the contextNode and the evaluator weren't spawned from the same
// document, this could fail with NS_ERROR_DOM_WRONG_DOCUMENT_ERR
nsCOMPtr<nsISupports> supResult;
rv = nsExpression->EvaluateWithContext(aContextNode, aContextPosition,
aContextSize, aResultType,

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

@ -40,6 +40,9 @@
#include "nsXFormsXPathAnalyzer.h"
#include "nsIDOMXPathResult.h"
#include "nsXFormsUtils.h"
#include "nsIDOMDocument.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsIXPathEvaluatorInternal.h"
#ifdef DEBUG
//#define DEBUG_XF_ANALYZER
@ -177,7 +180,20 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode,
xp = Substring(*mCurExprString, aNode->mStartIndex,
aNode->mEndIndex - aNode->mStartIndex);
}
rv = nsXFormsUtils::EvaluateXPath(mEvaluator, xp, aContextNode, mResolver,
// It is an error to use an evaluator from a different document than the
// context node. The context node can change as we recurse and be
// from an different instance document than the context node we used to
// kick off the evaluation. More efficient to just get the evaluator every
// time we recurse rather than caching it and testing.
nsCOMPtr<nsIDOMDocument> doc;
aContextNode->GetOwnerDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDOMXPathEvaluator> eval = do_QueryInterface(doc);
nsCOMPtr<nsIXPathEvaluatorInternal> evalInternal = do_QueryInterface(eval);
NS_ENSURE_STATE(evalInternal);
rv = nsXFormsUtils::EvaluateXPath(evalInternal, xp, aContextNode, mResolver,
mState, nsIDOMXPathResult::ANY_TYPE,
mCurPosition, mCurSize, nsnull,
getter_AddRefs(result));
@ -200,7 +216,7 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode,
xp.Length() - indexSize - 1); // remove final ')' too
nsCOMPtr<nsIDOMXPathResult> stringRes;
rv = nsXFormsUtils::EvaluateXPath(mEvaluator, indexExpr, aContextNode,
rv = nsXFormsUtils::EvaluateXPath(evalInternal, indexExpr, aContextNode,
mResolver, mState,
nsIDOMXPathResult::STRING_TYPE,
mCurPosition, mCurSize, nsnull,