Let controls using index() listen for changes to repeat indexes. Bug 289534, r=smaug+doronr, a=mkaply, NPOTB

This commit is contained in:
allan%beaufour.dk 2005-04-28 07:17:49 +00:00
Родитель 2d9c8da55d
Коммит c553b66916
11 изменённых файлов: 246 добавлений и 135 удалений

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

@ -43,6 +43,8 @@
#include "nsISupports.idl" #include "nsISupports.idl"
interface nsIXFormsControl;
[uuid(419e780d-4f31-4aa4-bae8-a18099d77bb6)] [uuid(419e780d-4f31-4aa4-bae8-a18099d77bb6)]
interface nsIXFormsRepeatElement : nsISupports interface nsIXFormsRepeatElement : nsISupports
{ {
@ -88,4 +90,20 @@ interface nsIXFormsRepeatElement : nsISupports
*/ */
void setCurrentRepeat(in nsIXFormsRepeatElement aCurrentRepeat, void setCurrentRepeat(in nsIXFormsRepeatElement aCurrentRepeat,
in unsigned long aIndex); 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();
}; };

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

@ -41,6 +41,7 @@
#include "nsXFormsControlStub.h" #include "nsXFormsControlStub.h"
#include "nsXFormsMDGEngine.h" #include "nsXFormsMDGEngine.h"
#include "nsIDOMDocument.h"
#include "nsIDOMEvent.h" #include "nsIDOMEvent.h"
#include "nsIDOMKeyEvent.h" #include "nsIDOMKeyEvent.h"
#include "nsIDOMEventTarget.h" #include "nsIDOMEventTarget.h"
@ -106,10 +107,27 @@ nsXFormsControlStub::GetElement(nsIDOMElement **aElement)
return NS_OK; return NS_OK;
} }
void
nsXFormsControlStub::RemoveIndexListeners()
{
if (!mIndexesUsed.Count())
return;
for (PRInt32 i = 0; i < mIndexesUsed.Count(); ++i) {
nsCOMPtr<nsIXFormsRepeatElement> rep = mIndexesUsed[i];
rep->RemoveIndexUser(this);
}
mIndexesUsed.Clear();
}
NS_IMETHODIMP NS_IMETHODIMP
nsXFormsControlStub::ResetBoundNode() nsXFormsControlStub::ResetBoundNode()
{ {
// Clear existing bound node, etc.
mBoundNode = nsnull; mBoundNode = nsnull;
mDependencies.Clear();
RemoveIndexListeners();
if (!mHasParent || !mBindAttrsCount) if (!mHasParent || !mBindAttrsCount)
return NS_OK; return NS_OK;
@ -157,7 +175,7 @@ nsXFormsControlStub::ProcessNodeBinding(const nsString &aBindingAttr,
nsIDOMXPathResult **aResult, nsIDOMXPathResult **aResult,
nsIModelElementPrivate **aModel) nsIModelElementPrivate **aModel)
{ {
mDependencies.Clear(); nsStringArray indexesUsed;
nsresult rv; nsresult rv;
rv = nsXFormsUtils::EvaluateNodeBinding(mElement, rv = nsXFormsUtils::EvaluateNodeBinding(mElement,
@ -167,12 +185,32 @@ nsXFormsControlStub::ProcessNodeBinding(const nsString &aBindingAttr,
aResultType, aResultType,
getter_AddRefs(mModel), getter_AddRefs(mModel),
aResult, aResult,
&mDependencies); &mDependencies,
&indexesUsed);
NS_ENSURE_STATE(mModel);
mModel->AddFormControl(this);
if (aModel)
NS_ADDREF(*aModel = mModel);
if (mModel) { if (NS_SUCCEEDED(rv) && indexesUsed.Count()) {
mModel->AddFormControl(this); // add index listeners on repeat elements
if (aModel) { nsCOMPtr<nsIDOMDocument> doc;
NS_ADDREF(*aModel = mModel); 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<nsIDOMElement> repElem;
doc->GetElementById(*(indexesUsed[i]), getter_AddRefs(repElem));
nsCOMPtr<nsIXFormsRepeatElement> 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() nsXFormsControlStub::OnDestroyed()
{ {
ResetHelpAndHint(PR_FALSE); ResetHelpAndHint(PR_FALSE);
RemoveIndexListeners();
if (mModel) { if (mModel) {
mModel->RemoveFormControl(this); mModel->RemoveFormControl(this);

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

@ -49,6 +49,7 @@
#include "nsIModelElementPrivate.h" #include "nsIModelElementPrivate.h"
#include "nsIXFormsControl.h" #include "nsIXFormsControl.h"
#include "nsIXFormsRepeatElement.h"
#include "nsXFormsStubElement.h" #include "nsXFormsStubElement.h"
#include "nsXFormsUtils.h" #include "nsXFormsUtils.h"
@ -143,22 +144,27 @@ public:
protected: protected:
/** The nsIXTFXMLVisualWrapper */ /** The nsIXTFXMLVisualWrapper */
nsCOMPtr<nsIDOMElement> mElement; nsCOMPtr<nsIDOMElement> mElement;
/** The node that the control is bound to. */ /** The node that the control is bound to. */
nsCOMPtr<nsIDOMNode> mBoundNode; nsCOMPtr<nsIDOMNode> mBoundNode;
/** Array of nsIDOMNodes that the control depends on. */ /** Array of nsIDOMNodes that the control depends on. */
nsCOMArray<nsIDOMNode> mDependencies; nsCOMArray<nsIDOMNode> mDependencies;
/** The model for the control */ /** The model for the control */
nsCOMPtr<nsIModelElementPrivate> mModel; nsCOMPtr<nsIModelElementPrivate> mModel;
/** This event listener is used to create xforms-hint and xforms-help events. */ /** This event listener is used to create xforms-hint and xforms-help events. */
nsCOMPtr<nsIDOMEventListener> mEventListener; nsCOMPtr<nsIDOMEventListener> mEventListener;
/** State that tells whether control has a parent or not */ /** 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<nsIXFormsRepeatElement> mIndexesUsed;
/** /**
* Used to keep track of whether this control has any single node binding * 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. * @param aValue - value that the attribute is being changed to.
*/ */
void MaybeRemoveFromModel(nsIAtom *aName, const nsAString &aValue); void MaybeRemoveFromModel(nsIAtom *aName, const nsAString &aValue);
/** Removes the index change event listeners */
void RemoveIndexListeners();
}; };
#endif #endif

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

@ -232,6 +232,11 @@ protected:
* The currently selected repeat (nested repeats) * The currently selected repeat (nested repeats)
*/ */
nsCOMPtr<nsIXFormsRepeatElement> mCurrentRepeat; nsCOMPtr<nsIXFormsRepeatElement> mCurrentRepeat;
/**
* Array of controls using the repeat-index
*/
nsCOMArray<nsIXFormsControl> mIndexUsers;
/** /**
* Retrieves an integer attribute and checks its type. * Retrieves an integer attribute and checks its type.
@ -369,6 +374,7 @@ NS_IMETHODIMP
nsXFormsRepeatElement::OnDestroyed() nsXFormsRepeatElement::OnDestroyed()
{ {
mHTMLElement = nsnull; mHTMLElement = nsnull;
mIndexUsers.Clear();
return nsXFormsControlStub::OnDestroyed(); return nsXFormsControlStub::OnDestroyed();
} }
@ -490,6 +496,9 @@ nsXFormsRepeatElement::SetIndex(PRUint32 *aIndex,
// Set current index to new value // Set current index to new value
mCurrentIndex = *aIndex; mCurrentIndex = *aIndex;
// Inform of index change
mParent ? mParent->IndexHasChanged() : IndexHasChanged();
return NS_OK; return NS_OK;
} }
@ -532,6 +541,42 @@ nsXFormsRepeatElement::SetCurrentRepeat(nsIXFormsRepeatElement *aRepeat,
return NS_OK; 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 \<bind\> elements too (XXX)
// copy the index array, as index users might add/remove themselves when
// they are rebound and refreshed().
nsCOMArray<nsIXFormsControl> indexes(mIndexUsers);
for (PRInt32 i = 0; i < indexes.Count(); ++i) {
nsCOMPtr<nsIXFormsControl> control = indexes[i];
control->Bind();
control->Refresh();
}
return NS_OK;
}
// NB: CloneNode() assumes that this always succeeds // NB: CloneNode() assumes that this always succeeds
NS_IMETHODIMP NS_IMETHODIMP
nsXFormsRepeatElement::GetIsParent(PRBool *aIsParent) nsXFormsRepeatElement::GetIsParent(PRBool *aIsParent)

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

@ -279,49 +279,64 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement,
*aContextSize = 1; *aContextSize = 1;
if (aContextPosition) if (aContextPosition)
*aContextPosition = 1; *aContextPosition = 1;
return FindBindContext(*aBindElement,
aOuterBind,
aModel,
aContextNode);
}
if (aElementFlags & ELEMENT_WITH_MODEL_ATTR) { *aOuterBind = GetParentModel(*aBindElement, aModel);
// CASE 2: Use @model NS_ENSURE_STATE(*aModel);
// If bind did not set model, and the element has a model attribute we use this } else {
nsAutoString modelId; if (aElementFlags & ELEMENT_WITH_MODEL_ATTR) {
NS_NAMED_LITERAL_STRING(modelStr, "model"); // CASE 2: Use @model
aElement->GetAttribute(modelStr, modelId); // If bind did not set model, and the element has a model attribute we use this
nsAutoString modelId;
if (!modelId.IsEmpty()) { NS_NAMED_LITERAL_STRING(modelStr, "model");
nsCOMPtr<nsIDOMElement> modelElement; aElement->GetAttribute(modelStr, modelId);
domDoc->GetElementById(modelId, getter_AddRefs(modelElement));
nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelElement);
// No element found, or element not a \<model\> element if (!modelId.IsEmpty()) {
if (!model) { nsCOMPtr<nsIDOMElement> modelElement;
const PRUnichar *strings[] = { modelId.get(), modelStr.get() }; domDoc->GetElementById(modelId, getter_AddRefs(modelElement));
nsXFormsUtils::ReportError(NS_LITERAL_STRING("idRefError"), nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelElement);
strings, 2, aElement, aElement);
nsXFormsUtils::DispatchEvent(aElement, eEvent_BindingException); // No element found, or element not a \<model\> element
return NS_ERROR_FAILURE; 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 // if context node is not set, it's the document element of the model's
nsresult rv = FindParentContext(aElement, // default instance
aModel, if (!*aContextNode) {
aContextNode, nsCOMPtr<nsIXFormsModelElement> modelInt = do_QueryInterface(*aModel);
aContextPosition, NS_ENSURE_STATE(modelInt);
aContextSize);
// CASE 3/4: Use parent's model / first model in document. nsCOMPtr<nsIDOMDocument> instanceDoc;
// If FindParentContext() does not find a parent context but |aModel| is not modelInt->GetInstanceDocument(NS_LITERAL_STRING(""),
// set, it sets the model to the first model in the document. getter_AddRefs(instanceDoc));
NS_ENSURE_STATE(instanceDoc);
NS_ENSURE_SUCCESS(rv, rv);
nsIDOMElement* docElement;
instanceDoc->GetDocumentElement(&docElement); // addrefs
NS_ENSURE_STATE(docElement);
*aContextNode = docElement; // addref'ed above
}
return NS_OK; return NS_OK;
} }
@ -358,7 +373,8 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
PRUint16 aResultType, PRUint16 aResultType,
PRInt32 aContextPosition, PRInt32 aContextPosition,
PRInt32 aContextSize, PRInt32 aContextSize,
nsCOMArray<nsIDOMNode> *aSet) nsCOMArray<nsIDOMNode> *aSet,
nsStringArray *aIndexesUsed)
{ {
nsCOMPtr<nsIDOMDocument> doc; nsCOMPtr<nsIDOMDocument> doc;
aContextNode->GetOwnerDocument(getter_AddRefs(doc)); aContextNode->GetOwnerDocument(getter_AddRefs(doc));
@ -397,13 +413,15 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
nsXFormsXPathParser parser; nsXFormsXPathParser parser;
nsXFormsXPathAnalyzer analyzer(eval, aResolverNode); nsXFormsXPathAnalyzer analyzer(eval, aResolverNode);
nsAutoPtr<nsXFormsXPathNode> xNode(parser.Parse(aExpression)); nsAutoPtr<nsXFormsXPathNode> xNode(parser.Parse(aExpression));
rv = analyzer.Analyze(aContextNode, rv = analyzer.Analyze(aContextNode,
xNode, xNode,
expression, expression,
&aExpression, &aExpression,
aSet); aSet);
NS_ENSURE_SUCCESS(rv, nsnull); NS_ENSURE_SUCCESS(rv, nsnull);
if (aIndexesUsed)
*aIndexesUsed = analyzer.IndexesUsed();
} }
CallQueryInterface(supResult, &result); // addrefs CallQueryInterface(supResult, &result); // addrefs
} }
@ -421,36 +439,6 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
return result; 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<nsIXFormsModelElement> modelInt = do_QueryInterface(*aModel);
NS_ENSURE_STATE(modelInt);
nsCOMPtr<nsIDOMDocument> 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 /* static */ nsresult
nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
PRUint32 aElementFlags, PRUint32 aElementFlags,
@ -459,7 +447,8 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
PRUint16 aResultType, PRUint16 aResultType,
nsIModelElementPrivate **aModel, nsIModelElementPrivate **aModel,
nsIDOMXPathResult **aResult, nsIDOMXPathResult **aResult,
nsCOMArray<nsIDOMNode> *aDeps) nsCOMArray<nsIDOMNode> *aDeps,
nsStringArray *aIndexesUsed)
{ {
if (!aElement || !aModel || !aResult) { if (!aElement || !aModel || !aResult) {
return NS_OK; return NS_OK;
@ -484,6 +473,10 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (!contextNode) {
return NS_OK; // this will happen if the doc is still loading
}
nsAutoString expr; nsAutoString expr;
if (bindElement) { if (bindElement) {
if (!outerBind) { if (!outerBind) {
@ -507,26 +500,6 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
return NS_OK; return NS_OK;
expr.Assign(aDefaultRef); expr.Assign(aDefaultRef);
}
if (!contextNode) {
nsCOMPtr<nsIDOMDocument> instanceDoc;
nsCOMPtr<nsIXFormsModelElement> 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<nsIDOMElement> 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, aResultType,
contextSize, contextSize,
contextPosition, contextPosition,
aDeps); aDeps,
aIndexesUsed);
res.swap(*aResult); // exchanges ref res.swap(*aResult); // exchanges ref

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

@ -47,6 +47,7 @@
#include "nsIDOMXPathResult.h" #include "nsIDOMXPathResult.h"
#include "nsIModelElementPrivate.h" #include "nsIModelElementPrivate.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsVoidArray.h"
class nsIDOMElement; class nsIDOMElement;
class nsIXFormsModelElement; class nsIXFormsModelElement;
@ -210,18 +211,9 @@ public:
PRUint16 aResultType, PRUint16 aResultType,
nsIModelElementPrivate **aModel, nsIModelElementPrivate **aModel,
nsIDOMXPathResult **aResult, nsIDOMXPathResult **aResult,
nsCOMArray<nsIDOMNode> *aDeps = nsnull); nsCOMArray<nsIDOMNode> *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 * Convenience method for doing XPath evaluations. This gets a
* nsIXFormsXPathEvaluator from |aContextNode|'s ownerDocument, and calls * nsIXFormsXPathEvaluator from |aContextNode|'s ownerDocument, and calls
@ -235,7 +227,8 @@ public:
PRUint16 aResultType, PRUint16 aResultType,
PRInt32 aContextPosition = 1, PRInt32 aContextPosition = 1,
PRInt32 aContextSize = 1, PRInt32 aContextSize = 1,
nsCOMArray<nsIDOMNode> *aSet = nsnull); nsCOMArray<nsIDOMNode> *aSet = nsnull,
nsStringArray *aIndexesUsed = nsnull);
/** /**
* Given a node in the instance data, get its string value according * Given a node in the instance data, get its string value according

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

@ -47,11 +47,9 @@
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathAnalyzer) MOZ_DECL_CTOR_COUNTER(nsXFormsXPathAnalyzer)
nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer( nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer(nsIXFormsXPathEvaluator *aEvaluator,
nsIXFormsXPathEvaluator *aEvaluator, nsIDOMNode *aResolver)
nsIDOMNode *aResolver) : mEvaluator(aEvaluator), mResolver(aResolver)
: mEvaluator(aEvaluator),
mResolver(aResolver)
{ {
MOZ_COUNT_CTOR(nsXFormsXPathAnalyzer); 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("\tChild: %p, Sibling: %p\n", (void*) aNode->mChild, (void*) aNode->mSibling);
printf("\tIndex: %d - %d\n", aNode->mStartIndex, aNode->mEndIndex); printf("\tIndex: %d - %d\n", aNode->mStartIndex, aNode->mEndIndex);
printf("\tCon: %d, Predicate: %d, Literal: %d\n", aNode->mCon, aNode->mPredicate, aNode->mLiteral); printf("\tCon: %d, Predicate: %d, Literal: %d\n", aNode->mCon, aNode->mPredicate, aNode->mLiteral);
printf("\tIsIndex: %d\n", aNode->mIsIndex);
#endif #endif
if (aNode->mEndIndex < 0 || aNode->mStartIndex >= aNode->mEndIndex) { if (aNode->mEndIndex < 0 || aNode->mStartIndex >= aNode->mEndIndex) {
@ -176,6 +175,24 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode,
rv = result->GetResultType(&type); rv = result->GetResultType(&type);
NS_ENSURE_SUCCESS(rv, rv); 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<nsIDOMXPathResult> 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 // We are only interested in nodes
if ( type != nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE if ( type != nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE
&& type != nsIDOMXPathResult::ORDERED_NODE_ITERATOR_TYPE) { && type != nsIDOMXPathResult::ORDERED_NODE_ITERATOR_TYPE) {
@ -204,3 +221,9 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode,
} }
return NS_OK; return NS_OK;
} }
const nsStringArray&
nsXFormsXPathAnalyzer::IndexesUsed() const
{
return mIndexesUsed;
}

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

@ -47,6 +47,7 @@
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsString.h" #include "nsString.h"
#include "nsVoidArray.h"
/** /**
* This class analyzes an XPath Expression parse tree (nsXFormsXPathNode), and * This class analyzes an XPath Expression parse tree (nsXFormsXPathNode), and
@ -58,11 +59,12 @@
class nsXFormsXPathAnalyzer { class nsXFormsXPathAnalyzer {
private: private:
nsCOMPtr<nsIXFormsXPathEvaluator> mEvaluator; nsCOMPtr<nsIXFormsXPathEvaluator> mEvaluator;
nsCOMPtr<nsIDOMNode> mResolver; nsCOMPtr<nsIDOMNode> mResolver;
nsCOMArray<nsIDOMNode> *mCurSet; nsCOMArray<nsIDOMNode> *mCurSet;
nsCOMPtr<nsIDOMXPathExpression> mCurExpression; nsCOMPtr<nsIDOMXPathExpression> mCurExpression;
const nsAString *mCurExprString; const nsAString *mCurExprString;
nsStringArray mIndexesUsed;
nsresult AnalyzeRecursively(nsIDOMNode *aContextNode, nsresult AnalyzeRecursively(nsIDOMNode *aContextNode,
const nsXFormsXPathNode *aNode, const nsXFormsXPathNode *aNode,
@ -78,4 +80,6 @@ public:
nsIDOMXPathExpression *aExpression, nsIDOMXPathExpression *aExpression,
const nsAString *aExprString, const nsAString *aExprString,
nsCOMArray<nsIDOMNode> *aSet); nsCOMArray<nsIDOMNode> *aSet);
const nsStringArray& IndexesUsed() const;
}; };

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

@ -43,7 +43,7 @@
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathNode) MOZ_DECL_CTOR_COUNTER(nsXFormsXPathNode)
nsXFormsXPathNode::nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue) 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); MOZ_COUNT_CTOR(nsXFormsXPathNode);

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

@ -56,6 +56,7 @@ public:
PRBool mCon; PRBool mCon;
PRBool mPredicate; PRBool mPredicate;
PRBool mLiteral; PRBool mLiteral;
PRBool mIsIndex;
nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue = PR_FALSE); nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue = PR_FALSE);
~nsXFormsXPathNode(); ~nsXFormsXPathNode();

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

@ -354,12 +354,13 @@ nsXFormsXPathParser::FilterExpr()
void void
nsXFormsXPathParser::FunctionCall() nsXFormsXPathParser::FunctionCall()
{ {
if (!mUsesDynamicFunc) { nsDependentSubstring fname = Substring(mScanner.Expression(),
nsDependentSubstring fname = Substring(mScanner.Expression(), mScanner.Offset() + 1, mScanner.Offset() + mScanner.Length() + 1); mScanner.Offset() + 1,
if (fname.Equals(NS_LITERAL_STRING("now"))) { mScanner.Length());
mUsesDynamicFunc = PR_TRUE; if (!mUsesDynamicFunc && fname.Equals(NS_LITERAL_STRING("now"))) {
} mUsesDynamicFunc = PR_TRUE;
} }
PopToken(); PopToken();
PopToken(); PopToken();
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken(); nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
@ -367,18 +368,22 @@ nsXFormsXPathParser::FunctionCall()
PRBool con = t == nsXFormsXPathScanner::RPARAN ? PR_FALSE : PR_TRUE; PRBool con = t == nsXFormsXPathScanner::RPARAN ? PR_FALSE : PR_TRUE;
while (con) { while (con) {
if (t == nsXFormsXPathScanner::XPATHEOF) { 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(); nsXFormsXPathNode* c = JustContext();
Expr(); Expr();
if (fname.Equals(NS_LITERAL_STRING("index"))) {
c->mIsIndex = PR_TRUE;
}
PushContext(c); PushContext(c);
t = PeekToken(); t = PeekToken();
if (t == nsXFormsXPathScanner::COMMA) { con = (t == nsXFormsXPathScanner::COMMA);
if (con) {
PopToken(); // Another Argument PopToken(); // Another Argument
con = PR_TRUE;
} else {
con = PR_FALSE;
} }
} }