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