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