js/jsd/jsd_val.cpp

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /*
     8  * JavaScript Debugging support - Value and Property support
     9  */
    11 #include "jsd.h"
    12 #include "jsapi.h"
    13 #include "jsfriendapi.h"
    14 #include "jswrapper.h"
    15 #include "nsCxPusher.h"
    17 using mozilla::AutoSafeJSContext;
    19 #ifdef DEBUG
    20 void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
    21 {
    22     MOZ_ASSERT(jsdval);
    23     MOZ_ASSERT(jsdval->nref > 0);
    24     if(!JS_CLIST_IS_EMPTY(&jsdval->props))
    25     {
    26         MOZ_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
    27         MOZ_ASSERT(!JSVAL_IS_PRIMITIVE(jsdval->val));
    28     }
    30     if(jsdval->proto)
    31     {
    32         MOZ_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
    33         MOZ_ASSERT(jsdval->proto->nref > 0);
    34     }
    35     if(jsdval->parent)
    36     {
    37         MOZ_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
    38         MOZ_ASSERT(jsdval->parent->nref > 0);
    39     }
    40     if(jsdval->ctor)
    41     {
    42         MOZ_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
    43         MOZ_ASSERT(jsdval->ctor->nref > 0);
    44     }
    45 }
    47 void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
    48 {
    49     MOZ_ASSERT(jsdprop);
    50     MOZ_ASSERT(jsdprop->name);
    51     MOZ_ASSERT(jsdprop->name->nref > 0);
    52     MOZ_ASSERT(jsdprop->val);
    53     MOZ_ASSERT(jsdprop->val->nref > 0);
    54     if(jsdprop->alias)
    55         MOZ_ASSERT(jsdprop->alias->nref > 0);
    56 }
    57 #endif
    60 bool
    61 jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
    62 {
    63     return !JSVAL_IS_PRIMITIVE(jsdval->val) || JSVAL_IS_NULL(jsdval->val);
    64 }
    66 bool
    67 jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
    68 {
    69     return JSVAL_IS_NUMBER(jsdval->val);
    70 }
    72 bool
    73 jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
    74 {
    75     return JSVAL_IS_INT(jsdval->val);
    76 }
    78 bool
    79 jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
    80 {
    81     return JSVAL_IS_DOUBLE(jsdval->val);
    82 }
    84 bool
    85 jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
    86 {
    87     return JSVAL_IS_STRING(jsdval->val);
    88 }
    90 bool
    91 jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
    92 {
    93     return JSVAL_IS_BOOLEAN(jsdval->val);
    94 }
    96 bool
    97 jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
    98 {
    99     return JSVAL_IS_NULL(jsdval->val);
   100 }
   102 bool
   103 jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
   104 {
   105     return JSVAL_IS_VOID(jsdval->val);
   106 }
   108 bool
   109 jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
   110 {
   111     return JSVAL_IS_PRIMITIVE(jsdval->val);
   112 }
   114 bool
   115 jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
   116 {
   117     AutoSafeJSContext cx; // NB: Actually unused.
   118     return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
   119            JS_ObjectIsCallable(cx, JSVAL_TO_OBJECT(jsdval->val));
   120 }
   122 bool
   123 jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
   124 {
   125     AutoSafeJSContext cx;
   126     JS::RootedFunction fun(cx);
   128     if(jsd_IsValueFunction(jsdc, jsdval))
   129     {
   130         JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(jsdval->val));
   131         AutoSaveExceptionState as(cx);
   132         bool ok = false;
   133         fun = JSD_GetValueFunction(jsdc, jsdval);
   134         if(fun)
   135             ok = JS_GetFunctionScript(cx, fun) ? false : true;
   136         MOZ_ASSERT(fun);
   137         return ok;
   138     }
   139     return !JSVAL_IS_PRIMITIVE(jsdval->val);
   140 }
   142 /***************************************************************************/
   144 bool
   145 jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
   146 {
   147     jsval val = jsdval->val;
   148     if(!JSVAL_IS_BOOLEAN(val))
   149         return false;
   150     return JSVAL_TO_BOOLEAN(val);
   151 }
   153 int32_t
   154 jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
   155 {
   156     jsval val = jsdval->val;
   157     if(!JSVAL_IS_INT(val))
   158         return 0;
   159     return JSVAL_TO_INT(val);
   160 }
   162 double
   163 jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
   164 {
   165     if(!JSVAL_IS_DOUBLE(jsdval->val))
   166         return 0;
   167     return JSVAL_TO_DOUBLE(jsdval->val);
   168 }
   170 JSString*
   171 jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
   172 {
   173     AutoSafeJSContext cx;
   174     JS::RootedValue stringval(cx);
   175     JS::RootedString string(cx);
   176     JS::RootedObject scopeObj(cx);
   178     if(jsdval->string)
   179         return jsdval->string;
   181     /* Reuse the string without copying or re-rooting it */
   182     if(JSVAL_IS_STRING(jsdval->val)) {
   183         jsdval->string = JSVAL_TO_STRING(jsdval->val);
   184         return jsdval->string;
   185     }
   187     /* Objects call JS_ValueToString in their own compartment. */
   188     scopeObj = !JSVAL_IS_PRIMITIVE(jsdval->val) ? JSVAL_TO_OBJECT(jsdval->val) : jsdc->glob;
   189     {
   190         JSAutoCompartment ac(cx, scopeObj);
   191         AutoSaveExceptionState as(cx);
   192         JS::RootedValue v(cx, jsdval->val);
   193         string = JS::ToString(cx, v);
   194     }
   196     JSAutoCompartment ac2(cx, jsdc->glob);
   197     if(string) {
   198         stringval = STRING_TO_JSVAL(string);
   199     }
   200     if(!string || !JS_WrapValue(cx, &stringval)) {
   201         return nullptr;
   202     }
   204     jsdval->string = JSVAL_TO_STRING(stringval);
   205     if(!JS::AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
   206         jsdval->string = nullptr;
   208     return jsdval->string;
   209 }
   211 JSString*
   212 jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval)
   213 {
   214     AutoSafeJSContext cx;
   215     JS::RootedFunction fun(cx);
   217     if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval))
   218     {
   219         JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(jsdval->val));
   220         AutoSaveExceptionState as(cx);
   221         fun = JSD_GetValueFunction(jsdc, jsdval);
   222         if(!fun)
   223             return nullptr;
   224         jsdval->funName = JS_GetFunctionId(fun);
   226         /* For compatibility we return "anonymous", not an empty string here. */
   227         if (!jsdval->funName)
   228             jsdval->funName = JS_GetAnonymousString(jsdc->jsrt);
   229     }
   230     return jsdval->funName;
   231 }
   233 /***************************************************************************/
   235 /*
   236  * Create a new JSD value referring to a jsval. Copy string values into the
   237  * JSD compartment. Leave all other GCTHINGs in their native compartments
   238  * and access them through cross-compartment calls.
   239  */
   240 JSDValue*
   241 jsd_NewValue(JSDContext* jsdc, jsval value)
   242 {
   243     JS::RootedValue val(jsdc->jsrt, value);
   244     AutoSafeJSContext cx;
   245     JSDValue* jsdval;
   247     if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
   248         return nullptr;
   250     if(JSVAL_IS_GCTHING(val))
   251     {
   252         bool ok;
   253         JSAutoCompartment ac(cx, jsdc->glob);
   255         ok = JS::AddNamedValueRoot(cx, &jsdval->val, "JSDValue");
   256         if(ok && JSVAL_IS_STRING(val)) {
   257             if(!JS_WrapValue(cx, &val)) {
   258                 ok = false;
   259             }
   260         }
   262         if(!ok)
   263         {
   264             free(jsdval);
   265             return nullptr;
   266         }
   267     }
   268     jsdval->val  = val;
   269     jsdval->nref = 1;
   270     JS_INIT_CLIST(&jsdval->props);
   272     return jsdval;
   273 }
   275 void
   276 jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
   277 {
   278     MOZ_ASSERT(jsdval->nref > 0);
   279     if(0 == --jsdval->nref)
   280     {
   281         jsd_RefreshValue(jsdc, jsdval);
   282         if(JSVAL_IS_GCTHING(jsdval->val))
   283         {
   284             AutoSafeJSContext cx;
   285             JSAutoCompartment ac(cx, jsdc->glob);
   286             JS::RemoveValueRoot(cx, &jsdval->val);
   287         }
   288         free(jsdval);
   289     }
   290 }
   292 jsval
   293 jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
   294 {
   295     AutoSafeJSContext cx;
   296     JS::RootedValue val(cx, jsdval->val);
   297     if (!val.isPrimitive()) {
   298         JS::RootedObject obj(cx, &val.toObject());
   299         JSAutoCompartment ac(cx, obj);
   300         obj = JS_ObjectToOuterObject(cx, obj);
   301         if (!obj)
   302         {
   303             JS_ClearPendingException(cx);
   304             val = JSVAL_NULL;
   305         }
   306         else
   307             val = JS::ObjectValue(*obj);
   308     }
   310     return val;
   311 }
   313 static JSDProperty* _newProperty(JSDContext* jsdc, JS::HandleValue propId,
   314                                  JS::HandleValue propValue, JS::HandleValue propAlias,
   315                                  uint8_t propFlags, unsigned additionalFlags)
   316 {
   317     JSDProperty* jsdprop;
   319     if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
   320         return nullptr;
   322     JS_INIT_CLIST(&jsdprop->links);
   323     jsdprop->nref = 1;
   324     jsdprop->flags = propFlags | additionalFlags;
   326     if(!(jsdprop->name = jsd_NewValue(jsdc, propId)))
   327         goto new_prop_fail;
   329     if(!(jsdprop->val = jsd_NewValue(jsdc, propValue)))
   330         goto new_prop_fail;
   332     if((jsdprop->flags & JSDPD_ALIAS) &&
   333        !(jsdprop->alias = jsd_NewValue(jsdc, propAlias)))
   334         goto new_prop_fail;
   336     return jsdprop;
   337 new_prop_fail:
   338     jsd_DropProperty(jsdc, jsdprop);
   339     return nullptr;
   340 }
   342 static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
   343 {
   344     JSDProperty* jsdprop;
   346     while(jsdprop = (JSDProperty*)jsdval->props.next,
   347           jsdprop != (JSDProperty*)&jsdval->props)
   348     {
   349         JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
   350         jsd_DropProperty(jsdc, jsdprop);
   351     }
   352     MOZ_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
   353     CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
   354 }
   356 static bool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
   357 {
   358     AutoSafeJSContext cx;
   359     JS::RootedObject obj(cx);
   360     JSPropertyDescArray pda;
   361     unsigned i;
   363     MOZ_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
   364     MOZ_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
   365     MOZ_ASSERT(!JSVAL_IS_PRIMITIVE(jsdval->val));
   367     if(JSVAL_IS_PRIMITIVE(jsdval->val))
   368         return false;
   370     obj = JSVAL_TO_OBJECT(jsdval->val);
   372     JSAutoCompartment ac(cx, obj);
   374     if(!JS_GetPropertyDescArray(cx, obj, &pda))
   375     {
   376         return false;
   377     }
   379     JS::RootedValue propId(cx);
   380     JS::RootedValue propValue(cx);
   381     JS::RootedValue propAlias(cx);
   382     uint8_t propFlags;
   383     for(i = 0; i < pda.length; i++)
   384     {
   385         propId = pda.array[i].id;
   386         propValue = pda.array[i].value;
   387         propAlias = pda.array[i].alias;
   388         propFlags = pda.array[i].flags;
   389         JSDProperty* prop = _newProperty(jsdc, propId, propValue, propAlias, propFlags, 0);
   390         if(!prop)
   391         {
   392             _freeProps(jsdc, jsdval);
   393             break;
   394         }
   395         JS_APPEND_LINK(&prop->links, &jsdval->props);
   396     }
   397     JS_PutPropertyDescArray(cx, &pda);
   398     SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
   399     return !JS_CLIST_IS_EMPTY(&jsdval->props);
   400 }
   402 #undef  DROP_CLEAR_VALUE
   403 #define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = nullptr;}
   405 void
   406 jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
   407 {
   408     AutoSafeJSContext cx;
   409     if(jsdval->string)
   410     {
   411         /* if the jsval is a string, then we didn't need to root the string */
   412         if(!JSVAL_IS_STRING(jsdval->val))
   413         {
   414             JSAutoCompartment ac(cx, jsdc->glob);
   415             JS::RemoveStringRoot(cx, &jsdval->string);
   416         }
   417         jsdval->string = nullptr;
   418     }
   420     jsdval->funName = nullptr;
   421     jsdval->className = nullptr;
   422     DROP_CLEAR_VALUE(jsdc, jsdval->proto);
   423     DROP_CLEAR_VALUE(jsdc, jsdval->parent);
   424     DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
   425     _freeProps(jsdc, jsdval);
   426     jsdval->flags = 0;
   427 }
   429 /***************************************************************************/
   431 unsigned
   432 jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
   433 {
   434     JSDProperty* jsdprop;
   435     unsigned count = 0;
   437     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
   438         if(!_buildProps(jsdc, jsdval))
   439             return 0;
   441     for(jsdprop = (JSDProperty*)jsdval->props.next;
   442         jsdprop != (JSDProperty*)&jsdval->props;
   443         jsdprop = (JSDProperty*)jsdprop->links.next)
   444     {
   445         count++;
   446     }
   447     return count;
   448 }
   450 JSDProperty*
   451 jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
   452 {
   453     JSDProperty* jsdprop = *iterp;
   454     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
   455     {
   456         MOZ_ASSERT(!jsdprop);
   457         if(!_buildProps(jsdc, jsdval))
   458             return nullptr;
   459     }
   461     if(!jsdprop)
   462         jsdprop = (JSDProperty*)jsdval->props.next;
   463     if(jsdprop == (JSDProperty*)&jsdval->props)
   464         return nullptr;
   465     *iterp = (JSDProperty*)jsdprop->links.next;
   467     MOZ_ASSERT(jsdprop);
   468     jsdprop->nref++;
   469     return jsdprop;
   470 }
   472 JSDProperty*
   473 jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
   474 {
   475     JS::RootedString name(jsdc->jsrt, nameStr);
   476     AutoSafeJSContext cx;
   477     JSAutoCompartment acBase(cx, jsdc->glob);
   478     JSDProperty* jsdprop;
   479     JSDProperty* iter = nullptr;
   480     JS::RootedObject obj(cx);
   481     JS::RootedValue val(cx), nameval(cx);
   482     JS::RootedId nameid(cx);
   483     JS::RootedValue propId(cx);
   484     JS::RootedValue propValue(cx);
   485     JS::RootedValue propAlias(cx);
   486     uint8_t propFlags;
   488     if(!jsd_IsValueObject(jsdc, jsdval))
   489         return nullptr;
   491     /* If we already have the prop, then return it */
   492     while(nullptr != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
   493     {
   494         JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
   495         if(propName) {
   496             int result;
   497             if (JS_CompareStrings(cx, propName, name, &result) && !result)
   498                 return jsdprop;
   499         }
   500         JSD_DropProperty(jsdc, jsdprop);
   501     }
   502     /* Not found in property list, look it up explicitly */
   504     nameval = STRING_TO_JSVAL(name);
   505     if(!JS_ValueToId(cx, nameval, &nameid))
   506         return nullptr;
   508     if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
   509         return nullptr;
   511     JS::Rooted<JSPropertyDescriptor> desc(cx);
   512     {
   513         JSAutoCompartment ac(cx, obj);
   514         JS::RootedId id(cx, nameid);
   516         if(!JS_WrapId(cx, &id))
   517             return nullptr;
   518         if(!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc))
   519             return nullptr;
   520         if(!desc.object())
   521             return nullptr;
   523         JS_ClearPendingException(cx);
   525         if(!JS_GetPropertyById(cx, obj, id, &val))
   526         {
   527             if (JS_IsExceptionPending(cx))
   528             {
   529                 if (!JS_GetPendingException(cx, &propValue))
   530                 {
   531                     return nullptr;
   532                 }
   533                 propFlags = JSPD_EXCEPTION;
   534             }
   535             else
   536             {
   537                 propFlags = JSPD_ERROR;
   538                 propValue = JSVAL_VOID;
   539             }
   540         }
   541         else
   542         {
   543             propValue = val;
   544         }
   545     }
   547     if (!JS_IdToValue(cx, nameid, &propId))
   548         return nullptr;
   550     propAlias = JSVAL_NULL;
   551     propFlags |= desc.isEnumerable() ? JSPD_ENUMERATE : 0
   552         | desc.isReadonly() ? JSPD_READONLY  : 0
   553         | desc.isPermanent() ? JSPD_PERMANENT : 0;
   555     return _newProperty(jsdc, propId, propValue, propAlias, propFlags, JSDPD_HINTED);
   556 }
   558 /*
   559  * Retrieve a JSFunction* from a JSDValue*. This differs from
   560  * JS_ValueToFunction by fully unwrapping the object first.
   561  */
   562 JSFunction*
   563 jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval)
   564 {
   565     AutoSafeJSContext cx;
   567     JS::RootedObject obj(cx);
   568     JS::RootedFunction fun(cx);
   570     if (JSVAL_IS_PRIMITIVE(jsdval->val))
   571         return nullptr;
   573     obj = js::UncheckedUnwrap(JSVAL_TO_OBJECT(jsdval->val));
   574     JSAutoCompartment ac(cx, obj);
   575     JS::RootedValue funval(cx, JS::ObjectValue(*obj));
   576     fun = JS_ValueToFunction(cx, funval);
   578     return fun;
   579 }
   581 JSDValue*
   582 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
   583 {
   584     AutoSafeJSContext cx;
   585     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
   586     {
   587         JS::RootedObject obj(cx);
   588         JS::RootedObject proto(cx);
   589         MOZ_ASSERT(!jsdval->proto);
   590         SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
   591         if(JSVAL_IS_PRIMITIVE(jsdval->val))
   592             return nullptr;
   593         obj = JSVAL_TO_OBJECT(jsdval->val);
   594         if(!JS_GetPrototype(cx, obj, &proto))
   595             return nullptr;
   596         if(!proto)
   597             return nullptr;
   598         jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
   599     }
   600     if(jsdval->proto)
   601         jsdval->proto->nref++;
   602     return jsdval->proto;
   603 }
   605 JSDValue*
   606 jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
   607 {
   608     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
   609     {
   610         AutoSafeJSContext cx;
   611         JS::RootedObject obj(cx);
   612         JS::RootedObject parent(cx);
   613         MOZ_ASSERT(!jsdval->parent);
   614         SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
   615         if(JSVAL_IS_PRIMITIVE(jsdval->val))
   616             return nullptr;
   617         obj = JSVAL_TO_OBJECT(jsdval->val);
   618         {
   619             JSAutoCompartment ac(cx, obj);
   620             parent = JS_GetParentOrScopeChain(cx, obj);
   621         }
   622         if(!parent)
   623             return nullptr;
   624         jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
   625     }
   626     if(jsdval->parent)
   627         jsdval->parent->nref++;
   628     return jsdval->parent;
   629 }
   631 JSDValue*
   632 jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
   633 {
   634     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
   635     {
   636         AutoSafeJSContext cx;
   637         JS::RootedObject obj(cx);
   638         JS::RootedObject proto(cx);
   639         JS::RootedObject ctor(cx);
   640         MOZ_ASSERT(!jsdval->ctor);
   641         SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
   642         if(JSVAL_IS_PRIMITIVE(jsdval->val))
   643             return nullptr;
   644         obj = JSVAL_TO_OBJECT(jsdval->val);
   645         if(!JS_GetPrototype(cx, obj, &proto))
   646             return nullptr;
   647         if(!proto)
   648             return nullptr;
   649         {
   650             JSAutoCompartment ac(cx, obj);
   651             ctor = JS_GetConstructor(cx, proto);
   652         }
   653         if(!ctor)
   654             return nullptr;
   655         jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
   656     }
   657     if(jsdval->ctor)
   658         jsdval->ctor->nref++;
   659     return jsdval->ctor;
   660 }
   662 const char*
   663 jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
   664 {
   665     jsval val = jsdval->val;
   666     if(!jsdval->className && !JSVAL_IS_PRIMITIVE(val))
   667     {
   668         JS::RootedObject obj(jsdc->jsrt, JSVAL_TO_OBJECT(val));
   669         AutoSafeJSContext cx;
   670         JSAutoCompartment ac(cx, obj);
   671         jsdval->className = JS_GetDebugClassName(obj);
   672     }
   673     return jsdval->className;
   674 }
   676 JSDScript*
   677 jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
   678 {
   679     AutoSafeJSContext cx;
   680     JS::RootedValue val(cx, jsdval->val);
   681     JS::RootedScript script(cx);
   682     JSDScript* jsdscript;
   684     if (!jsd_IsValueFunction(jsdc, jsdval))
   685         return nullptr;
   687     {
   688         JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(val));
   689         AutoSaveExceptionState as(cx);
   690         JS::RootedFunction fun(cx, JSD_GetValueFunction(jsdc, jsdval));
   691         if (fun)
   692             script = JS_GetFunctionScript(cx, fun);
   693     }
   695     if (!script)
   696         return nullptr;
   698     JSD_LOCK_SCRIPTS(jsdc);
   699     jsdscript = jsd_FindJSDScript(jsdc, script);
   700     JSD_UNLOCK_SCRIPTS(jsdc);
   701     return jsdscript;
   702 }
   705 /***************************************************************************/
   706 /***************************************************************************/
   708 JSDValue*
   709 jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
   710 {
   711     jsdprop->name->nref++;
   712     return jsdprop->name;
   713 }
   715 JSDValue*
   716 jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
   717 {
   718     jsdprop->val->nref++;
   719     return jsdprop->val;
   720 }
   722 JSDValue*
   723 jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
   724 {
   725     if(jsdprop->alias)
   726         jsdprop->alias->nref++;
   727     return jsdprop->alias;
   728 }
   730 unsigned
   731 jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
   732 {
   733     return jsdprop->flags;
   734 }
   736 void
   737 jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
   738 {
   739     MOZ_ASSERT(jsdprop->nref > 0);
   740     if(0 == --jsdprop->nref)
   741     {
   742         MOZ_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
   743         DROP_CLEAR_VALUE(jsdc, jsdprop->val);
   744         DROP_CLEAR_VALUE(jsdc, jsdprop->name);
   745         DROP_CLEAR_VALUE(jsdc, jsdprop->alias);
   746         free(jsdprop);
   747     }
   748 }

mercurial