From f2c58ee2fb0b67fc0fec03c7251adc3768ca18bb Mon Sep 17 00:00:00 2001 From: "aaronr%us.ibm.com" Date: Sun, 20 Aug 2006 20:46:15 +0000 Subject: [PATCH] [XForms] XPath expression errors when expr spans mult instances. Bug 348993, r=doronr+olli git-svn-id: svn://10.0.0.236/trunk@207966 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xforms/nsXFormsModelElement.cpp | 83 ++++++++++++++----- mozilla/extensions/xforms/nsXFormsUtils.cpp | 4 + .../xforms/nsXFormsXPathAnalyzer.cpp | 20 ++++- 3 files changed, 85 insertions(+), 22 deletions(-) diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.cpp b/mozilla/extensions/xforms/nsXFormsModelElement.cpp index c23a8bee8e8..d266ca216df 100644 --- a/mozilla/extensions/xforms/nsXFormsModelElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsModelElement.cpp @@ -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 deps; nsCOMPtr 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 nodesetDoc; + node->GetOwnerDocument(getter_AddRefs(nodesetDoc)); + + nsCOMPtr nodesetEval = do_QueryInterface(nodesetDoc); + nsCOMPtr 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 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; diff --git a/mozilla/extensions/xforms/nsXFormsUtils.cpp b/mozilla/extensions/xforms/nsXFormsUtils.cpp index 4348eed2368..ab9c62a22e7 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.cpp +++ b/mozilla/extensions/xforms/nsXFormsUtils.cpp @@ -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 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 supResult; rv = nsExpression->EvaluateWithContext(aContextNode, aContextPosition, aContextSize, aResultType, diff --git a/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.cpp b/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.cpp index 992d646bea9..6a8faa0aedf 100644 --- a/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.cpp +++ b/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.cpp @@ -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 doc; + aContextNode->GetOwnerDocument(getter_AddRefs(doc)); + nsCOMPtr eval = do_QueryInterface(doc); + nsCOMPtr 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 stringRes; - rv = nsXFormsUtils::EvaluateXPath(mEvaluator, indexExpr, aContextNode, + rv = nsXFormsUtils::EvaluateXPath(evalInternal, indexExpr, aContextNode, mResolver, mState, nsIDOMXPathResult::STRING_TYPE, mCurPosition, mCurSize, nsnull,