1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Mozilla Foundation.
20 : * Portions created by the Initial Developer are Copyright (C) 2008
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Jason Orendorff <jorendorff@mozilla.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef xpcquickstubs_h___
41 : #define xpcquickstubs_h___
42 :
43 : #include "xpcpublic.h"
44 : #include "xpcprivate.h"
45 :
46 : #include "nsINode.h"
47 :
48 : /* XPCQuickStubs.h - Support functions used only by quick stubs. */
49 :
50 : class XPCCallContext;
51 :
52 : #define XPC_QS_NULL_INDEX ((uint16_t) -1)
53 :
54 : struct xpc_qsPropertySpec {
55 : uint16_t name_index;
56 : JSPropertyOp getter;
57 : JSStrictPropertyOp setter;
58 : };
59 :
60 : struct xpc_qsFunctionSpec {
61 : uint16_t name_index;
62 : uint16_t arity;
63 : JSNative native;
64 : };
65 :
66 : /** A table mapping interfaces to quick stubs. */
67 : struct xpc_qsHashEntry {
68 : nsID iid;
69 : uint16_t prop_index;
70 : uint16_t n_props;
71 : uint16_t func_index;
72 : uint16_t n_funcs;
73 : // These last two fields index to other entries in the same table.
74 : // XPC_QS_NULL_ENTRY indicates there are no more entries in the chain.
75 : uint16_t parentInterface;
76 : uint16_t chain;
77 : };
78 :
79 : inline nsISupports*
80 34955 : ToSupports(nsISupports *p)
81 : {
82 34955 : return p;
83 : }
84 :
85 : inline nsISupports*
86 18223 : ToCanonicalSupports(nsISupports* p)
87 : {
88 18223 : return nsnull;
89 : }
90 :
91 : #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
92 : _MSC_FULL_VER >= 140050215
93 :
94 : /* Use a compiler intrinsic if one is available. */
95 :
96 : #define QS_CASTABLE_TO(_interface, _class) __is_base_of(_interface, _class)
97 :
98 : #else
99 :
100 : /* The generic version of this predicate relies on the overload resolution
101 : * rules. If |_class| inherits from |_interface|, the |_interface*|
102 : * overload of DOMCI_CastableTo<_interface>::p() will be chosen, otherwise
103 : * the |void*| overload will be chosen. There is no definition of these
104 : * functions; we determine which overload was selected by inspecting the
105 : * size of the return type.
106 : */
107 :
108 : template <typename Interface> struct QS_CastableTo {
109 : struct false_type { int x[1]; };
110 : struct true_type { int x[2]; };
111 : static false_type p(void*);
112 : static true_type p(Interface*);
113 : };
114 :
115 : #define QS_CASTABLE_TO(_interface, _class) \
116 : (sizeof(QS_CastableTo<_interface>::p(static_cast<_class*>(0))) == \
117 : sizeof(QS_CastableTo<_interface>::true_type))
118 :
119 : #endif
120 :
121 : #define QS_IS_NODE(_class) \
122 : QS_CASTABLE_TO(nsINode, _class) || \
123 : QS_CASTABLE_TO(nsIDOMNode, _class)
124 :
125 : class qsObjectHelper : public xpcObjectHelper
126 34990 : {
127 : public:
128 : template <class T>
129 : inline
130 18052 : qsObjectHelper(T *aObject, nsWrapperCache *aCache)
131 : : xpcObjectHelper(ToSupports(aObject), ToCanonicalSupports(aObject),
132 18052 : aCache, QS_IS_NODE(T))
133 18052 : {}
134 : template <class T>
135 : inline
136 16903 : qsObjectHelper(nsCOMPtr<T>& aObject, nsWrapperCache *aCache)
137 : : xpcObjectHelper(ToSupports(aObject.get()),
138 16903 : ToCanonicalSupports(aObject.get()), aCache, QS_IS_NODE(T))
139 : {
140 16903 : if (mCanonical) {
141 : // Transfer the strong reference.
142 207 : mCanonicalStrong = dont_AddRef(mCanonical);
143 207 : aObject.forget();
144 : }
145 16903 : }
146 : template <class T>
147 : inline
148 35 : qsObjectHelper(nsRefPtr<T>& aObject, nsWrapperCache *aCache)
149 : : xpcObjectHelper(ToSupports(aObject.get()),
150 35 : ToCanonicalSupports(aObject.get()), aCache, QS_IS_NODE(T))
151 : {
152 35 : if (mCanonical) {
153 : // Transfer the strong reference.
154 35 : mCanonicalStrong = dont_AddRef(mCanonical);
155 35 : aObject.forget();
156 : }
157 35 : }
158 : };
159 :
160 : JSBool
161 : xpc_qsDefineQuickStubs(JSContext *cx, JSObject *proto, unsigned extraFlags,
162 : PRUint32 ifacec, const nsIID **interfaces,
163 : PRUint32 tableSize, const xpc_qsHashEntry *table,
164 : const xpc_qsPropertySpec *propspecs,
165 : const xpc_qsFunctionSpec *funcspecs,
166 : const char *stringTable);
167 :
168 : /** Raise an exception on @a cx and return false. */
169 : JSBool
170 : xpc_qsThrow(JSContext *cx, nsresult rv);
171 :
172 : /**
173 : * Fail after an XPCOM getter or setter returned rv.
174 : *
175 : * NOTE: Here @a obj must be the JSObject whose private data field points to an
176 : * XPCWrappedNative, not merely an object that has an XPCWrappedNative
177 : * somewhere along the prototype chain! The same applies to @a obj in
178 : * xpc_qsThrowBadSetterValue and <code>vp[1]</code> in xpc_qsThrowMethodFailed
179 : * and xpc_qsThrowBadArg.
180 : *
181 : * This is one reason the UnwrapThis functions below have an out parameter that
182 : * receives the wrapper JSObject. (The other reason is to help the caller keep
183 : * that JSObject GC-reachable.)
184 : */
185 : JSBool
186 : xpc_qsThrowGetterSetterFailed(JSContext *cx, nsresult rv,
187 : JSObject *obj, jsid memberId);
188 :
189 : /**
190 : * Fail after an XPCOM method returned rv.
191 : *
192 : * See NOTE at xpc_qsThrowGetterSetterFailed.
193 : */
194 : JSBool
195 : xpc_qsThrowMethodFailed(JSContext *cx, nsresult rv, jsval *vp);
196 :
197 : JSBool
198 : xpc_qsThrowMethodFailedWithCcx(XPCCallContext &ccx, nsresult rv);
199 :
200 : bool
201 : xpc_qsThrowMethodFailedWithDetails(JSContext *cx, nsresult rv,
202 : const char *ifaceName,
203 : const char *memberName);
204 :
205 : /**
206 : * Fail after converting a method argument fails.
207 : *
208 : * See NOTE at xpc_qsThrowGetterSetterFailed.
209 : */
210 : void
211 : xpc_qsThrowBadArg(JSContext *cx, nsresult rv, jsval *vp, unsigned paramnum);
212 :
213 : void
214 : xpc_qsThrowBadArgWithCcx(XPCCallContext &ccx, nsresult rv, unsigned paramnum);
215 :
216 : void
217 : xpc_qsThrowBadArgWithDetails(JSContext *cx, nsresult rv, unsigned paramnum,
218 : const char *ifaceName, const char *memberName);
219 :
220 : /**
221 : * Fail after converting a setter argument fails.
222 : *
223 : * See NOTE at xpc_qsThrowGetterSetterFailed.
224 : */
225 : void
226 : xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, JSObject *obj,
227 : jsid propId);
228 :
229 :
230 : JSBool
231 : xpc_qsGetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
232 :
233 : /* Functions for converting values between COM and JS. */
234 :
235 : inline JSBool
236 : xpc_qsInt64ToJsval(JSContext *cx, PRInt64 i, jsval *rv)
237 : {
238 : return JS_NewNumberValue(cx, static_cast<double>(i), rv);
239 : }
240 :
241 : inline JSBool
242 34 : xpc_qsUint64ToJsval(JSContext *cx, PRUint64 u, jsval *rv)
243 : {
244 34 : return JS_NewNumberValue(cx, static_cast<double>(u), rv);
245 : }
246 :
247 :
248 : /* Classes for converting jsvals to string types. */
249 :
250 : template <class S, class T>
251 : class xpc_qsBasicString
252 26405 : {
253 : public:
254 : typedef S interface_type;
255 : typedef T implementation_type;
256 :
257 26405 : ~xpc_qsBasicString()
258 : {
259 26405 : if (mValid)
260 26405 : Ptr()->~implementation_type();
261 26405 : }
262 :
263 26405 : JSBool IsValid() { return mValid; }
264 :
265 52810 : implementation_type *Ptr()
266 : {
267 52810 : MOZ_ASSERT(mValid);
268 52810 : return reinterpret_cast<implementation_type *>(mBuf);
269 : }
270 :
271 26405 : operator interface_type &()
272 : {
273 26405 : MOZ_ASSERT(mValid);
274 26405 : return *Ptr();
275 : }
276 :
277 : /* Enum that defines how JS |null| and |undefined| should be treated. See
278 : * the WebIDL specification. eStringify means convert to the string "null"
279 : * or "undefined" respectively, via the standard JS ToString() operation;
280 : * eEmpty means convert to the string ""; eNull means convert to an empty
281 : * string with the void bit set.
282 : *
283 : * Per webidl the default behavior of an unannotated interface is
284 : * eStringify, but our de-facto behavior has been eNull for |null| and
285 : * eStringify for |undefined|, so leaving it that way for now. If we ever
286 : * get to a point where we go through and annotate our interfaces as
287 : * needed, we can change that.
288 : */
289 : enum StringificationBehavior {
290 : eStringify,
291 : eEmpty,
292 : eNull,
293 : eDefaultNullBehavior = eNull,
294 : eDefaultUndefinedBehavior = eStringify
295 : };
296 :
297 : protected:
298 : /*
299 : * Neither field is initialized; that is left to the derived class
300 : * constructor. However, the destructor destroys the string object
301 : * stored in mBuf, if mValid is true.
302 : */
303 : void *mBuf[JS_HOWMANY(sizeof(implementation_type), sizeof(void *))];
304 : JSBool mValid;
305 :
306 : /*
307 : * If null is returned, then we either failed or fully initialized
308 : * |this|; in either case the caller should return immediately
309 : * without doing anything else. Otherwise, the JSString* created
310 : * from |v| will be returned. It'll be rooted, as needed, in
311 : * *pval. nullBehavior and undefinedBehavior control what happens
312 : * when |v| is JSVAL_IS_NULL and JSVAL_IS_VOID respectively.
313 : */
314 : template<class traits>
315 26405 : JSString* InitOrStringify(JSContext* cx, jsval v, jsval* pval,
316 : StringificationBehavior nullBehavior,
317 : StringificationBehavior undefinedBehavior) {
318 : JSString *s;
319 26405 : if (JSVAL_IS_STRING(v)) {
320 24346 : s = JSVAL_TO_STRING(v);
321 : } else {
322 2059 : StringificationBehavior behavior = eStringify;
323 2059 : if (JSVAL_IS_NULL(v)) {
324 1573 : behavior = nullBehavior;
325 486 : } else if (JSVAL_IS_VOID(v)) {
326 11 : behavior = undefinedBehavior;
327 : }
328 :
329 : // If pval is null, that means the argument was optional and
330 : // not passed; turn those into void strings if they're
331 : // supposed to be stringified.
332 2059 : if (behavior != eStringify || !pval) {
333 : // Here behavior == eStringify implies !pval, so both eNull and
334 : // eStringify should end up with void strings.
335 1554 : (new(mBuf) implementation_type(traits::sEmptyBuffer, PRUint32(0)))->
336 : SetIsVoid(behavior != eEmpty);
337 1554 : mValid = true;
338 1554 : return nsnull;
339 : }
340 :
341 505 : s = JS_ValueToString(cx, v);
342 505 : if (!s) {
343 0 : mValid = false;
344 0 : return nsnull;
345 : }
346 505 : *pval = STRING_TO_JSVAL(s); // Root the new string.
347 : }
348 :
349 24851 : return s;
350 : }
351 : };
352 :
353 : /**
354 : * Class for converting a jsval to DOMString.
355 : *
356 : * xpc_qsDOMString arg0(cx, &argv[0]);
357 : * if (!arg0.IsValid())
358 : * return false;
359 : *
360 : * The second argument to the constructor is an in-out parameter. It must
361 : * point to a rooted jsval, such as a JSNative argument or return value slot.
362 : * The value in the jsval on entry is converted to a string. The constructor
363 : * may overwrite that jsval with a string value, to protect the characters of
364 : * the string from garbage collection. The caller must leave the jsval alone
365 : * for the lifetime of the xpc_qsDOMString.
366 : */
367 : class xpc_qsDOMString : public xpc_qsBasicString<nsAString, nsDependentString>
368 17378 : {
369 : public:
370 : xpc_qsDOMString(JSContext *cx, jsval v, jsval *pval,
371 : StringificationBehavior nullBehavior,
372 : StringificationBehavior undefinedBehavior);
373 : };
374 :
375 : /**
376 : * The same as xpc_qsDOMString, but with slightly different conversion behavior,
377 : * corresponding to the [astring] magic XPIDL annotation rather than [domstring].
378 : */
379 : class xpc_qsAString : public xpc_qsDOMString
380 1 : {
381 : public:
382 1 : xpc_qsAString(JSContext *cx, jsval v, jsval *pval)
383 1 : : xpc_qsDOMString(cx, v, pval, eNull, eNull)
384 1 : {}
385 : };
386 :
387 : /**
388 : * Like xpc_qsDOMString and xpc_qsAString, but for XPIDL native types annotated
389 : * with [cstring] rather than [domstring] or [astring].
390 : */
391 : class xpc_qsACString : public xpc_qsBasicString<nsACString, nsCString>
392 7833 : {
393 : public:
394 : xpc_qsACString(JSContext *cx, jsval v, jsval *pval,
395 : StringificationBehavior nullBehavior = eNull,
396 : StringificationBehavior undefinedBehavior = eNull);
397 : };
398 :
399 : /**
400 : * And similar for AUTF8String.
401 : */
402 : class xpc_qsAUTF8String :
403 : public xpc_qsBasicString<nsACString, NS_ConvertUTF16toUTF8>
404 1194 : {
405 : public:
406 : xpc_qsAUTF8String(JSContext* cx, jsval v, jsval *pval);
407 : };
408 :
409 : struct xpc_qsSelfRef
410 : {
411 72923 : xpc_qsSelfRef() : ptr(nsnull) {}
412 : explicit xpc_qsSelfRef(nsISupports *p) : ptr(p) {}
413 72923 : ~xpc_qsSelfRef() { NS_IF_RELEASE(ptr); }
414 :
415 : nsISupports* ptr;
416 : };
417 :
418 : /**
419 : * Convert a jsval to char*, returning true on success.
420 : *
421 : * @param cx
422 : * A context.
423 : * @param v
424 : * A value to convert.
425 : * @param bytes
426 : * Out. On success it receives the converted string unless v is null or
427 : * undefinedin which case bytes->ptr() remains null.
428 : */
429 : JSBool
430 : xpc_qsJsvalToCharStr(JSContext *cx, jsval v, JSAutoByteString *bytes);
431 :
432 : JSBool
433 : xpc_qsJsvalToWcharStr(JSContext *cx, jsval v, jsval *pval, const PRUnichar **pstr);
434 :
435 :
436 : /** Convert an nsString to JSString, returning true on success. This will sometimes modify |str| to be empty. */
437 : JSBool
438 : xpc_qsStringToJsstring(JSContext *cx, nsString &str, JSString **rval);
439 :
440 : nsresult
441 : getWrapper(JSContext *cx,
442 : JSObject *obj,
443 : JSObject *callee,
444 : XPCWrappedNative **wrapper,
445 : JSObject **cur,
446 : XPCWrappedNativeTearOff **tearoff);
447 :
448 : nsresult
449 : castNative(JSContext *cx,
450 : XPCWrappedNative *wrapper,
451 : JSObject *cur,
452 : XPCWrappedNativeTearOff *tearoff,
453 : const nsIID &iid,
454 : void **ppThis,
455 : nsISupports **ppThisRef,
456 : jsval *vp,
457 : XPCLazyCallContext *lccx);
458 :
459 : /**
460 : * Search @a obj and its prototype chain for an XPCOM object that implements
461 : * the interface T.
462 : *
463 : * If an object implementing T is found, store a reference to the wrapper
464 : * JSObject in @a *pThisVal, store a pointer to the T in @a *ppThis, and return
465 : * true. Otherwise, raise an exception on @a cx and return false.
466 : *
467 : * @a *pThisRef receives the same pointer as *ppThis if the T was AddRefed.
468 : * Otherwise it receives null (even on error).
469 : *
470 : * This supports split objects and XPConnect tear-offs and it sees through
471 : * XOWs, XPCNativeWrappers, and SafeJSObjectWrappers.
472 : *
473 : * Requires a request on @a cx.
474 : */
475 : template <class T>
476 : inline JSBool
477 32852 : xpc_qsUnwrapThis(JSContext *cx,
478 : JSObject *obj,
479 : JSObject *callee,
480 : T **ppThis,
481 : nsISupports **pThisRef,
482 : jsval *pThisVal,
483 : XPCLazyCallContext *lccx,
484 : bool failureFatal = true)
485 : {
486 : XPCWrappedNative *wrapper;
487 : XPCWrappedNativeTearOff *tearoff;
488 32852 : nsresult rv = getWrapper(cx, obj, callee, &wrapper, &obj, &tearoff);
489 32852 : if (NS_SUCCEEDED(rv))
490 32852 : rv = castNative(cx, wrapper, obj, tearoff, NS_GET_TEMPLATE_IID(T),
491 : reinterpret_cast<void **>(ppThis), pThisRef, pThisVal,
492 : lccx);
493 :
494 32852 : if (failureFatal)
495 32852 : return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv);
496 :
497 0 : if (NS_FAILED(rv))
498 0 : *ppThis = nsnull;
499 0 : return true;
500 : }
501 :
502 : inline nsISupports*
503 34690 : castNativeFromWrapper(JSContext *cx,
504 : JSObject *obj,
505 : JSObject *callee,
506 : PRUint32 interfaceBit,
507 : nsISupports **pRef,
508 : jsval *pVal,
509 : XPCLazyCallContext *lccx,
510 : nsresult *rv NS_OUTPARAM)
511 : {
512 : XPCWrappedNative *wrapper;
513 : XPCWrappedNativeTearOff *tearoff;
514 : JSObject *cur;
515 :
516 34690 : if (!callee && IS_WRAPPER_CLASS(js::GetObjectClass(obj))) {
517 31155 : cur = obj;
518 62310 : wrapper = IS_WN_WRAPPER_OBJECT(cur) ?
519 5385 : (XPCWrappedNative*)xpc_GetJSPrivate(obj) :
520 67695 : nsnull;
521 31155 : tearoff = nsnull;
522 : } else {
523 3535 : *rv = getWrapper(cx, obj, callee, &wrapper, &cur, &tearoff);
524 3535 : if (NS_FAILED(*rv))
525 0 : return nsnull;
526 : }
527 :
528 : nsISupports *native;
529 34690 : if (wrapper) {
530 5830 : native = wrapper->GetIdentityObject();
531 5830 : cur = wrapper->GetFlatJSObject();
532 : } else {
533 : native = cur ?
534 28860 : static_cast<nsISupports*>(xpc_GetJSPrivate(cur)) :
535 57720 : nsnull;
536 : }
537 :
538 34690 : *rv = NS_ERROR_XPC_BAD_CONVERT_JS;
539 :
540 34690 : if (!native)
541 0 : return nsnull;
542 :
543 34690 : NS_ASSERTION(IS_WRAPPER_CLASS(js::GetObjectClass(cur)), "Not a wrapper?");
544 :
545 : XPCWrappedNativeJSClass *clasp =
546 34690 : (XPCWrappedNativeJSClass*)js::GetObjectClass(cur);
547 34690 : if (!(clasp->interfacesBitmap & (1 << interfaceBit)))
548 0 : return nsnull;
549 :
550 34690 : *pRef = nsnull;
551 34690 : *pVal = OBJECT_TO_JSVAL(cur);
552 :
553 34690 : if (lccx) {
554 15852 : if (wrapper)
555 5282 : lccx->SetWrapper(wrapper, tearoff);
556 : else
557 10570 : lccx->SetWrapper(cur);
558 : }
559 :
560 34690 : *rv = NS_OK;
561 :
562 34690 : return native;
563 : }
564 :
565 : JSBool
566 : xpc_qsUnwrapThisFromCcxImpl(XPCCallContext &ccx,
567 : const nsIID &iid,
568 : void **ppThis,
569 : nsISupports **pThisRef,
570 : jsval *vp);
571 :
572 : /**
573 : * Alternate implementation of xpc_qsUnwrapThis using information already
574 : * present in the given XPCCallContext.
575 : */
576 : template <class T>
577 : inline JSBool
578 596 : xpc_qsUnwrapThisFromCcx(XPCCallContext &ccx,
579 : T **ppThis,
580 : nsISupports **pThisRef,
581 : jsval *pThisVal)
582 : {
583 : return xpc_qsUnwrapThisFromCcxImpl(ccx,
584 : NS_GET_TEMPLATE_IID(T),
585 : reinterpret_cast<void **>(ppThis),
586 : pThisRef,
587 596 : pThisVal);
588 : }
589 :
590 : JSObject*
591 : xpc_qsUnwrapObj(jsval v, nsISupports **ppArgRef, nsresult *rv);
592 :
593 : nsresult
594 : xpc_qsUnwrapArgImpl(JSContext *cx, jsval v, const nsIID &iid, void **ppArg,
595 : nsISupports **ppArgRef, jsval *vp);
596 :
597 : /** Convert a jsval to an XPCOM pointer. */
598 : template <class T>
599 : inline nsresult
600 4785 : xpc_qsUnwrapArg(JSContext *cx, jsval v, T **ppArg, nsISupports **ppArgRef,
601 : jsval *vp)
602 : {
603 : return xpc_qsUnwrapArgImpl(cx, v, NS_GET_TEMPLATE_IID(T),
604 4785 : reinterpret_cast<void **>(ppArg), ppArgRef, vp);
605 : }
606 :
607 : inline nsISupports*
608 1523 : castNativeArgFromWrapper(JSContext *cx,
609 : jsval v,
610 : PRUint32 bit,
611 : nsISupports **pArgRef,
612 : jsval *vp,
613 : nsresult *rv NS_OUTPARAM)
614 : {
615 1523 : JSObject *src = xpc_qsUnwrapObj(v, pArgRef, rv);
616 1523 : if (!src)
617 0 : return nsnull;
618 :
619 1523 : return castNativeFromWrapper(cx, src, nsnull, bit, pArgRef, vp, nsnull, rv);
620 : }
621 :
622 : inline nsWrapperCache*
623 11129 : xpc_qsGetWrapperCache(nsWrapperCache *cache)
624 : {
625 11129 : return cache;
626 : }
627 :
628 : // nsGlobalWindow implements nsWrapperCache, but doesn't always use it. Don't
629 : // try to use it without fixing that first.
630 : class nsGlobalWindow;
631 : inline nsWrapperCache*
632 : xpc_qsGetWrapperCache(nsGlobalWindow *not_allowed);
633 :
634 : inline nsWrapperCache*
635 16696 : xpc_qsGetWrapperCache(void *p)
636 : {
637 16696 : return nsnull;
638 : }
639 :
640 : /** Convert an XPCOM pointer to jsval. Return true on success.
641 : * aIdentity is a performance optimization. Set it to true,
642 : * only if p is the identity pointer.
643 : */
644 : JSBool
645 : xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx,
646 : qsObjectHelper &aHelper,
647 : const nsIID *iid,
648 : XPCNativeInterface **iface,
649 : jsval *rval);
650 :
651 : /**
652 : * Convert a variant to jsval. Return true on success.
653 : */
654 : JSBool
655 : xpc_qsVariantToJsval(XPCLazyCallContext &ccx,
656 : nsIVariant *p,
657 : jsval *rval);
658 :
659 : /**
660 : * Convert a jsval to PRInt64. Return true on success.
661 : */
662 : inline JSBool
663 76 : xpc_qsValueToInt64(JSContext *cx,
664 : jsval v,
665 : PRInt64 *result)
666 : {
667 76 : if (JSVAL_IS_INT(v)) {
668 : int32_t intval;
669 76 : if (!JS_ValueToECMAInt32(cx, v, &intval))
670 0 : return false;
671 76 : *result = static_cast<PRInt64>(intval);
672 : } else {
673 : double doubleval;
674 0 : if (!JS_ValueToNumber(cx, v, &doubleval))
675 0 : return false;
676 0 : *result = static_cast<PRInt64>(doubleval);
677 : }
678 76 : return true;
679 : }
680 :
681 : /**
682 : * Convert a jsval to PRUint64. Return true on success.
683 : */
684 : inline JSBool
685 0 : xpc_qsValueToUint64(JSContext *cx,
686 : jsval v,
687 : PRUint64 *result)
688 : {
689 0 : if (JSVAL_IS_INT(v)) {
690 : uint32_t intval;
691 0 : if (!JS_ValueToECMAUint32(cx, v, &intval))
692 0 : return false;
693 0 : *result = static_cast<PRUint64>(intval);
694 : } else {
695 : double doubleval;
696 0 : if (!JS_ValueToNumber(cx, v, &doubleval))
697 0 : return false;
698 0 : *result = static_cast<PRUint64>(doubleval);
699 : }
700 0 : return true;
701 : }
702 :
703 : #ifdef DEBUG
704 : void
705 : xpc_qsAssertContextOK(JSContext *cx);
706 :
707 : inline bool
708 10496 : xpc_qsSameResult(nsISupports *result1, nsISupports *result2)
709 : {
710 10496 : return SameCOMIdentity(result1, result2);
711 : }
712 :
713 : inline bool
714 4875 : xpc_qsSameResult(const nsString &result1, const nsString &result2)
715 : {
716 4875 : return result1.Equals(result2);
717 : }
718 :
719 : inline bool
720 368 : xpc_qsSameResult(PRInt32 result1, PRInt32 result2)
721 : {
722 368 : return result1 == result2;
723 : }
724 :
725 : #define XPC_QS_ASSERT_CONTEXT_OK(cx) xpc_qsAssertContextOK(cx)
726 : #else
727 : #define XPC_QS_ASSERT_CONTEXT_OK(cx) ((void) 0)
728 : #endif
729 :
730 : #endif /* xpcquickstubs_h___ */
|