LCOV - app.info - js/jsd/jsd_val.c

LCOV - code coverage report
| Current view: | directory - js/jsd - jsd_val.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 472 | 82 | 17.4 %
| Date: | 2012-07-07 | Functions: | 40 | 7 | 17.5 %

           1                 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : /*
          39                 :  * JavaScript Debugging support - Value and Property support
          40                 :  */
          41                 :
          42                 : #include "jsd.h"
          43                 : #include "jsapi.h"
          44                 : #include "jsfriendapi.h"
          45                 :
          46                 : #ifdef DEBUG
          47               4 : void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
          48                 : {
          49               4 :     JS_ASSERT(jsdval);
          50               4 :     JS_ASSERT(jsdval->nref > 0);
          51               4 :     if(!JS_CLIST_IS_EMPTY(&jsdval->props))
          52                 :     {
          53               0 :         JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
          54               0 :         JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
          55                 :     }
          56                 :
          57               4 :     if(jsdval->proto)
          58                 :     {
          59               0 :         JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
          60               0 :         JS_ASSERT(jsdval->proto->nref > 0);
          61                 :     }
          62               4 :     if(jsdval->parent)
          63                 :     {
          64               2 :         JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
          65               2 :         JS_ASSERT(jsdval->parent->nref > 0);
          66                 :     }
          67               4 :     if(jsdval->ctor)
          68                 :     {
          69               0 :         JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
          70               0 :         JS_ASSERT(jsdval->ctor->nref > 0);
          71                 :     }
          72               4 : }
          73                 :
          74               0 : void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
          75                 : {
          76               0 :     JS_ASSERT(jsdprop);
          77               0 :     JS_ASSERT(jsdprop->name);
          78               0 :     JS_ASSERT(jsdprop->name->nref > 0);
          79               0 :     JS_ASSERT(jsdprop->val);
          80               0 :     JS_ASSERT(jsdprop->val->nref > 0);
          81               0 :     if(jsdprop->alias)
          82               0 :         JS_ASSERT(jsdprop->alias->nref > 0);
          83               0 : }
          84                 : #endif
          85                 :
          86                 :
          87                 : JSBool
          88               0 : jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
          89                 : {
          90               0 :     return JSVAL_IS_OBJECT(jsdval->val);
          91                 : }
          92                 :
          93                 : JSBool
          94               0 : jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
          95                 : {
          96               0 :     return JSVAL_IS_NUMBER(jsdval->val);
          97                 : }
          98                 :
          99                 : JSBool
         100               0 : jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
         101                 : {
         102               0 :     return JSVAL_IS_INT(jsdval->val);
         103                 : }
         104                 :
         105                 : JSBool
         106               0 : jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
         107                 : {
         108               0 :     return JSVAL_IS_DOUBLE(jsdval->val);
         109                 : }
         110                 :
         111                 : JSBool
         112               0 : jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
         113                 : {
         114               0 :     return JSVAL_IS_STRING(jsdval->val);
         115                 : }
         116                 :
         117                 : JSBool
         118               0 : jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
         119                 : {
         120               0 :     return JSVAL_IS_BOOLEAN(jsdval->val);
         121                 : }
         122                 :
         123                 : JSBool
         124               0 : jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
         125                 : {
         126               0 :     return JSVAL_IS_NULL(jsdval->val);
         127                 : }
         128                 :
         129                 : JSBool
         130               0 : jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
         131                 : {
         132               0 :     return JSVAL_IS_VOID(jsdval->val);
         133                 : }
         134                 :
         135                 : JSBool
         136               0 : jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
         137                 : {
         138               0 :     return JSVAL_IS_PRIMITIVE(jsdval->val);
         139                 : }
         140                 :
         141                 : JSBool
         142               0 : jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
         143                 : {
         144               0 :     return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
         145               0 :            JS_ObjectIsCallable(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
         146                 : }
         147                 :
         148                 : JSBool
         149               0 : jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
         150                 : {
         151               0 :     JSContext* cx = jsdc->dumbContext;
         152                 :     JSFunction* fun;
         153                 :     JSExceptionState* exceptionState;
         154               0 :     JSCrossCompartmentCall *call = NULL;
         155                 :
         156               0 :     if(jsd_IsValueFunction(jsdc, jsdval))
         157                 :     {
         158               0 :         JSBool ok = JS_FALSE;
         159               0 :         JS_BeginRequest(cx);
         160               0 :         call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
         161               0 :         if(!call) {
         162               0 :             JS_EndRequest(cx);
         163                 :
         164               0 :             return JS_FALSE;
         165                 :         }
         166                 :
         167               0 :         exceptionState = JS_SaveExceptionState(cx);
         168               0 :         fun = JSD_GetValueFunction(jsdc, jsdval);
         169               0 :         JS_RestoreExceptionState(cx, exceptionState);
         170               0 :         if(fun)
         171               0 :             ok = JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
         172               0 :         JS_LeaveCrossCompartmentCall(call);
         173               0 :         JS_EndRequest(cx);
         174               0 :         JS_ASSERT(fun);
         175               0 :         return ok;
         176                 :     }
         177               0 :     return !JSVAL_IS_PRIMITIVE(jsdval->val);
         178                 : }
         179                 :
         180                 : /***************************************************************************/
         181                 :
         182                 : JSBool
         183               0 : jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
         184                 : {
         185               0 :     jsval val = jsdval->val;
         186               0 :     if(!JSVAL_IS_BOOLEAN(val))
         187               0 :         return JS_FALSE;
         188               0 :     return JSVAL_TO_BOOLEAN(val);
         189                 : }
         190                 :
         191                 : int32_t
         192               0 : jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
         193                 : {
         194               0 :     jsval val = jsdval->val;
         195               0 :     if(!JSVAL_IS_INT(val))
         196               0 :         return 0;
         197               0 :     return JSVAL_TO_INT(val);
         198                 : }
         199                 :
         200                 : double
         201               0 : jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
         202                 : {
         203               0 :     if(!JSVAL_IS_DOUBLE(jsdval->val))
         204               0 :         return 0;
         205               0 :     return JSVAL_TO_DOUBLE(jsdval->val);
         206                 : }
         207                 :
         208                 : JSString*
         209               0 : jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
         210                 : {
         211               0 :     JSContext* cx = jsdc->dumbContext;
         212                 :     JSExceptionState* exceptionState;
         213               0 :     JSCrossCompartmentCall *call = NULL;
         214                 :     jsval stringval;
         215                 :     JSString *string;
         216                 :     JSBool needWrap;
         217                 :     JSObject *scopeObj;
         218                 :
         219               0 :     if(jsdval->string)
         220               0 :         return jsdval->string;
         221                 :
         222                 :     /* Reuse the string without copying or re-rooting it */
         223               0 :     if(JSVAL_IS_STRING(jsdval->val)) {
         224               0 :         jsdval->string = JSVAL_TO_STRING(jsdval->val);
         225               0 :         return jsdval->string;
         226                 :     }
         227                 :
         228               0 :     JS_BeginRequest(cx);
         229                 :
         230                 :     /* Objects call JS_ValueToString in their own compartment. */
         231               0 :     scopeObj = !JSVAL_IS_PRIMITIVE(jsdval->val) ? JSVAL_TO_OBJECT(jsdval->val) : jsdc->glob;
         232               0 :     call = JS_EnterCrossCompartmentCall(cx, scopeObj);
         233               0 :     if(!call) {
         234               0 :         JS_EndRequest(cx);
         235               0 :         return NULL;
         236                 :     }
         237               0 :     exceptionState = JS_SaveExceptionState(cx);
         238                 :
         239               0 :     string = JS_ValueToString(cx, jsdval->val);
         240                 :
         241               0 :     JS_RestoreExceptionState(cx, exceptionState);
         242               0 :     JS_LeaveCrossCompartmentCall(call);
         243               0 :     call = NULL;
         244                 :
         245               0 :     if(string) {
         246               0 :         stringval = STRING_TO_JSVAL(string);
         247               0 :         call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
         248                 :     }
         249               0 :     if(!string || !call || !JS_WrapValue(cx, &stringval)) {
         250               0 :         if(call)
         251               0 :             JS_LeaveCrossCompartmentCall(call);
         252               0 :         JS_EndRequest(cx);
         253               0 :         return NULL;
         254                 :     }
         255                 :
         256               0 :     jsdval->string = JSVAL_TO_STRING(stringval);
         257               0 :     if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
         258               0 :         jsdval->string = NULL;
         259                 :
         260               0 :     JS_LeaveCrossCompartmentCall(call);
         261               0 :     JS_EndRequest(cx);
         262                 :
         263               0 :     return jsdval->string;
         264                 : }
         265                 :
         266                 : JSString*
         267               0 : jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval)
         268                 : {
         269               0 :     JSContext* cx = jsdc->dumbContext;
         270                 :     JSFunction* fun;
         271                 :     JSExceptionState* exceptionState;
         272               0 :     JSCrossCompartmentCall *call = NULL;
         273                 :
         274               0 :     if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval))
         275                 :     {
         276               0 :         JS_BeginRequest(cx);
         277                 :
         278               0 :         call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
         279               0 :         if(!call) {
         280               0 :             JS_EndRequest(cx);
         281                 :
         282               0 :             return NULL;
         283                 :         }
         284                 :
         285               0 :         exceptionState = JS_SaveExceptionState(cx);
         286               0 :         fun = JSD_GetValueFunction(jsdc, jsdval);
         287               0 :         JS_RestoreExceptionState(cx, exceptionState);
         288               0 :         JS_LeaveCrossCompartmentCall(call);
         289               0 :         JS_EndRequest(cx);
         290               0 :         if(!fun)
         291               0 :             return NULL;
         292               0 :         jsdval->funName = JS_GetFunctionId(fun);
         293                 :
         294                 :         /* For compatibility we return "anonymous", not an empty string here. */
         295               0 :         if (!jsdval->funName)
         296               0 :             jsdval->funName = JS_GetAnonymousString(jsdc->jsrt);
         297                 :     }
         298               0 :     return jsdval->funName;
         299                 : }
         300                 :
         301                 : /***************************************************************************/
         302                 :
         303                 : /*
         304                 :  * Create a new JSD value referring to a jsval. Copy string values into the
         305                 :  * JSD compartment. Leave all other GCTHINGs in their native compartments
         306                 :  * and access them through cross-compartment calls.
         307                 :  */
         308                 : JSDValue*
         309               2 : jsd_NewValue(JSDContext* jsdc, jsval val)
         310                 : {
         311                 :     JSDValue* jsdval;
         312               2 :     JSCrossCompartmentCall *call = NULL;
         313                 :
         314               2 :     if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
         315               0 :         return NULL;
         316                 :
         317               2 :     if(JSVAL_IS_GCTHING(val))
         318                 :     {
         319                 :         JSBool ok;
         320               2 :         JS_BeginRequest(jsdc->dumbContext);
         321                 :
         322               2 :         call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
         323               2 :         if(!call) {
         324               0 :             JS_EndRequest(jsdc->dumbContext);
         325               0 :             free(jsdval);
         326               0 :             return NULL;
         327                 :         }
         328                 :
         329               2 :         ok = JS_AddNamedValueRoot(jsdc->dumbContext, &jsdval->val, "JSDValue");
         330               2 :         if(ok && JSVAL_IS_STRING(val)) {
         331               0 :             if(!JS_WrapValue(jsdc->dumbContext, &val)) {
         332               0 :                 ok = JS_FALSE;
         333                 :             }
         334                 :         }
         335                 :
         336               2 :         JS_LeaveCrossCompartmentCall(call);
         337               2 :         JS_EndRequest(jsdc->dumbContext);
         338               2 :         if(!ok)
         339                 :         {
         340               0 :             free(jsdval);
         341               0 :             return NULL;
         342                 :         }
         343                 :     }
         344               2 :     jsdval->val  = val;
         345               2 :     jsdval->nref = 1;
         346               2 :     JS_INIT_CLIST(&jsdval->props);
         347                 :
         348               2 :     return jsdval;
         349                 : }
         350                 :
         351                 : void
         352               3 : jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
         353                 : {
         354               3 :     JSCrossCompartmentCall *call = NULL;
         355                 :
         356               3 :     JS_ASSERT(jsdval->nref > 0);
         357               3 :     if(0 == --jsdval->nref)
         358                 :     {
         359               2 :         jsd_RefreshValue(jsdc, jsdval);
         360               2 :         if(JSVAL_IS_GCTHING(jsdval->val))
         361                 :         {
         362               2 :             JS_BeginRequest(jsdc->dumbContext);
         363               2 :             call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
         364               2 :             if(!call) {
         365               0 :                 JS_EndRequest(jsdc->dumbContext);
         366                 :
         367               0 :                 return;
         368                 :             }
         369                 :
         370               2 :             JS_RemoveValueRoot(jsdc->dumbContext, &jsdval->val);
         371               2 :             JS_LeaveCrossCompartmentCall(call);
         372               2 :             JS_EndRequest(jsdc->dumbContext);
         373                 :         }
         374               2 :         free(jsdval);
         375                 :     }
         376                 : }
         377                 :
         378                 : jsval
         379               1 : jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
         380                 : {
         381                 :     JSObject* obj;
         382                 :     JSContext* cx;
         383               1 :     jsval val = jsdval->val;
         384               1 :     if (!JSVAL_IS_PRIMITIVE(val)) {
         385               1 :         cx = JSD_GetDefaultJSContext(jsdc);
         386               1 :         obj = JS_ObjectToOuterObject(cx, JSVAL_TO_OBJECT(val));
         387               1 :         if (!obj)
         388                 :         {
         389               0 :             JS_ClearPendingException(cx);
         390               0 :             val = JSVAL_NULL;
         391                 :         }
         392                 :         else
         393               1 :             val = OBJECT_TO_JSVAL(obj);
         394                 :     }
         395                 :
         396               1 :     return val;
         397                 : }
         398                 :
         399               0 : static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
         400                 :                                  unsigned additionalFlags)
         401                 : {
         402                 :     JSDProperty* jsdprop;
         403                 :
         404               0 :     if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
         405               0 :         return NULL;
         406                 :
         407               0 :     JS_INIT_CLIST(&jsdprop->links);
         408               0 :     jsdprop->nref = 1;
         409               0 :     jsdprop->flags = pd->flags | additionalFlags;
         410               0 :     jsdprop->slot = pd->slot;
         411                 :
         412               0 :     if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
         413               0 :         goto new_prop_fail;
         414                 :
         415               0 :     if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
         416               0 :         goto new_prop_fail;
         417                 :
         418               0 :     if((jsdprop->flags & JSDPD_ALIAS) &&
         419               0 :        !(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
         420               0 :         goto new_prop_fail;
         421                 :
         422               0 :     return jsdprop;
         423                 : new_prop_fail:
         424               0 :     jsd_DropProperty(jsdc, jsdprop);
         425               0 :     return NULL;
         426                 : }
         427                 :
         428               2 : static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
         429                 : {
         430                 :     JSDProperty* jsdprop;
         431                 :
         432               6 :     while(jsdprop = (JSDProperty*)jsdval->props.next,
         433               2 :           jsdprop != (JSDProperty*)&jsdval->props)
         434                 :     {
         435               0 :         JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
         436               0 :         jsd_DropProperty(jsdc, jsdprop);
         437                 :     }
         438               2 :     JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
         439               2 :     CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
         440               2 : }
         441                 :
         442               0 : static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
         443                 : {
         444               0 :     JSContext* cx = jsdc->dumbContext;
         445                 :     JSObject *obj;
         446                 :     JSPropertyDescArray pda;
         447                 :     unsigned i;
         448               0 :     JSCrossCompartmentCall *call = NULL;
         449                 :
         450               0 :     JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
         451               0 :     JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
         452               0 :     JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
         453                 :
         454               0 :     if(JSVAL_IS_PRIMITIVE(jsdval->val))
         455               0 :         return JS_FALSE;
         456                 :
         457               0 :     obj = JSVAL_TO_OBJECT(jsdval->val);
         458                 :
         459               0 :     JS_BeginRequest(cx);
         460               0 :     call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
         461               0 :     if(!call)
         462                 :     {
         463               0 :         JS_EndRequest(jsdc->dumbContext);
         464               0 :         return JS_FALSE;
         465                 :     }
         466                 :
         467               0 :     if(!JS_GetPropertyDescArray(cx, obj, &pda))
         468                 :     {
         469               0 :         JS_EndRequest(cx);
         470               0 :         JS_LeaveCrossCompartmentCall(call);
         471               0 :         return JS_FALSE;
         472                 :     }
         473                 :
         474               0 :     for(i = 0; i < pda.length; i++)
         475                 :     {
         476               0 :         JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
         477               0 :         if(!prop)
         478                 :         {
         479               0 :             _freeProps(jsdc, jsdval);
         480               0 :             break;
         481                 :         }
         482               0 :         JS_APPEND_LINK(&prop->links, &jsdval->props);
         483                 :     }
         484               0 :     JS_PutPropertyDescArray(cx, &pda);
         485               0 :     JS_LeaveCrossCompartmentCall(call);
         486               0 :     JS_EndRequest(cx);
         487               0 :     SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
         488               0 :     return !JS_CLIST_IS_EMPTY(&jsdval->props);
         489                 : }
         490                 :
         491                 : #undef  DROP_CLEAR_VALUE
         492                 : #define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
         493                 :
         494                 : void
         495               2 : jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
         496                 : {
         497               2 :     JSContext* cx = jsdc->dumbContext;
         498               2 :     JSCrossCompartmentCall *call = NULL;
         499                 :
         500               2 :     if(jsdval->string)
         501                 :     {
         502                 :         /* if the jsval is a string, then we didn't need to root the string */
         503               0 :         if(!JSVAL_IS_STRING(jsdval->val))
         504                 :         {
         505               0 :             JS_BeginRequest(cx);
         506               0 :             call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
         507               0 :             if(!call) {
         508               0 :                 JS_EndRequest(cx);
         509                 :
         510               0 :                 return;
         511                 :             }
         512                 :
         513               0 :             JS_RemoveStringRoot(cx, &jsdval->string);
         514               0 :             JS_LeaveCrossCompartmentCall(call);
         515               0 :             JS_EndRequest(cx);
         516                 :         }
         517               0 :         jsdval->string = NULL;
         518                 :     }
         519                 :
         520               2 :     jsdval->funName = NULL;
         521               2 :     jsdval->className = NULL;
         522               2 :     DROP_CLEAR_VALUE(jsdc, jsdval->proto);
         523               2 :     DROP_CLEAR_VALUE(jsdc, jsdval->parent);
         524               2 :     DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
         525               2 :     _freeProps(jsdc, jsdval);
         526               2 :     jsdval->flags = 0;
         527                 : }
         528                 :
         529                 : /***************************************************************************/
         530                 :
         531                 : unsigned
         532               0 : jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
         533                 : {
         534                 :     JSDProperty* jsdprop;
         535               0 :     unsigned count = 0;
         536                 :
         537               0 :     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
         538               0 :         if(!_buildProps(jsdc, jsdval))
         539               0 :             return 0;
         540                 :
         541               0 :     for(jsdprop = (JSDProperty*)jsdval->props.next;
         542               0 :         jsdprop != (JSDProperty*)&jsdval->props;
         543               0 :         jsdprop = (JSDProperty*)jsdprop->links.next)
         544                 :     {
         545               0 :         count++;
         546                 :     }
         547               0 :     return count;
         548                 : }
         549                 :
         550                 : JSDProperty*
         551               0 : jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
         552                 : {
         553               0 :     JSDProperty* jsdprop = *iterp;
         554               0 :     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
         555                 :     {
         556               0 :         JS_ASSERT(!jsdprop);
         557               0 :         if(!_buildProps(jsdc, jsdval))
         558               0 :             return NULL;
         559                 :     }
         560                 :
         561               0 :     if(!jsdprop)
         562               0 :         jsdprop = (JSDProperty*)jsdval->props.next;
         563               0 :     if(jsdprop == (JSDProperty*)&jsdval->props)
         564               0 :         return NULL;
         565               0 :     *iterp = (JSDProperty*)jsdprop->links.next;
         566                 :
         567               0 :     JS_ASSERT(jsdprop);
         568               0 :     jsdprop->nref++;
         569               0 :     return jsdprop;
         570                 : }
         571                 :
         572                 : JSDProperty*
         573               0 : jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
         574                 : {
         575               0 :     JSContext* cx = jsdc->dumbContext;
         576                 :     JSDProperty* jsdprop;
         577               0 :     JSDProperty* iter = NULL;
         578                 :     JSObject* obj;
         579               0 :     unsigned  attrs = 0;
         580                 :     JSBool found;
         581                 :     JSPropertyDesc pd;
         582                 :     const jschar * nameChars;
         583                 :     size_t nameLen;
         584                 :     jsval val, nameval;
         585                 :     jsid nameid;
         586               0 :     JSCrossCompartmentCall *call = NULL;
         587                 :
         588               0 :     if(!jsd_IsValueObject(jsdc, jsdval))
         589               0 :         return NULL;
         590                 :
         591                 :     /* If we already have the prop, then return it */
         592               0 :     while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
         593                 :     {
         594               0 :         JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
         595               0 :         if(propName) {
         596                 :             int result;
         597               0 :             if (JS_CompareStrings(cx, propName, name, &result) && !result)
         598               0 :                 return jsdprop;
         599                 :         }
         600               0 :         JSD_DropProperty(jsdc, jsdprop);
         601                 :     }
         602                 :     /* Not found in property list, look it up explicitly */
         603                 :
         604               0 :     if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         605               0 :         return NULL;
         606                 :
         607               0 :     if (!(nameChars = JS_GetStringCharsZAndLength(cx, name, &nameLen)))
         608               0 :         return NULL;
         609                 :
         610               0 :     JS_BeginRequest(cx);
         611               0 :     call = JS_EnterCrossCompartmentCall(cx, obj);
         612               0 :     if(!call) {
         613               0 :         JS_EndRequest(cx);
         614                 :
         615               0 :         return NULL;
         616                 :     }
         617                 :
         618               0 :     JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
         619               0 :     if (!found)
         620                 :     {
         621               0 :         JS_LeaveCrossCompartmentCall(call);
         622               0 :         JS_EndRequest(cx);
         623               0 :         return NULL;
         624                 :     }
         625                 :
         626               0 :     JS_ClearPendingException(cx);
         627                 :
         628               0 :     if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
         629                 :     {
         630               0 :         if (JS_IsExceptionPending(cx))
         631                 :         {
         632               0 :             if (!JS_GetPendingException(cx, &pd.value))
         633                 :             {
         634               0 :                 JS_LeaveCrossCompartmentCall(call);
         635               0 :                 JS_EndRequest(cx);
         636               0 :                 return NULL;
         637                 :             }
         638               0 :             pd.flags = JSPD_EXCEPTION;
         639                 :         }
         640                 :         else
         641                 :         {
         642               0 :             pd.flags = JSPD_ERROR;
         643               0 :             pd.value = JSVAL_VOID;
         644                 :         }
         645                 :     }
         646                 :     else
         647                 :     {
         648               0 :         pd.value = val;
         649                 :     }
         650                 :
         651               0 :     JS_LeaveCrossCompartmentCall(call);
         652               0 :     JS_EndRequest(cx);
         653                 :
         654               0 :     nameval = STRING_TO_JSVAL(name);
         655               0 :     if (!JS_ValueToId(cx, nameval, &nameid) ||
         656               0 :         !JS_IdToValue(cx, nameid, &pd.id)) {
         657               0 :         return NULL;
         658                 :     }
         659                 :
         660               0 :     pd.slot = pd.spare = 0;
         661               0 :     pd.alias = JSVAL_NULL;
         662               0 :     pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
         663               0 :         | (attrs & JSPROP_READONLY)  ? JSPD_READONLY  : 0
         664                 :         | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
         665                 :
         666               0 :     return _newProperty(jsdc, &pd, JSDPD_HINTED);
         667                 : }
         668                 :
         669                 : /*
         670                 :  * Retrieve a JSFunction* from a JSDValue*. This differs from
         671                 :  * JS_ValueToFunction by fully unwrapping the object first.
         672                 :  */
         673                 : JSFunction*
         674               0 : jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval)
         675                 : {
         676                 :     JSObject *obj;
         677                 :     JSFunction *fun;
         678               0 :     JSCrossCompartmentCall *call = NULL;
         679               0 :     if (!JSVAL_IS_OBJECT(jsdval->val))
         680               0 :         return NULL;
         681               0 :     if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         682               0 :         return NULL;
         683               0 :     obj = JS_UnwrapObject(obj);
         684                 :
         685               0 :     call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
         686               0 :     if (!call)
         687               0 :         return NULL;
         688               0 :     fun = JS_ValueToFunction(jsdc->dumbContext, OBJECT_TO_JSVAL(obj));
         689               0 :     JS_LeaveCrossCompartmentCall(call);
         690                 :
         691               0 :     return fun;
         692                 : }
         693                 :
         694                 : JSDValue*
         695               0 : jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
         696                 : {
         697               0 :     JSCrossCompartmentCall *call = NULL;
         698                 :
         699               0 :     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
         700                 :     {
         701                 :         JSObject* obj;
         702                 :         JSObject* proto;
         703               0 :         JS_ASSERT(!jsdval->proto);
         704               0 :         SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
         705               0 :         if(!JSVAL_IS_OBJECT(jsdval->val))
         706               0 :             return NULL;
         707               0 :         if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         708               0 :             return NULL;
         709               0 :         proto = JS_GetPrototype(obj);
         710               0 :         if(!proto)
         711               0 :             return NULL;
         712               0 :         jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
         713                 :     }
         714               0 :     if(jsdval->proto)
         715               0 :         jsdval->proto->nref++;
         716               0 :     return jsdval->proto;
         717                 : }
         718                 :
         719                 : JSDValue*
         720               1 : jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
         721                 : {
         722               1 :     JSCrossCompartmentCall *call = NULL;
         723                 :
         724               1 :     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
         725                 :     {
         726                 :         JSObject* obj;
         727                 :         JSObject* parent;
         728               1 :         JS_ASSERT(!jsdval->parent);
         729               1 :         SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
         730               1 :         if(!JSVAL_IS_OBJECT(jsdval->val))
         731               0 :             return NULL;
         732               1 :         if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         733               0 :             return NULL;
         734               1 :         JS_BeginRequest(jsdc->dumbContext);
         735               1 :         call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
         736               1 :         if(!call) {
         737               0 :             JS_EndRequest(jsdc->dumbContext);
         738                 :
         739               0 :             return NULL;
         740                 :         }
         741               1 :         parent = JS_GetParentOrScopeChain(jsdc->dumbContext,obj);
         742               1 :         JS_LeaveCrossCompartmentCall(call);
         743               1 :         JS_EndRequest(jsdc->dumbContext);
         744               1 :         if(!parent)
         745               0 :             return NULL;
         746               1 :         jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
         747                 :     }
         748               1 :     if(jsdval->parent)
         749               1 :         jsdval->parent->nref++;
         750               1 :     return jsdval->parent;
         751                 : }
         752                 :
         753                 : JSDValue*
         754               0 : jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
         755                 : {
         756               0 :     JSCrossCompartmentCall *call = NULL;
         757                 :
         758               0 :     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
         759                 :     {
         760                 :         JSObject* obj;
         761                 :         JSObject* proto;
         762                 :         JSObject* ctor;
         763               0 :         JS_ASSERT(!jsdval->ctor);
         764               0 :         SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
         765               0 :         if(!JSVAL_IS_OBJECT(jsdval->val))
         766               0 :             return NULL;
         767               0 :         if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         768               0 :             return NULL;
         769               0 :         proto = JS_GetPrototype(obj);
         770               0 :         if(!proto)
         771               0 :             return NULL;
         772               0 :         JS_BeginRequest(jsdc->dumbContext);
         773               0 :         call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
         774               0 :         if(!call) {
         775               0 :             JS_EndRequest(jsdc->dumbContext);
         776                 :
         777               0 :             return NULL;
         778                 :         }
         779               0 :         ctor = JS_GetConstructor(jsdc->dumbContext,proto);
         780               0 :         JS_LeaveCrossCompartmentCall(call);
         781               0 :         JS_EndRequest(jsdc->dumbContext);
         782               0 :         if(!ctor)
         783               0 :             return NULL;
         784               0 :         jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
         785                 :     }
         786               0 :     if(jsdval->ctor)
         787               0 :         jsdval->ctor->nref++;
         788               0 :     return jsdval->ctor;
         789                 : }
         790                 :
         791                 : const char*
         792               0 : jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
         793                 : {
         794               0 :     jsval val = jsdval->val;
         795               0 :     JSCrossCompartmentCall *call = NULL;
         796                 :
         797               0 :     if(!jsdval->className && JSVAL_IS_OBJECT(val))
         798                 :     {
         799                 :         JSObject* obj;
         800               0 :         if(!(obj = JSVAL_TO_OBJECT(val)))
         801               0 :             return NULL;
         802               0 :         JS_BeginRequest(jsdc->dumbContext);
         803               0 :         call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
         804               0 :         if(!call) {
         805               0 :             JS_EndRequest(jsdc->dumbContext);
         806                 :
         807               0 :             return NULL;
         808                 :         }
         809               0 :         jsdval->className = JS_GetClass(obj)->name;
         810               0 :         JS_LeaveCrossCompartmentCall(call);
         811               0 :         JS_EndRequest(jsdc->dumbContext);
         812                 :     }
         813               0 :     return jsdval->className;
         814                 : }
         815                 :
         816                 : JSDScript*
         817               0 : jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
         818                 : {
         819               0 :     JSContext* cx = jsdc->dumbContext;
         820               0 :     jsval val = jsdval->val;
         821               0 :     JSFunction* fun = NULL;
         822                 :     JSExceptionState* exceptionState;
         823               0 :     JSScript* script = NULL;
         824                 :     JSDScript* jsdscript;
         825               0 :     JSCrossCompartmentCall *call = NULL;
         826                 :
         827               0 :     if (!jsd_IsValueFunction(jsdc, jsdval))
         828               0 :         return NULL;
         829                 :
         830               0 :     JS_BeginRequest(cx);
         831               0 :     call = JS_EnterCrossCompartmentCall(cx, JSVAL_TO_OBJECT(val));
         832               0 :     if (!call) {
         833               0 :         JS_EndRequest(cx);
         834                 :
         835               0 :         return NULL;
         836                 :     }
         837                 :
         838               0 :     exceptionState = JS_SaveExceptionState(cx);
         839               0 :     fun = JSD_GetValueFunction(jsdc, jsdval);
         840               0 :     JS_RestoreExceptionState(cx, exceptionState);
         841               0 :     if (fun)
         842               0 :         script = JS_GetFunctionScript(cx, fun);
         843               0 :     JS_LeaveCrossCompartmentCall(call);
         844               0 :     JS_EndRequest(cx);
         845                 :
         846               0 :     if (!script)
         847               0 :         return NULL;
         848                 :
         849               0 :     JSD_LOCK_SCRIPTS(jsdc);
         850               0 :     jsdscript = jsd_FindJSDScript(jsdc, script);
         851               0 :     JSD_UNLOCK_SCRIPTS(jsdc);
         852               0 :     return jsdscript;
         853                 : }
         854                 :
         855                 :
         856                 : /***************************************************************************/
         857                 : /***************************************************************************/
         858                 :
         859                 : JSDValue*
         860               0 : jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
         861                 : {
         862               0 :     jsdprop->name->nref++;
         863               0 :     return jsdprop->name;
         864                 : }
         865                 :
         866                 : JSDValue*
         867               0 : jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
         868                 : {
         869               0 :     jsdprop->val->nref++;
         870               0 :     return jsdprop->val;
         871                 : }
         872                 :
         873                 : JSDValue*
         874               0 : jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
         875                 : {
         876               0 :     if(jsdprop->alias)
         877               0 :         jsdprop->alias->nref++;
         878               0 :     return jsdprop->alias;
         879                 : }
         880                 :
         881                 : unsigned
         882               0 : jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
         883                 : {
         884               0 :     return jsdprop->flags;
         885                 : }
         886                 :
         887                 : unsigned
         888               0 : jsd_GetPropertyVarArgSlot(JSDContext* jsdc, JSDProperty* jsdprop)
         889                 : {
         890               0 :     return jsdprop->slot;
         891                 : }
         892                 :
         893                 : void
         894               0 : jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
         895                 : {
         896               0 :     JS_ASSERT(jsdprop->nref > 0);
         897               0 :     if(0 == --jsdprop->nref)
         898                 :     {
         899               0 :         JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
         900               0 :         DROP_CLEAR_VALUE(jsdc, jsdprop->val);
         901               0 :         DROP_CLEAR_VALUE(jsdc, jsdprop->name);
         902               0 :         DROP_CLEAR_VALUE(jsdc, jsdprop->alias);
         903               0 :         free(jsdprop);
         904                 :     }
         905               0 : }

Generated by: LCOV version 1.7