LCOV - code coverage report
Current view: directory - js/xpconnect/src - XPCWrappedNativeJSOps.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 746 553 74.1 %
Date: 2012-06-02 Functions: 54 41 75.9 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=78:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla Communicator client code, released
      18                 :  * March 31, 1998.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  * Netscape Communications Corporation.
      22                 :  * Portions created by the Initial Developer are Copyright (C) 1999
      23                 :  * the Initial Developer. All Rights Reserved.
      24                 :  *
      25                 :  * Contributor(s):
      26                 :  *   John Bandhauer <jband@netscape.com> (original author)
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /* JavaScript JSClasses and JSOps for our Wrapped Native JS Objects. */
      43                 : 
      44                 : #include "xpcprivate.h"
      45                 : #include "XPCWrapper.h"
      46                 : #include "nsWrapperCacheInlines.h"
      47                 : 
      48                 : /***************************************************************************/
      49                 : 
      50                 : // All of the exceptions thrown into JS from this file go through here.
      51                 : // That makes this a nice place to set a breakpoint.
      52                 : 
      53               4 : static JSBool Throw(unsigned errNum, JSContext* cx)
      54                 : {
      55               4 :     XPCThrower::Throw(errNum, cx);
      56               4 :     return false;
      57                 : }
      58                 : 
      59                 : // Handy macro used in many callback stub below.
      60                 : 
      61                 : #define MORPH_SLIM_WRAPPER(cx, obj)                                           \
      62                 :     PR_BEGIN_MACRO                                                            \
      63                 :     SLIM_LOG_WILL_MORPH(cx, obj);                                             \
      64                 :     if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))                   \
      65                 :         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);                    \
      66                 :     PR_END_MACRO
      67                 : 
      68                 : #define THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper)                          \
      69                 :     PR_BEGIN_MACRO                                                            \
      70                 :     if (!wrapper)                                                             \
      71                 :         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);                    \
      72                 :     if (!wrapper->IsValid())                                                  \
      73                 :         return Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx);                     \
      74                 :     PR_END_MACRO
      75                 : 
      76                 : /***************************************************************************/
      77                 : 
      78                 : static JSBool
      79           18545 : ToStringGuts(XPCCallContext& ccx)
      80                 : {
      81                 :     char* sz;
      82           18545 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
      83                 : 
      84           18545 :     if (wrapper)
      85           18545 :         sz = wrapper->ToString(ccx, ccx.GetTearOff());
      86                 :     else
      87               0 :         sz = JS_smprintf("[xpconnect wrapped native prototype]");
      88                 : 
      89           18545 :     if (!sz) {
      90               0 :         JS_ReportOutOfMemory(ccx);
      91               0 :         return false;
      92                 :     }
      93                 : 
      94           18545 :     JSString* str = JS_NewStringCopyZ(ccx, sz);
      95           18545 :     JS_smprintf_free(sz);
      96           18545 :     if (!str)
      97               0 :         return false;
      98                 : 
      99           18545 :     ccx.SetRetVal(STRING_TO_JSVAL(str));
     100           18545 :     return true;
     101                 : }
     102                 : 
     103                 : /***************************************************************************/
     104                 : 
     105                 : static JSBool
     106               0 : XPC_WN_Shared_ToString(JSContext *cx, unsigned argc, jsval *vp)
     107                 : {
     108               0 :     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     109               0 :     if (!obj)
     110               0 :         return false;
     111                 : 
     112               0 :     if (IS_SLIM_WRAPPER(obj)) {
     113                 :         XPCNativeScriptableInfo *si =
     114               0 :             GetSlimWrapperProto(obj)->GetScriptableInfo();
     115                 : #ifdef DEBUG
     116                 : #  define FMT_ADDR " @ 0x%p"
     117                 : #  define FMT_STR(str) str
     118                 : #  define PARAM_ADDR(w) , w
     119                 : #else
     120                 : #  define FMT_ADDR ""
     121                 : #  define FMT_STR(str)
     122                 : #  define PARAM_ADDR(w)
     123                 : #endif
     124               0 :         char *sz = JS_smprintf("[object %s" FMT_ADDR FMT_STR(" (native") FMT_ADDR FMT_STR(")") "]", si->GetJSClass()->name PARAM_ADDR(obj) PARAM_ADDR(xpc_GetJSPrivate(obj)));
     125               0 :         if (!sz)
     126               0 :             return false;
     127                 : 
     128               0 :         JSString* str = JS_NewStringCopyZ(cx, sz);
     129               0 :         JS_smprintf_free(sz);
     130               0 :         if (!str)
     131               0 :             return false;
     132                 : 
     133               0 :         *vp = STRING_TO_JSVAL(str);
     134                 : 
     135               0 :         return true;
     136                 :     }
     137                 : 
     138               0 :     XPCCallContext ccx(JS_CALLER, cx, obj);
     139               0 :     ccx.SetName(ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_TO_STRING));
     140               0 :     ccx.SetArgsAndResultPtr(argc, JS_ARGV(cx, vp), vp);
     141               0 :     return ToStringGuts(ccx);
     142                 : }
     143                 : 
     144                 : static JSBool
     145               1 : XPC_WN_Shared_ToSource(JSContext *cx, unsigned argc, jsval *vp)
     146                 : {
     147                 :     static const char empty[] = "({})";
     148               1 :     JSString *str = JS_NewStringCopyN(cx, empty, sizeof(empty)-1);
     149               1 :     if (!str)
     150               0 :         return false;
     151               1 :     *vp = STRING_TO_JSVAL(str);
     152                 : 
     153               1 :     return true;
     154                 : }
     155                 : 
     156                 : /***************************************************************************/
     157                 : 
     158                 : // A "double wrapped object" is a user JSObject that has been wrapped as a
     159                 : // wrappedJS in order to be used by native code and then re-wrapped by a
     160                 : // wrappedNative wrapper to be used by JS code. One might think of it as:
     161                 : //    wrappedNative(wrappedJS(underlying_JSObject))
     162                 : // This is done (as opposed to just unwrapping the wrapped JS and automatically
     163                 : // returning the underlying JSObject) so that JS callers will see what looks
     164                 : // Like any other xpcom object - and be limited to use its interfaces.
     165                 : //
     166                 : // See the comment preceding nsIXPCWrappedJSObjectGetter in nsIXPConnect.idl.
     167                 : 
     168                 : static JSObject*
     169           11996 : GetDoubleWrappedJSObject(XPCCallContext& ccx, XPCWrappedNative* wrapper)
     170                 : {
     171           11996 :     JSObject* obj = nsnull;
     172                 :     nsCOMPtr<nsIXPConnectWrappedJS>
     173           23992 :         underware = do_QueryInterface(wrapper->GetIdentityObject());
     174           11996 :     if (underware) {
     175           11785 :         JSObject* mainObj = nsnull;
     176           11785 :         if (NS_SUCCEEDED(underware->GetJSObject(&mainObj)) && mainObj) {
     177                 :             jsid id = ccx.GetRuntime()->
     178           11785 :                     GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
     179                 : 
     180           23570 :             JSAutoEnterCompartment ac;
     181           11785 :             if (!ac.enter(ccx, mainObj))
     182               0 :                 return NULL;
     183                 : 
     184                 :             jsval val;
     185           23570 :             if (JS_GetPropertyById(ccx, mainObj, id, &val) &&
     186           11785 :                 !JSVAL_IS_PRIMITIVE(val)) {
     187           11785 :                 obj = JSVAL_TO_OBJECT(val);
     188                 :             }
     189                 :         }
     190                 :     }
     191           11996 :     return obj;
     192                 : }
     193                 : 
     194                 : // This is the getter native function we use to handle 'wrappedJSObject' for
     195                 : // double wrapped JSObjects.
     196                 : 
     197                 : static JSBool
     198            9898 : XPC_WN_DoubleWrappedGetter(JSContext *cx, unsigned argc, jsval *vp)
     199                 : {
     200            9898 :     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     201            9898 :     if (!obj)
     202               0 :         return false;
     203                 : 
     204            9898 :     MORPH_SLIM_WRAPPER(cx, obj);
     205           19796 :     XPCCallContext ccx(JS_CALLER, cx, obj);
     206            9898 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
     207            9898 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
     208                 : 
     209            9898 :     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
     210                 : 
     211            9898 :     JSObject* realObject = GetDoubleWrappedJSObject(ccx, wrapper);
     212            9898 :     if (!realObject) {
     213                 :         // This is pretty unexpected at this point. The object originally
     214                 :         // responded to this get property call and now gives no object.
     215                 :         // XXX Should this throw something at the caller?
     216               0 :         *vp = JSVAL_NULL;
     217               0 :         return true;
     218                 :     }
     219                 : 
     220                 :     // It is a double wrapped object. Figure out if the caller
     221                 :     // is allowed to see it.
     222                 : 
     223                 :     nsIXPCSecurityManager* sm;
     224            9898 :     XPCContext* xpcc = ccx.GetXPCContext();
     225                 : 
     226            9898 :     sm = xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_GET_PROPERTY);
     227            9898 :     if (sm) {
     228           19796 :         AutoMarkingNativeInterfacePtr iface(ccx);
     229                 :         iface = XPCNativeInterface::
     230            9898 :                     GetNewOrUsed(ccx, &NS_GET_IID(nsIXPCWrappedJSObjectGetter));
     231                 : 
     232            9898 :         if (iface) {
     233                 :             jsid id = ccx.GetRuntime()->
     234            9898 :                         GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
     235                 : 
     236            9898 :             ccx.SetCallInfo(iface, iface->GetMemberAt(1), false);
     237            9898 :             if (NS_FAILED(sm->
     238                 :                           CanAccess(nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
     239                 :                                     &ccx, ccx,
     240                 :                                     ccx.GetFlattenedJSObject(),
     241                 :                                     wrapper->GetIdentityObject(),
     242                 :                                     wrapper->GetClassInfo(), id,
     243                 :                                     wrapper->GetSecurityInfoAddr()))) {
     244                 :                 // The SecurityManager should have set an exception.
     245               0 :                 return false;
     246                 :             }
     247                 :         }
     248                 :     }
     249            9898 :     *vp = OBJECT_TO_JSVAL(realObject);
     250            9898 :     return JS_WrapValue(cx, vp);
     251                 : }
     252                 : 
     253                 : /***************************************************************************/
     254                 : 
     255                 : // This is our shared function to define properties on our JSObjects.
     256                 : 
     257                 : /*
     258                 :  * NOTE:
     259                 :  * We *never* set the tearoff names (e.g. nsIFoo) as JS_ENUMERATE.
     260                 :  * We *never* set toString or toSource as JS_ENUMERATE.
     261                 :  */
     262                 : 
     263                 : static JSBool
     264         2702162 : DefinePropertyIfFound(XPCCallContext& ccx,
     265                 :                       JSObject *obj, jsid id,
     266                 :                       XPCNativeSet* set,
     267                 :                       XPCNativeInterface* iface,
     268                 :                       XPCNativeMember* member,
     269                 :                       XPCWrappedNativeScope* scope,
     270                 :                       JSBool reflectToStringAndToSource,
     271                 :                       XPCWrappedNative* wrapperToReflectInterfaceNames,
     272                 :                       XPCWrappedNative* wrapperToReflectDoubleWrap,
     273                 :                       XPCNativeScriptableInfo* scriptableInfo,
     274                 :                       unsigned propFlags,
     275                 :                       JSBool* resolved)
     276                 : {
     277         2702162 :     XPCJSRuntime* rt = ccx.GetRuntime();
     278                 :     JSBool found;
     279                 :     const char* name;
     280                 : 
     281         2702162 :     if (set) {
     282         2702083 :         if (iface)
     283           25385 :             found = true;
     284                 :         else
     285         2676698 :             found = set->FindMember(id, &member, &iface);
     286                 :     } else
     287              79 :         found = (nsnull != (member = iface->FindMember(id)));
     288                 : 
     289         2702162 :     if (!found) {
     290          984846 :         if (reflectToStringAndToSource) {
     291                 :             JSNative call;
     292                 : 
     293          984846 :             if (id == rt->GetStringID(XPCJSRuntime::IDX_TO_STRING)) {
     294               0 :                 call = XPC_WN_Shared_ToString;
     295               0 :                 name = rt->GetStringName(XPCJSRuntime::IDX_TO_STRING);
     296               0 :                 id   = rt->GetStringID(XPCJSRuntime::IDX_TO_STRING);
     297          984846 :             } else if (id == rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE)) {
     298               1 :                 call = XPC_WN_Shared_ToSource;
     299               1 :                 name = rt->GetStringName(XPCJSRuntime::IDX_TO_SOURCE);
     300               1 :                 id   = rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE);
     301                 :             }
     302                 : 
     303                 :             else
     304          984845 :                 call = nsnull;
     305                 : 
     306          984846 :             if (call) {
     307               1 :                 JSFunction* fun = JS_NewFunction(ccx, call, 0, 0, obj, name);
     308               1 :                 if (!fun) {
     309               0 :                     JS_ReportOutOfMemory(ccx);
     310               0 :                     return false;
     311                 :                 }
     312                 : 
     313               2 :                 AutoResolveName arn(ccx, id);
     314               1 :                 if (resolved)
     315               0 :                     *resolved = true;
     316                 :                 return JS_DefinePropertyById(ccx, obj, id,
     317               1 :                                              OBJECT_TO_JSVAL(JS_GetFunctionObject(fun)),
     318                 :                                              nsnull, nsnull,
     319               2 :                                              propFlags & ~JSPROP_ENUMERATE);
     320                 :             }
     321                 :         }
     322                 :         // This *might* be a tearoff name that is not yet part of our
     323                 :         // set. Let's lookup the name and see if it is the name of an
     324                 :         // interface. Then we'll see if the object actually *does* this
     325                 :         // interface and add a tearoff as necessary.
     326                 : 
     327          984845 :         if (wrapperToReflectInterfaceNames) {
     328           21528 :             JSAutoByteString name;
     329           21528 :             AutoMarkingNativeInterfacePtr iface2(ccx);
     330                 :             XPCWrappedNativeTearOff* to;
     331                 :             JSObject* jso;
     332           10764 :             nsresult rv = NS_OK;
     333                 : 
     334           21603 :             if (JSID_IS_STRING(id) &&
     335            5400 :                 name.encode(ccx, JSID_TO_STRING(id)) &&
     336            5400 :                 (iface2 = XPCNativeInterface::GetNewOrUsed(ccx, name.ptr()), iface2) &&
     337                 :                 nsnull != (to = wrapperToReflectInterfaceNames->
     338              39 :                            FindTearOff(ccx, iface2, true, &rv)) &&
     339                 :                 nsnull != (jso = to->GetJSObject()))
     340                 : 
     341                 :             {
     342              78 :                 AutoResolveName arn(ccx, id);
     343              39 :                 if (resolved)
     344               0 :                     *resolved = true;
     345                 :                 return JS_DefinePropertyById(ccx, obj, id, OBJECT_TO_JSVAL(jso),
     346                 :                                              nsnull, nsnull,
     347              39 :                                              propFlags & ~JSPROP_ENUMERATE);
     348           10725 :             } else if (NS_FAILED(rv) && rv != NS_ERROR_NO_INTERFACE) {
     349               0 :                 return Throw(rv, ccx);
     350                 :             }
     351                 :         }
     352                 : 
     353                 :         // This *might* be a double wrapped JSObject
     354          997629 :         if (wrapperToReflectDoubleWrap &&
     355           10725 :             id == rt->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT) &&
     356            2098 :             GetDoubleWrappedJSObject(ccx, wrapperToReflectDoubleWrap)) {
     357                 :             // We build and add a getter function.
     358                 :             // A security check is done on a per-get basis.
     359                 : 
     360                 :             JSFunction* fun;
     361                 : 
     362            1887 :             id = rt->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
     363            1887 :             name = rt->GetStringName(XPCJSRuntime::IDX_WRAPPED_JSOBJECT);
     364                 : 
     365                 :             fun = JS_NewFunction(ccx, XPC_WN_DoubleWrappedGetter,
     366            1887 :                                  0, 0, obj, name);
     367                 : 
     368            1887 :             if (!fun)
     369               0 :                 return false;
     370                 : 
     371            1887 :             JSObject* funobj = JS_GetFunctionObject(fun);
     372            1887 :             if (!funobj)
     373               0 :                 return false;
     374                 : 
     375            1887 :             propFlags |= JSPROP_GETTER;
     376            1887 :             propFlags &= ~JSPROP_ENUMERATE;
     377                 : 
     378            3774 :             AutoResolveName arn(ccx, id);
     379            1887 :             if (resolved)
     380               0 :                 *resolved = true;
     381                 :             return JS_DefinePropertyById(ccx, obj, id, JSVAL_VOID,
     382                 :                                          JS_DATA_TO_FUNC_PTR(JSPropertyOp,
     383                 :                                                              funobj),
     384            1887 :                                          nsnull, propFlags);
     385                 :         }
     386                 : 
     387          982919 :         if (resolved)
     388               0 :             *resolved = false;
     389          982919 :         return true;
     390                 :     }
     391                 : 
     392         1717316 :     if (!member) {
     393              36 :         if (wrapperToReflectInterfaceNames) {
     394                 :             XPCWrappedNativeTearOff* to =
     395              21 :               wrapperToReflectInterfaceNames->FindTearOff(ccx, iface, true);
     396                 : 
     397              21 :             if (!to)
     398               0 :                 return false;
     399              21 :             JSObject* jso = to->GetJSObject();
     400              21 :             if (!jso)
     401               0 :                 return false;
     402                 : 
     403              42 :             AutoResolveName arn(ccx, id);
     404              21 :             if (resolved)
     405               0 :                 *resolved = true;
     406                 :             return JS_DefinePropertyById(ccx, obj, id, OBJECT_TO_JSVAL(jso),
     407                 :                                          nsnull, nsnull,
     408              21 :                                          propFlags & ~JSPROP_ENUMERATE);
     409                 :         }
     410              15 :         if (resolved)
     411               0 :             *resolved = false;
     412              15 :         return true;
     413                 :     }
     414                 : 
     415         1717280 :     if (member->IsConstant()) {
     416                 :         jsval val;
     417           12722 :         AutoResolveName arn(ccx, id);
     418            6361 :         if (resolved)
     419             177 :             *resolved = true;
     420            6361 :         return member->GetConstantValue(ccx, iface, &val) &&
     421                 :                JS_DefinePropertyById(ccx, obj, id, val, nsnull, nsnull,
     422            6361 :                                      propFlags);
     423                 :     }
     424                 : 
     425         3449647 :     if (id == rt->GetStringID(XPCJSRuntime::IDX_TO_STRING) ||
     426         1707264 :         id == rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE) ||
     427                 :         (scriptableInfo &&
     428           30439 :          scriptableInfo->GetFlags().DontEnumQueryInterface() &&
     429            1025 :          id == rt->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE)))
     430            3760 :         propFlags &= ~JSPROP_ENUMERATE;
     431                 : 
     432                 :     jsval funval;
     433         1710919 :     if (!member->NewFunctionObject(ccx, iface, obj, &funval))
     434               0 :         return false;
     435                 : 
     436                 :     // protect funobj until it is actually attached
     437         3421838 :     AUTO_MARK_JSVAL(ccx, funval);
     438                 : 
     439                 : #ifdef off_DEBUG_jband
     440                 :     {
     441                 :         static int cloneCount = 0;
     442                 :         if (!(++cloneCount%10))
     443                 :             printf("<><><> %d cloned functions created\n", cloneCount);
     444                 :     }
     445                 : #endif
     446                 : 
     447         1710919 :     if (member->IsMethod()) {
     448         1377710 :         AutoResolveName arn(ccx, id);
     449          688855 :         if (resolved)
     450           13509 :             *resolved = true;
     451                 :         return JS_DefinePropertyById(ccx, obj, id, funval, nsnull, nsnull,
     452          688855 :                                      propFlags);
     453                 :     }
     454                 : 
     455                 :     // else...
     456                 : 
     457         1022064 :     NS_ASSERTION(member->IsAttribute(), "way broken!");
     458                 : 
     459         1022064 :     propFlags |= JSPROP_GETTER | JSPROP_SHARED;
     460         1022064 :     JSObject* funobj = JSVAL_TO_OBJECT(funval);
     461         1022064 :     JSPropertyOp getter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, funobj);
     462                 :     JSStrictPropertyOp setter;
     463         1022064 :     if (member->IsWritableAttribute()) {
     464          221084 :         propFlags |= JSPROP_SETTER;
     465          221084 :         propFlags &= ~JSPROP_READONLY;
     466          221084 :         setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, funobj);
     467                 :     } else {
     468          800980 :         setter = js_GetterOnlyPropertyStub;
     469                 :     }
     470                 : 
     471         2044128 :     AutoResolveName arn(ccx, id);
     472         1022064 :     if (resolved)
     473           11699 :         *resolved = true;
     474                 : 
     475                 :     return JS_DefinePropertyById(ccx, obj, id, JSVAL_VOID, getter, setter,
     476         1022064 :                                  propFlags);
     477                 : }
     478                 : 
     479                 : /***************************************************************************/
     480                 : /***************************************************************************/
     481                 : 
     482                 : static JSBool
     483         1547943 : XPC_WN_OnlyIWrite_AddPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
     484                 : {
     485         3095886 :     XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, id);
     486         1547943 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
     487         1547943 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
     488                 : 
     489                 :     // Allow only XPConnect to add/set the property
     490         1547943 :     if (ccx.GetResolveName() == id)
     491         1547941 :         return true;
     492                 : 
     493               2 :     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
     494                 : }
     495                 : 
     496                 : static JSBool
     497               0 : XPC_WN_OnlyIWrite_SetPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
     498                 : {
     499               0 :     return XPC_WN_OnlyIWrite_AddPropertyStub(cx, obj, id, vp);
     500                 : }
     501                 : 
     502                 : static JSBool
     503               0 : XPC_WN_CannotModifyPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
     504                 : {
     505               0 :     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
     506                 : }
     507                 : 
     508                 : static JSBool
     509               0 : XPC_WN_CannotModifyStrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
     510                 :                                       jsval *vp)
     511                 : {
     512               0 :     return XPC_WN_CannotModifyPropertyStub(cx, obj, id, vp);
     513                 : }
     514                 : 
     515                 : static JSBool
     516           49120 : XPC_WN_Shared_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
     517                 : {
     518           49120 :     if (type == JSTYPE_OBJECT) {
     519               0 :         *vp = OBJECT_TO_JSVAL(obj);
     520               0 :         return true;
     521                 :     }
     522                 : 
     523           49120 :     MORPH_SLIM_WRAPPER(cx, obj);
     524           98240 :     XPCCallContext ccx(JS_CALLER, cx, obj);
     525           49120 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
     526           49120 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
     527                 : 
     528           49120 :     switch (type) {
     529                 :         case JSTYPE_FUNCTION:
     530                 :             {
     531               0 :                 if (!ccx.GetTearOff()) {
     532               0 :                     XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
     533               0 :                     if (si && (si->GetFlags().WantCall() ||
     534               0 :                                si->GetFlags().WantConstruct())) {
     535               0 :                         *vp = OBJECT_TO_JSVAL(obj);
     536               0 :                         return true;
     537                 :                     }
     538                 :                 }
     539                 :             }
     540               0 :             return Throw(NS_ERROR_XPC_CANT_CONVERT_WN_TO_FUN, cx);
     541                 :         case JSTYPE_NUMBER:
     542               1 :             *vp = JS_GetNaNValue(cx);
     543               1 :             return true;
     544                 :         case JSTYPE_BOOLEAN:
     545               0 :             *vp = JSVAL_TRUE;
     546               0 :             return true;
     547                 :         case JSTYPE_VOID:
     548                 :         case JSTYPE_STRING:
     549                 :         {
     550           49119 :             ccx.SetName(ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_TO_STRING));
     551           49119 :             ccx.SetArgsAndResultPtr(0, nsnull, vp);
     552                 : 
     553           49119 :             XPCNativeMember* member = ccx.GetMember();
     554           49119 :             if (member && member->IsMethod()) {
     555           30574 :                 if (!XPCWrappedNative::CallMethod(ccx))
     556               0 :                     return false;
     557                 : 
     558           30574 :                 if (JSVAL_IS_PRIMITIVE(*vp))
     559           30574 :                     return true;
     560                 :             }
     561                 : 
     562                 :             // else...
     563           18545 :             return ToStringGuts(ccx);
     564                 :         }
     565                 :         default:
     566               0 :             NS_ERROR("bad type in conversion");
     567               0 :             return false;
     568                 :     }
     569                 :     NS_NOTREACHED("huh?");
     570                 :     return false;
     571                 : }
     572                 : 
     573                 : static JSBool
     574              29 : XPC_WN_Shared_Enumerate(JSContext *cx, JSObject *obj)
     575                 : {
     576              29 :     MORPH_SLIM_WRAPPER(cx, obj);
     577              58 :     XPCCallContext ccx(JS_CALLER, cx, obj);
     578              29 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
     579              29 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
     580                 : 
     581                 :     // Since we aren't going to enumerate tearoff names and the prototype
     582                 :     // handles non-mutated members, we can do this potential short-circuit.
     583              29 :     if (!wrapper->HasMutatedSet())
     584               7 :         return true;
     585                 : 
     586              22 :     XPCNativeSet* set = wrapper->GetSet();
     587              22 :     XPCNativeSet* protoSet = wrapper->HasProto() ?
     588              22 :                                 wrapper->GetProto()->GetSet() : nsnull;
     589                 : 
     590              22 :     PRUint16 interface_count = set->GetInterfaceCount();
     591              22 :     XPCNativeInterface** interfaceArray = set->GetInterfaceArray();
     592              67 :     for (PRUint16 i = 0; i < interface_count; i++) {
     593              45 :         XPCNativeInterface* iface = interfaceArray[i];
     594              45 :         PRUint16 member_count = iface->GetMemberCount();
     595             256 :         for (PRUint16 k = 0; k < member_count; k++) {
     596             211 :             XPCNativeMember* member = iface->GetMemberAt(k);
     597             211 :             jsid name = member->GetName();
     598                 : 
     599                 :             // Skip if this member is going to come from the proto.
     600                 :             PRUint16 index;
     601             211 :             if (protoSet &&
     602               0 :                 protoSet->FindMember(name, nsnull, &index) && index == i)
     603               0 :                 continue;
     604             211 :             if (!xpc_ForcePropertyResolve(cx, obj, name))
     605               0 :                 return false;
     606                 :         }
     607                 :     }
     608              22 :     return true;
     609                 : }
     610                 : 
     611                 : /***************************************************************************/
     612                 : 
     613                 : #ifdef DEBUG_slimwrappers
     614                 : static PRUint32 sFinalizedSlimWrappers;
     615                 : #endif
     616                 : 
     617                 : static void
     618         1265286 : XPC_WN_NoHelper_Finalize(JSContext *cx, JSObject *obj)
     619                 : {
     620         1265286 :     nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
     621         1265286 :     if (!p)
     622             704 :         return;
     623                 : 
     624         1264582 :     if (IS_SLIM_WRAPPER_OBJECT(obj)) {
     625                 :         SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
     626                 :                   ++sFinalizedSlimWrappers, obj, p));
     627                 : 
     628                 :         nsWrapperCache* cache;
     629            9090 :         CallQueryInterface(p, &cache);
     630            9090 :         cache->ClearWrapper();
     631                 : 
     632            9090 :         XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
     633            9090 :         if(rt)
     634            9090 :             rt->DeferredRelease(p);
     635                 :         else
     636               0 :             NS_RELEASE(p);
     637            9090 :         return;
     638                 :     }
     639                 : 
     640         1255492 :     static_cast<XPCWrappedNative*>(p)->FlatJSObjectFinalized();
     641                 : }
     642                 : 
     643                 : static void
     644         3176709 : TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
     645                 : {
     646         3176709 :     NS_ASSERTION(scope, "bad scope");
     647                 : 
     648                 :     JSObject* obj;
     649                 : 
     650         3176709 :     obj = scope->GetGlobalJSObject();
     651         3176709 :     NS_ASSERTION(obj, "bad scope JSObject");
     652         3176709 :     JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
     653                 : 
     654         3176709 :     obj = scope->GetPrototypeJSObject();
     655         3176709 :     if (obj) {
     656         3176709 :         JS_CALL_OBJECT_TRACER(trc, obj,
     657                 :                               "XPCWrappedNativeScope::mPrototypeJSObject");
     658                 :     }
     659         3176709 : }
     660                 : 
     661                 : static void
     662         2285144 : TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
     663                 : {
     664                 :     // NOTE: It might be nice to also do the wrapper->Mark() call here too
     665                 :     // when we are called during the marking phase of JS GC to mark the
     666                 :     // wrapper's and wrapper's proto's interface sets.
     667                 :     //
     668                 :     // We currently do that in the GC callback code. The reason we don't do that
     669                 :     // here is because the bits used in that marking do unpleasant things to the
     670                 :     // member counts in the interface and interface set objects. Those counts
     671                 :     // are used in the DealWithDyingGCThings calls that are part of this JS GC
     672                 :     // marking phase. By doing these calls later during our GC callback we
     673                 :     // avoid that problem. Arguably this could be changed. But it ain't broke.
     674                 :     //
     675                 :     // However, we do need to call the wrapper's TraceJS so that
     676                 :     // it can be sure that its (potentially shared) JSClass is traced. The
     677                 :     // danger is that a live wrapper might not be in a wrapper map and thus
     678                 :     // won't be fully marked in the GC callback. This can happen if there is
     679                 :     // a security exception during wrapper creation or if during wrapper
     680                 :     // creation it is determined that the wrapper is not needed. In those cases
     681                 :     // the wrapper can never actually be used from JS code - so resources like
     682                 :     // the interface set will never be accessed. But the JS engine will still
     683                 :     // need to use the JSClass. So, some marking is required for protection.
     684                 : 
     685         2285144 :     wrapper->TraceJS(trc);
     686                 : 
     687         2285144 :     TraceScopeJSObjects(trc, wrapper->GetScope());
     688         2285144 : }
     689                 : 
     690                 : static void
     691         2285386 : MarkWrappedNative(JSTracer *trc, JSObject *obj)
     692                 : {
     693                 :     JSObject *obj2;
     694                 : 
     695                 :     // Pass null for the first JSContext* parameter  to skip any security
     696                 :     // checks and to avoid potential state change there.
     697                 :     XPCWrappedNative* wrapper =
     698         2285386 :         XPCWrappedNative::GetWrappedNativeOfJSObject(nsnull, obj, nsnull, &obj2);
     699                 : 
     700         2285386 :     if (wrapper) {
     701         2285144 :         if (wrapper->IsValid())
     702         2285144 :              TraceForValidWrapper(trc, wrapper);
     703             242 :     } else if (obj2) {
     704              88 :         GetSlimWrapperProto(obj2)->TraceJS(trc);
     705                 :     }
     706         2285386 : }
     707                 : 
     708                 : static void
     709         2285386 : XPC_WN_NoHelper_Trace(JSTracer *trc, JSObject *obj)
     710                 : {
     711         2285386 :     MarkWrappedNative(trc, obj);
     712         2285386 : }
     713                 : 
     714                 : static JSBool
     715         1688293 : XPC_WN_NoHelper_Resolve(JSContext *cx, JSObject *obj, jsid id)
     716                 : {
     717         1688293 :     MORPH_SLIM_WRAPPER(cx, obj);
     718         3376586 :     XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, id);
     719         1688293 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
     720         1688293 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
     721                 : 
     722         1688293 :     XPCNativeSet* set = ccx.GetSet();
     723         1688293 :     if (!set)
     724               0 :         return true;
     725                 : 
     726                 :     // Don't resolve properties that are on our prototype.
     727         1688293 :     if (ccx.GetInterface() && !ccx.GetStaticMemberIsLocal())
     728          131593 :         return true;
     729                 : 
     730                 :     return DefinePropertyIfFound(ccx, obj, id,
     731                 :                                  set, nsnull, nsnull, wrapper->GetScope(),
     732                 :                                  true, wrapper, wrapper, nsnull,
     733                 :                                  JSPROP_ENUMERATE |
     734                 :                                  JSPROP_READONLY |
     735         1556700 :                                  JSPROP_PERMANENT, nsnull);
     736                 : }
     737                 : 
     738                 : nsISupports *
     739            1012 : XPC_GetIdentityObject(JSContext *cx, JSObject *obj)
     740                 : {
     741                 :     XPCWrappedNative *wrapper =
     742            1012 :         XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
     743                 : 
     744            1012 :     return wrapper ? wrapper->GetIdentityObject() : nsnull;
     745                 : }
     746                 : 
     747                 : JSBool
     748            1473 : XPC_WN_Equality(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp)
     749                 : {
     750            1473 :     jsval v = *valp;
     751            1473 :     *bp = false;
     752                 : 
     753                 :     JSObject *obj2;
     754                 :     XPCWrappedNative *wrapper =
     755            1473 :         XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, nsnull, &obj2);
     756            1473 :     if (obj2) {
     757               0 :         *bp = !JSVAL_IS_PRIMITIVE(v) && (JSVAL_TO_OBJECT(v) == obj2);
     758                 : 
     759               0 :         return true;
     760                 :     }
     761                 : 
     762            1473 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
     763                 : 
     764            1473 :     XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
     765            1473 :     if (si && si->GetFlags().WantEquality()) {
     766                 :         bool res;
     767               0 :         nsresult rv = si->GetCallback()->Equality(wrapper, cx, obj, v, &res);
     768               0 :         if (NS_FAILED(rv))
     769               0 :             return Throw(rv, cx);
     770               0 :         *bp = res;
     771            1473 :     } else if (!JSVAL_IS_PRIMITIVE(v)) {
     772            1473 :         JSObject *other = JSVAL_TO_OBJECT(v);
     773                 : 
     774                 :         *bp = (obj == other ||
     775             506 :                XPC_GetIdentityObject(cx, obj) ==
     776            1979 :                XPC_GetIdentityObject(cx, other));
     777                 :     }
     778                 : 
     779            1473 :     return true;
     780                 : }
     781                 : 
     782                 : static JSObject *
     783               0 : XPC_WN_OuterObject(JSContext *cx, JSObject *obj)
     784                 : {
     785                 :     XPCWrappedNative *wrapper =
     786               0 :         static_cast<XPCWrappedNative *>(js::GetObjectPrivate(obj));
     787               0 :     if (!wrapper) {
     788               0 :         Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
     789                 : 
     790               0 :         return nsnull;
     791                 :     }
     792                 : 
     793               0 :     if (!wrapper->IsValid()) {
     794               0 :         Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx);
     795                 : 
     796               0 :         return nsnull;
     797                 :     }
     798                 : 
     799               0 :     XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
     800               0 :     if (si && si->GetFlags().WantOuterObject()) {
     801                 :         JSObject *newThis;
     802                 :         nsresult rv =
     803               0 :             si->GetCallback()->OuterObject(wrapper, cx, obj, &newThis);
     804                 : 
     805               0 :         if (NS_FAILED(rv)) {
     806               0 :             Throw(rv, cx);
     807                 : 
     808               0 :             return nsnull;
     809                 :         }
     810                 : 
     811               0 :         obj = newThis;
     812                 :     }
     813                 : 
     814               0 :     return obj;
     815                 : }
     816                 : 
     817                 : XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
     818                 :   { // base
     819                 :     "XPCWrappedNative_NoHelper",    // name;
     820                 :     WRAPPER_SLOTS |
     821                 :     JSCLASS_PRIVATE_IS_NSISUPPORTS, // flags
     822                 : 
     823                 :     /* Mandatory non-null function pointer members. */
     824                 :     XPC_WN_OnlyIWrite_AddPropertyStub, // addProperty
     825                 :     XPC_WN_CannotModifyPropertyStub,   // delProperty
     826                 :     JS_PropertyStub,                   // getProperty
     827                 :     XPC_WN_OnlyIWrite_SetPropertyStub, // setProperty
     828                 : 
     829                 :     XPC_WN_Shared_Enumerate,           // enumerate
     830                 :     XPC_WN_NoHelper_Resolve,           // resolve
     831                 :     XPC_WN_Shared_Convert,             // convert
     832                 :     XPC_WN_NoHelper_Finalize,          // finalize
     833                 : 
     834                 :     /* Optionally non-null members start here. */
     835                 :     nsnull,                         // checkAccess
     836                 :     nsnull,                         // call
     837                 :     nsnull,                         // construct
     838                 :     nsnull,                         // hasInstance
     839                 :     XPC_WN_NoHelper_Trace,          // trace
     840                 : 
     841                 :     // ClassExtension
     842                 :     {
     843                 :         XPC_WN_Equality,
     844                 :         nsnull, // outerObject
     845                 :         nsnull, // innerObject
     846                 :         nsnull, // iteratorObject
     847                 :         nsnull, // unused
     848                 :         true,   // isWrappedNative
     849                 :     },
     850                 : 
     851                 :     // ObjectOps
     852                 :     {
     853                 :         nsnull, // lookupGeneric
     854                 :         nsnull, // lookupProperty
     855                 :         nsnull, // lookupElement
     856                 :         nsnull, // lookupSpecial
     857                 :         nsnull, // defineGeneric
     858                 :         nsnull, // defineProperty
     859                 :         nsnull, // defineElement
     860                 :         nsnull, // defineSpecial
     861                 :         nsnull, // getGeneric
     862                 :         nsnull, // getProperty
     863                 :         nsnull, // getElement
     864                 :         nsnull, // getElementIfPresent
     865                 :         nsnull, // getSpecial
     866                 :         nsnull, // setGeneric
     867                 :         nsnull, // setProperty
     868                 :         nsnull, // setElement
     869                 :         nsnull, // setSpecial
     870                 :         nsnull, // getGenericAttributes
     871                 :         nsnull, // getAttributes
     872                 :         nsnull, // getElementAttributes
     873                 :         nsnull, // getSpecialAttributes
     874                 :         nsnull, // setGenericAttributes
     875                 :         nsnull, // setAttributes
     876                 :         nsnull, // setElementAttributes
     877                 :         nsnull, // setSpecialAttributes
     878                 :         nsnull, // deleteProperty
     879                 :         nsnull, // deleteElement
     880                 :         nsnull, // deleteSpecial
     881                 :         XPC_WN_JSOp_Enumerate,
     882                 :         XPC_WN_JSOp_TypeOf_Object,
     883                 :         nsnull, // fix
     884                 :         XPC_WN_JSOp_ThisObject,
     885                 :         XPC_WN_JSOp_Clear
     886                 :     }
     887                 :   },
     888                 :   0 // interfacesBitmap
     889                 : };
     890                 : 
     891                 : 
     892                 : /***************************************************************************/
     893                 : 
     894                 : static JSBool
     895          224081 : XPC_WN_MaybeResolvingPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
     896                 : {
     897          224081 :     MORPH_SLIM_WRAPPER(cx, obj);
     898          448162 :     XPCCallContext ccx(JS_CALLER, cx, obj);
     899          224081 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
     900          224081 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
     901                 : 
     902          224081 :     if (ccx.GetResolvingWrapper() == wrapper)
     903          224081 :         return true;
     904               0 :     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
     905                 : }
     906                 : 
     907                 : static JSBool
     908               0 : XPC_WN_MaybeResolvingStrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
     909                 :                                         jsval *vp)
     910                 : {
     911               0 :     return XPC_WN_MaybeResolvingPropertyStub(cx, obj, id, vp);
     912                 : }
     913                 : 
     914                 : // macro fun!
     915                 : #define PRE_HELPER_STUB_NO_SLIM                                               \
     916                 :     XPCWrappedNative* wrapper =                                               \
     917                 :         XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj);        \
     918                 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);                             \
     919                 :     bool retval = true;                                                       \
     920                 :     nsresult rv = wrapper->GetScriptableCallback()->
     921                 : 
     922                 : #define PRE_HELPER_STUB                                                       \
     923                 :     XPCWrappedNative* wrapper;                                                \
     924                 :     nsIXPCScriptable* si;                                                     \
     925                 :     if (IS_SLIM_WRAPPER(obj)) {                                               \
     926                 :         wrapper = nsnull;                                                     \
     927                 :         si = GetSlimWrapperProto(obj)->GetScriptableInfo()->GetCallback();    \
     928                 :     }                                                                         \
     929                 :     else                                                                      \
     930                 :     {                                                                         \
     931                 :         wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);      \
     932                 :         THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);                         \
     933                 :         si = wrapper->GetScriptableCallback();                                \
     934                 :     }                                                                         \
     935                 :     bool retval = true;                                                       \
     936                 :     nsresult rv = si->
     937                 : 
     938                 : #define POST_HELPER_STUB                                                      \
     939                 :     if (NS_FAILED(rv))                                                        \
     940                 :         return Throw(rv, cx);                                                 \
     941                 :     return retval;
     942                 : 
     943                 : static JSBool
     944               3 : XPC_WN_Helper_AddProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
     945                 : {
     946               3 :     PRE_HELPER_STUB
     947               3 :     AddProperty(wrapper, cx, obj, id, vp, &retval);
     948               3 :     POST_HELPER_STUB
     949                 : }
     950                 : 
     951                 : static JSBool
     952               0 : XPC_WN_Helper_DelProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
     953                 : {
     954               0 :     PRE_HELPER_STUB
     955               0 :     DelProperty(wrapper, cx, obj, id, vp, &retval);
     956               0 :     POST_HELPER_STUB
     957                 : }
     958                 : 
     959                 : static JSBool
     960          166762 : XPC_WN_Helper_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
     961                 : {
     962          166762 :     PRE_HELPER_STUB
     963          166762 :     GetProperty(wrapper, cx, obj, id, vp, &retval);
     964          166762 :     POST_HELPER_STUB
     965                 : }
     966                 : 
     967                 : static JSBool
     968          115514 : XPC_WN_Helper_SetProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
     969                 : {
     970          115514 :     PRE_HELPER_STUB
     971          115514 :     SetProperty(wrapper, cx, obj, id, vp, &retval);
     972          115514 :     POST_HELPER_STUB
     973                 : }
     974                 : 
     975                 : static JSBool
     976               0 : XPC_WN_Helper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
     977                 : {
     978                 :     SLIM_LOG_WILL_MORPH(cx, obj);
     979               0 :     PRE_HELPER_STUB_NO_SLIM
     980               0 :     Convert(wrapper, cx, obj, type, vp, &retval);
     981               0 :     POST_HELPER_STUB
     982                 : }
     983                 : 
     984                 : static JSBool
     985               0 : XPC_WN_Helper_CheckAccess(JSContext *cx, JSObject *obj, jsid id,
     986                 :                           JSAccessMode mode, jsval *vp)
     987                 : {
     988               0 :     PRE_HELPER_STUB
     989               0 :     CheckAccess(wrapper, cx, obj, id, mode, vp, &retval);
     990               0 :     POST_HELPER_STUB
     991                 : }
     992                 : 
     993                 : static JSBool
     994            8354 : XPC_WN_Helper_Call(JSContext *cx, unsigned argc, jsval *vp)
     995                 : {
     996                 :     // N.B. we want obj to be the callee, not JS_THIS(cx, vp)
     997            8354 :     JSObject *obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
     998                 : 
     999                 :     XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, JSID_VOID,
    1000           16708 :                        argc, JS_ARGV(cx, vp), vp);
    1001            8354 :     if (!ccx.IsValid())
    1002               0 :         return false;
    1003                 : 
    1004            8354 :     JS_ASSERT(obj == ccx.GetFlattenedJSObject());
    1005                 : 
    1006                 :     SLIM_LOG_WILL_MORPH(cx, obj);
    1007            8354 :     PRE_HELPER_STUB_NO_SLIM
    1008            8354 :     Call(wrapper, cx, obj, argc, JS_ARGV(cx, vp), vp, &retval);
    1009            8354 :     POST_HELPER_STUB
    1010                 : }
    1011                 : 
    1012                 : static JSBool
    1013           47565 : XPC_WN_Helper_Construct(JSContext *cx, unsigned argc, jsval *vp)
    1014                 : {
    1015           47565 :     JSObject *obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
    1016           47565 :     if (!obj)
    1017               0 :         return false;
    1018                 : 
    1019                 :     XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, JSID_VOID,
    1020           95130 :                        argc, JS_ARGV(cx, vp), vp);
    1021           47565 :     if (!ccx.IsValid())
    1022               0 :         return false;
    1023                 : 
    1024           47565 :     JS_ASSERT(obj == ccx.GetFlattenedJSObject());
    1025                 : 
    1026                 :     SLIM_LOG_WILL_MORPH(cx, obj);
    1027           47565 :     PRE_HELPER_STUB_NO_SLIM
    1028           47565 :     Construct(wrapper, cx, obj, argc, JS_ARGV(cx, vp), vp, &retval);
    1029           47565 :     POST_HELPER_STUB
    1030                 : }
    1031                 : 
    1032                 : static JSBool
    1033          167930 : XPC_WN_Helper_HasInstance(JSContext *cx, JSObject *obj, const jsval *valp, JSBool *bp)
    1034                 : {
    1035                 :     SLIM_LOG_WILL_MORPH(cx, obj);
    1036                 :     bool retval2;
    1037          167930 :     PRE_HELPER_STUB_NO_SLIM
    1038          167930 :     HasInstance(wrapper, cx, obj, *valp, &retval2, &retval);
    1039          167930 :     *bp = retval2;
    1040          167930 :     POST_HELPER_STUB
    1041                 : }
    1042                 : 
    1043                 : static void
    1044               0 : XPC_WN_Helper_Finalize(JSContext *cx, JSObject *obj)
    1045                 : {
    1046               0 :     nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
    1047               0 :     if (IS_SLIM_WRAPPER(obj)) {
    1048                 :         SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
    1049                 :                   ++sFinalizedSlimWrappers, obj, p));
    1050                 : 
    1051                 :         nsWrapperCache* cache;
    1052               0 :         CallQueryInterface(p, &cache);
    1053               0 :         cache->ClearWrapper();
    1054               0 :         NS_RELEASE(p);
    1055               0 :         return;
    1056                 :     }
    1057                 : 
    1058               0 :     XPCWrappedNative* wrapper = (XPCWrappedNative*)p;
    1059               0 :     if (!wrapper)
    1060               0 :         return;
    1061               0 :     wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
    1062               0 :     wrapper->FlatJSObjectFinalized();
    1063                 : }
    1064                 : 
    1065                 : static JSBool
    1066         1538913 : XPC_WN_Helper_NewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
    1067                 :                          JSObject **objp)
    1068                 : {
    1069         1538913 :     nsresult rv = NS_OK;
    1070         1538913 :     bool retval = true;
    1071         1538913 :     JSObject* obj2FromScriptable = nsnull;
    1072         1538913 :     if (IS_SLIM_WRAPPER(obj)) {
    1073                 :         XPCNativeScriptableInfo *si =
    1074            7467 :             GetSlimWrapperProto(obj)->GetScriptableInfo();
    1075            7467 :         if (!si->GetFlags().WantNewResolve())
    1076               0 :             return retval;
    1077                 : 
    1078            7467 :         NS_ASSERTION(si->GetFlags().AllowPropModsToPrototype() &&
    1079                 :                      !si->GetFlags().AllowPropModsDuringResolve(),
    1080                 :                      "We don't support these flags for slim wrappers!");
    1081                 : 
    1082            7467 :         rv = si->GetCallback()->NewResolve(nsnull, cx, obj, id, flags,
    1083            7467 :                                            &obj2FromScriptable, &retval);
    1084            7467 :         if (NS_FAILED(rv))
    1085               0 :             return Throw(rv, cx);
    1086                 : 
    1087            7467 :         if (obj2FromScriptable)
    1088               0 :             *objp = obj2FromScriptable;
    1089                 : 
    1090            7467 :         return retval;
    1091                 :     }
    1092                 : 
    1093         3062892 :     XPCCallContext ccx(JS_CALLER, cx, obj);
    1094         1531446 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
    1095         1531446 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
    1096                 : 
    1097         1531446 :     jsid old = ccx.SetResolveName(id);
    1098                 : 
    1099         1531446 :     XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
    1100         1531446 :     if (si && si->GetFlags().WantNewResolve()) {
    1101                 :         XPCWrappedNative* oldResolvingWrapper;
    1102         1385441 :         JSBool allowPropMods = si->GetFlags().AllowPropModsDuringResolve();
    1103                 : 
    1104         1385441 :         if (allowPropMods)
    1105          493604 :             oldResolvingWrapper = ccx.SetResolvingWrapper(wrapper);
    1106                 : 
    1107         1385441 :         rv = si->GetCallback()->NewResolve(wrapper, cx, obj, id, flags,
    1108         1385441 :                                            &obj2FromScriptable, &retval);
    1109                 : 
    1110         1385441 :         if (allowPropMods)
    1111          493604 :             (void)ccx.SetResolvingWrapper(oldResolvingWrapper);
    1112                 :     }
    1113                 : 
    1114         1531446 :     old = ccx.SetResolveName(old);
    1115         1531446 :     NS_ASSERTION(old == id, "bad nest");
    1116                 : 
    1117         1531446 :     if (NS_FAILED(rv)) {
    1118               0 :         return Throw(rv, cx);
    1119                 :     }
    1120                 : 
    1121         1531446 :     if (obj2FromScriptable) {
    1122          221880 :         *objp = obj2FromScriptable;
    1123         1309566 :     } else if (wrapper->HasMutatedSet()) {
    1124                 :         // We are here if scriptable did not resolve this property and
    1125                 :         // it *might* be in the instance set but not the proto set.
    1126                 : 
    1127           26513 :         XPCNativeSet* set = wrapper->GetSet();
    1128           26513 :         XPCNativeSet* protoSet = wrapper->HasProto() ?
    1129           26513 :                                     wrapper->GetProto()->GetSet() : nsnull;
    1130                 :         XPCNativeMember* member;
    1131                 :         XPCNativeInterface* iface;
    1132                 :         JSBool IsLocal;
    1133                 : 
    1134           26513 :         if (set->FindMember(id, &member, &iface, protoSet, &IsLocal) &&
    1135                 :             IsLocal) {
    1136                 :             XPCWrappedNative* oldResolvingWrapper;
    1137                 : 
    1138           25385 :             XPCNativeScriptableFlags siFlags(0);
    1139           25385 :             if (si)
    1140           25385 :                 siFlags = si->GetFlags();
    1141                 : 
    1142                 :             unsigned enumFlag =
    1143           25385 :                 siFlags.DontEnumStaticProps() ? 0 : JSPROP_ENUMERATE;
    1144                 : 
    1145                 :             XPCWrappedNative* wrapperForInterfaceNames =
    1146           25385 :                 siFlags.DontReflectInterfaceNames() ? nsnull : wrapper;
    1147                 : 
    1148                 :             JSBool resolved;
    1149           25385 :             oldResolvingWrapper = ccx.SetResolvingWrapper(wrapper);
    1150                 :             retval = DefinePropertyIfFound(ccx, obj, id,
    1151                 :                                            set, iface, member,
    1152                 :                                            wrapper->GetScope(),
    1153                 :                                            false,
    1154                 :                                            wrapperForInterfaceNames,
    1155                 :                                            nsnull, si,
    1156           25385 :                                            enumFlag, &resolved);
    1157           25385 :             (void)ccx.SetResolvingWrapper(oldResolvingWrapper);
    1158           25385 :             if (retval && resolved)
    1159           25385 :                 *objp = obj;
    1160                 :         }
    1161                 :     }
    1162                 : 
    1163         1531446 :     return retval;
    1164                 : }
    1165                 : 
    1166                 : /***************************************************************************/
    1167                 : 
    1168                 : /*
    1169                 :     Here are the enumerator cases:
    1170                 : 
    1171                 :     set jsclass enumerate to stub (unless noted otherwise)
    1172                 : 
    1173                 :     if ( helper wants new enumerate )
    1174                 :         if ( DONT_ENUM_STATICS )
    1175                 :             forward to scriptable enumerate
    1176                 :         else
    1177                 :             if ( set not mutated )
    1178                 :                 forward to scriptable enumerate
    1179                 :             else
    1180                 :                 call shared enumerate
    1181                 :                 forward to scriptable enumerate
    1182                 :     else if ( helper wants old enumerate )
    1183                 :         use this JSOp
    1184                 :         if ( DONT_ENUM_STATICS )
    1185                 :             call scriptable enumerate
    1186                 :             call stub
    1187                 :         else
    1188                 :             if ( set not mutated )
    1189                 :                 call scriptable enumerate
    1190                 :                 call stub
    1191                 :             else
    1192                 :                 call shared enumerate
    1193                 :                 call scriptable enumerate
    1194                 :                 call stub
    1195                 : 
    1196                 :     else //... if ( helper wants NO enumerate )
    1197                 :         if ( DONT_ENUM_STATICS )
    1198                 :             use enumerate stub - don't use this JSOp thing at all
    1199                 :         else
    1200                 :             do shared enumerate - don't use this JSOp thing at all
    1201                 : */
    1202                 : 
    1203                 : JSBool
    1204             353 : XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
    1205                 :                       jsval *statep, jsid *idp)
    1206                 : {
    1207             353 :     js::Class *clazz = js::GetObjectClass(obj);
    1208             353 :     if (!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) {
    1209                 :         // obj must be a prototype object or a wrapper w/o a
    1210                 :         // helper. Short circuit this call to the default
    1211                 :         // implementation.
    1212                 : 
    1213              35 :         return JS_EnumerateState(cx, obj, enum_op, statep, idp);
    1214                 :     }
    1215                 : 
    1216             318 :     MORPH_SLIM_WRAPPER(cx, obj);
    1217                 : 
    1218             636 :     XPCCallContext ccx(JS_CALLER, cx, obj);
    1219             318 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
    1220             318 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
    1221                 : 
    1222             318 :     XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
    1223             318 :     if (!si)
    1224               0 :         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
    1225                 : 
    1226             318 :     bool retval = true;
    1227                 :     nsresult rv;
    1228                 : 
    1229             318 :     if (si->GetFlags().WantNewEnumerate()) {
    1230              80 :         if (((enum_op == JSENUMERATE_INIT &&
    1231              13 :               !si->GetFlags().DontEnumStaticProps()) ||
    1232                 :              enum_op == JSENUMERATE_INIT_ALL) &&
    1233              13 :             wrapper->HasMutatedSet() &&
    1234              13 :             !XPC_WN_Shared_Enumerate(cx, obj)) {
    1235               0 :             *statep = JSVAL_NULL;
    1236               0 :             return false;
    1237                 :         }
    1238                 : 
    1239                 :         // XXX Might we really need to wrap this call and *also* call
    1240                 :         // js_ObjectOps.enumerate ???
    1241                 : 
    1242              41 :         rv = si->GetCallback()->
    1243              41 :             NewEnumerate(wrapper, cx, obj, enum_op, statep, idp, &retval);
    1244                 : 
    1245              67 :         if ((enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) &&
    1246              26 :             (NS_FAILED(rv) || !retval)) {
    1247               0 :             *statep = JSVAL_NULL;
    1248                 :         }
    1249                 : 
    1250              41 :         if (NS_FAILED(rv))
    1251               0 :             return Throw(rv, cx);
    1252              41 :         return retval;
    1253                 :     }
    1254                 : 
    1255             277 :     if (si->GetFlags().WantEnumerate()) {
    1256               0 :         if (enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) {
    1257               0 :             if ((enum_op == JSENUMERATE_INIT_ALL ||
    1258               0 :                  !si->GetFlags().DontEnumStaticProps()) &&
    1259               0 :                 wrapper->HasMutatedSet() &&
    1260               0 :                 !XPC_WN_Shared_Enumerate(cx, obj)) {
    1261               0 :                 *statep = JSVAL_NULL;
    1262               0 :                 return false;
    1263                 :             }
    1264               0 :             rv = si->GetCallback()->
    1265               0 :                 Enumerate(wrapper, cx, obj, &retval);
    1266                 : 
    1267               0 :             if (NS_FAILED(rv) || !retval)
    1268               0 :                 *statep = JSVAL_NULL;
    1269                 : 
    1270               0 :             if (NS_FAILED(rv))
    1271               0 :                 return Throw(rv, cx);
    1272               0 :             if (!retval)
    1273               0 :                 return false;
    1274                 :             // Then fall through and call the default implementation...
    1275                 :         }
    1276                 :     }
    1277                 : 
    1278                 :     // else call js_ObjectOps.enumerate...
    1279                 : 
    1280             277 :     return JS_EnumerateState(cx, obj, enum_op, statep, idp);
    1281                 : }
    1282                 : 
    1283                 : JSType
    1284            7482 : XPC_WN_JSOp_TypeOf_Object(JSContext *cx, JSObject *obj)
    1285                 : {
    1286            7482 :     return JSTYPE_OBJECT;
    1287                 : }
    1288                 : 
    1289                 : JSType
    1290               0 : XPC_WN_JSOp_TypeOf_Function(JSContext *cx, JSObject *obj)
    1291                 : {
    1292               0 :     return JSTYPE_FUNCTION;
    1293                 : }
    1294                 : 
    1295                 : void
    1296           13218 : XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj)
    1297                 : {
    1298                 :     // XXX Clear XrayWrappers?
    1299           13218 : }
    1300                 : 
    1301                 : namespace {
    1302                 : 
    1303                 : NS_STACK_CLASS class AutoPopJSContext
    1304                 : {
    1305                 : public:
    1306                 :   AutoPopJSContext(XPCJSContextStack *stack)
    1307                 :   : mCx(nsnull), mStack(stack)
    1308                 :   {
    1309                 :       NS_ASSERTION(stack, "Null stack!");
    1310                 :   }
    1311                 : 
    1312                 :   ~AutoPopJSContext()
    1313                 :   {
    1314                 :       if (mCx)
    1315                 :           mStack->Pop();
    1316                 :   }
    1317                 : 
    1318                 :   void PushIfNotTop(JSContext *cx)
    1319                 :   {
    1320                 :       NS_ASSERTION(cx, "Null context!");
    1321                 :       NS_ASSERTION(!mCx, "This class is only meant to be used once!");
    1322                 : 
    1323                 :       JSContext *cxTop = mStack->Peek();
    1324                 : 
    1325                 :       if (cxTop != cx && mStack->Push(cx))
    1326                 :           mCx = cx;
    1327                 :   }
    1328                 : 
    1329                 : private:
    1330                 :   JSContext *mCx;
    1331                 :   XPCJSContextStack *mStack;
    1332                 : };
    1333                 : 
    1334                 : } // namespace
    1335                 : 
    1336                 : JSObject*
    1337         2478743 : XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj)
    1338                 : {
    1339                 :     // None of the wrappers we could potentially hand out are threadsafe so
    1340                 :     // just hand out the given object.
    1341         2478743 :     if (!XPCPerThreadData::IsMainThread(cx))
    1342               0 :         return obj;
    1343                 : 
    1344         2478743 :     return JS_ObjectToOuterObject(cx, obj);
    1345                 : }
    1346                 : 
    1347                 : /***************************************************************************/
    1348                 : 
    1349                 : // static
    1350                 : XPCNativeScriptableInfo*
    1351          249788 : XPCNativeScriptableInfo::Construct(XPCCallContext& ccx,
    1352                 :                                    const XPCNativeScriptableCreateInfo* sci)
    1353                 : {
    1354          249788 :     NS_ASSERTION(sci, "bad param");
    1355          249788 :     NS_ASSERTION(sci->GetCallback(), "bad param");
    1356                 : 
    1357                 :     XPCNativeScriptableInfo* newObj =
    1358          499576 :         new XPCNativeScriptableInfo(sci->GetCallback());
    1359          249788 :     if (!newObj)
    1360               0 :         return nsnull;
    1361                 : 
    1362          249788 :     char* name = nsnull;
    1363          249788 :     if (NS_FAILED(sci->GetCallback()->GetClassName(&name)) || !name) {
    1364               0 :         delete newObj;
    1365               0 :         return nsnull;
    1366                 :     }
    1367                 : 
    1368                 :     JSBool success;
    1369                 : 
    1370          249788 :     XPCJSRuntime* rt = ccx.GetRuntime();
    1371          249788 :     XPCNativeScriptableSharedMap* map = rt->GetNativeScriptableSharedMap();
    1372                 :     {   // scoped lock
    1373          499576 :         XPCAutoLock lock(rt->GetMapLock());
    1374          249788 :         success = map->GetNewOrUsed(sci->GetFlags(), name,
    1375          499576 :                                     sci->GetInterfacesBitmap(), newObj);
    1376                 :     }
    1377                 : 
    1378          249788 :     if (!success) {
    1379               0 :         delete newObj;
    1380               0 :         return nsnull;
    1381                 :     }
    1382                 : 
    1383          249788 :     return newObj;
    1384                 : }
    1385                 : 
    1386                 : void
    1387           21231 : XPCNativeScriptableShared::PopulateJSClass()
    1388                 : {
    1389           21231 :     NS_ASSERTION(mJSClass.base.name, "bad state!");
    1390                 : 
    1391                 :     mJSClass.base.flags = WRAPPER_SLOTS |
    1392                 :                           JSCLASS_PRIVATE_IS_NSISUPPORTS |
    1393           21231 :                           JSCLASS_NEW_RESOLVE;
    1394                 : 
    1395           21231 :     if (mFlags.IsGlobalObject())
    1396            1391 :         mJSClass.base.flags |= XPCONNECT_GLOBAL_FLAGS;
    1397                 : 
    1398                 :     JSPropertyOp addProperty;
    1399           21231 :     if (mFlags.WantAddProperty())
    1400            1798 :         addProperty = XPC_WN_Helper_AddProperty;
    1401           19433 :     else if (mFlags.UseJSStubForAddProperty())
    1402            2354 :         addProperty = JS_PropertyStub;
    1403           17079 :     else if (mFlags.AllowPropModsDuringResolve())
    1404           13978 :         addProperty = XPC_WN_MaybeResolvingPropertyStub;
    1405                 :     else
    1406            3101 :         addProperty = XPC_WN_CannotModifyPropertyStub;
    1407           21231 :     mJSClass.base.addProperty = addProperty;
    1408                 : 
    1409                 :     JSPropertyOp delProperty;
    1410           21231 :     if (mFlags.WantDelProperty())
    1411               3 :         delProperty = XPC_WN_Helper_DelProperty;
    1412           21228 :     else if (mFlags.UseJSStubForDelProperty())
    1413            4149 :         delProperty = JS_PropertyStub;
    1414           17079 :     else if (mFlags.AllowPropModsDuringResolve())
    1415           13978 :         delProperty = XPC_WN_MaybeResolvingPropertyStub;
    1416                 :     else
    1417            3101 :         delProperty = XPC_WN_CannotModifyPropertyStub;
    1418           21231 :     mJSClass.base.delProperty = delProperty;
    1419                 : 
    1420           21231 :     if (mFlags.WantGetProperty())
    1421            2391 :         mJSClass.base.getProperty = XPC_WN_Helper_GetProperty;
    1422                 :     else
    1423           18840 :         mJSClass.base.getProperty = JS_PropertyStub;
    1424                 : 
    1425                 :     JSStrictPropertyOp setProperty;
    1426           21231 :     if (mFlags.WantSetProperty())
    1427            1905 :         setProperty = XPC_WN_Helper_SetProperty;
    1428           19326 :     else if (mFlags.UseJSStubForSetProperty())
    1429            4153 :         setProperty = JS_StrictPropertyStub;
    1430           15173 :     else if (mFlags.AllowPropModsDuringResolve())
    1431           12072 :         setProperty = XPC_WN_MaybeResolvingStrictPropertyStub;
    1432                 :     else
    1433            3101 :         setProperty = XPC_WN_CannotModifyStrictPropertyStub;
    1434           21231 :     mJSClass.base.setProperty = setProperty;
    1435                 : 
    1436                 :     // We figure out most of the enumerate strategy at call time.
    1437                 : 
    1438           34564 :     if (mFlags.WantNewEnumerate() || mFlags.WantEnumerate() ||
    1439           13333 :         mFlags.DontEnumStaticProps())
    1440           10961 :         mJSClass.base.enumerate = JS_EnumerateStub;
    1441                 :     else
    1442           10270 :         mJSClass.base.enumerate = XPC_WN_Shared_Enumerate;
    1443                 : 
    1444                 :     // We have to figure out resolve strategy at call time
    1445           21231 :     mJSClass.base.resolve = (JSResolveOp) XPC_WN_Helper_NewResolve;
    1446                 : 
    1447           21231 :     if (mFlags.WantConvert())
    1448               0 :         mJSClass.base.convert = XPC_WN_Helper_Convert;
    1449                 :     else
    1450           21231 :         mJSClass.base.convert = XPC_WN_Shared_Convert;
    1451                 : 
    1452           21231 :     if (mFlags.WantFinalize())
    1453               0 :         mJSClass.base.finalize = XPC_WN_Helper_Finalize;
    1454                 :     else
    1455           21231 :         mJSClass.base.finalize = XPC_WN_NoHelper_Finalize;
    1456                 : 
    1457                 :     // We let the rest default to nsnull unless the helper wants them...
    1458           21231 :     if (mFlags.WantCheckAccess())
    1459            2621 :         mJSClass.base.checkAccess = XPC_WN_Helper_CheckAccess;
    1460                 : 
    1461                 :     // Note that we *must* set the ObjectOps (even for the cases were it does
    1462                 :     // not do much) because with these dynamically generated JSClasses, the
    1463                 :     // code in XPCWrappedNative::GetWrappedNativeOfJSObject() needs to look
    1464                 :     // for that these callback pointers in order to identify that a given
    1465                 :     // JSObject represents a wrapper.
    1466           21231 :     js::ObjectOps *ops = &mJSClass.base.ops;
    1467           21231 :     ops->enumerate = XPC_WN_JSOp_Enumerate;
    1468           21231 :     ops->clear = XPC_WN_JSOp_Clear;
    1469           21231 :     ops->thisObject = XPC_WN_JSOp_ThisObject;
    1470                 : 
    1471           21231 :     if (mFlags.WantCall() || mFlags.WantConstruct()) {
    1472            5178 :         ops->typeOf = XPC_WN_JSOp_TypeOf_Function;
    1473            5178 :         if (mFlags.WantCall())
    1474            3508 :             mJSClass.base.call = XPC_WN_Helper_Call;
    1475            5178 :         if (mFlags.WantConstruct())
    1476            4900 :             mJSClass.base.construct = XPC_WN_Helper_Construct;
    1477                 :     } else {
    1478           16053 :         ops->typeOf = XPC_WN_JSOp_TypeOf_Object;
    1479                 :     }
    1480                 : 
    1481           21231 :     if (mFlags.UseStubEqualityHook()) {
    1482            1370 :         NS_ASSERTION(!mFlags.WantEquality(),
    1483                 :                      "If you want an Equality callback, you can't use a stub "
    1484                 :                      "equality hook");
    1485            1370 :         mJSClass.base.ext.equality = nsnull;
    1486                 :     } else {
    1487           19861 :         mJSClass.base.ext.equality = XPC_WN_Equality;
    1488                 :     }
    1489                 : 
    1490           21231 :     if (mFlags.WantHasInstance())
    1491            5415 :         mJSClass.base.hasInstance = XPC_WN_Helper_HasInstance;
    1492                 : 
    1493           21231 :     mJSClass.base.trace = XPC_WN_NoHelper_Trace;
    1494                 : 
    1495           21231 :     if (mFlags.WantOuterObject())
    1496               0 :         mJSClass.base.ext.outerObject = XPC_WN_OuterObject;
    1497                 : 
    1498           21231 :     if (!(mFlags & nsIXPCScriptable::WANT_OUTER_OBJECT))
    1499           21231 :         mCanBeSlim = true;
    1500                 : 
    1501           21231 :     mJSClass.base.ext.isWrappedNative = true;
    1502           21231 : }
    1503                 : 
    1504                 : /***************************************************************************/
    1505                 : /***************************************************************************/
    1506                 : 
    1507                 : JSBool
    1508         4364331 : XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp)
    1509                 : {
    1510         4364331 :     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
    1511         4364331 :     JSObject* funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
    1512                 : 
    1513         4364331 :     JSObject* obj = JS_THIS_OBJECT(cx, vp);
    1514         4364331 :     if (!obj)
    1515               0 :         return false;
    1516                 : 
    1517                 : #ifdef DEBUG_slimwrappers
    1518                 :     {
    1519                 :         JSFunction* fun = funobj->getFunctionPrivate();
    1520                 :         JSString *funid = JS_GetFunctionId(fun);
    1521                 :         JSAutoByteString bytes;
    1522                 :         const char *funname = !funid ? "" : bytes.encode(cx, funid) ? bytes.ptr() : "<error>";
    1523                 :         SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
    1524                 :     }
    1525                 : #endif
    1526         4364331 :     if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
    1527               0 :         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
    1528                 : 
    1529         8728662 :     XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOID, argc, JS_ARGV(cx, vp), vp);
    1530         4364331 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
    1531         4364331 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
    1532                 : 
    1533                 :     XPCNativeInterface* iface;
    1534                 :     XPCNativeMember*    member;
    1535                 : 
    1536         4364331 :     if (!XPCNativeMember::GetCallInfo(ccx, funobj, &iface, &member))
    1537               0 :         return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
    1538         4364331 :     ccx.SetCallInfo(iface, member, false);
    1539         4364331 :     return XPCWrappedNative::CallMethod(ccx);
    1540                 : }
    1541                 : 
    1542                 : JSBool
    1543         2357439 : XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp)
    1544                 : {
    1545         2357439 :     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
    1546         2357439 :     JSObject* funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
    1547                 : 
    1548         2357439 :     JSObject* obj = JS_THIS_OBJECT(cx, vp);
    1549         2357439 :     if (!obj)
    1550               0 :         return false;
    1551                 : 
    1552                 : #ifdef DEBUG_slimwrappers
    1553                 :     {
    1554                 :         const char* funname = nsnull;
    1555                 :         JSAutoByteString bytes;
    1556                 :         if (JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION) {
    1557                 :             JSString *funid = JS_GetFunctionId(funobj->getFunctionPrivate());
    1558                 :             funname = !funid ? "" : bytes.encode(cx, funid) ? bytes.ptr() : "<error>";
    1559                 :         }
    1560                 :         SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
    1561                 :     }
    1562                 : #endif
    1563         2357439 :     if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
    1564               0 :         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
    1565                 : 
    1566         4714878 :     XPCCallContext ccx(JS_CALLER, cx, obj, funobj);
    1567         2357439 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
    1568         2357439 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
    1569                 : 
    1570                 :     XPCNativeInterface* iface;
    1571                 :     XPCNativeMember*    member;
    1572                 : 
    1573         2357439 :     if (!XPCNativeMember::GetCallInfo(ccx, funobj, &iface, &member))
    1574               0 :         return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
    1575                 : 
    1576         2357439 :     ccx.SetArgsAndResultPtr(argc, JS_ARGV(cx, vp), vp);
    1577         2357439 :     if (argc && member->IsWritableAttribute()) {
    1578          102335 :         ccx.SetCallInfo(iface, member, true);
    1579          102335 :         JSBool retval = XPCWrappedNative::SetAttribute(ccx);
    1580          102335 :         if (retval)
    1581          102216 :             *vp = JS_ARGV(cx, vp)[0];
    1582          102335 :         return retval;
    1583                 :     }
    1584                 :     // else...
    1585                 : 
    1586         2255104 :     ccx.SetCallInfo(iface, member, false);
    1587         2255104 :     return XPCWrappedNative::GetAttribute(ccx);
    1588                 : }
    1589                 : 
    1590                 : /***************************************************************************/
    1591                 : 
    1592                 : static JSBool
    1593               4 : XPC_WN_Shared_Proto_Enumerate(JSContext *cx, JSObject *obj)
    1594                 : {
    1595               4 :     NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
    1596                 :                  js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass ||
    1597                 :                  js::GetObjectClass(obj) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
    1598                 :                  js::GetObjectClass(obj) == &XPC_WN_NoMods_NoCall_Proto_JSClass,
    1599                 :                  "bad proto");
    1600                 :     XPCWrappedNativeProto* self =
    1601               4 :         (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
    1602               4 :     if (!self)
    1603               0 :         return false;
    1604                 : 
    1605               4 :     if (self->GetScriptableInfo() &&
    1606               0 :         self->GetScriptableInfo()->GetFlags().DontEnumStaticProps())
    1607               0 :         return true;
    1608                 : 
    1609               4 :     XPCNativeSet* set = self->GetSet();
    1610               4 :     if (!set)
    1611               0 :         return false;
    1612                 : 
    1613               8 :     XPCCallContext ccx(JS_CALLER, cx);
    1614               4 :     if (!ccx.IsValid())
    1615               0 :         return false;
    1616               4 :     ccx.SetScopeForNewJSObjects(obj);
    1617                 : 
    1618               4 :     PRUint16 interface_count = set->GetInterfaceCount();
    1619               4 :     XPCNativeInterface** interfaceArray = set->GetInterfaceArray();
    1620              16 :     for (PRUint16 i = 0; i < interface_count; i++) {
    1621              12 :         XPCNativeInterface* iface = interfaceArray[i];
    1622              12 :         PRUint16 member_count = iface->GetMemberCount();
    1623                 : 
    1624             103 :         for (PRUint16 k = 0; k < member_count; k++) {
    1625              91 :             if (!xpc_ForcePropertyResolve(cx, obj, iface->GetMemberAt(k)->GetName()))
    1626               0 :                 return false;
    1627                 :         }
    1628                 :     }
    1629                 : 
    1630               4 :     return true;
    1631                 : }
    1632                 : 
    1633                 : static void
    1634          186868 : XPC_WN_Shared_Proto_Finalize(JSContext *cx, JSObject *obj)
    1635                 : {
    1636                 :     // This can be null if xpc shutdown has already happened
    1637          186868 :     XPCWrappedNativeProto* p = (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
    1638          186868 :     if (p)
    1639          186781 :         p->JSProtoObjectFinalized(cx, obj);
    1640          186868 : }
    1641                 : 
    1642                 : static void
    1643          891643 : XPC_WN_Shared_Proto_Trace(JSTracer *trc, JSObject *obj)
    1644                 : {
    1645                 :     // This can be null if xpc shutdown has already happened
    1646                 :     XPCWrappedNativeProto* p =
    1647          891643 :         (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
    1648          891643 :     if (p)
    1649          891565 :         TraceScopeJSObjects(trc, p->GetScope());
    1650          891643 : }
    1651                 : 
    1652                 : /*****************************************************/
    1653                 : 
    1654                 : static JSBool
    1655            1042 : XPC_WN_ModsAllowed_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id)
    1656                 : {
    1657            1042 :     NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass ||
    1658                 :                  js::GetObjectClass(obj) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass,
    1659                 :                  "bad proto");
    1660                 : 
    1661                 :     XPCWrappedNativeProto* self =
    1662            1042 :         (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
    1663            1042 :     if (!self)
    1664               0 :         return false;
    1665                 : 
    1666            2084 :     XPCCallContext ccx(JS_CALLER, cx);
    1667            1042 :     if (!ccx.IsValid())
    1668               0 :         return false;
    1669            1042 :     ccx.SetScopeForNewJSObjects(obj);
    1670                 : 
    1671            1042 :     XPCNativeScriptableInfo* si = self->GetScriptableInfo();
    1672            1042 :     unsigned enumFlag = (si && si->GetFlags().DontEnumStaticProps()) ?
    1673            2084 :                                                 0 : JSPROP_ENUMERATE;
    1674                 : 
    1675                 :     return DefinePropertyIfFound(ccx, obj, id,
    1676                 :                                  self->GetSet(), nsnull, nsnull,
    1677                 :                                  self->GetScope(),
    1678                 :                                  true, nsnull, nsnull, si,
    1679            1042 :                                  enumFlag, nsnull);
    1680                 : }
    1681                 : 
    1682                 : js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass = {
    1683                 :     "XPC_WN_ModsAllowed_WithCall_Proto_JSClass", // name;
    1684                 :     WRAPPER_SLOTS, // flags;
    1685                 : 
    1686                 :     /* Mandatory non-null function pointer members. */
    1687                 :     JS_PropertyStub,                // addProperty;
    1688                 :     JS_PropertyStub,                // delProperty;
    1689                 :     JS_PropertyStub,                // getProperty;
    1690                 :     JS_StrictPropertyStub,          // setProperty;
    1691                 :     XPC_WN_Shared_Proto_Enumerate,  // enumerate;
    1692                 :     XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
    1693                 :     JS_ConvertStub,                 // convert;
    1694                 :     XPC_WN_Shared_Proto_Finalize,   // finalize;
    1695                 : 
    1696                 :     /* Optionally non-null members start here. */
    1697                 :     nsnull,                         // checkAccess;
    1698                 :     nsnull,                         // call;
    1699                 :     nsnull,                         // construct;
    1700                 :     nsnull,                         // hasInstance;
    1701                 :     XPC_WN_Shared_Proto_Trace,      // trace;
    1702                 : 
    1703                 :     JS_NULL_CLASS_EXT,
    1704                 :     XPC_WN_WithCall_ObjectOps
    1705                 : };
    1706                 : 
    1707                 : js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass = {
    1708                 :     "XPC_WN_ModsAllowed_NoCall_Proto_JSClass", // name;
    1709                 :     WRAPPER_SLOTS,                  // flags;
    1710                 : 
    1711                 :     /* Mandatory non-null function pointer members. */
    1712                 :     JS_PropertyStub,                // addProperty;
    1713                 :     JS_PropertyStub,                // delProperty;
    1714                 :     JS_PropertyStub,                // getProperty;
    1715                 :     JS_StrictPropertyStub,          // setProperty;
    1716                 :     XPC_WN_Shared_Proto_Enumerate,  // enumerate;
    1717                 :     XPC_WN_ModsAllowed_Proto_Resolve, // resolve;
    1718                 :     JS_ConvertStub,                 // convert;
    1719                 :     XPC_WN_Shared_Proto_Finalize,   // finalize;
    1720                 : 
    1721                 :     /* Optionally non-null members start here. */
    1722                 :     nsnull,                         // checkAccess;
    1723                 :     nsnull,                         // call;
    1724                 :     nsnull,                         // construct;
    1725                 :     nsnull,                         // hasInstance;
    1726                 :     XPC_WN_Shared_Proto_Trace,      // trace;
    1727                 : 
    1728                 :     JS_NULL_CLASS_EXT,
    1729                 :     XPC_WN_NoCall_ObjectOps
    1730                 : };
    1731                 : 
    1732                 : /***************************************************************************/
    1733                 : 
    1734                 : static JSBool
    1735          144878 : XPC_WN_OnlyIWrite_Proto_AddPropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
    1736                 : {
    1737          144878 :     NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
    1738                 :                  js::GetObjectClass(obj) == &XPC_WN_NoMods_NoCall_Proto_JSClass,
    1739                 :                  "bad proto");
    1740                 : 
    1741                 :     XPCWrappedNativeProto* self =
    1742          144878 :         (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
    1743          144878 :     if (!self)
    1744               0 :         return false;
    1745                 : 
    1746          289756 :     XPCCallContext ccx(JS_CALLER, cx);
    1747          144878 :     if (!ccx.IsValid())
    1748               0 :         return false;
    1749          144878 :     ccx.SetScopeForNewJSObjects(obj);
    1750                 : 
    1751                 :     // Allow XPConnect to add the property only
    1752          144878 :     if (ccx.GetResolveName() == id)
    1753          144878 :         return true;
    1754                 : 
    1755               0 :     return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
    1756                 : }
    1757                 : 
    1758                 : static JSBool
    1759               0 : XPC_WN_OnlyIWrite_Proto_SetPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
    1760                 :                                         jsval *vp)
    1761                 : {
    1762               0 :     return XPC_WN_OnlyIWrite_Proto_AddPropertyStub(cx, obj, id, vp);
    1763                 : }
    1764                 : 
    1765                 : static JSBool
    1766         1118956 : XPC_WN_NoMods_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id)
    1767                 : {
    1768         1118956 :     NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
    1769                 :                  js::GetObjectClass(obj) == &XPC_WN_NoMods_NoCall_Proto_JSClass,
    1770                 :                  "bad proto");
    1771                 : 
    1772                 :     XPCWrappedNativeProto* self =
    1773         1118956 :         (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
    1774         1118956 :     if (!self)
    1775               0 :         return false;
    1776                 : 
    1777         2237912 :     XPCCallContext ccx(JS_CALLER, cx);
    1778         1118956 :     if (!ccx.IsValid())
    1779               0 :         return false;
    1780         1118956 :     ccx.SetScopeForNewJSObjects(obj);
    1781                 : 
    1782         1118956 :     XPCNativeScriptableInfo* si = self->GetScriptableInfo();
    1783          107208 :     unsigned enumFlag = (si && si->GetFlags().DontEnumStaticProps()) ?
    1784         1226164 :                                                 0 : JSPROP_ENUMERATE;
    1785                 : 
    1786                 :     return DefinePropertyIfFound(ccx, obj, id,
    1787                 :                                  self->GetSet(), nsnull, nsnull,
    1788                 :                                  self->GetScope(),
    1789                 :                                  true, nsnull, nsnull, si,
    1790                 :                                  JSPROP_READONLY |
    1791                 :                                  JSPROP_PERMANENT |
    1792         1118956 :                                  enumFlag, nsnull);
    1793                 : }
    1794                 : 
    1795                 : js::Class XPC_WN_NoMods_WithCall_Proto_JSClass = {
    1796                 :     "XPC_WN_NoMods_WithCall_Proto_JSClass",    // name;
    1797                 :     WRAPPER_SLOTS,                             // flags;
    1798                 : 
    1799                 :     /* Mandatory non-null function pointer members. */
    1800                 :     XPC_WN_OnlyIWrite_Proto_AddPropertyStub,   // addProperty;
    1801                 :      XPC_WN_CannotModifyPropertyStub,          // delProperty;
    1802                 :     JS_PropertyStub,                           // getProperty;
    1803                 :     XPC_WN_OnlyIWrite_Proto_SetPropertyStub,   // setProperty;
    1804                 :     XPC_WN_Shared_Proto_Enumerate,             // enumerate;
    1805                 :     XPC_WN_NoMods_Proto_Resolve,               // resolve;
    1806                 :     JS_ConvertStub,                            // convert;
    1807                 :     XPC_WN_Shared_Proto_Finalize,              // finalize;
    1808                 : 
    1809                 :     /* Optionally non-null members start here. */
    1810                 :     nsnull,                         // checkAccess;
    1811                 :     nsnull,                         // call;
    1812                 :     nsnull,                         // construct;
    1813                 :     nsnull,                         // hasInstance;
    1814                 :     XPC_WN_Shared_Proto_Trace,      // trace;
    1815                 : 
    1816                 :     JS_NULL_CLASS_EXT,
    1817                 :     XPC_WN_WithCall_ObjectOps
    1818                 : };
    1819                 : 
    1820                 : js::Class XPC_WN_NoMods_NoCall_Proto_JSClass = {
    1821                 :     "XPC_WN_NoMods_NoCall_Proto_JSClass",      // name;
    1822                 :     WRAPPER_SLOTS,                             // flags;
    1823                 : 
    1824                 :     /* Mandatory non-null function pointer members. */
    1825                 :     XPC_WN_OnlyIWrite_Proto_AddPropertyStub,   // addProperty;
    1826                 :     XPC_WN_CannotModifyPropertyStub,           // delProperty;
    1827                 :     JS_PropertyStub,                           // getProperty;
    1828                 :     XPC_WN_OnlyIWrite_Proto_SetPropertyStub,   // setProperty;
    1829                 :     XPC_WN_Shared_Proto_Enumerate,             // enumerate;
    1830                 :     XPC_WN_NoMods_Proto_Resolve,               // resolve;
    1831                 :     JS_ConvertStub,                            // convert;
    1832                 :     XPC_WN_Shared_Proto_Finalize,              // finalize;
    1833                 : 
    1834                 :     /* Optionally non-null members start here. */
    1835                 :     nsnull,                         // checkAccess;
    1836                 :     nsnull,                         // call;
    1837                 :     nsnull,                         // construct;
    1838                 :     nsnull,                         // hasInstance;
    1839                 :     XPC_WN_Shared_Proto_Trace,      // trace;
    1840                 : 
    1841                 :     JS_NULL_CLASS_EXT,
    1842                 :     XPC_WN_NoCall_ObjectOps
    1843                 : };
    1844                 : 
    1845                 : /***************************************************************************/
    1846                 : 
    1847                 : static JSBool
    1848               0 : XPC_WN_TearOff_Enumerate(JSContext *cx, JSObject *obj)
    1849                 : {
    1850               0 :     MORPH_SLIM_WRAPPER(cx, obj);
    1851               0 :     XPCCallContext ccx(JS_CALLER, cx, obj);
    1852               0 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
    1853               0 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
    1854                 : 
    1855               0 :     XPCWrappedNativeTearOff* to = ccx.GetTearOff();
    1856                 :     XPCNativeInterface* iface;
    1857                 : 
    1858               0 :     if (!to || nsnull == (iface = to->GetInterface()))
    1859               0 :         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
    1860                 : 
    1861               0 :     PRUint16 member_count = iface->GetMemberCount();
    1862               0 :     for (PRUint16 k = 0; k < member_count; k++) {
    1863               0 :         if (!xpc_ForcePropertyResolve(cx, obj, iface->GetMemberAt(k)->GetName()))
    1864               0 :             return false;
    1865                 :     }
    1866                 : 
    1867               0 :     return true;
    1868                 : }
    1869                 : 
    1870                 : static JSBool
    1871              79 : XPC_WN_TearOff_Resolve(JSContext *cx, JSObject *obj, jsid id)
    1872                 : {
    1873              79 :     MORPH_SLIM_WRAPPER(cx, obj);
    1874             158 :     XPCCallContext ccx(JS_CALLER, cx, obj);
    1875              79 :     XPCWrappedNative* wrapper = ccx.GetWrapper();
    1876              79 :     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
    1877                 : 
    1878              79 :     XPCWrappedNativeTearOff* to = ccx.GetTearOff();
    1879                 :     XPCNativeInterface* iface;
    1880                 : 
    1881              79 :     if (!to || nsnull == (iface = to->GetInterface()))
    1882               0 :         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
    1883                 : 
    1884                 :     return DefinePropertyIfFound(ccx, obj, id, nsnull, iface, nsnull,
    1885                 :                                  wrapper->GetScope(),
    1886                 :                                  true, nsnull, nsnull, nsnull,
    1887                 :                                  JSPROP_READONLY |
    1888                 :                                  JSPROP_PERMANENT |
    1889              79 :                                  JSPROP_ENUMERATE, nsnull);
    1890                 : }
    1891                 : 
    1892                 : static void
    1893              60 : XPC_WN_TearOff_Finalize(JSContext *cx, JSObject *obj)
    1894                 : {
    1895                 :     XPCWrappedNativeTearOff* p = (XPCWrappedNativeTearOff*)
    1896              60 :         xpc_GetJSPrivate(obj);
    1897              60 :     if (!p)
    1898              41 :         return;
    1899              19 :     p->JSObjectFinalized();
    1900                 : }
    1901                 : 
    1902                 : js::Class XPC_WN_Tearoff_JSClass = {
    1903                 :     "WrappedNative_TearOff",                   // name;
    1904                 :     WRAPPER_SLOTS,                             // flags;
    1905                 : 
    1906                 :     XPC_WN_OnlyIWrite_AddPropertyStub,         // addProperty;
    1907                 :     XPC_WN_CannotModifyPropertyStub,           // delProperty;
    1908                 :     JS_PropertyStub,                           // getProperty;
    1909                 :     XPC_WN_OnlyIWrite_SetPropertyStub,         // setProperty;
    1910                 :     XPC_WN_TearOff_Enumerate,                  // enumerate;
    1911                 :     XPC_WN_TearOff_Resolve,                    // resolve;
    1912                 :     XPC_WN_Shared_Convert,                     // convert;
    1913                 :     XPC_WN_TearOff_Finalize                    // finalize;
    1914                 : };

Generated by: LCOV version 1.7