Back to index

lightning-sunbird  0.9+nobinonly
jsd_val.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * JavaScript Debugging support - Value and Property support
00040  */
00041 
00042 #include "jsd.h"
00043 
00044 #ifdef DEBUG
00045 void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
00046 {
00047     JS_ASSERT(jsdval);
00048     JS_ASSERT(jsdval->nref > 0);
00049     if(!JS_CLIST_IS_EMPTY(&jsdval->props))
00050     {
00051         JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
00052         JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
00053     }
00054 
00055     if(jsdval->proto)
00056     {
00057         JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
00058         JS_ASSERT(jsdval->proto->nref > 0);
00059     }
00060     if(jsdval->parent)
00061     {
00062         JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
00063         JS_ASSERT(jsdval->parent->nref > 0);
00064     }
00065     if(jsdval->ctor)
00066     {
00067         JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
00068         JS_ASSERT(jsdval->ctor->nref > 0);
00069     }
00070 }
00071 
00072 void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
00073 {
00074     JS_ASSERT(jsdprop);
00075     JS_ASSERT(jsdprop->name);
00076     JS_ASSERT(jsdprop->name->nref > 0);
00077     JS_ASSERT(jsdprop->val);
00078     JS_ASSERT(jsdprop->val->nref > 0);
00079     if(jsdprop->alias)
00080         JS_ASSERT(jsdprop->alias->nref > 0);
00081 }
00082 #endif
00083 
00084 
00085 JSBool
00086 jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
00087 {
00088     return JSVAL_IS_OBJECT(jsdval->val);
00089 }
00090 
00091 JSBool
00092 jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
00093 {
00094     return JSVAL_IS_NUMBER(jsdval->val);
00095 }
00096 
00097 JSBool
00098 jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
00099 {
00100     return JSVAL_IS_INT(jsdval->val);
00101 }
00102 
00103 JSBool
00104 jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
00105 {
00106     return JSVAL_IS_DOUBLE(jsdval->val);
00107 }
00108 
00109 JSBool
00110 jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
00111 {
00112     return JSVAL_IS_STRING(jsdval->val);
00113 }
00114 
00115 JSBool
00116 jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
00117 {
00118     return JSVAL_IS_BOOLEAN(jsdval->val);
00119 }
00120 
00121 JSBool
00122 jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
00123 {
00124     return JSVAL_IS_NULL(jsdval->val);
00125 }
00126 
00127 JSBool
00128 jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
00129 {
00130     return JSVAL_IS_VOID(jsdval->val);
00131 }
00132 
00133 JSBool
00134 jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
00135 {
00136     return JSVAL_IS_PRIMITIVE(jsdval->val);
00137 }
00138 
00139 JSBool
00140 jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
00141 {
00142     return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
00143            JS_ObjectIsFunction(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
00144 }
00145 
00146 JSBool
00147 jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
00148 {
00149     JSContext* cx = jsdc->dumbContext;
00150     jsval val = jsdval->val;
00151     JSFunction* fun;
00152     JSExceptionState* exceptionState;
00153 
00154     if(jsd_IsValueFunction(jsdc, jsdval))
00155     {
00156         exceptionState = JS_SaveExceptionState(cx);
00157         fun = JS_ValueToFunction(cx, val);
00158         JS_RestoreExceptionState(cx, exceptionState);
00159         if(!fun)
00160         {
00161             JS_ASSERT(0);
00162             return JS_FALSE;
00163         }
00164         return JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
00165     }
00166     return !JSVAL_IS_PRIMITIVE(val);
00167 }
00168 
00169 /***************************************************************************/
00170 
00171 JSBool
00172 jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
00173 {
00174     jsval val = jsdval->val;
00175     if(!JSVAL_IS_BOOLEAN(val))
00176         return JS_FALSE;
00177     return JSVAL_TO_BOOLEAN(val);
00178 }
00179 
00180 int32
00181 jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
00182 {
00183     jsval val = jsdval->val;
00184     if(!JSVAL_IS_INT(val))
00185         return 0;
00186     return JSVAL_TO_INT(val);
00187 }
00188 
00189 jsdouble*
00190 jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
00191 {
00192     jsval val = jsdval->val;
00193     if(!JSVAL_IS_DOUBLE(val))
00194         return 0;
00195     return JSVAL_TO_DOUBLE(val);
00196 }
00197 
00198 JSString*
00199 jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
00200 {
00201     JSContext* cx = jsdc->dumbContext;
00202     JSExceptionState* exceptionState;
00203 
00204     if(!jsdval->string)
00205     {
00206         /* if the jsval is a string, then we don't need to double root it */
00207         if(JSVAL_IS_STRING(jsdval->val))
00208             jsdval->string = JSVAL_TO_STRING(jsdval->val);
00209         else
00210         {
00211             exceptionState = JS_SaveExceptionState(cx);
00212             jsdval->string = JS_ValueToString(cx, jsdval->val);
00213             JS_RestoreExceptionState(cx, exceptionState);
00214             if(jsdval->string)
00215             {
00216                 if(!JS_AddNamedRoot(cx, &jsdval->string, "ValueString"))
00217                     jsdval->string = NULL;
00218             }
00219         }
00220     }
00221     return jsdval->string;
00222 }
00223 
00224 const char*
00225 jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
00226 {
00227     JSContext* cx = jsdc->dumbContext;
00228     JSFunction* fun;
00229     JSExceptionState* exceptionState;
00230 
00231     if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval))
00232     {
00233         exceptionState = JS_SaveExceptionState(cx);
00234         fun = JS_ValueToFunction(cx, jsdval->val);
00235         JS_RestoreExceptionState(cx, exceptionState);
00236         if(!fun)
00237             return NULL;
00238         jsdval->funName = JS_GetFunctionName(fun);
00239     }
00240     return jsdval->funName;
00241 }
00242 
00243 /***************************************************************************/
00244 
00245 JSDValue*
00246 jsd_NewValue(JSDContext* jsdc, jsval val)
00247 {
00248     JSDValue* jsdval;
00249 
00250     if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
00251         return NULL;
00252 
00253     if(JSVAL_IS_GCTHING(val))
00254     {
00255         if(!JS_AddNamedRoot(jsdc->dumbContext, &jsdval->val, "JSDValue"))
00256         {
00257             free(jsdval);
00258             return NULL;
00259         }
00260     }
00261     jsdval->val  = val;
00262     jsdval->nref = 1;
00263     JS_INIT_CLIST(&jsdval->props);
00264 
00265     return jsdval;
00266 }
00267 
00268 void
00269 jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
00270 {
00271     JS_ASSERT(jsdval->nref > 0);
00272     if(0 == --jsdval->nref)
00273     {
00274         jsd_RefreshValue(jsdc, jsdval);
00275         if(JSVAL_IS_GCTHING(jsdval->val))
00276             JS_RemoveRoot(jsdc->dumbContext, &jsdval->val);
00277         free(jsdval);
00278     }
00279 }
00280 
00281 jsval
00282 jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
00283 {
00284     return jsdval->val;
00285 }
00286 
00287 static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
00288                                  uintN additionalFlags)
00289 {
00290     JSDProperty* jsdprop;
00291 
00292     if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
00293         return NULL;
00294 
00295     JS_INIT_CLIST(&jsdprop->links);
00296     jsdprop->nref = 1;
00297     jsdprop->flags = pd->flags | additionalFlags;
00298     jsdprop->slot = pd->slot;
00299 
00300     if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
00301         goto new_prop_fail;
00302 
00303     if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
00304         goto new_prop_fail;
00305 
00306     if((jsdprop->flags & JSDPD_ALIAS) &&
00307        !(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
00308         goto new_prop_fail;
00309 
00310     return jsdprop;
00311 new_prop_fail:
00312     jsd_DropProperty(jsdc, jsdprop);
00313     return NULL;
00314 }
00315 
00316 static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
00317 {
00318     JSDProperty* jsdprop;
00319 
00320     while(jsdprop = (JSDProperty*)jsdval->props.next,
00321           jsdprop != (JSDProperty*)&jsdval->props)
00322     {
00323         JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
00324         jsd_DropProperty(jsdc, jsdprop);
00325     }
00326     JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
00327     CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
00328 }
00329 
00330 static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
00331 {
00332     JSContext* cx = jsdc->dumbContext;
00333     JSPropertyDescArray pda;
00334     uintN i;
00335 
00336     JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
00337     JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
00338     JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
00339 
00340     if(!JSVAL_IS_OBJECT(jsdval->val) || JSVAL_IS_NULL(jsdval->val))
00341         return JS_FALSE;
00342 
00343     if(!JS_GetPropertyDescArray(cx, JSVAL_TO_OBJECT(jsdval->val), &pda))
00344         return JS_FALSE;
00345 
00346     for(i = 0; i < pda.length; i++)
00347     {
00348         JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
00349         if(!prop)
00350         {
00351             _freeProps(jsdc, jsdval);
00352             break;
00353         }
00354         JS_APPEND_LINK(&prop->links, &jsdval->props);
00355     }
00356     JS_PutPropertyDescArray(cx, &pda);
00357     SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
00358     return !JS_CLIST_IS_EMPTY(&jsdval->props);
00359 }
00360 
00361 #undef  DROP_CLEAR_VALUE
00362 #define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
00363 
00364 void
00365 jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
00366 {
00367     JSContext* cx = jsdc->dumbContext;
00368 
00369     if(jsdval->string)
00370     {
00371         /* if the jsval is a string, then we didn't need to root the string */
00372         if(!JSVAL_IS_STRING(jsdval->val))
00373             JS_RemoveRoot(cx, &jsdval->string);
00374         jsdval->string = NULL;
00375     }
00376 
00377     jsdval->funName = NULL;
00378     jsdval->className = NULL;
00379     DROP_CLEAR_VALUE(jsdc, jsdval->proto);
00380     DROP_CLEAR_VALUE(jsdc, jsdval->parent);
00381     DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
00382     _freeProps(jsdc, jsdval);
00383     jsdval->flags = 0;
00384 }
00385 
00386 /***************************************************************************/
00387 
00388 uintN
00389 jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
00390 {
00391     JSDProperty* jsdprop;
00392     uintN count = 0;
00393 
00394     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
00395         if(!_buildProps(jsdc, jsdval))
00396             return 0;
00397 
00398     for(jsdprop = (JSDProperty*)jsdval->props.next;
00399         jsdprop != (JSDProperty*)&jsdval->props;
00400         jsdprop = (JSDProperty*)jsdprop->links.next)
00401     {
00402         count++;
00403     }
00404     return count;
00405 }
00406 
00407 JSDProperty*
00408 jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
00409 {
00410     JSDProperty* jsdprop = *iterp;
00411     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
00412     {
00413         JS_ASSERT(!jsdprop);
00414         if(!_buildProps(jsdc, jsdval))
00415             return NULL;
00416     }
00417 
00418     if(!jsdprop)
00419         jsdprop = (JSDProperty*)jsdval->props.next;
00420     if(jsdprop == (JSDProperty*)&jsdval->props)
00421         return NULL;
00422     *iterp = (JSDProperty*)jsdprop->links.next;
00423 
00424     JS_ASSERT(jsdprop);
00425     jsdprop->nref++;
00426     return jsdprop;
00427 }
00428 
00429 JSDProperty*
00430 jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
00431 {
00432     JSContext* cx = jsdc->dumbContext;
00433     JSDProperty* jsdprop;
00434     JSDProperty* iter = NULL;
00435     JSObject* obj;
00436     uintN  attrs = 0;
00437     JSBool found;
00438     JSPropertyDesc pd;
00439     const jschar * nameChars;
00440     size_t nameLen;
00441     jsval val;
00442 
00443     if(!jsd_IsValueObject(jsdc, jsdval))
00444         return NULL;
00445 
00446     /* If we already have the prop, then return it */
00447     while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
00448     {
00449         JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
00450         if(propName && !JS_CompareStrings(propName, name))
00451             return jsdprop;
00452         JSD_DropProperty(jsdc, jsdprop);
00453     }
00454     /* Not found in property list, look it up explicitly */
00455 
00456     if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
00457         return NULL;
00458 
00459     nameChars = JS_GetStringChars(name);
00460     nameLen   = JS_GetStringLength(name);
00461 
00462     JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
00463     if (!found)
00464         return NULL;
00465 
00466     JS_ClearPendingException(cx);
00467 
00468     if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
00469     {
00470         if (JS_IsExceptionPending(cx))
00471         {
00472             if (!JS_GetPendingException(cx, &pd.value))
00473                 return NULL;
00474             pd.flags = JSPD_EXCEPTION;
00475         }
00476         else
00477         {
00478             pd.flags = JSPD_ERROR;
00479             pd.value = JSVAL_VOID;
00480         }
00481     }
00482     else
00483     {
00484         pd.value = val;
00485     }
00486 
00487     pd.id = STRING_TO_JSVAL(name);
00488     pd.alias = pd.slot = pd.spare = 0;
00489     pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
00490         | (attrs & JSPROP_READONLY)  ? JSPD_READONLY  : 0
00491         | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
00492 
00493     return _newProperty(jsdc, &pd, JSDPD_HINTED);
00494 }
00495 
00496 
00497 JSDValue*
00498 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
00499 {
00500     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
00501     {
00502         JSObject* obj;
00503         JSObject* proto;
00504         JS_ASSERT(!jsdval->proto);
00505         SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
00506         if(!JSVAL_IS_OBJECT(jsdval->val))
00507             return NULL;
00508         if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
00509             return NULL;
00510         if(!(proto = JS_GetPrototype(jsdc->dumbContext, obj)))
00511             return NULL;
00512         jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
00513     }
00514     if(jsdval->proto)
00515         jsdval->proto->nref++;
00516     return jsdval->proto;
00517 }
00518 
00519 JSDValue*
00520 jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
00521 {
00522     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
00523     {
00524         JSObject* obj;
00525         JSObject* parent;
00526         JS_ASSERT(!jsdval->parent);
00527         SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
00528         if(!JSVAL_IS_OBJECT(jsdval->val))
00529             return NULL;
00530         if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
00531             return NULL;
00532         if(!(parent = JS_GetParent(jsdc->dumbContext,obj)))
00533             return NULL;
00534         jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
00535     }
00536     if(jsdval->parent)
00537         jsdval->parent->nref++;
00538     return jsdval->parent;
00539 }
00540 
00541 JSDValue*
00542 jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
00543 {
00544     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
00545     {
00546         JSObject* obj;
00547         JSObject* proto;
00548         JSObject* ctor;
00549         JS_ASSERT(!jsdval->ctor);
00550         SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
00551         if(!JSVAL_IS_OBJECT(jsdval->val))
00552             return NULL;
00553         if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
00554             return NULL;
00555         if(!(proto = JS_GetPrototype(jsdc->dumbContext,obj)))
00556             return NULL;
00557         if(!(ctor = JS_GetConstructor(jsdc->dumbContext,proto)))
00558             return NULL;
00559         jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
00560     }
00561     if(jsdval->ctor)
00562         jsdval->ctor->nref++;
00563     return jsdval->ctor;
00564 }
00565 
00566 const char*
00567 jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
00568 {
00569     jsval val = jsdval->val;
00570     if(!jsdval->className && JSVAL_IS_OBJECT(val))
00571     {
00572         JSObject* obj;
00573         if(!(obj = JSVAL_TO_OBJECT(val)))
00574             return NULL;
00575         if(JS_GET_CLASS(jsdc->dumbContext, obj))
00576             jsdval->className = JS_GET_CLASS(jsdc->dumbContext, obj)->name;
00577     }
00578     return jsdval->className;
00579 }
00580 
00581 /***************************************************************************/
00582 /***************************************************************************/
00583 
00584 JSDValue*
00585 jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
00586 {
00587     jsdprop->name->nref++;
00588     return jsdprop->name;
00589 }
00590 
00591 JSDValue*
00592 jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
00593 {
00594     jsdprop->val->nref++;
00595     return jsdprop->val;
00596 }
00597 
00598 JSDValue*
00599 jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
00600 {
00601     if(jsdprop->alias)
00602         jsdprop->alias->nref++;
00603     return jsdprop->alias;
00604 }
00605 
00606 uintN
00607 jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
00608 {
00609     return jsdprop->flags;
00610 }
00611 
00612 uintN
00613 jsd_GetPropertyVarArgSlot(JSDContext* jsdc, JSDProperty* jsdprop)
00614 {
00615     return jsdprop->slot;
00616 }
00617 
00618 void
00619 jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
00620 {
00621     JS_ASSERT(jsdprop->nref > 0);
00622     if(0 == --jsdprop->nref)
00623     {
00624         JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
00625         DROP_CLEAR_VALUE(jsdc, jsdprop->val);
00626         DROP_CLEAR_VALUE(jsdc, jsdprop->name);
00627         DROP_CLEAR_VALUE(jsdc, jsdprop->alias);
00628         free(jsdprop);
00629     }
00630 }