Fix for bug 248025 (cannot add a DOM Node as an xsl:param using XSLTProcessor.setParameter()). r=Pike, sr=jst.

This commit is contained in:
peterv%propagandism.org 2005-08-18 09:14:10 +00:00
parent e91966348c
commit 08c98d6b62
4 changed files with 494 additions and 168 deletions

View File

@ -47,8 +47,7 @@
#include "nsIDOMDocument.h"
#include "nsDOMString.h"
nsXPathResult::nsXPathResult() : mNumberValue(0),
mDocument(0),
nsXPathResult::nsXPathResult() : mDocument(nsnull),
mCurrentPos(0),
mResultType(ANY_TYPE),
mInvalidIteratorState(PR_TRUE)
@ -57,7 +56,9 @@ nsXPathResult::nsXPathResult() : mNumberValue(0),
nsXPathResult::~nsXPathResult()
{
Reset();
if (mDocument) {
mDocument->RemoveObserver(this);
}
}
NS_IMPL_ADDREF(nsXPathResult)
@ -73,125 +74,124 @@ NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsXPathResult::GetResultType(PRUint16 *aResultType)
{
NS_ENSURE_ARG(aResultType);
*aResultType = mResultType;
return NS_OK;
}
NS_IMETHODIMP
nsXPathResult::GetNumberValue(double *aNumberValue)
{
if (mResultType != NUMBER_TYPE)
if (mResultType != NUMBER_TYPE) {
return NS_ERROR_DOM_TYPE_ERR;
}
*aNumberValue = mResult.get()->numberValue();
NS_ENSURE_ARG(aNumberValue);
*aNumberValue = mNumberValue;
return NS_OK;
}
NS_IMETHODIMP
nsXPathResult::GetStringValue(nsAString &aStringValue)
{
if (mResultType != STRING_TYPE)
if (mResultType != STRING_TYPE) {
return NS_ERROR_DOM_TYPE_ERR;
}
mResult.get()->stringValue(aStringValue);
if (mStringValue)
aStringValue.Assign(*mStringValue);
else
SetDOMStringToNull(aStringValue);
return NS_OK;
}
NS_IMETHODIMP
nsXPathResult::GetBooleanValue(PRBool *aBooleanValue)
{
if (mResultType != BOOLEAN_TYPE)
if (mResultType != BOOLEAN_TYPE) {
return NS_ERROR_DOM_TYPE_ERR;
}
*aBooleanValue = mResult.get()->booleanValue();
NS_ENSURE_ARG(aBooleanValue);
*aBooleanValue = mBooleanValue;
return NS_OK;
}
NS_IMETHODIMP
nsXPathResult::GetSingleNodeValue(nsIDOMNode **aSingleNodeValue)
{
if (mResultType != FIRST_ORDERED_NODE_TYPE &&
mResultType != ANY_UNORDERED_NODE_TYPE)
if (!isNode()) {
return NS_ERROR_DOM_TYPE_ERR;
}
txNodeSet *nodeSet = NS_STATIC_CAST(txNodeSet*, mResult.get());
if (nodeSet->size() > 0) {
return txXPathNativeNode::getNode(nodeSet->get(0), aSingleNodeValue);
}
*aSingleNodeValue = nsnull;
NS_ENSURE_ARG(aSingleNodeValue);
*aSingleNodeValue = mNode;
NS_IF_ADDREF(*aSingleNodeValue);
return NS_OK;
}
NS_IMETHODIMP
nsXPathResult::GetInvalidIteratorState(PRBool *aInvalidIteratorState)
{
NS_ENSURE_ARG(aInvalidIteratorState);
*aInvalidIteratorState = isIterator() && mInvalidIteratorState;
if (mResultType != UNORDERED_NODE_ITERATOR_TYPE &&
mResultType != ORDERED_NODE_ITERATOR_TYPE) {
*aInvalidIteratorState = PR_FALSE;
return NS_OK;
}
*aInvalidIteratorState = mInvalidIteratorState;
return NS_OK;
}
NS_IMETHODIMP
nsXPathResult::GetSnapshotLength(PRUint32 *aSnapshotLength)
{
if (mResultType != UNORDERED_NODE_SNAPSHOT_TYPE &&
mResultType != ORDERED_NODE_SNAPSHOT_TYPE)
if (!isSnapshot()) {
return NS_ERROR_DOM_TYPE_ERR;
}
txNodeSet *nodeSet = NS_STATIC_CAST(txNodeSet*, mResult.get());
*aSnapshotLength = (PRUint32)nodeSet->size();
NS_ENSURE_ARG(aSnapshotLength);
*aSnapshotLength = 0;
if (mElements)
*aSnapshotLength = mElements->Count();
return NS_OK;
}
NS_IMETHODIMP
nsXPathResult::IterateNext(nsIDOMNode **aResult)
{
if (mResultType != UNORDERED_NODE_ITERATOR_TYPE &&
mResultType != ORDERED_NODE_ITERATOR_TYPE)
if (!isIterator()) {
return NS_ERROR_DOM_TYPE_ERR;
if (mDocument)
mDocument->FlushPendingNotifications(Flush_Content);
if (mInvalidIteratorState)
return NS_ERROR_DOM_INVALID_STATE_ERR;
NS_ENSURE_ARG(aResult);
if (mElements && mCurrentPos < (PRUint32)mElements->Count()) {
*aResult = mElements->ObjectAt(mCurrentPos++);
NS_ADDREF(*aResult);
return NS_OK;
}
if (mDocument) {
mDocument->FlushPendingNotifications(Flush_Content);
}
if (mInvalidIteratorState) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
txNodeSet *nodeSet = NS_STATIC_CAST(txNodeSet*, mResult.get());
if (mCurrentPos < (PRUint32)nodeSet->size()) {
return txXPathNativeNode::getNode(nodeSet->get(mCurrentPos), aResult);
}
*aResult = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXPathResult::SnapshotItem(PRUint32 aIndex, nsIDOMNode **aResult)
{
if (mResultType != UNORDERED_NODE_SNAPSHOT_TYPE &&
mResultType != ORDERED_NODE_SNAPSHOT_TYPE)
if (!isSnapshot()) {
return NS_ERROR_DOM_TYPE_ERR;
NS_ENSURE_ARG(aResult);
if (mElements && aIndex < (PRUint32)mElements->Count()) {
*aResult = mElements->ObjectAt(aIndex);
NS_ADDREF(*aResult);
return NS_OK;
}
txNodeSet *nodeSet = NS_STATIC_CAST(txNodeSet*, mResult.get());
if (aIndex < (PRUint32)nodeSet->size()) {
return txXPathNativeNode::getNode(nodeSet->get(aIndex), aResult);
}
*aResult = nsnull;
return NS_OK;
}
@ -245,81 +245,48 @@ nsXPathResult::ContentRemoved(nsIDocument* aDocument,
Invalidate();
}
NS_IMETHODIMP
nsresult
nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType)
{
Reset();
if (mDocument) {
mDocument->RemoveObserver(this);
mDocument = nsnull;
}
mResultType = aResultType;
mResult.set(aExprResult);
if (mResultType == NUMBER_TYPE) {
mNumberValue = aExprResult->numberValue();
if (!isIterator()) {
return NS_OK;
}
if (mResultType == STRING_TYPE) {
mStringValue = new nsString;
NS_ENSURE_TRUE(mStringValue, NS_ERROR_OUT_OF_MEMORY);
aExprResult->stringValue(*mStringValue);
return NS_OK;
}
mInvalidIteratorState = PR_FALSE;
if (mResultType == BOOLEAN_TYPE) {
mBooleanValue = aExprResult->booleanValue();
return NS_OK;
}
txNodeSet* nodeSet = NS_STATIC_CAST(txNodeSet*, aExprResult);
nsCOMPtr<nsIDOMNode> node;
if (nodeSet->size() > 0) {
nsresult rv = txXPathNativeNode::getNode(nodeSet->get(0),
getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
if (aExprResult->getResultType() == txAExprResult::NODESET) {
nsresult rv = NS_OK;
txNodeSet* nodeSet = NS_STATIC_CAST(txNodeSet*, aExprResult);
if (mResultType == FIRST_ORDERED_NODE_TYPE ||
mResultType == ANY_UNORDERED_NODE_TYPE) {
if (nodeSet->size() > 0) {
txXPathNativeNode::getNode(nodeSet->get(0), &mNode);
}
// If we support the document() function in DOM-XPath we need to
// observe all documents that we have resultnodes in.
nsCOMPtr<nsIDOMDocument> document;
node->GetOwnerDocument(getter_AddRefs(document));
if (document) {
mDocument = do_QueryInterface(document);
}
else {
if (mResultType == UNORDERED_NODE_ITERATOR_TYPE ||
mResultType == ORDERED_NODE_ITERATOR_TYPE) {
mInvalidIteratorState = PR_FALSE;
}
PRInt32 count = nodeSet->size();
if (count == 0)
return NS_OK;
mElements = new nsCOMArray<nsIDOMNode>;
NS_ENSURE_TRUE(mElements, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIDOMNode> node;
PRInt32 i;
for (i = 0; i < count; ++i) {
txXPathNativeNode::getNode(nodeSet->get(i), getter_AddRefs(node));
NS_ASSERTION(node, "node isn't an nsIDOMNode");
mElements->AppendObject(node);
}
// If we support the document() function in DOM-XPath we need to
// observe all documents that we have resultnodes in.
if (mResultType == UNORDERED_NODE_ITERATOR_TYPE ||
mResultType == ORDERED_NODE_ITERATOR_TYPE) {
nsCOMPtr<nsIDOMDocument> document;
node->GetOwnerDocument(getter_AddRefs(document));
if (document)
mDocument = do_QueryInterface(document);
else
mDocument = do_QueryInterface(node);
NS_ASSERTION(mDocument, "We need a document!");
if (mDocument)
mDocument->AddObserver(this);
}
mDocument = do_QueryInterface(node);
}
NS_ASSERTION(mDocument, "We need a document!");
if (mDocument) {
mDocument->AddObserver(this);
}
return rv;
}
return NS_ERROR_DOM_TYPE_ERR;
return NS_OK;
}
void
@ -327,32 +294,79 @@ nsXPathResult::Invalidate()
{
if (mDocument) {
mDocument->RemoveObserver(this);
mDocument = 0;
mDocument = nsnull;
}
mInvalidIteratorState = PR_TRUE;
}
void
nsXPathResult::Reset()
nsresult
nsXPathResult::GetExprResult(txAExprResult** aExprResult)
{
Invalidate();
if (mResultType == STRING_TYPE) {
delete mStringValue;
mStringValue = 0;
}
else if (mResultType == UNORDERED_NODE_ITERATOR_TYPE ||
mResultType == ORDERED_NODE_ITERATOR_TYPE ||
mResultType == UNORDERED_NODE_SNAPSHOT_TYPE ||
mResultType == ORDERED_NODE_SNAPSHOT_TYPE) {
delete mElements;
mCurrentPos = 0;
}
else if (mResultType == FIRST_ORDERED_NODE_TYPE ||
mResultType == ANY_UNORDERED_NODE_TYPE) {
NS_IF_RELEASE(mNode);
if (isIterator() && mInvalidIteratorState) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
mResultType = ANY_TYPE;
return;
*aExprResult = mResult.get();
if (!*aExprResult) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
NS_ADDREF(*aExprResult);
return NS_OK;
}
nsresult
nsXPathResult::Clone(nsIXPathResult **aResult)
{
*aResult = nsnull;
if (isIterator() && mInvalidIteratorState) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
nsCOMPtr<nsIXPathResult> result = new nsXPathResult();
if (!result) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = result->SetExprResult(mResult.get(), mResultType);
NS_ENSURE_SUCCESS(rv, rv);
result.swap(*aResult);
return NS_OK;
}
void
txResultHolder::set(txAExprResult *aResult)
{
releaseNodeSet();
// XXX This will keep the recycler alive, should we clear it?
mResult = aResult;
if (mResult && mResult->getResultType() == txAExprResult::NODESET) {
txNodeSet *nodeSet =
NS_STATIC_CAST(txNodeSet*,
NS_STATIC_CAST(txAExprResult*, mResult));
PRInt32 i, count = nodeSet->size();
for (i = 0; i < count; ++i) {
txXPathNativeNode::addRef(nodeSet->get(i));
}
}
}
void
txResultHolder::releaseNodeSet()
{
if (mResult && mResult->getResultType() == txAExprResult::NODESET) {
txNodeSet *nodeSet =
NS_STATIC_CAST(txNodeSet*,
NS_STATIC_CAST(txAExprResult*, mResult));
PRInt32 i, count = nodeSet->size();
for (i = 0; i < count; ++i) {
txXPathNativeNode::release(nodeSet->get(i));
}
}
}

View File

@ -39,14 +39,13 @@
#ifndef nsXPathResult_h__
#define nsXPathResult_h__
#include "ExprResult.h"
#include "nsIDOMXPathResult.h"
#include "nsIDocument.h"
#include "nsIDocumentObserver.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
class txAExprResult;
// {15b9b301-2012-11d6-a7f2-e6d0a678995c}
#define NS_IXPATHRESULT_IID \
{ 0x15b9b301, 0x2012, 0x11d6, {0xa7, 0xf2, 0xe6, 0xd0, 0xa6, 0x78, 0x99, 0x5c }};
@ -55,8 +54,34 @@ class nsIXPathResult : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IXPATHRESULT_IID)
NS_IMETHOD SetExprResult(txAExprResult* aExprResult,
PRUint16 aResultType) = 0;
virtual nsresult SetExprResult(txAExprResult *aExprResult,
PRUint16 aResultType) = 0;
virtual nsresult GetExprResult(txAExprResult **aExprResult) = 0;
virtual nsresult Clone(nsIXPathResult **aResult) = 0;
};
/**
* Helper class to keep Mozilla node objects alive as long as the nodeset is
* alive.
*/
class txResultHolder
{
public:
~txResultHolder()
{
releaseNodeSet();
}
txAExprResult *get()
{
return mResult;
}
void set(txAExprResult *aResult);
private:
void releaseNodeSet();
nsRefPtr<txAExprResult> mResult;
};
/**
@ -80,19 +105,30 @@ public:
NS_DECL_NSIDOCUMENTOBSERVER
// nsIXPathResult interface
NS_IMETHOD SetExprResult(txAExprResult* aExprResult,
PRUint16 aResultType);
private:
void Invalidate();
void Reset();
nsresult SetExprResult(txAExprResult *aExprResult, PRUint16 aResultType);
nsresult GetExprResult(txAExprResult **aExprResult);
nsresult Clone(nsIXPathResult **aResult);
union {
double mNumberValue;
nsString* mStringValue;
PRBool mBooleanValue;
nsIDOMNode* mNode;
nsCOMArray<nsIDOMNode>* mElements;
};
private:
PRBool isSnapshot() const
{
return mResultType == UNORDERED_NODE_SNAPSHOT_TYPE ||
mResultType == ORDERED_NODE_SNAPSHOT_TYPE;
}
PRBool isIterator() const
{
return mResultType == UNORDERED_NODE_ITERATOR_TYPE ||
mResultType == ORDERED_NODE_ITERATOR_TYPE;
}
PRBool isNode() const
{
return mResultType == FIRST_ORDERED_NODE_TYPE ||
mResultType == ANY_UNORDERED_NODE_TYPE;
}
void Invalidate();
txResultHolder mResult;
nsCOMPtr<nsIDocument> mDocument;
PRUint32 mCurrentPos;
PRUint16 mResultType;

View File

@ -162,6 +162,17 @@ public:
static nsresult getNode(const txXPathNode& aNode, nsIDOMNode** aResult);
static nsIContent* getContent(const txXPathNode& aNode);
static nsIDocument* getDocument(const txXPathNode& aNode);
static void addRef(const txXPathNode& aNode)
{
// Hopefully it's ok to access mContent through mDocument.
NS_ADDREF(aNode.mDocument);
}
static void release(const txXPathNode& aNode)
{
// Hopefully it's ok to access mContent through mDocument.
nsISupports *node = aNode.mDocument;
NS_RELEASE(node);
}
};
#endif

View File

@ -47,12 +47,14 @@
#include "nsIDOMClassInfo.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentFragment.h"
#include "nsIDOMNodeList.h"
#include "nsIIOService.h"
#include "nsILoadGroup.h"
#include "nsIScriptLoader.h"
#include "nsIStringBundle.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsXPathResult.h"
#include "txExecutionState.h"
#include "txMozillaTextOutput.h"
#include "txMozillaXMLOutput.h"
@ -61,6 +63,7 @@
#include "txUnknownHandler.h"
#include "txXSLTProcessor.h"
#include "nsIPrincipal.h"
#include "jsapi.h"
static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
@ -482,8 +485,11 @@ txMozillaXSLTProcessor::SetParameter(const nsAString & aNamespaceURI,
nsIVariant *aValue)
{
NS_ENSURE_ARG(aValue);
nsCOMPtr<nsIVariant> value = aValue;
PRUint16 dataType;
aValue->GetDataType(&dataType);
value->GetDataType(&dataType);
switch (dataType) {
// Number
case nsIDataType::VTYPE_INT8:
@ -511,14 +517,145 @@ txMozillaXSLTProcessor::SetParameter(const nsAString & aNamespaceURI,
case nsIDataType::VTYPE_UTF8STRING:
case nsIDataType::VTYPE_CSTRING:
case nsIDataType::VTYPE_ASTRING:
{
break;
}
// Nodeset
case nsIDataType::VTYPE_INTERFACE:
case nsIDataType::VTYPE_INTERFACE_IS:
{
nsCOMPtr<nsISupports> supports;
nsresult rv = value->GetAsISupports(getter_AddRefs(supports));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
if (node) {
if (!URIUtils::CanCallerAccess(node)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
break;
}
nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(supports);
if (xpathResult) {
nsRefPtr<txAExprResult> result;
nsresult rv = xpathResult->GetExprResult(getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
if (result->getResultType() == txAExprResult::NODESET) {
txNodeSet *nodeSet =
NS_STATIC_CAST(txNodeSet*,
NS_STATIC_CAST(txAExprResult*, result));
nsCOMPtr<nsIDOMNode> node;
PRInt32 i, count = nodeSet->size();
for (i = 0; i < count; ++i) {
rv = txXPathNativeNode::getNode(nodeSet->get(i),
getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
if (!URIUtils::CanCallerAccess(node)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
}
}
// Clone the nsXPathResult so that mutations don't affect this
// variable.
nsCOMPtr<nsIXPathResult> clone;
rv = xpathResult->Clone(getter_AddRefs(clone));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIWritableVariant> variant =
do_CreateInstance("@mozilla.org/variant;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = variant->SetAsISupports(clone);
NS_ENSURE_SUCCESS(rv, rv);
value = variant;
break;
}
nsCOMPtr<nsIDOMNodeList> nodeList = do_QueryInterface(supports);
if (nodeList) {
PRUint32 length;
nodeList->GetLength(&length);
nsCOMPtr<nsIDOMNode> node;
PRUint32 i;
for (i = 0; i < length; ++i) {
nodeList->Item(i, getter_AddRefs(node));
if (!URIUtils::CanCallerAccess(node)) {
return NS_ERROR_DOM_SECURITY_ERR;
}
}
break;
}
// Random JS Objects will be converted to a string.
nsCOMPtr<nsIXPConnectJSObjectHolder> holder =
do_QueryInterface(supports);
if (holder) {
break;
}
// We don't know how to handle this type of param.
return NS_ERROR_ILLEGAL_VALUE;
}
case nsIDataType::VTYPE_ARRAY:
{
// This might still be an error, but we'll only
// find out later since we lazily evaluate.
PRUint16 type;
nsIID iid;
PRUint32 count;
void* array;
nsresult rv = value->GetAsArray(&type, &iid, &count, &array);
NS_ENSURE_SUCCESS(rv, rv);
if (type != nsIDataType::VTYPE_INTERFACE &&
type != nsIDataType::VTYPE_INTERFACE_IS) {
nsMemory::Free(array);
// We only support arrays of DOM nodes.
return NS_ERROR_ILLEGAL_VALUE;
}
nsISupports** values = NS_STATIC_CAST(nsISupports**, array);
PRUint32 i;
for (i = 0; i < count; ++i) {
nsISupports *supports = values[i];
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
if (node) {
rv = URIUtils::CanCallerAccess(node) ? NS_OK :
NS_ERROR_DOM_SECURITY_ERR;
}
else {
// We only support arrays of DOM nodes.
rv = NS_ERROR_ILLEGAL_VALUE;
}
if (NS_FAILED(rv)) {
while (i < count) {
NS_RELEASE(values[i++]);
}
nsMemory::Free(array);
return rv;
}
NS_RELEASE(supports);
}
nsMemory::Free(array);
break;
}
@ -536,11 +673,11 @@ txMozillaXSLTProcessor::SetParameter(const nsAString & aNamespaceURI,
txVariable* var = (txVariable*)mVariables.get(varName);
if (var) {
var->setValue(aValue);
var->setValue(value);
return NS_OK;
}
var = new txVariable(aValue);
var = new txVariable(value);
NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY);
return mVariables.add(varName, var);
@ -927,25 +1064,153 @@ txVariable::Convert(nsIVariant *aValue, txAExprResult** aResult)
case nsIDataType::VTYPE_INTERFACE:
case nsIDataType::VTYPE_INTERFACE_IS:
{
nsID *iid;
nsCOMPtr<nsISupports> supports;
nsresult rv = aValue->GetAsInterface(&iid, getter_AddRefs(supports));
nsresult rv = aValue->GetAsISupports(getter_AddRefs(supports));
NS_ENSURE_SUCCESS(rv, rv);
if (iid) {
// XXX Figure out what the user added and if we can do
// anything with it.
// nsIDOMNode, nsIDOMNodeList, nsIDOMXPathResult
nsMemory::Free(iid);
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
if (node) {
nsAutoPtr<txXPathNode> xpathNode(txXPathNativeNode::createXPathNode(node));
if (!xpathNode) {
return NS_ERROR_FAILURE;
}
*aResult = new txNodeSet(*xpathNode, nsnull);
if (!*aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aResult);
return NS_OK;
}
nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(supports);
if (xpathResult) {
return xpathResult->GetExprResult(aResult);
}
nsCOMPtr<nsIDOMNodeList> nodeList = do_QueryInterface(supports);
if (nodeList) {
nsRefPtr<txNodeSet> nodeSet = new txNodeSet(nsnull);
if (!nodeSet) {
return NS_ERROR_OUT_OF_MEMORY;
}
PRUint32 length;
nodeList->GetLength(&length);
nsCOMPtr<nsIDOMNode> node;
PRUint32 i;
for (i = 0; i < length; ++i) {
nodeList->Item(i, getter_AddRefs(node));
txXPathNode *xpathNode =
txXPathNativeNode::createXPathNode(node);
if (!xpathNode) {
return NS_ERROR_FAILURE;
}
nodeSet->add(*xpathNode);
}
NS_ADDREF(*aResult = nodeSet);
return NS_OK;
}
// Convert random JS Objects to a string.
nsCOMPtr<nsIXPConnectJSObjectHolder> holder =
do_QueryInterface(supports);
if (holder) {
nsCOMPtr<nsIXPConnect> xpc =
do_GetService(nsIXPConnect::GetCID(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPCNativeCallContext> cc;
rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
NS_ENSURE_SUCCESS(rv, rv);
JSContext* cx;
rv = cc->GetJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
JSObject *jsobj;
rv = holder->GetJSObject(&jsobj);
NS_ENSURE_SUCCESS(rv, rv);
JSString *str = JS_ValueToString(cx, OBJECT_TO_JSVAL(jsobj));
NS_ENSURE_TRUE(str, NS_ERROR_FAILURE);
const PRUnichar *strChars =
NS_REINTERPRET_CAST(const PRUnichar*,
::JS_GetStringChars(str));
nsDependentString value(strChars, ::JS_GetStringLength(str));
*aResult = new StringResult(value, nsnull);
if (!*aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aResult);
return NS_OK;
}
break;
}
case nsIDataType::VTYPE_ARRAY:
{
// XXX Figure out what the user added and if we can do
// anything with it. Array of Nodes.
break;
PRUint16 type;
nsIID iid;
PRUint32 count;
void* array;
nsresult rv = aValue->GetAsArray(&type, &iid, &count, &array);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(type == nsIDataType::VTYPE_INTERFACE ||
type == nsIDataType::VTYPE_INTERFACE_IS,
"Huh, we checked this in SetParameter?");
nsISupports** values = NS_STATIC_CAST(nsISupports**, array);
nsRefPtr<txNodeSet> nodeSet = new txNodeSet(nsnull);
if (!nodeSet) {
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, values);
return NS_ERROR_OUT_OF_MEMORY;
}
PRUint32 i;
for (i = 0; i < count; ++i) {
nsISupports *supports = values[i];
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(supports);
NS_ASSERTION(node, "Huh, we checked this in SetParameter?");
txXPathNode *xpathNode =
txXPathNativeNode::createXPathNode(node);
if (!xpathNode) {
while (i < count) {
NS_RELEASE(values[i++]);
}
nsMemory::Free(array);
return NS_ERROR_FAILURE;
}
nodeSet->add(*xpathNode);
NS_RELEASE(supports);
}
nsMemory::Free(array);
NS_ADDREF(*aResult = nodeSet);
return NS_OK;
}
}
return NS_ERROR_ILLEGAL_VALUE;
}