diff --git a/extensions/xforms/nsIXFormsRepeatElement.idl b/extensions/xforms/nsIXFormsRepeatElement.idl index 3b6aac828ec..beee24ceaaf 100644 --- a/extensions/xforms/nsIXFormsRepeatElement.idl +++ b/extensions/xforms/nsIXFormsRepeatElement.idl @@ -43,6 +43,8 @@ #include "nsISupports.idl" +interface nsIXFormsControl; + [uuid(419e780d-4f31-4aa4-bae8-a18099d77bb6)] interface nsIXFormsRepeatElement : nsISupports { @@ -88,4 +90,20 @@ interface nsIXFormsRepeatElement : nsISupports */ void setCurrentRepeat(in nsIXFormsRepeatElement aCurrentRepeat, in unsigned long aIndex); + + /** + * Add user of repeat-index. The control will have Bind() and Refresh() + * called on it, when the index changes. + */ + void addIndexUser(in nsIXFormsControl aControl); + + /** + * Remove user of repeat-index. + */ + void removeIndexUser(in nsIXFormsControl aControl); + + /** + * Informs repeat-index users of index change. + */ + void indexHasChanged(); }; diff --git a/extensions/xforms/nsXFormsControlStub.cpp b/extensions/xforms/nsXFormsControlStub.cpp index 6674db71465..3bd4c0e05fe 100644 --- a/extensions/xforms/nsXFormsControlStub.cpp +++ b/extensions/xforms/nsXFormsControlStub.cpp @@ -41,6 +41,7 @@ #include "nsXFormsControlStub.h" #include "nsXFormsMDGEngine.h" +#include "nsIDOMDocument.h" #include "nsIDOMEvent.h" #include "nsIDOMKeyEvent.h" #include "nsIDOMEventTarget.h" @@ -106,10 +107,27 @@ nsXFormsControlStub::GetElement(nsIDOMElement **aElement) return NS_OK; } +void +nsXFormsControlStub::RemoveIndexListeners() +{ + if (!mIndexesUsed.Count()) + return; + + for (PRInt32 i = 0; i < mIndexesUsed.Count(); ++i) { + nsCOMPtr rep = mIndexesUsed[i]; + rep->RemoveIndexUser(this); + } + + mIndexesUsed.Clear(); +} + NS_IMETHODIMP nsXFormsControlStub::ResetBoundNode() { + // Clear existing bound node, etc. mBoundNode = nsnull; + mDependencies.Clear(); + RemoveIndexListeners(); if (!mHasParent || !mBindAttrsCount) return NS_OK; @@ -157,7 +175,7 @@ nsXFormsControlStub::ProcessNodeBinding(const nsString &aBindingAttr, nsIDOMXPathResult **aResult, nsIModelElementPrivate **aModel) { - mDependencies.Clear(); + nsStringArray indexesUsed; nsresult rv; rv = nsXFormsUtils::EvaluateNodeBinding(mElement, @@ -167,12 +185,32 @@ nsXFormsControlStub::ProcessNodeBinding(const nsString &aBindingAttr, aResultType, getter_AddRefs(mModel), aResult, - &mDependencies); + &mDependencies, + &indexesUsed); + NS_ENSURE_STATE(mModel); + + mModel->AddFormControl(this); + if (aModel) + NS_ADDREF(*aModel = mModel); - if (mModel) { - mModel->AddFormControl(this); - if (aModel) { - NS_ADDREF(*aModel = mModel); + if (NS_SUCCEEDED(rv) && indexesUsed.Count()) { + // add index listeners on repeat elements + nsCOMPtr doc; + mElement->GetOwnerDocument(getter_AddRefs(doc)); + NS_ENSURE_STATE(doc); + + for (PRInt32 i = 0; i < indexesUsed.Count(); ++i) { + // Find the repeat element and add |this| as a listener + nsCOMPtr repElem; + doc->GetElementById(*(indexesUsed[i]), getter_AddRefs(repElem)); + nsCOMPtr rep(do_QueryInterface(repElem)); + NS_ENSURE_STATE(rep); + rv = rep->AddIndexUser(this); + if (NS_FAILED(rv)) { + return rv; + } + rv = mIndexesUsed.AppendObject(rep); + NS_ENSURE_SUCCESS(rv, rv); } } @@ -314,6 +352,7 @@ NS_IMETHODIMP nsXFormsControlStub::OnDestroyed() { ResetHelpAndHint(PR_FALSE); + RemoveIndexListeners(); if (mModel) { mModel->RemoveFormControl(this); diff --git a/extensions/xforms/nsXFormsControlStub.h b/extensions/xforms/nsXFormsControlStub.h index 254bb92ea0f..27cf1e29e35 100644 --- a/extensions/xforms/nsXFormsControlStub.h +++ b/extensions/xforms/nsXFormsControlStub.h @@ -49,6 +49,7 @@ #include "nsIModelElementPrivate.h" #include "nsIXFormsControl.h" +#include "nsIXFormsRepeatElement.h" #include "nsXFormsStubElement.h" #include "nsXFormsUtils.h" @@ -143,22 +144,27 @@ public: protected: /** The nsIXTFXMLVisualWrapper */ - nsCOMPtr mElement; + nsCOMPtr mElement; /** The node that the control is bound to. */ - nsCOMPtr mBoundNode; + nsCOMPtr mBoundNode; /** Array of nsIDOMNodes that the control depends on. */ - nsCOMArray mDependencies; + nsCOMArray mDependencies; /** The model for the control */ - nsCOMPtr mModel; + nsCOMPtr mModel; /** This event listener is used to create xforms-hint and xforms-help events. */ - nsCOMPtr mEventListener; + nsCOMPtr mEventListener; /** State that tells whether control has a parent or not */ - PRBool mHasParent; + PRBool mHasParent; + + /** + * Array of repeat-elements of which the control uses repeat-index. + */ + nsCOMArray mIndexesUsed; /** * Used to keep track of whether this control has any single node binding @@ -219,6 +225,9 @@ protected: * @param aValue - value that the attribute is being changed to. */ void MaybeRemoveFromModel(nsIAtom *aName, const nsAString &aValue); + + /** Removes the index change event listeners */ + void RemoveIndexListeners(); }; #endif diff --git a/extensions/xforms/nsXFormsRepeatElement.cpp b/extensions/xforms/nsXFormsRepeatElement.cpp index 797591cc5d3..35cb2f0f3b0 100644 --- a/extensions/xforms/nsXFormsRepeatElement.cpp +++ b/extensions/xforms/nsXFormsRepeatElement.cpp @@ -232,6 +232,11 @@ protected: * The currently selected repeat (nested repeats) */ nsCOMPtr mCurrentRepeat; + + /** + * Array of controls using the repeat-index + */ + nsCOMArray mIndexUsers; /** * Retrieves an integer attribute and checks its type. @@ -369,6 +374,7 @@ NS_IMETHODIMP nsXFormsRepeatElement::OnDestroyed() { mHTMLElement = nsnull; + mIndexUsers.Clear(); return nsXFormsControlStub::OnDestroyed(); } @@ -490,6 +496,9 @@ nsXFormsRepeatElement::SetIndex(PRUint32 *aIndex, // Set current index to new value mCurrentIndex = *aIndex; + // Inform of index change + mParent ? mParent->IndexHasChanged() : IndexHasChanged(); + return NS_OK; } @@ -532,6 +541,42 @@ nsXFormsRepeatElement::SetCurrentRepeat(nsIXFormsRepeatElement *aRepeat, return NS_OK; } + +NS_IMETHODIMP +nsXFormsRepeatElement::AddIndexUser(nsIXFormsControl *aControl) +{ + nsresult rv = NS_OK; + if (mIndexUsers.IndexOf(aControl) == -1 && !mIndexUsers.AppendObject(aControl)) + rv = NS_ERROR_FAILURE; + + return rv; +} + +NS_IMETHODIMP +nsXFormsRepeatElement::RemoveIndexUser(nsIXFormsControl *aControl) +{ + return mIndexUsers.RemoveObject(aControl) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsXFormsRepeatElement::IndexHasChanged() +{ + /// + /// @bug We need to handle \ elements too (XXX) + + // copy the index array, as index users might add/remove themselves when + // they are rebound and refreshed(). + nsCOMArray indexes(mIndexUsers); + + for (PRInt32 i = 0; i < indexes.Count(); ++i) { + nsCOMPtr control = indexes[i]; + control->Bind(); + control->Refresh(); + } + + return NS_OK; +} + // NB: CloneNode() assumes that this always succeeds NS_IMETHODIMP nsXFormsRepeatElement::GetIsParent(PRBool *aIsParent) diff --git a/extensions/xforms/nsXFormsUtils.cpp b/extensions/xforms/nsXFormsUtils.cpp index d181b5df2ee..2473b8fb348 100644 --- a/extensions/xforms/nsXFormsUtils.cpp +++ b/extensions/xforms/nsXFormsUtils.cpp @@ -279,49 +279,64 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement, *aContextSize = 1; if (aContextPosition) *aContextPosition = 1; - - return FindBindContext(*aBindElement, - aOuterBind, - aModel, - aContextNode); - } - if (aElementFlags & ELEMENT_WITH_MODEL_ATTR) { - // CASE 2: Use @model - // If bind did not set model, and the element has a model attribute we use this - nsAutoString modelId; - NS_NAMED_LITERAL_STRING(modelStr, "model"); - aElement->GetAttribute(modelStr, modelId); - - if (!modelId.IsEmpty()) { - nsCOMPtr modelElement; - domDoc->GetElementById(modelId, getter_AddRefs(modelElement)); - nsCOMPtr model = do_QueryInterface(modelElement); + *aOuterBind = GetParentModel(*aBindElement, aModel); + NS_ENSURE_STATE(*aModel); + } else { + if (aElementFlags & ELEMENT_WITH_MODEL_ATTR) { + // CASE 2: Use @model + // If bind did not set model, and the element has a model attribute we use this + nsAutoString modelId; + NS_NAMED_LITERAL_STRING(modelStr, "model"); + aElement->GetAttribute(modelStr, modelId); - // No element found, or element not a \ element - if (!model) { - const PRUnichar *strings[] = { modelId.get(), modelStr.get() }; - nsXFormsUtils::ReportError(NS_LITERAL_STRING("idRefError"), - strings, 2, aElement, aElement); - nsXFormsUtils::DispatchEvent(aElement, eEvent_BindingException); - return NS_ERROR_FAILURE; + if (!modelId.IsEmpty()) { + nsCOMPtr modelElement; + domDoc->GetElementById(modelId, getter_AddRefs(modelElement)); + nsCOMPtr model = do_QueryInterface(modelElement); + + // No element found, or element not a \ element + if (!model) { + const PRUnichar *strings[] = { modelId.get(), modelStr.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("idRefError"), + strings, 2, aElement, aElement); + nsXFormsUtils::DispatchEvent(aElement, eEvent_BindingException); + return NS_ERROR_FAILURE; + } + + NS_ADDREF(*aModel = model); } - - NS_ADDREF(*aModel = model); } + + // Search for a parent setting context for us + nsresult rv = FindParentContext(aElement, + aModel, + aContextNode, + aContextPosition, + aContextSize); + // CASE 3/4: Use parent's model / first model in document. + // If FindParentContext() does not find a parent context but |aModel| is not + // set, it sets the model to the first model in the document. + + NS_ENSURE_SUCCESS(rv, rv); } - // Search for a parent setting context for us - nsresult rv = FindParentContext(aElement, - aModel, - aContextNode, - aContextPosition, - aContextSize); - // CASE 3/4: Use parent's model / first model in document. - // If FindParentContext() does not find a parent context but |aModel| is not - // set, it sets the model to the first model in the document. - - NS_ENSURE_SUCCESS(rv, rv); + // if context node is not set, it's the document element of the model's + // default instance + if (!*aContextNode) { + nsCOMPtr modelInt = do_QueryInterface(*aModel); + NS_ENSURE_STATE(modelInt); + + nsCOMPtr instanceDoc; + modelInt->GetInstanceDocument(NS_LITERAL_STRING(""), + getter_AddRefs(instanceDoc)); + NS_ENSURE_STATE(instanceDoc); + + nsIDOMElement* docElement; + instanceDoc->GetDocumentElement(&docElement); // addrefs + NS_ENSURE_STATE(docElement); + *aContextNode = docElement; // addref'ed above + } return NS_OK; } @@ -358,7 +373,8 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression, PRUint16 aResultType, PRInt32 aContextPosition, PRInt32 aContextSize, - nsCOMArray *aSet) + nsCOMArray *aSet, + nsStringArray *aIndexesUsed) { nsCOMPtr doc; aContextNode->GetOwnerDocument(getter_AddRefs(doc)); @@ -397,13 +413,15 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression, nsXFormsXPathParser parser; nsXFormsXPathAnalyzer analyzer(eval, aResolverNode); nsAutoPtr xNode(parser.Parse(aExpression)); - rv = analyzer.Analyze(aContextNode, xNode, expression, &aExpression, aSet); NS_ENSURE_SUCCESS(rv, nsnull); + + if (aIndexesUsed) + *aIndexesUsed = analyzer.IndexesUsed(); } CallQueryInterface(supResult, &result); // addrefs } @@ -421,36 +439,6 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression, return result; } -/* static */ nsresult -nsXFormsUtils::FindBindContext(nsIDOMElement *aBindElement, - PRBool *aOuterBind, - nsIModelElementPrivate **aModel, - nsIDOMNode **aContextNode) -{ - NS_ENSURE_ARG_POINTER(aContextNode); - *aContextNode = nsnull; - - // 1) Find the model for the bind - *aOuterBind = GetParentModel(aBindElement, aModel); - NS_ENSURE_STATE(*aModel); - - // 2) Find the context node - nsCOMPtr modelInt = do_QueryInterface(*aModel); - NS_ENSURE_STATE(modelInt); - - nsCOMPtr instanceDoc; - modelInt->GetInstanceDocument(NS_LITERAL_STRING(""), - getter_AddRefs(instanceDoc)); - NS_ENSURE_STATE(instanceDoc); - - nsIDOMElement* docElement; - instanceDoc->GetDocumentElement(&docElement); // addrefs - NS_ENSURE_STATE(docElement); - *aContextNode = docElement; // addref'ed above - - return NS_OK; -} - /* static */ nsresult nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, PRUint32 aElementFlags, @@ -459,7 +447,8 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, PRUint16 aResultType, nsIModelElementPrivate **aModel, nsIDOMXPathResult **aResult, - nsCOMArray *aDeps) + nsCOMArray *aDeps, + nsStringArray *aIndexesUsed) { if (!aElement || !aModel || !aResult) { return NS_OK; @@ -484,6 +473,10 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, NS_ENSURE_SUCCESS(rv, rv); + if (!contextNode) { + return NS_OK; // this will happen if the doc is still loading + } + nsAutoString expr; if (bindElement) { if (!outerBind) { @@ -507,26 +500,6 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, return NS_OK; expr.Assign(aDefaultRef); - } - - if (!contextNode) { - nsCOMPtr instanceDoc; - nsCOMPtr model = do_QueryInterface(*aModel); - - NS_ENSURE_STATE(model); // The referenced model is not actually a model element, or does not exist. - - model->GetInstanceDocument(NS_LITERAL_STRING(""), - getter_AddRefs(instanceDoc)); - - NS_ENSURE_STATE(instanceDoc); - - nsCOMPtr docElement; - instanceDoc->GetDocumentElement(getter_AddRefs(docElement)); - contextNode = docElement; - - if (!contextNode) { - return NS_OK; // this will happen if the doc is still loading - } } } @@ -537,7 +510,8 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, aResultType, contextSize, contextPosition, - aDeps); + aDeps, + aIndexesUsed); res.swap(*aResult); // exchanges ref diff --git a/extensions/xforms/nsXFormsUtils.h b/extensions/xforms/nsXFormsUtils.h index 775af3f4184..d0ec9275848 100644 --- a/extensions/xforms/nsXFormsUtils.h +++ b/extensions/xforms/nsXFormsUtils.h @@ -47,6 +47,7 @@ #include "nsIDOMXPathResult.h" #include "nsIModelElementPrivate.h" #include "nsIScriptError.h" +#include "nsVoidArray.h" class nsIDOMElement; class nsIXFormsModelElement; @@ -210,18 +211,9 @@ public: PRUint16 aResultType, nsIModelElementPrivate **aModel, nsIDOMXPathResult **aResult, - nsCOMArray *aDeps = nsnull); + nsCOMArray *aDeps = nsnull, + nsStringArray *aIndexesUsed = nsnull); - /** - * Given a bind element |aBindElement|, find the model and the context node - * for it. |aOuterBind| tells whether the bind element is an outermost bind. - */ - static NS_HIDDEN_(nsresult) - FindBindContext(nsIDOMElement *aBindElement, - PRBool *aOuterBind, - nsIModelElementPrivate **aModel, - nsIDOMNode **aContextNode); - /** * Convenience method for doing XPath evaluations. This gets a * nsIXFormsXPathEvaluator from |aContextNode|'s ownerDocument, and calls @@ -235,7 +227,8 @@ public: PRUint16 aResultType, PRInt32 aContextPosition = 1, PRInt32 aContextSize = 1, - nsCOMArray *aSet = nsnull); + nsCOMArray *aSet = nsnull, + nsStringArray *aIndexesUsed = nsnull); /** * Given a node in the instance data, get its string value according diff --git a/extensions/xforms/nsXFormsXPathAnalyzer.cpp b/extensions/xforms/nsXFormsXPathAnalyzer.cpp index 2a3465d66d1..5ad026d2ea4 100644 --- a/extensions/xforms/nsXFormsXPathAnalyzer.cpp +++ b/extensions/xforms/nsXFormsXPathAnalyzer.cpp @@ -47,11 +47,9 @@ MOZ_DECL_CTOR_COUNTER(nsXFormsXPathAnalyzer) -nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer( - nsIXFormsXPathEvaluator *aEvaluator, - nsIDOMNode *aResolver) - : mEvaluator(aEvaluator), - mResolver(aResolver) +nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer(nsIXFormsXPathEvaluator *aEvaluator, + nsIDOMNode *aResolver) + : mEvaluator(aEvaluator), mResolver(aResolver) { MOZ_COUNT_CTOR(nsXFormsXPathAnalyzer); } @@ -119,6 +117,7 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode, printf("\tChild: %p, Sibling: %p\n", (void*) aNode->mChild, (void*) aNode->mSibling); printf("\tIndex: %d - %d\n", aNode->mStartIndex, aNode->mEndIndex); printf("\tCon: %d, Predicate: %d, Literal: %d\n", aNode->mCon, aNode->mPredicate, aNode->mLiteral); + printf("\tIsIndex: %d\n", aNode->mIsIndex); #endif if (aNode->mEndIndex < 0 || aNode->mStartIndex >= aNode->mEndIndex) { @@ -176,6 +175,24 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode, rv = result->GetResultType(&type); NS_ENSURE_SUCCESS(rv, rv); + if (aNode->mIsIndex) { + // Extract index parameter, xp is "index(parameter)" + const PRUint32 indexSize = sizeof("index(") - 1; + nsDependentSubstring indexExpr = Substring(xp, + indexSize, + xp.Length() - indexSize - 1); // remove final ')' too + nsCOMPtr stringRes; + rv = mEvaluator->Evaluate(indexExpr, aContextNode, mResolver, + nsIDOMXPathResult::STRING_TYPE, + nsnull, getter_AddRefs(stringRes)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString indexId; + rv = stringRes->GetStringValue(indexId); + NS_ENSURE_SUCCESS(rv, rv); + mIndexesUsed.AppendString(indexId); + } + // We are only interested in nodes if ( type != nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE && type != nsIDOMXPathResult::ORDERED_NODE_ITERATOR_TYPE) { @@ -204,3 +221,9 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode, } return NS_OK; } + +const nsStringArray& +nsXFormsXPathAnalyzer::IndexesUsed() const +{ + return mIndexesUsed; +} diff --git a/extensions/xforms/nsXFormsXPathAnalyzer.h b/extensions/xforms/nsXFormsXPathAnalyzer.h index 85d00c3c923..41ee71c29e6 100644 --- a/extensions/xforms/nsXFormsXPathAnalyzer.h +++ b/extensions/xforms/nsXFormsXPathAnalyzer.h @@ -47,6 +47,7 @@ #include "nsIDOMNode.h" #include "nsCOMPtr.h" #include "nsString.h" +#include "nsVoidArray.h" /** * This class analyzes an XPath Expression parse tree (nsXFormsXPathNode), and @@ -58,11 +59,12 @@ class nsXFormsXPathAnalyzer { private: nsCOMPtr mEvaluator; - nsCOMPtr mResolver; + nsCOMPtr mResolver; - nsCOMArray *mCurSet; - nsCOMPtr mCurExpression; - const nsAString *mCurExprString; + nsCOMArray *mCurSet; + nsCOMPtr mCurExpression; + const nsAString *mCurExprString; + nsStringArray mIndexesUsed; nsresult AnalyzeRecursively(nsIDOMNode *aContextNode, const nsXFormsXPathNode *aNode, @@ -78,4 +80,6 @@ public: nsIDOMXPathExpression *aExpression, const nsAString *aExprString, nsCOMArray *aSet); + + const nsStringArray& IndexesUsed() const; }; diff --git a/extensions/xforms/nsXFormsXPathNode.cpp b/extensions/xforms/nsXFormsXPathNode.cpp index e6774b05b84..00340e73591 100644 --- a/extensions/xforms/nsXFormsXPathNode.cpp +++ b/extensions/xforms/nsXFormsXPathNode.cpp @@ -43,7 +43,7 @@ MOZ_DECL_CTOR_COUNTER(nsXFormsXPathNode) nsXFormsXPathNode::nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue) - : mChild(nsnull), mEndIndex(-100), mCon(aContinue) + : mChild(nsnull), mEndIndex(-100), mCon(aContinue), mIsIndex(PR_FALSE) { MOZ_COUNT_CTOR(nsXFormsXPathNode); diff --git a/extensions/xforms/nsXFormsXPathNode.h b/extensions/xforms/nsXFormsXPathNode.h index b122e0aa6a4..7cd91522f63 100644 --- a/extensions/xforms/nsXFormsXPathNode.h +++ b/extensions/xforms/nsXFormsXPathNode.h @@ -56,6 +56,7 @@ public: PRBool mCon; PRBool mPredicate; PRBool mLiteral; + PRBool mIsIndex; nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue = PR_FALSE); ~nsXFormsXPathNode(); diff --git a/extensions/xforms/nsXFormsXPathParser.cpp b/extensions/xforms/nsXFormsXPathParser.cpp index cfb500f9943..a71df1c8054 100644 --- a/extensions/xforms/nsXFormsXPathParser.cpp +++ b/extensions/xforms/nsXFormsXPathParser.cpp @@ -354,12 +354,13 @@ nsXFormsXPathParser::FilterExpr() void nsXFormsXPathParser::FunctionCall() { - if (!mUsesDynamicFunc) { - nsDependentSubstring fname = Substring(mScanner.Expression(), mScanner.Offset() + 1, mScanner.Offset() + mScanner.Length() + 1); - if (fname.Equals(NS_LITERAL_STRING("now"))) { - mUsesDynamicFunc = PR_TRUE; - } + nsDependentSubstring fname = Substring(mScanner.Expression(), + mScanner.Offset() + 1, + mScanner.Length()); + if (!mUsesDynamicFunc && fname.Equals(NS_LITERAL_STRING("now"))) { + mUsesDynamicFunc = PR_TRUE; } + PopToken(); PopToken(); nsXFormsXPathScanner::XPATHTOKEN t = PeekToken(); @@ -367,18 +368,22 @@ nsXFormsXPathParser::FunctionCall() PRBool con = t == nsXFormsXPathScanner::RPARAN ? PR_FALSE : PR_TRUE; while (con) { if (t == nsXFormsXPathScanner::XPATHEOF) { - XPathCompilerException("Expected ) got EOF", mScanner.Expression(), mScanner.Offset(), mScanner.Length()); + XPathCompilerException("Expected ) got EOF", + mScanner.Expression(), + mScanner.Offset(), + mScanner.Length()); } nsXFormsXPathNode* c = JustContext(); Expr(); + if (fname.Equals(NS_LITERAL_STRING("index"))) { + c->mIsIndex = PR_TRUE; + } PushContext(c); t = PeekToken(); - if (t == nsXFormsXPathScanner::COMMA) { + con = (t == nsXFormsXPathScanner::COMMA); + if (con) { PopToken(); // Another Argument - con = PR_TRUE; - } else { - con = PR_FALSE; } }