diff --git a/content/xslt/src/xpath/nsXPathResult.cpp b/content/xslt/src/xpath/nsXPathResult.cpp index 9bb3790fa037..5c6daf4bc9e3 100644 --- a/content/xslt/src/xpath/nsXPathResult.cpp +++ b/content/xslt/src/xpath/nsXPathResult.cpp @@ -52,7 +52,9 @@ nsXPathResult::nsXPathResult() : mDocument(nsnull), mCurrentPos(0), mResultType(ANY_TYPE), - mInvalidIteratorState(PR_TRUE) + mInvalidIteratorState(PR_TRUE), + mBooleanResult(PR_FALSE), + mNumberResult(0) { } @@ -120,7 +122,7 @@ nsXPathResult::GetNumberValue(double *aNumberValue) return NS_ERROR_DOM_TYPE_ERR; } - *aNumberValue = mResult->numberValue(); + *aNumberValue = mNumberResult; return NS_OK; } @@ -132,10 +134,7 @@ nsXPathResult::GetStringValue(nsAString &aStringValue) return NS_ERROR_DOM_TYPE_ERR; } - nsAutoString stringValue; - mResult->stringValue(stringValue); - - aStringValue.Assign(stringValue); + aStringValue = mStringResult; return NS_OK; } @@ -147,7 +146,7 @@ nsXPathResult::GetBooleanValue(PRBool *aBooleanValue) return NS_ERROR_DOM_TYPE_ERR; } - *aBooleanValue = mResult->booleanValue(); + *aBooleanValue = mBooleanResult; return NS_OK; } @@ -284,14 +283,18 @@ nsresult nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType, nsINode* aContextNode) { - mResultType = aResultType; - mContextNode = do_GetWeakReference(aContextNode); - - if ((isSnapshot() || isIterator() || isNode()) && + if ((isSnapshot(aResultType) || isIterator(aResultType) || + isNode(aResultType)) && aExprResult->getResultType() != txAExprResult::NODESET) { + // The DOM spec doesn't really say what should happen when reusing an + // XPathResult and an error is thrown. Let's not touch the XPathResult + // in that case. return NS_ERROR_DOM_TYPE_ERR; } + mResultType = aResultType; + mContextNode = do_GetWeakReference(aContextNode); + if (mDocument) { mDocument->RemoveMutationObserver(this); mDocument = nsnull; @@ -301,6 +304,9 @@ nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType, // XXX This will keep the recycler alive, should we clear it? mResult = aExprResult; + mBooleanResult = mResult->booleanValue(); + mNumberResult = mResult->numberValue(); + mResult->stringValue(mStringResult); if (aExprResult && aExprResult->getResultType() == txAExprResult::NODESET) { txNodeSet *nodeSet = static_cast(aExprResult); diff --git a/content/xslt/src/xpath/nsXPathResult.h b/content/xslt/src/xpath/nsXPathResult.h index 0b5cbd1e8ed9..5973a9c5b3d1 100644 --- a/content/xslt/src/xpath/nsXPathResult.h +++ b/content/xslt/src/xpath/nsXPathResult.h @@ -99,20 +99,32 @@ public: nsresult Clone(nsIXPathResult **aResult); void RemoveObserver(); private: + static PRBool isSnapshot(PRUint16 aResultType) + { + return aResultType == UNORDERED_NODE_SNAPSHOT_TYPE || + aResultType == ORDERED_NODE_SNAPSHOT_TYPE; + } + static PRBool isIterator(PRUint16 aResultType) + { + return aResultType == UNORDERED_NODE_ITERATOR_TYPE || + aResultType == ORDERED_NODE_ITERATOR_TYPE; + } + static PRBool isNode(PRUint16 aResultType) + { + return aResultType == FIRST_ORDERED_NODE_TYPE || + aResultType == ANY_UNORDERED_NODE_TYPE; + } PRBool isSnapshot() const { - return mResultType == UNORDERED_NODE_SNAPSHOT_TYPE || - mResultType == ORDERED_NODE_SNAPSHOT_TYPE; + return isSnapshot(mResultType); } PRBool isIterator() const { - return mResultType == UNORDERED_NODE_ITERATOR_TYPE || - mResultType == ORDERED_NODE_ITERATOR_TYPE; + return isIterator(mResultType); } PRBool isNode() const { - return mResultType == FIRST_ORDERED_NODE_TYPE || - mResultType == ANY_UNORDERED_NODE_TYPE; + return isNode(mResultType); } void Invalidate(const nsIContent* aChangeRoot); @@ -124,6 +136,9 @@ private: PRUint16 mResultType; nsWeakPtr mContextNode; PRPackedBool mInvalidIteratorState; + PRBool mBooleanResult; + double mNumberResult; + nsString mStringResult; }; #endif