dom/xslt/xpath/txXPCOMExtensionFunction.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsAutoPtr.h"
michael@0 7 #include "nsComponentManagerUtils.h"
michael@0 8 #include "nsDependentString.h"
michael@0 9 #include "nsIAtom.h"
michael@0 10 #include "nsIInterfaceInfoManager.h"
michael@0 11 #include "nsServiceManagerUtils.h"
michael@0 12 #include "txExpr.h"
michael@0 13 #include "txIFunctionEvaluationContext.h"
michael@0 14 #include "txIXPathContext.h"
michael@0 15 #include "txNodeSetAdaptor.h"
michael@0 16 #include "txXPathTreeWalker.h"
michael@0 17 #include "xptcall.h"
michael@0 18 #include "txXPathObjectAdaptor.h"
michael@0 19 #include "mozilla/Attributes.h"
michael@0 20 #include "nsIClassInfo.h"
michael@0 21 #include "nsIInterfaceInfo.h"
michael@0 22
michael@0 23 NS_IMPL_ISUPPORTS(txXPathObjectAdaptor, txIXPathObject)
michael@0 24
michael@0 25 class txFunctionEvaluationContext MOZ_FINAL : public txIFunctionEvaluationContext
michael@0 26 {
michael@0 27 public:
michael@0 28 txFunctionEvaluationContext(txIEvalContext *aContext, nsISupports *aState);
michael@0 29
michael@0 30 NS_DECL_ISUPPORTS
michael@0 31 NS_DECL_TXIFUNCTIONEVALUATIONCONTEXT
michael@0 32
michael@0 33 void ClearContext()
michael@0 34 {
michael@0 35 mContext = nullptr;
michael@0 36 }
michael@0 37
michael@0 38 private:
michael@0 39 txIEvalContext *mContext;
michael@0 40 nsCOMPtr<nsISupports> mState;
michael@0 41 };
michael@0 42
michael@0 43 txFunctionEvaluationContext::txFunctionEvaluationContext(txIEvalContext *aContext,
michael@0 44 nsISupports *aState)
michael@0 45 : mContext(aContext),
michael@0 46 mState(aState)
michael@0 47 {
michael@0 48 }
michael@0 49
michael@0 50 NS_IMPL_ISUPPORTS(txFunctionEvaluationContext, txIFunctionEvaluationContext)
michael@0 51
michael@0 52 NS_IMETHODIMP
michael@0 53 txFunctionEvaluationContext::GetPosition(uint32_t *aPosition)
michael@0 54 {
michael@0 55 NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
michael@0 56
michael@0 57 *aPosition = mContext->position();
michael@0 58
michael@0 59 return NS_OK;
michael@0 60 }
michael@0 61
michael@0 62 NS_IMETHODIMP
michael@0 63 txFunctionEvaluationContext::GetSize(uint32_t *aSize)
michael@0 64 {
michael@0 65 NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
michael@0 66
michael@0 67 *aSize = mContext->size();
michael@0 68
michael@0 69 return NS_OK;
michael@0 70 }
michael@0 71
michael@0 72 NS_IMETHODIMP
michael@0 73 txFunctionEvaluationContext::GetContextNode(nsIDOMNode **aNode)
michael@0 74 {
michael@0 75 NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
michael@0 76
michael@0 77 return txXPathNativeNode::getNode(mContext->getContextNode(), aNode);
michael@0 78 }
michael@0 79
michael@0 80 NS_IMETHODIMP
michael@0 81 txFunctionEvaluationContext::GetState(nsISupports **aState)
michael@0 82 {
michael@0 83 NS_IF_ADDREF(*aState = mState);
michael@0 84
michael@0 85 return NS_OK;
michael@0 86 }
michael@0 87
michael@0 88 enum txArgumentType {
michael@0 89 eBOOLEAN = nsXPTType::T_BOOL,
michael@0 90 eNUMBER = nsXPTType::T_DOUBLE,
michael@0 91 eSTRING = nsXPTType::T_DOMSTRING,
michael@0 92 eNODESET,
michael@0 93 eCONTEXT,
michael@0 94 eOBJECT,
michael@0 95 eUNKNOWN
michael@0 96 };
michael@0 97
michael@0 98 class txXPCOMExtensionFunctionCall : public FunctionCall
michael@0 99 {
michael@0 100 public:
michael@0 101 txXPCOMExtensionFunctionCall(nsISupports *aHelper, const nsIID &aIID,
michael@0 102 uint16_t aMethodIndex,
michael@0 103 #ifdef TX_TO_STRING
michael@0 104 nsIAtom *aName,
michael@0 105 #endif
michael@0 106 nsISupports *aState);
michael@0 107
michael@0 108 TX_DECL_FUNCTION
michael@0 109
michael@0 110 private:
michael@0 111 txArgumentType GetParamType(const nsXPTParamInfo &aParam,
michael@0 112 nsIInterfaceInfo *aInfo);
michael@0 113
michael@0 114 nsCOMPtr<nsISupports> mHelper;
michael@0 115 nsIID mIID;
michael@0 116 uint16_t mMethodIndex;
michael@0 117 #ifdef TX_TO_STRING
michael@0 118 nsCOMPtr<nsIAtom> mName;
michael@0 119 #endif
michael@0 120 nsCOMPtr<nsISupports> mState;
michael@0 121 };
michael@0 122
michael@0 123 txXPCOMExtensionFunctionCall::txXPCOMExtensionFunctionCall(nsISupports *aHelper,
michael@0 124 const nsIID &aIID,
michael@0 125 uint16_t aMethodIndex,
michael@0 126 #ifdef TX_TO_STRING
michael@0 127 nsIAtom *aName,
michael@0 128 #endif
michael@0 129 nsISupports *aState)
michael@0 130 : mHelper(aHelper),
michael@0 131 mIID(aIID),
michael@0 132 mMethodIndex(aMethodIndex),
michael@0 133 #ifdef TX_TO_STRING
michael@0 134 mName(aName),
michael@0 135 #endif
michael@0 136 mState(aState)
michael@0 137 {
michael@0 138 }
michael@0 139
michael@0 140 class txInterfacesArrayHolder
michael@0 141 {
michael@0 142 public:
michael@0 143 txInterfacesArrayHolder(nsIID **aArray, uint32_t aCount) : mArray(aArray),
michael@0 144 mCount(aCount)
michael@0 145 {
michael@0 146 }
michael@0 147 ~txInterfacesArrayHolder()
michael@0 148 {
michael@0 149 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mArray);
michael@0 150 }
michael@0 151
michael@0 152 private:
michael@0 153 nsIID **mArray;
michael@0 154 uint32_t mCount;
michael@0 155 };
michael@0 156
michael@0 157 static nsresult
michael@0 158 LookupFunction(const char *aContractID, nsIAtom* aName, nsIID &aIID,
michael@0 159 uint16_t &aMethodIndex, nsISupports **aHelper)
michael@0 160 {
michael@0 161 nsresult rv;
michael@0 162 nsCOMPtr<nsISupports> helper = do_GetService(aContractID, &rv);
michael@0 163 NS_ENSURE_SUCCESS(rv, rv);
michael@0 164
michael@0 165 nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(helper, &rv);
michael@0 166 NS_ENSURE_SUCCESS(rv, rv);
michael@0 167
michael@0 168 nsCOMPtr<nsIInterfaceInfoManager> iim =
michael@0 169 do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
michael@0 170 NS_ENSURE_TRUE(iim, NS_ERROR_FAILURE);
michael@0 171
michael@0 172 nsIID** iidArray = nullptr;
michael@0 173 uint32_t iidCount = 0;
michael@0 174 rv = classInfo->GetInterfaces(&iidCount, &iidArray);
michael@0 175 NS_ENSURE_SUCCESS(rv, rv);
michael@0 176
michael@0 177 txInterfacesArrayHolder holder(iidArray, iidCount);
michael@0 178
michael@0 179 // Remove any minus signs and uppercase the following letter (so
michael@0 180 // foo-bar becomes fooBar). Note that if there are any names that already
michael@0 181 // have uppercase letters they might cause false matches (both fooBar and
michael@0 182 // foo-bar matching fooBar).
michael@0 183 const char16_t *name = aName->GetUTF16String();
michael@0 184 nsAutoCString methodName;
michael@0 185 char16_t letter;
michael@0 186 bool upperNext = false;
michael@0 187 while ((letter = *name)) {
michael@0 188 if (letter == '-') {
michael@0 189 upperNext = true;
michael@0 190 }
michael@0 191 else {
michael@0 192 MOZ_ASSERT(nsCRT::IsAscii(letter),
michael@0 193 "invalid static_cast coming up");
michael@0 194 methodName.Append(upperNext ?
michael@0 195 nsCRT::ToUpper(static_cast<char>(letter)) :
michael@0 196 letter);
michael@0 197 upperNext = false;
michael@0 198 }
michael@0 199 ++name;
michael@0 200 }
michael@0 201
michael@0 202 uint32_t i;
michael@0 203 for (i = 0; i < iidCount; ++i) {
michael@0 204 nsIID *iid = iidArray[i];
michael@0 205
michael@0 206 nsCOMPtr<nsIInterfaceInfo> info;
michael@0 207 rv = iim->GetInfoForIID(iid, getter_AddRefs(info));
michael@0 208 NS_ENSURE_SUCCESS(rv, rv);
michael@0 209
michael@0 210 uint16_t methodIndex;
michael@0 211 const nsXPTMethodInfo *methodInfo;
michael@0 212 rv = info->GetMethodInfoForName(methodName.get(), &methodIndex,
michael@0 213 &methodInfo);
michael@0 214 if (NS_SUCCEEDED(rv)) {
michael@0 215 // Exclude notxpcom and hidden. Also check that we have at least a
michael@0 216 // return value (the xpidl compiler ensures that that return value
michael@0 217 // is the last argument).
michael@0 218 uint8_t paramCount = methodInfo->GetParamCount();
michael@0 219 if (methodInfo->IsNotXPCOM() || methodInfo->IsHidden() ||
michael@0 220 paramCount == 0 ||
michael@0 221 !methodInfo->GetParam(paramCount - 1).IsRetval()) {
michael@0 222 return NS_ERROR_FAILURE;
michael@0 223 }
michael@0 224
michael@0 225 aIID = *iid;
michael@0 226 aMethodIndex = methodIndex;
michael@0 227 return helper->QueryInterface(aIID, (void**)aHelper);
michael@0 228 }
michael@0 229 }
michael@0 230
michael@0 231 return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
michael@0 232 }
michael@0 233
michael@0 234 /* static */
michael@0 235 nsresult
michael@0 236 TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
michael@0 237 nsIAtom* aName, nsISupports *aState,
michael@0 238 FunctionCall **aFunction)
michael@0 239 {
michael@0 240 nsIID iid;
michael@0 241 uint16_t methodIndex = 0;
michael@0 242 nsCOMPtr<nsISupports> helper;
michael@0 243
michael@0 244 nsresult rv = LookupFunction(aContractID.get(), aName, iid, methodIndex,
michael@0 245 getter_AddRefs(helper));
michael@0 246 NS_ENSURE_SUCCESS(rv, rv);
michael@0 247
michael@0 248 if (!aFunction) {
michael@0 249 return NS_OK;
michael@0 250 }
michael@0 251
michael@0 252 *aFunction = new txXPCOMExtensionFunctionCall(helper, iid, methodIndex,
michael@0 253 #ifdef TX_TO_STRING
michael@0 254 aName,
michael@0 255 #endif
michael@0 256 aState);
michael@0 257
michael@0 258 return *aFunction ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
michael@0 259 }
michael@0 260
michael@0 261 txArgumentType
michael@0 262 txXPCOMExtensionFunctionCall::GetParamType(const nsXPTParamInfo &aParam,
michael@0 263 nsIInterfaceInfo *aInfo)
michael@0 264 {
michael@0 265 uint8_t tag = aParam.GetType().TagPart();
michael@0 266 switch (tag) {
michael@0 267 case nsXPTType::T_BOOL:
michael@0 268 case nsXPTType::T_DOUBLE:
michael@0 269 case nsXPTType::T_DOMSTRING:
michael@0 270 {
michael@0 271 return txArgumentType(tag);
michael@0 272 }
michael@0 273 case nsXPTType::T_INTERFACE:
michael@0 274 case nsXPTType::T_INTERFACE_IS:
michael@0 275 {
michael@0 276 nsIID iid;
michael@0 277 aInfo->GetIIDForParamNoAlloc(mMethodIndex, &aParam, &iid);
michael@0 278 if (iid.Equals(NS_GET_IID(txINodeSet))) {
michael@0 279 return eNODESET;
michael@0 280 }
michael@0 281 if (iid.Equals(NS_GET_IID(txIFunctionEvaluationContext))) {
michael@0 282 return eCONTEXT;
michael@0 283 }
michael@0 284 if (iid.Equals(NS_GET_IID(txIXPathObject))) {
michael@0 285 return eOBJECT;
michael@0 286 }
michael@0 287 }
michael@0 288 // FALLTHROUGH
michael@0 289 default:
michael@0 290 {
michael@0 291 // XXX Error!
michael@0 292 return eUNKNOWN;
michael@0 293 }
michael@0 294 }
michael@0 295 }
michael@0 296
michael@0 297 class txParamArrayHolder
michael@0 298 {
michael@0 299 public:
michael@0 300 txParamArrayHolder()
michael@0 301 : mCount(0)
michael@0 302 {
michael@0 303 }
michael@0 304 ~txParamArrayHolder();
michael@0 305
michael@0 306 bool Init(uint8_t aCount);
michael@0 307 operator nsXPTCVariant*() const
michael@0 308 {
michael@0 309 return mArray;
michael@0 310 }
michael@0 311
michael@0 312 private:
michael@0 313 nsAutoArrayPtr<nsXPTCVariant> mArray;
michael@0 314 uint8_t mCount;
michael@0 315 };
michael@0 316
michael@0 317 txParamArrayHolder::~txParamArrayHolder()
michael@0 318 {
michael@0 319 uint8_t i;
michael@0 320 for (i = 0; i < mCount; ++i) {
michael@0 321 nsXPTCVariant &variant = mArray[i];
michael@0 322 if (variant.DoesValNeedCleanup()) {
michael@0 323 if (variant.type.TagPart() == nsXPTType::T_DOMSTRING)
michael@0 324 delete (nsAString*)variant.val.p;
michael@0 325 else {
michael@0 326 NS_ABORT_IF_FALSE(variant.type.TagPart() == nsXPTType::T_INTERFACE ||
michael@0 327 variant.type.TagPart() == nsXPTType::T_INTERFACE_IS,
michael@0 328 "We only support cleanup of strings and interfaces "
michael@0 329 "here, and this looks like neither!");
michael@0 330 static_cast<nsISupports*>(variant.val.p)->Release();
michael@0 331 }
michael@0 332 }
michael@0 333 }
michael@0 334 }
michael@0 335
michael@0 336 bool
michael@0 337 txParamArrayHolder::Init(uint8_t aCount)
michael@0 338 {
michael@0 339 mCount = aCount;
michael@0 340 mArray = new nsXPTCVariant[mCount];
michael@0 341 if (!mArray) {
michael@0 342 return false;
michael@0 343 }
michael@0 344
michael@0 345 memset(mArray, 0, mCount * sizeof(nsXPTCVariant));
michael@0 346
michael@0 347 return true;
michael@0 348 }
michael@0 349
michael@0 350 nsresult
michael@0 351 txXPCOMExtensionFunctionCall::evaluate(txIEvalContext* aContext,
michael@0 352 txAExprResult** aResult)
michael@0 353 {
michael@0 354 nsCOMPtr<nsIInterfaceInfoManager> iim =
michael@0 355 do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID);
michael@0 356 NS_ENSURE_TRUE(iim, NS_ERROR_FAILURE);
michael@0 357
michael@0 358 nsCOMPtr<nsIInterfaceInfo> info;
michael@0 359 nsresult rv = iim->GetInfoForIID(&mIID, getter_AddRefs(info));
michael@0 360 NS_ENSURE_SUCCESS(rv, rv);
michael@0 361
michael@0 362 const nsXPTMethodInfo *methodInfo;
michael@0 363 rv = info->GetMethodInfo(mMethodIndex, &methodInfo);
michael@0 364 NS_ENSURE_SUCCESS(rv, rv);
michael@0 365
michael@0 366 uint8_t paramCount = methodInfo->GetParamCount();
michael@0 367 uint8_t inArgs = paramCount - 1;
michael@0 368
michael@0 369 txParamArrayHolder invokeParams;
michael@0 370 if (!invokeParams.Init(paramCount)) {
michael@0 371 return NS_ERROR_OUT_OF_MEMORY;
michael@0 372 }
michael@0 373
michael@0 374 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(0);
michael@0 375 txArgumentType type = GetParamType(paramInfo, info);
michael@0 376 if (type == eUNKNOWN) {
michael@0 377 return NS_ERROR_FAILURE;
michael@0 378 }
michael@0 379
michael@0 380 txFunctionEvaluationContext *context;
michael@0 381 uint32_t paramStart = 0;
michael@0 382 if (type == eCONTEXT) {
michael@0 383 if (paramInfo.IsOut()) {
michael@0 384 // We don't support out values.
michael@0 385 return NS_ERROR_FAILURE;
michael@0 386 }
michael@0 387
michael@0 388 // Create context wrapper.
michael@0 389 context = new txFunctionEvaluationContext(aContext, mState);
michael@0 390 if (!context) {
michael@0 391 return NS_ERROR_OUT_OF_MEMORY;
michael@0 392 }
michael@0 393
michael@0 394 nsXPTCVariant &invokeParam = invokeParams[0];
michael@0 395 invokeParam.type = paramInfo.GetType();
michael@0 396 invokeParam.SetValNeedsCleanup();
michael@0 397 NS_ADDREF((txIFunctionEvaluationContext*&)invokeParam.val.p = context);
michael@0 398
michael@0 399 // Skip first argument, since it's the context.
michael@0 400 paramStart = 1;
michael@0 401 }
michael@0 402 else {
michael@0 403 context = nullptr;
michael@0 404 }
michael@0 405
michael@0 406 // XXX varargs
michael@0 407 if (!requireParams(inArgs - paramStart, inArgs - paramStart, aContext)) {
michael@0 408 return NS_ERROR_FAILURE;
michael@0 409 }
michael@0 410
michael@0 411 uint32_t i;
michael@0 412 for (i = paramStart; i < inArgs; ++i) {
michael@0 413 Expr* expr = mParams[i - paramStart];
michael@0 414
michael@0 415 const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
michael@0 416 txArgumentType type = GetParamType(paramInfo, info);
michael@0 417 if (type == eUNKNOWN) {
michael@0 418 return NS_ERROR_FAILURE;
michael@0 419 }
michael@0 420
michael@0 421 nsXPTCVariant &invokeParam = invokeParams[i];
michael@0 422 if (paramInfo.IsOut()) {
michael@0 423 // We don't support out values.
michael@0 424 return NS_ERROR_FAILURE;
michael@0 425 }
michael@0 426
michael@0 427 invokeParam.type = paramInfo.GetType();
michael@0 428 switch (type) {
michael@0 429 case eNODESET:
michael@0 430 {
michael@0 431 nsRefPtr<txNodeSet> nodes;
michael@0 432 rv = evaluateToNodeSet(expr, aContext, getter_AddRefs(nodes));
michael@0 433 NS_ENSURE_SUCCESS(rv, rv);
michael@0 434
michael@0 435 txNodeSetAdaptor *adaptor = new txNodeSetAdaptor(nodes);
michael@0 436 if (!adaptor) {
michael@0 437 return NS_ERROR_OUT_OF_MEMORY;
michael@0 438 }
michael@0 439
michael@0 440 nsCOMPtr<txINodeSet> nodeSet = adaptor;
michael@0 441 rv = adaptor->Init();
michael@0 442 NS_ENSURE_SUCCESS(rv, rv);
michael@0 443
michael@0 444 invokeParam.SetValNeedsCleanup();
michael@0 445 nodeSet.swap((txINodeSet*&)invokeParam.val.p);
michael@0 446 break;
michael@0 447 }
michael@0 448 case eBOOLEAN:
michael@0 449 {
michael@0 450 rv = expr->evaluateToBool(aContext, invokeParam.val.b);
michael@0 451 NS_ENSURE_SUCCESS(rv, rv);
michael@0 452
michael@0 453 break;
michael@0 454 }
michael@0 455 case eNUMBER:
michael@0 456 {
michael@0 457 double dbl;
michael@0 458 rv = evaluateToNumber(mParams[0], aContext, &dbl);
michael@0 459 NS_ENSURE_SUCCESS(rv, rv);
michael@0 460
michael@0 461 invokeParam.val.d = dbl;
michael@0 462 break;
michael@0 463 }
michael@0 464 case eSTRING:
michael@0 465 {
michael@0 466 nsString *value = new nsString();
michael@0 467 if (!value) {
michael@0 468 return NS_ERROR_OUT_OF_MEMORY;
michael@0 469 }
michael@0 470
michael@0 471 rv = expr->evaluateToString(aContext, *value);
michael@0 472 NS_ENSURE_SUCCESS(rv, rv);
michael@0 473
michael@0 474 invokeParam.SetValNeedsCleanup();
michael@0 475 invokeParam.val.p = value;
michael@0 476 break;
michael@0 477 }
michael@0 478 case eOBJECT:
michael@0 479 {
michael@0 480 nsRefPtr<txAExprResult> exprRes;
michael@0 481 rv = expr->evaluate(aContext, getter_AddRefs(exprRes));
michael@0 482 NS_ENSURE_SUCCESS(rv, rv);
michael@0 483
michael@0 484 nsCOMPtr<txIXPathObject> adaptor =
michael@0 485 new txXPathObjectAdaptor(exprRes);
michael@0 486 if (!adaptor) {
michael@0 487 return NS_ERROR_OUT_OF_MEMORY;
michael@0 488 }
michael@0 489
michael@0 490 invokeParam.SetValNeedsCleanup();
michael@0 491 adaptor.swap((txIXPathObject*&)invokeParam.val.p);
michael@0 492 break;
michael@0 493 }
michael@0 494 case eCONTEXT:
michael@0 495 case eUNKNOWN:
michael@0 496 {
michael@0 497 // We only support passing the context as the *first* argument.
michael@0 498 return NS_ERROR_FAILURE;
michael@0 499 }
michael@0 500 }
michael@0 501 }
michael@0 502
michael@0 503 const nsXPTParamInfo &returnInfo = methodInfo->GetParam(inArgs);
michael@0 504 txArgumentType returnType = GetParamType(returnInfo, info);
michael@0 505 if (returnType == eUNKNOWN) {
michael@0 506 return NS_ERROR_FAILURE;
michael@0 507 }
michael@0 508
michael@0 509 nsXPTCVariant &returnParam = invokeParams[inArgs];
michael@0 510 returnParam.type = returnInfo.GetType();
michael@0 511 if (returnType == eSTRING) {
michael@0 512 nsString *value = new nsString();
michael@0 513 if (!value) {
michael@0 514 return NS_ERROR_FAILURE;
michael@0 515 }
michael@0 516
michael@0 517 returnParam.SetValNeedsCleanup();
michael@0 518 returnParam.val.p = value;
michael@0 519 }
michael@0 520 else {
michael@0 521 returnParam.SetIndirect();
michael@0 522 if (returnType == eNODESET || returnType == eOBJECT) {
michael@0 523 returnParam.SetValNeedsCleanup();
michael@0 524 }
michael@0 525 }
michael@0 526
michael@0 527 rv = NS_InvokeByIndex(mHelper, mMethodIndex, paramCount, invokeParams);
michael@0 528
michael@0 529 // In case someone is holding on to the txFunctionEvaluationContext which
michael@0 530 // could thus stay alive longer than this function.
michael@0 531 if (context) {
michael@0 532 context->ClearContext();
michael@0 533 }
michael@0 534
michael@0 535 NS_ENSURE_SUCCESS(rv, rv);
michael@0 536
michael@0 537 switch (returnType) {
michael@0 538 case eNODESET:
michael@0 539 {
michael@0 540 txINodeSet* nodeSet = static_cast<txINodeSet*>(returnParam.val.p);
michael@0 541 nsCOMPtr<txIXPathObject> object = do_QueryInterface(nodeSet, &rv);
michael@0 542 NS_ENSURE_SUCCESS(rv, rv);
michael@0 543
michael@0 544 NS_ADDREF(*aResult = object->GetResult());
michael@0 545
michael@0 546 return NS_OK;
michael@0 547 }
michael@0 548 case eBOOLEAN:
michael@0 549 {
michael@0 550 aContext->recycler()->getBoolResult(returnParam.val.b, aResult);
michael@0 551
michael@0 552 return NS_OK;
michael@0 553 }
michael@0 554 case eNUMBER:
michael@0 555 {
michael@0 556 return aContext->recycler()->getNumberResult(returnParam.val.d,
michael@0 557 aResult);
michael@0 558 }
michael@0 559 case eSTRING:
michael@0 560 {
michael@0 561 nsString *returned = static_cast<nsString*>
michael@0 562 (returnParam.val.p);
michael@0 563 return aContext->recycler()->getStringResult(*returned, aResult);
michael@0 564 }
michael@0 565 case eOBJECT:
michael@0 566 {
michael@0 567 txIXPathObject *object =
michael@0 568 static_cast<txIXPathObject*>(returnParam.val.p);
michael@0 569
michael@0 570 NS_ADDREF(*aResult = object->GetResult());
michael@0 571
michael@0 572 return NS_OK;
michael@0 573 }
michael@0 574 default:
michael@0 575 {
michael@0 576 // Huh?
michael@0 577 return NS_ERROR_FAILURE;
michael@0 578 }
michael@0 579 }
michael@0 580 }
michael@0 581
michael@0 582 Expr::ResultType
michael@0 583 txXPCOMExtensionFunctionCall::getReturnType()
michael@0 584 {
michael@0 585 // It doesn't really matter what we return here, but it might
michael@0 586 // be a good idea to try to keep this as unoptimizable as possible
michael@0 587 return ANY_RESULT;
michael@0 588 }
michael@0 589
michael@0 590 bool
michael@0 591 txXPCOMExtensionFunctionCall::isSensitiveTo(ContextSensitivity aContext)
michael@0 592 {
michael@0 593 // It doesn't really matter what we return here, but it might
michael@0 594 // be a good idea to try to keep this as unoptimizable as possible
michael@0 595 return true;
michael@0 596 }
michael@0 597
michael@0 598 #ifdef TX_TO_STRING
michael@0 599 nsresult
michael@0 600 txXPCOMExtensionFunctionCall::getNameAtom(nsIAtom** aAtom)
michael@0 601 {
michael@0 602 NS_ADDREF(*aAtom = mName);
michael@0 603
michael@0 604 return NS_OK;
michael@0 605 }
michael@0 606 #endif

mercurial