LCOV - code coverage report
Current view: directory - js/xpconnect/src - XPCQuickStubs.h (source / functions) Found Hit Coverage
Test: app.info Lines: 137 115 83.9 %
Date: 2012-06-02 Functions: 258 95 36.8 %

       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___ */

Generated by: LCOV version 1.7