dom/xslt/xpath/txXPCOMExtensionFunction.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/xslt/xpath/txXPCOMExtensionFunction.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,606 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nsAutoPtr.h"
    1.10 +#include "nsComponentManagerUtils.h"
    1.11 +#include "nsDependentString.h"
    1.12 +#include "nsIAtom.h"
    1.13 +#include "nsIInterfaceInfoManager.h"
    1.14 +#include "nsServiceManagerUtils.h"
    1.15 +#include "txExpr.h"
    1.16 +#include "txIFunctionEvaluationContext.h"
    1.17 +#include "txIXPathContext.h"
    1.18 +#include "txNodeSetAdaptor.h"
    1.19 +#include "txXPathTreeWalker.h"
    1.20 +#include "xptcall.h"
    1.21 +#include "txXPathObjectAdaptor.h"
    1.22 +#include "mozilla/Attributes.h"
    1.23 +#include "nsIClassInfo.h"
    1.24 +#include "nsIInterfaceInfo.h"
    1.25 +
    1.26 +NS_IMPL_ISUPPORTS(txXPathObjectAdaptor, txIXPathObject)
    1.27 +
    1.28 +class txFunctionEvaluationContext MOZ_FINAL : public txIFunctionEvaluationContext
    1.29 +{
    1.30 +public:
    1.31 +    txFunctionEvaluationContext(txIEvalContext *aContext, nsISupports *aState);
    1.32 +
    1.33 +    NS_DECL_ISUPPORTS
    1.34 +    NS_DECL_TXIFUNCTIONEVALUATIONCONTEXT
    1.35 +
    1.36 +    void ClearContext()
    1.37 +    {
    1.38 +        mContext = nullptr;
    1.39 +    }
    1.40 +
    1.41 +private:
    1.42 +    txIEvalContext *mContext;
    1.43 +    nsCOMPtr<nsISupports> mState;
    1.44 +};
    1.45 +
    1.46 +txFunctionEvaluationContext::txFunctionEvaluationContext(txIEvalContext *aContext,
    1.47 +                                                         nsISupports *aState)
    1.48 +    : mContext(aContext),
    1.49 +      mState(aState)
    1.50 +{
    1.51 +}
    1.52 +
    1.53 +NS_IMPL_ISUPPORTS(txFunctionEvaluationContext, txIFunctionEvaluationContext)
    1.54 +
    1.55 +NS_IMETHODIMP
    1.56 +txFunctionEvaluationContext::GetPosition(uint32_t *aPosition)
    1.57 +{
    1.58 +    NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
    1.59 +
    1.60 +    *aPosition = mContext->position();
    1.61 +
    1.62 +    return NS_OK;
    1.63 +}
    1.64 +
    1.65 +NS_IMETHODIMP
    1.66 +txFunctionEvaluationContext::GetSize(uint32_t *aSize)
    1.67 +{
    1.68 +    NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
    1.69 +
    1.70 +    *aSize = mContext->size();
    1.71 +
    1.72 +    return NS_OK;
    1.73 +}
    1.74 +
    1.75 +NS_IMETHODIMP
    1.76 +txFunctionEvaluationContext::GetContextNode(nsIDOMNode **aNode)
    1.77 +{
    1.78 +    NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
    1.79 +
    1.80 +    return txXPathNativeNode::getNode(mContext->getContextNode(), aNode);
    1.81 +}
    1.82 +
    1.83 +NS_IMETHODIMP
    1.84 +txFunctionEvaluationContext::GetState(nsISupports **aState)
    1.85 +{
    1.86 +    NS_IF_ADDREF(*aState = mState);
    1.87 +
    1.88 +    return NS_OK;
    1.89 +}
    1.90 +
    1.91 +enum txArgumentType {
    1.92 +    eBOOLEAN = nsXPTType::T_BOOL,
    1.93 +    eNUMBER = nsXPTType::T_DOUBLE,
    1.94 +    eSTRING = nsXPTType::T_DOMSTRING,
    1.95 +    eNODESET,
    1.96 +    eCONTEXT,
    1.97 +    eOBJECT,
    1.98 +    eUNKNOWN
    1.99 +};
   1.100 +
   1.101 +class txXPCOMExtensionFunctionCall : public FunctionCall
   1.102 +{
   1.103 +public:
   1.104 +    txXPCOMExtensionFunctionCall(nsISupports *aHelper, const nsIID &aIID,
   1.105 +                                 uint16_t aMethodIndex,
   1.106 +#ifdef TX_TO_STRING
   1.107 +                                 nsIAtom *aName,
   1.108 +#endif
   1.109 +                                 nsISupports *aState);
   1.110 +
   1.111 +    TX_DECL_FUNCTION
   1.112 +
   1.113 +private:
   1.114 +    txArgumentType GetParamType(const nsXPTParamInfo &aParam,
   1.115 +                                nsIInterfaceInfo *aInfo);
   1.116 +
   1.117 +    nsCOMPtr<nsISupports> mHelper;
   1.118 +    nsIID mIID;
   1.119 +    uint16_t mMethodIndex;
   1.120 +#ifdef TX_TO_STRING
   1.121 +    nsCOMPtr<nsIAtom> mName;
   1.122 +#endif
   1.123 +    nsCOMPtr<nsISupports> mState;
   1.124 +};
   1.125 +
   1.126 +txXPCOMExtensionFunctionCall::txXPCOMExtensionFunctionCall(nsISupports *aHelper,
   1.127 +                                                           const nsIID &aIID,
   1.128 +                                                           uint16_t aMethodIndex,
   1.129 +#ifdef TX_TO_STRING
   1.130 +                                                           nsIAtom *aName,
   1.131 +#endif
   1.132 +                                                           nsISupports *aState)
   1.133 +    : mHelper(aHelper),
   1.134 +      mIID(aIID),
   1.135 +      mMethodIndex(aMethodIndex),
   1.136 +#ifdef TX_TO_STRING
   1.137 +      mName(aName),
   1.138 +#endif
   1.139 +      mState(aState)
   1.140 +{
   1.141 +}
   1.142 +
   1.143 +class txInterfacesArrayHolder
   1.144 +{
   1.145 +public:
   1.146 +    txInterfacesArrayHolder(nsIID **aArray, uint32_t aCount) : mArray(aArray),
   1.147 +                                                               mCount(aCount)
   1.148 +    {
   1.149 +    }
   1.150 +    ~txInterfacesArrayHolder()
   1.151 +    {
   1.152 +        NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mArray);
   1.153 +    }
   1.154 +
   1.155 +private:
   1.156 +    nsIID **mArray;
   1.157 +    uint32_t mCount;
   1.158 +};
   1.159 +
   1.160 +static nsresult
   1.161 +LookupFunction(const char *aContractID, nsIAtom* aName, nsIID &aIID,
   1.162 +               uint16_t &aMethodIndex, nsISupports **aHelper)
   1.163 +{
   1.164 +    nsresult rv;
   1.165 +    nsCOMPtr<nsISupports> helper = do_GetService(aContractID, &rv);
   1.166 +    NS_ENSURE_SUCCESS(rv, rv);
   1.167 +
   1.168 +    nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(helper, &rv);
   1.169 +    NS_ENSURE_SUCCESS(rv, rv);
   1.170 +
   1.171 +    nsCOMPtr<nsIInterfaceInfoManager> iim =
   1.172 +        do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
   1.173 +    NS_ENSURE_TRUE(iim, NS_ERROR_FAILURE);
   1.174 +
   1.175 +    nsIID** iidArray = nullptr;
   1.176 +    uint32_t iidCount = 0;
   1.177 +    rv = classInfo->GetInterfaces(&iidCount, &iidArray);
   1.178 +    NS_ENSURE_SUCCESS(rv, rv);
   1.179 +
   1.180 +    txInterfacesArrayHolder holder(iidArray, iidCount);
   1.181 +
   1.182 +    // Remove any minus signs and uppercase the following letter (so
   1.183 +    // foo-bar becomes fooBar). Note that if there are any names that already
   1.184 +    // have uppercase letters they might cause false matches (both fooBar and
   1.185 +    // foo-bar matching fooBar).
   1.186 +    const char16_t *name = aName->GetUTF16String();
   1.187 +    nsAutoCString methodName;
   1.188 +    char16_t letter;
   1.189 +    bool upperNext = false;
   1.190 +    while ((letter = *name)) {
   1.191 +        if (letter == '-') {
   1.192 +            upperNext = true;
   1.193 +        }
   1.194 +        else {
   1.195 +            MOZ_ASSERT(nsCRT::IsAscii(letter),
   1.196 +                       "invalid static_cast coming up");
   1.197 +            methodName.Append(upperNext ?
   1.198 +                              nsCRT::ToUpper(static_cast<char>(letter)) :
   1.199 +                              letter);
   1.200 +            upperNext = false;
   1.201 +        }
   1.202 +        ++name;
   1.203 +    }
   1.204 +
   1.205 +    uint32_t i;
   1.206 +    for (i = 0; i < iidCount; ++i) {
   1.207 +        nsIID *iid = iidArray[i];
   1.208 +
   1.209 +        nsCOMPtr<nsIInterfaceInfo> info;
   1.210 +        rv = iim->GetInfoForIID(iid, getter_AddRefs(info));
   1.211 +        NS_ENSURE_SUCCESS(rv, rv);
   1.212 +
   1.213 +        uint16_t methodIndex;
   1.214 +        const nsXPTMethodInfo *methodInfo;
   1.215 +        rv = info->GetMethodInfoForName(methodName.get(), &methodIndex,
   1.216 +                                        &methodInfo);
   1.217 +        if (NS_SUCCEEDED(rv)) {
   1.218 +            // Exclude notxpcom and hidden. Also check that we have at least a
   1.219 +            // return value (the xpidl compiler ensures that that return value
   1.220 +            // is the last argument).
   1.221 +            uint8_t paramCount = methodInfo->GetParamCount();
   1.222 +            if (methodInfo->IsNotXPCOM() || methodInfo->IsHidden() ||
   1.223 +                paramCount == 0 ||
   1.224 +                !methodInfo->GetParam(paramCount - 1).IsRetval()) {
   1.225 +                return NS_ERROR_FAILURE;
   1.226 +            }
   1.227 +
   1.228 +            aIID = *iid;
   1.229 +            aMethodIndex = methodIndex;
   1.230 +            return helper->QueryInterface(aIID, (void**)aHelper);
   1.231 +        }
   1.232 +    }
   1.233 +
   1.234 +    return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
   1.235 +}
   1.236 +
   1.237 +/* static */
   1.238 +nsresult
   1.239 +TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
   1.240 +                            nsIAtom* aName, nsISupports *aState,
   1.241 +                            FunctionCall **aFunction)
   1.242 +{
   1.243 +    nsIID iid;
   1.244 +    uint16_t methodIndex = 0;
   1.245 +    nsCOMPtr<nsISupports> helper;
   1.246 +
   1.247 +    nsresult rv = LookupFunction(aContractID.get(), aName, iid, methodIndex,
   1.248 +                                 getter_AddRefs(helper));
   1.249 +    NS_ENSURE_SUCCESS(rv, rv);
   1.250 +
   1.251 +    if (!aFunction) {
   1.252 +        return NS_OK;
   1.253 +    }
   1.254 +
   1.255 +    *aFunction = new txXPCOMExtensionFunctionCall(helper, iid, methodIndex,
   1.256 +#ifdef TX_TO_STRING
   1.257 +                                                  aName,
   1.258 +#endif
   1.259 +                                                  aState);
   1.260 +
   1.261 +    return *aFunction ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
   1.262 +}
   1.263 +
   1.264 +txArgumentType
   1.265 +txXPCOMExtensionFunctionCall::GetParamType(const nsXPTParamInfo &aParam,
   1.266 +                                           nsIInterfaceInfo *aInfo)
   1.267 +{
   1.268 +    uint8_t tag = aParam.GetType().TagPart();
   1.269 +    switch (tag) {
   1.270 +        case nsXPTType::T_BOOL:
   1.271 +        case nsXPTType::T_DOUBLE:
   1.272 +        case nsXPTType::T_DOMSTRING:
   1.273 +        {
   1.274 +            return txArgumentType(tag);
   1.275 +        }
   1.276 +        case nsXPTType::T_INTERFACE:
   1.277 +        case nsXPTType::T_INTERFACE_IS:
   1.278 +        {
   1.279 +            nsIID iid;
   1.280 +            aInfo->GetIIDForParamNoAlloc(mMethodIndex, &aParam, &iid);
   1.281 +            if (iid.Equals(NS_GET_IID(txINodeSet))) {
   1.282 +                return eNODESET;
   1.283 +            }
   1.284 +            if (iid.Equals(NS_GET_IID(txIFunctionEvaluationContext))) {
   1.285 +                return eCONTEXT;
   1.286 +            }
   1.287 +            if (iid.Equals(NS_GET_IID(txIXPathObject))) {
   1.288 +                return eOBJECT;
   1.289 +            }
   1.290 +        }
   1.291 +        // FALLTHROUGH
   1.292 +        default:
   1.293 +        {
   1.294 +            // XXX Error!
   1.295 +            return eUNKNOWN;
   1.296 +        }
   1.297 +    }
   1.298 +}
   1.299 +
   1.300 +class txParamArrayHolder
   1.301 +{
   1.302 +public:
   1.303 +    txParamArrayHolder()
   1.304 +        : mCount(0)
   1.305 +    {
   1.306 +    }
   1.307 +    ~txParamArrayHolder();
   1.308 +
   1.309 +    bool Init(uint8_t aCount);
   1.310 +    operator nsXPTCVariant*() const
   1.311 +    {
   1.312 +      return mArray;
   1.313 +    }
   1.314 +
   1.315 +private:
   1.316 +    nsAutoArrayPtr<nsXPTCVariant> mArray;
   1.317 +    uint8_t mCount;
   1.318 +};
   1.319 +
   1.320 +txParamArrayHolder::~txParamArrayHolder()
   1.321 +{
   1.322 +    uint8_t i;
   1.323 +    for (i = 0; i < mCount; ++i) {
   1.324 +        nsXPTCVariant &variant = mArray[i];
   1.325 +        if (variant.DoesValNeedCleanup()) {
   1.326 +            if (variant.type.TagPart() == nsXPTType::T_DOMSTRING)
   1.327 +                delete (nsAString*)variant.val.p;
   1.328 +            else {
   1.329 +                NS_ABORT_IF_FALSE(variant.type.TagPart() == nsXPTType::T_INTERFACE ||
   1.330 +                                  variant.type.TagPart() == nsXPTType::T_INTERFACE_IS,
   1.331 +                                  "We only support cleanup of strings and interfaces "
   1.332 +                                  "here, and this looks like neither!");
   1.333 +                static_cast<nsISupports*>(variant.val.p)->Release();
   1.334 +            }
   1.335 +        }
   1.336 +    }
   1.337 +}
   1.338 +
   1.339 +bool
   1.340 +txParamArrayHolder::Init(uint8_t aCount)
   1.341 +{
   1.342 +    mCount = aCount;
   1.343 +    mArray = new nsXPTCVariant[mCount];
   1.344 +    if (!mArray) {
   1.345 +        return false;
   1.346 +    }
   1.347 +
   1.348 +    memset(mArray, 0, mCount * sizeof(nsXPTCVariant));
   1.349 +
   1.350 +    return true;
   1.351 +}
   1.352 +
   1.353 +nsresult
   1.354 +txXPCOMExtensionFunctionCall::evaluate(txIEvalContext* aContext,
   1.355 +                                       txAExprResult** aResult)
   1.356 +{
   1.357 +    nsCOMPtr<nsIInterfaceInfoManager> iim =
   1.358 +        do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
   1.359 +    NS_ENSURE_TRUE(iim, NS_ERROR_FAILURE);
   1.360 +
   1.361 +    nsCOMPtr<nsIInterfaceInfo> info;
   1.362 +    nsresult rv = iim->GetInfoForIID(&mIID, getter_AddRefs(info));
   1.363 +    NS_ENSURE_SUCCESS(rv, rv);
   1.364 +
   1.365 +    const nsXPTMethodInfo *methodInfo;
   1.366 +    rv = info->GetMethodInfo(mMethodIndex, &methodInfo);
   1.367 +    NS_ENSURE_SUCCESS(rv, rv);
   1.368 +
   1.369 +    uint8_t paramCount = methodInfo->GetParamCount();
   1.370 +    uint8_t inArgs = paramCount - 1;
   1.371 +
   1.372 +    txParamArrayHolder invokeParams;
   1.373 +    if (!invokeParams.Init(paramCount)) {
   1.374 +        return NS_ERROR_OUT_OF_MEMORY;
   1.375 +    }
   1.376 +
   1.377 +    const nsXPTParamInfo &paramInfo = methodInfo->GetParam(0);
   1.378 +    txArgumentType type = GetParamType(paramInfo, info);
   1.379 +    if (type == eUNKNOWN) {
   1.380 +        return NS_ERROR_FAILURE;
   1.381 +    }
   1.382 +
   1.383 +    txFunctionEvaluationContext *context;
   1.384 +    uint32_t paramStart = 0;
   1.385 +    if (type == eCONTEXT) {
   1.386 +        if (paramInfo.IsOut()) {
   1.387 +            // We don't support out values.
   1.388 +            return NS_ERROR_FAILURE;
   1.389 +        }
   1.390 +
   1.391 +        // Create context wrapper.
   1.392 +        context = new txFunctionEvaluationContext(aContext, mState);
   1.393 +        if (!context) {
   1.394 +            return NS_ERROR_OUT_OF_MEMORY;
   1.395 +        }
   1.396 +
   1.397 +        nsXPTCVariant &invokeParam = invokeParams[0];
   1.398 +        invokeParam.type = paramInfo.GetType();
   1.399 +        invokeParam.SetValNeedsCleanup();
   1.400 +        NS_ADDREF((txIFunctionEvaluationContext*&)invokeParam.val.p = context);
   1.401 +
   1.402 +        // Skip first argument, since it's the context.
   1.403 +        paramStart = 1;
   1.404 +    }
   1.405 +    else {
   1.406 +        context = nullptr;
   1.407 +    }
   1.408 +
   1.409 +    // XXX varargs
   1.410 +    if (!requireParams(inArgs - paramStart, inArgs - paramStart, aContext)) {
   1.411 +        return NS_ERROR_FAILURE;
   1.412 +    }
   1.413 +
   1.414 +    uint32_t i;
   1.415 +    for (i = paramStart; i < inArgs; ++i) {
   1.416 +        Expr* expr = mParams[i - paramStart];
   1.417 +
   1.418 +        const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
   1.419 +        txArgumentType type = GetParamType(paramInfo, info);
   1.420 +        if (type == eUNKNOWN) {
   1.421 +            return NS_ERROR_FAILURE;
   1.422 +        }
   1.423 +
   1.424 +        nsXPTCVariant &invokeParam = invokeParams[i];
   1.425 +        if (paramInfo.IsOut()) {
   1.426 +            // We don't support out values.
   1.427 +            return NS_ERROR_FAILURE;
   1.428 +        }
   1.429 +
   1.430 +        invokeParam.type = paramInfo.GetType();
   1.431 +        switch (type) {
   1.432 +            case eNODESET:
   1.433 +            {
   1.434 +                nsRefPtr<txNodeSet> nodes;
   1.435 +                rv = evaluateToNodeSet(expr, aContext, getter_AddRefs(nodes));
   1.436 +                NS_ENSURE_SUCCESS(rv, rv);
   1.437 +
   1.438 +                txNodeSetAdaptor *adaptor = new txNodeSetAdaptor(nodes);
   1.439 +                if (!adaptor) {
   1.440 +                    return NS_ERROR_OUT_OF_MEMORY;
   1.441 +                }
   1.442 +
   1.443 +                nsCOMPtr<txINodeSet> nodeSet = adaptor;
   1.444 +                rv = adaptor->Init();
   1.445 +                NS_ENSURE_SUCCESS(rv, rv);
   1.446 +
   1.447 +                invokeParam.SetValNeedsCleanup();
   1.448 +                nodeSet.swap((txINodeSet*&)invokeParam.val.p);
   1.449 +                break;
   1.450 +            }
   1.451 +            case eBOOLEAN:
   1.452 +            {
   1.453 +                rv = expr->evaluateToBool(aContext, invokeParam.val.b);
   1.454 +                NS_ENSURE_SUCCESS(rv, rv);
   1.455 +
   1.456 +                break;
   1.457 +            }
   1.458 +            case eNUMBER:
   1.459 +            {
   1.460 +                double dbl;
   1.461 +                rv = evaluateToNumber(mParams[0], aContext, &dbl);
   1.462 +                NS_ENSURE_SUCCESS(rv, rv);
   1.463 +
   1.464 +                invokeParam.val.d = dbl;
   1.465 +                break;
   1.466 +            }
   1.467 +            case eSTRING:
   1.468 +            {
   1.469 +                nsString *value = new nsString();
   1.470 +                if (!value) {
   1.471 +                    return NS_ERROR_OUT_OF_MEMORY;
   1.472 +                }
   1.473 +
   1.474 +                rv = expr->evaluateToString(aContext, *value);
   1.475 +                NS_ENSURE_SUCCESS(rv, rv);
   1.476 +
   1.477 +                invokeParam.SetValNeedsCleanup();
   1.478 +                invokeParam.val.p = value;
   1.479 +                break;
   1.480 +            }
   1.481 +            case eOBJECT:
   1.482 +            {
   1.483 +              nsRefPtr<txAExprResult> exprRes;
   1.484 +              rv = expr->evaluate(aContext, getter_AddRefs(exprRes));
   1.485 +              NS_ENSURE_SUCCESS(rv, rv);
   1.486 +
   1.487 +              nsCOMPtr<txIXPathObject> adaptor =
   1.488 +                new txXPathObjectAdaptor(exprRes);
   1.489 +              if (!adaptor) {
   1.490 +                  return NS_ERROR_OUT_OF_MEMORY;
   1.491 +              }
   1.492 +
   1.493 +              invokeParam.SetValNeedsCleanup();
   1.494 +              adaptor.swap((txIXPathObject*&)invokeParam.val.p);
   1.495 +              break;
   1.496 +            }
   1.497 +            case eCONTEXT:
   1.498 +            case eUNKNOWN:
   1.499 +            {
   1.500 +                // We only support passing the context as the *first* argument.
   1.501 +                return NS_ERROR_FAILURE;
   1.502 +            }
   1.503 +        }
   1.504 +    }
   1.505 +
   1.506 +    const nsXPTParamInfo &returnInfo = methodInfo->GetParam(inArgs);
   1.507 +    txArgumentType returnType = GetParamType(returnInfo, info);
   1.508 +    if (returnType == eUNKNOWN) {
   1.509 +        return NS_ERROR_FAILURE;
   1.510 +    }
   1.511 +
   1.512 +    nsXPTCVariant &returnParam = invokeParams[inArgs];
   1.513 +    returnParam.type = returnInfo.GetType();
   1.514 +    if (returnType == eSTRING) {
   1.515 +        nsString *value = new nsString();
   1.516 +        if (!value) {
   1.517 +            return NS_ERROR_FAILURE;
   1.518 +        }
   1.519 +
   1.520 +        returnParam.SetValNeedsCleanup();
   1.521 +        returnParam.val.p = value;
   1.522 +    }
   1.523 +    else {
   1.524 +        returnParam.SetIndirect();
   1.525 +        if (returnType == eNODESET || returnType == eOBJECT) {
   1.526 +            returnParam.SetValNeedsCleanup();
   1.527 +        }
   1.528 +    }
   1.529 +
   1.530 +    rv = NS_InvokeByIndex(mHelper, mMethodIndex, paramCount, invokeParams);
   1.531 +
   1.532 +    // In case someone is holding on to the txFunctionEvaluationContext which
   1.533 +    // could thus stay alive longer than this function.
   1.534 +    if (context) {
   1.535 +        context->ClearContext();
   1.536 +    }
   1.537 +
   1.538 +    NS_ENSURE_SUCCESS(rv, rv);
   1.539 +
   1.540 +    switch (returnType) {
   1.541 +        case eNODESET:
   1.542 +        {
   1.543 +            txINodeSet* nodeSet = static_cast<txINodeSet*>(returnParam.val.p);
   1.544 +            nsCOMPtr<txIXPathObject> object = do_QueryInterface(nodeSet, &rv);
   1.545 +            NS_ENSURE_SUCCESS(rv, rv);
   1.546 +
   1.547 +            NS_ADDREF(*aResult = object->GetResult());
   1.548 +
   1.549 +            return NS_OK;
   1.550 +        }
   1.551 +        case eBOOLEAN:
   1.552 +        {
   1.553 +            aContext->recycler()->getBoolResult(returnParam.val.b, aResult);
   1.554 +
   1.555 +            return NS_OK;
   1.556 +        }
   1.557 +        case eNUMBER:
   1.558 +        {
   1.559 +            return aContext->recycler()->getNumberResult(returnParam.val.d,
   1.560 +                                                         aResult);
   1.561 +        }
   1.562 +        case eSTRING:
   1.563 +        {
   1.564 +            nsString *returned = static_cast<nsString*>
   1.565 +                                            (returnParam.val.p);
   1.566 +            return aContext->recycler()->getStringResult(*returned, aResult);
   1.567 +        }
   1.568 +        case eOBJECT:
   1.569 +        {
   1.570 +            txIXPathObject *object =
   1.571 +                 static_cast<txIXPathObject*>(returnParam.val.p);
   1.572 +
   1.573 +            NS_ADDREF(*aResult = object->GetResult());
   1.574 +
   1.575 +            return NS_OK;
   1.576 +        }
   1.577 +        default:
   1.578 +        {
   1.579 +            // Huh?
   1.580 +            return NS_ERROR_FAILURE;
   1.581 +        }
   1.582 +    }
   1.583 +}
   1.584 +
   1.585 +Expr::ResultType
   1.586 +txXPCOMExtensionFunctionCall::getReturnType()
   1.587 +{
   1.588 +    // It doesn't really matter what we return here, but it might
   1.589 +    // be a good idea to try to keep this as unoptimizable as possible
   1.590 +    return ANY_RESULT;
   1.591 +}
   1.592 +
   1.593 +bool
   1.594 +txXPCOMExtensionFunctionCall::isSensitiveTo(ContextSensitivity aContext)
   1.595 +{
   1.596 +    // It doesn't really matter what we return here, but it might
   1.597 +    // be a good idea to try to keep this as unoptimizable as possible
   1.598 +    return true;
   1.599 +}
   1.600 +
   1.601 +#ifdef TX_TO_STRING
   1.602 +nsresult
   1.603 +txXPCOMExtensionFunctionCall::getNameAtom(nsIAtom** aAtom)
   1.604 +{
   1.605 +    NS_ADDREF(*aAtom = mName);
   1.606 +
   1.607 +    return NS_OK;
   1.608 +}
   1.609 +#endif

mercurial