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
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/
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
15 * The Original Code is mozilla.org code.
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.
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.
36 * ***** END LICENSE BLOCK ***** */
39 * JavaScript Debugging support - Value and Property support
44 #include "jsfriendapi.h"
47 void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
50 JS_ASSERT(jsdval->nref > 0);
51 if(!JS_CLIST_IS_EMPTY(&jsdval->props))
53 JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
54 JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
59 JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
60 JS_ASSERT(jsdval->proto->nref > 0);
64 JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
65 JS_ASSERT(jsdval->parent->nref > 0);
69 JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
70 JS_ASSERT(jsdval->ctor->nref > 0);
74 void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
77 JS_ASSERT(jsdprop->name);
78 JS_ASSERT(jsdprop->name->nref > 0);
79 JS_ASSERT(jsdprop->val);
80 JS_ASSERT(jsdprop->val->nref > 0);
82 JS_ASSERT(jsdprop->alias->nref > 0);
88 jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
90 return JSVAL_IS_OBJECT(jsdval->val);
94 jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
96 return JSVAL_IS_NUMBER(jsdval->val);
100 jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
102 return JSVAL_IS_INT(jsdval->val);
106 jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
108 return JSVAL_IS_DOUBLE(jsdval->val);
112 jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
114 return JSVAL_IS_STRING(jsdval->val);
118 jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
120 return JSVAL_IS_BOOLEAN(jsdval->val);
124 jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
126 return JSVAL_IS_NULL(jsdval->val);
130 jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
132 return JSVAL_IS_VOID(jsdval->val);
136 jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
138 return JSVAL_IS_PRIMITIVE(jsdval->val);
142 jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
144 return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
145 JS_ObjectIsCallable(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
149 jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
151 JSContext* cx = jsdc->dumbContext;
153 JSExceptionState* exceptionState;
154 JSCrossCompartmentCall *call = NULL;
156 if(jsd_IsValueFunction(jsdc, jsdval))
158 JSBool ok = JS_FALSE;
160 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
167 exceptionState = JS_SaveExceptionState(cx);
168 fun = JSD_GetValueFunction(jsdc, jsdval);
169 JS_RestoreExceptionState(cx, exceptionState);
171 ok = JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
172 JS_LeaveCrossCompartmentCall(call);
177 return !JSVAL_IS_PRIMITIVE(jsdval->val);
180 /***************************************************************************/
183 jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
185 jsval val = jsdval->val;
186 if(!JSVAL_IS_BOOLEAN(val))
188 return JSVAL_TO_BOOLEAN(val);
192 jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
194 jsval val = jsdval->val;
195 if(!JSVAL_IS_INT(val))
197 return JSVAL_TO_INT(val);
201 jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
203 if(!JSVAL_IS_DOUBLE(jsdval->val))
205 return JSVAL_TO_DOUBLE(jsdval->val);
209 jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
211 JSContext* cx = jsdc->dumbContext;
212 JSExceptionState* exceptionState;
213 JSCrossCompartmentCall *call = NULL;
220 return jsdval->string;
222 /* Reuse the string without copying or re-rooting it */
223 if(JSVAL_IS_STRING(jsdval->val)) {
224 jsdval->string = JSVAL_TO_STRING(jsdval->val);
225 return jsdval->string;
230 /* Objects call JS_ValueToString in their own compartment. */
231 scopeObj = JSVAL_IS_OBJECT(jsdval->val) ? JSVAL_TO_OBJECT(jsdval->val) : jsdc->glob;
232 call = JS_EnterCrossCompartmentCall(cx, scopeObj);
237 exceptionState = JS_SaveExceptionState(cx);
239 string = JS_ValueToString(cx, jsdval->val);
241 JS_RestoreExceptionState(cx, exceptionState);
242 JS_LeaveCrossCompartmentCall(call);
245 stringval = STRING_TO_JSVAL(string);
246 call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
248 if(!string || !call || !JS_WrapValue(cx, &stringval)) {
250 JS_LeaveCrossCompartmentCall(call);
255 jsdval->string = JSVAL_TO_STRING(stringval);
256 if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
257 jsdval->string = NULL;
259 JS_LeaveCrossCompartmentCall(call);
262 return jsdval->string;
266 jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval)
268 JSContext* cx = jsdc->dumbContext;
270 JSExceptionState* exceptionState;
271 JSCrossCompartmentCall *call = NULL;
273 if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval))
277 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
284 exceptionState = JS_SaveExceptionState(cx);
285 fun = JSD_GetValueFunction(jsdc, jsdval);
286 JS_RestoreExceptionState(cx, exceptionState);
287 JS_LeaveCrossCompartmentCall(call);
291 jsdval->funName = JS_GetFunctionId(fun);
293 /* For compatibility we return "anonymous", not an empty string here. */
294 if (!jsdval->funName)
295 jsdval->funName = JS_GetAnonymousString(jsdc->jsrt);
297 return jsdval->funName;
300 /***************************************************************************/
303 * Create a new JSD value referring to a jsval. Copy string values into the
304 * JSD compartment. Leave all other GCTHINGs in their native compartments
305 * and access them through cross-compartment calls.
308 jsd_NewValue(JSDContext* jsdc, jsval val)
311 JSCrossCompartmentCall *call = NULL;
313 if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
316 if(JSVAL_IS_GCTHING(val))
319 JS_BeginRequest(jsdc->dumbContext);
321 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
323 JS_EndRequest(jsdc->dumbContext);
328 ok = JS_AddNamedValueRoot(jsdc->dumbContext, &jsdval->val, "JSDValue");
329 if(ok && JSVAL_IS_STRING(val)) {
330 if(!JS_WrapValue(jsdc->dumbContext, &val)) {
335 JS_LeaveCrossCompartmentCall(call);
336 JS_EndRequest(jsdc->dumbContext);
345 JS_INIT_CLIST(&jsdval->props);
351 jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
353 JSCrossCompartmentCall *call = NULL;
355 JS_ASSERT(jsdval->nref > 0);
356 if(0 == --jsdval->nref)
358 jsd_RefreshValue(jsdc, jsdval);
359 if(JSVAL_IS_GCTHING(jsdval->val))
361 JS_BeginRequest(jsdc->dumbContext);
362 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
364 JS_EndRequest(jsdc->dumbContext);
369 JS_RemoveValueRoot(jsdc->dumbContext, &jsdval->val);
370 JS_LeaveCrossCompartmentCall(call);
371 JS_EndRequest(jsdc->dumbContext);
378 jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
382 jsval val = jsdval->val;
383 if (!JSVAL_IS_PRIMITIVE(val)) {
384 cx = JSD_GetDefaultJSContext(jsdc);
385 obj = js_ObjectToOuterObject(cx, JSVAL_TO_OBJECT(val));
388 JS_ClearPendingException(cx);
392 val = OBJECT_TO_JSVAL(obj);
398 static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
399 uintN additionalFlags)
401 JSDProperty* jsdprop;
403 if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
406 JS_INIT_CLIST(&jsdprop->links);
408 jsdprop->flags = pd->flags | additionalFlags;
409 jsdprop->slot = pd->slot;
411 if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
414 if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
417 if((jsdprop->flags & JSDPD_ALIAS) &&
418 !(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
423 jsd_DropProperty(jsdc, jsdprop);
427 static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
429 JSDProperty* jsdprop;
431 while(jsdprop = (JSDProperty*)jsdval->props.next,
432 jsdprop != (JSDProperty*)&jsdval->props)
434 JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
435 jsd_DropProperty(jsdc, jsdprop);
437 JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
438 CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
441 static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
443 JSContext* cx = jsdc->dumbContext;
445 JSPropertyDescArray pda;
447 JSCrossCompartmentCall *call = NULL;
449 JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
450 JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
451 JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
453 if(JSVAL_IS_PRIMITIVE(jsdval->val))
456 obj = JSVAL_TO_OBJECT(jsdval->val);
459 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
462 JS_EndRequest(jsdc->dumbContext);
466 if(!JS_GetPropertyDescArray(cx, obj, &pda))
469 JS_LeaveCrossCompartmentCall(call);
473 for(i = 0; i < pda.length; i++)
475 JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
478 _freeProps(jsdc, jsdval);
481 JS_APPEND_LINK(&prop->links, &jsdval->props);
483 JS_PutPropertyDescArray(cx, &pda);
484 JS_LeaveCrossCompartmentCall(call);
486 SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
487 return !JS_CLIST_IS_EMPTY(&jsdval->props);
490 #undef DROP_CLEAR_VALUE
491 #define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
494 jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
496 JSContext* cx = jsdc->dumbContext;
497 JSCrossCompartmentCall *call = NULL;
501 /* if the jsval is a string, then we didn't need to root the string */
502 if(!JSVAL_IS_STRING(jsdval->val))
505 call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
512 JS_RemoveStringRoot(cx, &jsdval->string);
513 JS_LeaveCrossCompartmentCall(call);
516 jsdval->string = NULL;
519 jsdval->funName = NULL;
520 jsdval->className = NULL;
521 DROP_CLEAR_VALUE(jsdc, jsdval->proto);
522 DROP_CLEAR_VALUE(jsdc, jsdval->parent);
523 DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
524 _freeProps(jsdc, jsdval);
528 /***************************************************************************/
531 jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
533 JSDProperty* jsdprop;
536 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
537 if(!_buildProps(jsdc, jsdval))
540 for(jsdprop = (JSDProperty*)jsdval->props.next;
541 jsdprop != (JSDProperty*)&jsdval->props;
542 jsdprop = (JSDProperty*)jsdprop->links.next)
550 jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
552 JSDProperty* jsdprop = *iterp;
553 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
556 if(!_buildProps(jsdc, jsdval))
561 jsdprop = (JSDProperty*)jsdval->props.next;
562 if(jsdprop == (JSDProperty*)&jsdval->props)
564 *iterp = (JSDProperty*)jsdprop->links.next;
572 jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
574 JSContext* cx = jsdc->dumbContext;
575 JSDProperty* jsdprop;
576 JSDProperty* iter = NULL;
581 const jschar * nameChars;
585 JSCrossCompartmentCall *call = NULL;
587 if(!jsd_IsValueObject(jsdc, jsdval))
590 /* If we already have the prop, then return it */
591 while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
593 JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
596 if (JS_CompareStrings(cx, propName, name, &result) && !result)
599 JSD_DropProperty(jsdc, jsdprop);
601 /* Not found in property list, look it up explicitly */
603 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
606 if (!(nameChars = JS_GetStringCharsZAndLength(cx, name, &nameLen)))
610 call = JS_EnterCrossCompartmentCall(cx, obj);
617 JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
620 JS_LeaveCrossCompartmentCall(call);
625 JS_ClearPendingException(cx);
627 if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
629 if (JS_IsExceptionPending(cx))
631 if (!JS_GetPendingException(cx, &pd.value))
633 JS_LeaveCrossCompartmentCall(call);
637 pd.flags = JSPD_EXCEPTION;
641 pd.flags = JSPD_ERROR;
642 pd.value = JSVAL_VOID;
650 JS_LeaveCrossCompartmentCall(call);
653 nameval = STRING_TO_JSVAL(name);
654 if (!JS_ValueToId(cx, nameval, &nameid) ||
655 !JS_IdToValue(cx, nameid, &pd.id)) {
659 pd.slot = pd.spare = 0;
660 pd.alias = JSVAL_NULL;
661 pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
662 | (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0
663 | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
665 return _newProperty(jsdc, &pd, JSDPD_HINTED);
669 * Retrieve a JSFunction* from a JSDValue*. This differs from
670 * JS_ValueToFunction by fully unwrapping the object first.
673 jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval)
677 JSCrossCompartmentCall *call = NULL;
678 if (!JSVAL_IS_OBJECT(jsdval->val))
680 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
682 obj = JS_UnwrapObject(jsdc->dumbContext, obj);
684 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
687 fun = JS_ValueToFunction(jsdc->dumbContext, OBJECT_TO_JSVAL(obj));
688 JS_LeaveCrossCompartmentCall(call);
694 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
696 JSCrossCompartmentCall *call = NULL;
698 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
702 JS_ASSERT(!jsdval->proto);
703 SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
704 if(!JSVAL_IS_OBJECT(jsdval->val))
706 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
708 JS_BeginRequest(jsdc->dumbContext);
709 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
711 JS_EndRequest(jsdc->dumbContext);
715 proto = JS_GetPrototype(jsdc->dumbContext, obj);
716 JS_LeaveCrossCompartmentCall(call);
717 JS_EndRequest(jsdc->dumbContext);
720 jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
723 jsdval->proto->nref++;
724 return jsdval->proto;
728 jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
730 JSCrossCompartmentCall *call = NULL;
732 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
736 JS_ASSERT(!jsdval->parent);
737 SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
738 if(!JSVAL_IS_OBJECT(jsdval->val))
740 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
742 JS_BeginRequest(jsdc->dumbContext);
743 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
745 JS_EndRequest(jsdc->dumbContext);
749 parent = JS_GetParent(jsdc->dumbContext,obj);
750 JS_LeaveCrossCompartmentCall(call);
751 JS_EndRequest(jsdc->dumbContext);
754 jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
757 jsdval->parent->nref++;
758 return jsdval->parent;
762 jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
764 JSCrossCompartmentCall *call = NULL;
766 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
771 JS_ASSERT(!jsdval->ctor);
772 SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
773 if(!JSVAL_IS_OBJECT(jsdval->val))
775 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
777 JS_BeginRequest(jsdc->dumbContext);
778 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
780 JS_EndRequest(jsdc->dumbContext);
784 proto = JS_GetPrototype(jsdc->dumbContext,obj);
787 JS_LeaveCrossCompartmentCall(call);
788 JS_EndRequest(jsdc->dumbContext);
791 ctor = JS_GetConstructor(jsdc->dumbContext,proto);
792 JS_LeaveCrossCompartmentCall(call);
793 JS_EndRequest(jsdc->dumbContext);
796 jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
799 jsdval->ctor->nref++;
804 jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
806 jsval val = jsdval->val;
807 JSCrossCompartmentCall *call = NULL;
809 if(!jsdval->className && JSVAL_IS_OBJECT(val))
812 if(!(obj = JSVAL_TO_OBJECT(val)))
814 JS_BeginRequest(jsdc->dumbContext);
815 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
817 JS_EndRequest(jsdc->dumbContext);
821 if(JS_GET_CLASS(jsdc->dumbContext, obj))
822 jsdval->className = JS_GET_CLASS(jsdc->dumbContext, obj)->name;
823 JS_LeaveCrossCompartmentCall(call);
824 JS_EndRequest(jsdc->dumbContext);
826 return jsdval->className;
830 jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
832 JSContext* cx = jsdc->dumbContext;
833 jsval val = jsdval->val;
834 JSFunction* fun = NULL;
835 JSExceptionState* exceptionState;
836 JSScript* script = NULL;
837 JSDScript* jsdscript;
838 JSCrossCompartmentCall *call = NULL;
840 if (!jsd_IsValueFunction(jsdc, jsdval))
844 call = JS_EnterCrossCompartmentCall(cx, JSVAL_TO_OBJECT(val));
851 exceptionState = JS_SaveExceptionState(cx);
852 fun = JSD_GetValueFunction(jsdc, jsdval);
853 JS_RestoreExceptionState(cx, exceptionState);
855 script = JS_GetFunctionScript(cx, fun);
856 JS_LeaveCrossCompartmentCall(call);
862 JSD_LOCK_SCRIPTS(jsdc);
863 jsdscript = jsd_FindJSDScript(jsdc, script);
864 JSD_UNLOCK_SCRIPTS(jsdc);
869 /***************************************************************************/
870 /***************************************************************************/
873 jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
875 jsdprop->name->nref++;
876 return jsdprop->name;
880 jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
882 jsdprop->val->nref++;
887 jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
890 jsdprop->alias->nref++;
891 return jsdprop->alias;
895 jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
897 return jsdprop->flags;
901 jsd_GetPropertyVarArgSlot(JSDContext* jsdc, JSDProperty* jsdprop)
903 return jsdprop->slot;
907 jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
909 JS_ASSERT(jsdprop->nref > 0);
910 if(0 == --jsdprop->nref)
912 JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
913 DROP_CLEAR_VALUE(jsdc, jsdprop->val);
914 DROP_CLEAR_VALUE(jsdc, jsdprop->name);
915 DROP_CLEAR_VALUE(jsdc, jsdprop->alias);