Bug 612150 - Eliminating JS_GetFunctionName. r=mrbkap
[mozilla-central.git] / js / jsd / jsd_val.c
blob01fbe85c37cc6d8ae23ff89c874f0b0ddcac7ea2
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
13 * License.
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.
22 * Contributor(s):
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
42 #include "jsd.h"
43 #include "jsapi.h"
44 #include "jspubtd.h"
45 #include "jsprvtd.h"
47 #ifdef DEBUG
48 void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
50 JS_ASSERT(jsdval);
51 JS_ASSERT(jsdval->nref > 0);
52 if(!JS_CLIST_IS_EMPTY(&jsdval->props))
54 JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
55 JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
58 if(jsdval->proto)
60 JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
61 JS_ASSERT(jsdval->proto->nref > 0);
63 if(jsdval->parent)
65 JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
66 JS_ASSERT(jsdval->parent->nref > 0);
68 if(jsdval->ctor)
70 JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
71 JS_ASSERT(jsdval->ctor->nref > 0);
75 void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
77 JS_ASSERT(jsdprop);
78 JS_ASSERT(jsdprop->name);
79 JS_ASSERT(jsdprop->name->nref > 0);
80 JS_ASSERT(jsdprop->val);
81 JS_ASSERT(jsdprop->val->nref > 0);
82 if(jsdprop->alias)
83 JS_ASSERT(jsdprop->alias->nref > 0);
85 #endif
88 JSBool
89 jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
91 return JSVAL_IS_OBJECT(jsdval->val);
94 JSBool
95 jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
97 return JSVAL_IS_NUMBER(jsdval->val);
100 JSBool
101 jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
103 return JSVAL_IS_INT(jsdval->val);
106 JSBool
107 jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
109 return JSVAL_IS_DOUBLE(jsdval->val);
112 JSBool
113 jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
115 return JSVAL_IS_STRING(jsdval->val);
118 JSBool
119 jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
121 return JSVAL_IS_BOOLEAN(jsdval->val);
124 JSBool
125 jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
127 return JSVAL_IS_NULL(jsdval->val);
130 JSBool
131 jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
133 return JSVAL_IS_VOID(jsdval->val);
136 JSBool
137 jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
139 return JSVAL_IS_PRIMITIVE(jsdval->val);
142 JSBool
143 jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
145 return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
146 JS_ObjectIsFunction(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
149 JSBool
150 jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
152 JSContext* cx = jsdc->dumbContext;
153 jsval val = jsdval->val;
154 JSFunction* fun;
155 JSExceptionState* exceptionState;
156 JSCrossCompartmentCall *call = NULL;
158 if(jsd_IsValueFunction(jsdc, jsdval))
160 JSBool ok = JS_FALSE;
161 JS_BeginRequest(cx);
162 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(val));
163 if(!call) {
164 JS_EndRequest(cx);
166 return JS_FALSE;
169 exceptionState = JS_SaveExceptionState(cx);
170 fun = JS_ValueToFunction(cx, val);
171 JS_RestoreExceptionState(cx, exceptionState);
172 if(fun)
173 ok = JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
174 JS_LeaveCrossCompartmentCall(call);
175 JS_EndRequest(cx);
176 JS_ASSERT(fun);
177 return ok;
179 return !JSVAL_IS_PRIMITIVE(val);
182 /***************************************************************************/
184 JSBool
185 jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
187 jsval val = jsdval->val;
188 if(!JSVAL_IS_BOOLEAN(val))
189 return JS_FALSE;
190 return JSVAL_TO_BOOLEAN(val);
193 int32
194 jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
196 jsval val = jsdval->val;
197 if(!JSVAL_IS_INT(val))
198 return 0;
199 return JSVAL_TO_INT(val);
202 jsdouble
203 jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
205 if(!JSVAL_IS_DOUBLE(jsdval->val))
206 return 0;
207 return JSVAL_TO_DOUBLE(jsdval->val);
210 JSString*
211 jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
213 JSContext* cx = jsdc->dumbContext;
214 JSExceptionState* exceptionState;
215 JSCrossCompartmentCall *call = NULL;
217 if(!jsdval->string)
219 /* if the jsval is a string, then we don't need to double root it */
220 if(JSVAL_IS_STRING(jsdval->val))
221 jsdval->string = JSVAL_TO_STRING(jsdval->val);
222 else
224 JS_BeginRequest(cx);
225 call = JSVAL_IS_PRIMITIVE(jsdval->val)
226 ? NULL
227 : JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
228 if(!call) {
229 JS_EndRequest(cx);
231 return NULL;
234 exceptionState = JS_SaveExceptionState(cx);
235 jsdval->string = JS_ValueToString(cx, jsdval->val);
236 JS_RestoreExceptionState(cx, exceptionState);
237 if(jsdval->string)
239 if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
240 jsdval->string = NULL;
242 JS_LeaveCrossCompartmentCall(call);
243 JS_EndRequest(cx);
246 return jsdval->string;
249 JSString*
250 jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
252 JSContext* cx = jsdc->dumbContext;
253 JSFunction* fun;
254 JSExceptionState* exceptionState;
255 JSCrossCompartmentCall *call = NULL;
257 if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval))
259 JS_BeginRequest(cx);
261 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
262 if(!call) {
263 JS_EndRequest(cx);
265 return NULL;
268 exceptionState = JS_SaveExceptionState(cx);
269 fun = JS_ValueToFunction(cx, jsdval->val);
270 JS_RestoreExceptionState(cx, exceptionState);
271 JS_LeaveCrossCompartmentCall(call);
272 JS_EndRequest(cx);
273 if(!fun)
274 return NULL;
275 jsdval->funName = JS_GetFunctionId(fun);
276 if (!jsdval->funName)
277 jsdval->funName = JS_GetEmptyString(jsdc->jsrt);
279 return jsdval->funName;
282 /***************************************************************************/
284 JSDValue*
285 jsd_NewValue(JSDContext* jsdc, jsval val)
287 JSDValue* jsdval;
288 JSCrossCompartmentCall *call = NULL;
290 if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
291 return NULL;
293 if(JSVAL_IS_GCTHING(val))
295 JSBool ok = JS_FALSE;
296 JS_BeginRequest(jsdc->dumbContext);
298 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
299 if(!call) {
300 JS_EndRequest(jsdc->dumbContext);
302 return NULL;
305 ok = JS_AddNamedValueRoot(jsdc->dumbContext, &jsdval->val, "JSDValue");
306 JS_LeaveCrossCompartmentCall(call);
307 JS_EndRequest(jsdc->dumbContext);
308 if(!ok)
310 free(jsdval);
311 return NULL;
314 jsdval->val = val;
315 jsdval->nref = 1;
316 JS_INIT_CLIST(&jsdval->props);
318 return jsdval;
321 void
322 jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
324 JSCrossCompartmentCall *call = NULL;
326 JS_ASSERT(jsdval->nref > 0);
327 if(0 == --jsdval->nref)
329 jsd_RefreshValue(jsdc, jsdval);
330 if(JSVAL_IS_GCTHING(jsdval->val))
332 JS_BeginRequest(jsdc->dumbContext);
333 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
334 if(!call) {
335 JS_EndRequest(jsdc->dumbContext);
337 return;
340 JS_RemoveValueRoot(jsdc->dumbContext, &jsdval->val);
341 JS_LeaveCrossCompartmentCall(call);
342 JS_EndRequest(jsdc->dumbContext);
344 free(jsdval);
348 jsval
349 jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
351 JSObject* obj;
352 JSContext* cx;
353 jsval val = jsdval->val;
354 if (!JSVAL_IS_PRIMITIVE(val)) {
355 cx = JSD_GetDefaultJSContext(jsdc);
356 obj = js_ObjectToOuterObject(cx, JSVAL_TO_OBJECT(val));
357 if (!obj)
359 JS_ClearPendingException(cx);
360 val = JSVAL_NULL;
362 else
363 val = OBJECT_TO_JSVAL(obj);
366 return val;
369 static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
370 uintN additionalFlags)
372 JSDProperty* jsdprop;
374 if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
375 return NULL;
377 JS_INIT_CLIST(&jsdprop->links);
378 jsdprop->nref = 1;
379 jsdprop->flags = pd->flags | additionalFlags;
380 jsdprop->slot = pd->slot;
382 if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
383 goto new_prop_fail;
385 if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
386 goto new_prop_fail;
388 if((jsdprop->flags & JSDPD_ALIAS) &&
389 !(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
390 goto new_prop_fail;
392 return jsdprop;
393 new_prop_fail:
394 jsd_DropProperty(jsdc, jsdprop);
395 return NULL;
398 static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
400 JSDProperty* jsdprop;
402 while(jsdprop = (JSDProperty*)jsdval->props.next,
403 jsdprop != (JSDProperty*)&jsdval->props)
405 JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
406 jsd_DropProperty(jsdc, jsdprop);
408 JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
409 CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
412 static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
414 JSContext* cx = jsdc->dumbContext;
415 JSObject *obj;
416 JSPropertyDescArray pda;
417 uintN i;
418 JSCrossCompartmentCall *call = NULL;
420 JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
421 JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
422 JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
424 if(JSVAL_IS_PRIMITIVE(jsdval->val))
425 return JS_FALSE;
427 obj = JSVAL_TO_OBJECT(jsdval->val);
429 JS_BeginRequest(cx);
430 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
431 if(!call)
433 JS_EndRequest(jsdc->dumbContext);
434 return JS_FALSE;
437 if(!JS_GetPropertyDescArray(cx, obj, &pda))
439 JS_EndRequest(cx);
440 JS_LeaveCrossCompartmentCall(call);
441 return JS_FALSE;
444 for(i = 0; i < pda.length; i++)
446 JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
447 if(!prop)
449 _freeProps(jsdc, jsdval);
450 break;
452 JS_APPEND_LINK(&prop->links, &jsdval->props);
454 JS_PutPropertyDescArray(cx, &pda);
455 JS_LeaveCrossCompartmentCall(call);
456 JS_EndRequest(cx);
457 SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
458 return !JS_CLIST_IS_EMPTY(&jsdval->props);
461 #undef DROP_CLEAR_VALUE
462 #define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
464 void
465 jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
467 JSContext* cx = jsdc->dumbContext;
468 JSCrossCompartmentCall *call = NULL;
470 if(jsdval->string)
472 /* if the jsval is a string, then we didn't need to root the string */
473 if(!JSVAL_IS_STRING(jsdval->val))
475 JS_BeginRequest(cx);
476 call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
477 if(!call) {
478 JS_EndRequest(cx);
480 return;
483 JS_RemoveStringRoot(cx, &jsdval->string);
484 JS_LeaveCrossCompartmentCall(call);
485 JS_EndRequest(cx);
487 jsdval->string = NULL;
490 jsdval->funName = NULL;
491 jsdval->className = NULL;
492 DROP_CLEAR_VALUE(jsdc, jsdval->proto);
493 DROP_CLEAR_VALUE(jsdc, jsdval->parent);
494 DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
495 _freeProps(jsdc, jsdval);
496 jsdval->flags = 0;
499 /***************************************************************************/
501 uintN
502 jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
504 JSDProperty* jsdprop;
505 uintN count = 0;
507 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
508 if(!_buildProps(jsdc, jsdval))
509 return 0;
511 for(jsdprop = (JSDProperty*)jsdval->props.next;
512 jsdprop != (JSDProperty*)&jsdval->props;
513 jsdprop = (JSDProperty*)jsdprop->links.next)
515 count++;
517 return count;
520 JSDProperty*
521 jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
523 JSDProperty* jsdprop = *iterp;
524 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
526 JS_ASSERT(!jsdprop);
527 if(!_buildProps(jsdc, jsdval))
528 return NULL;
531 if(!jsdprop)
532 jsdprop = (JSDProperty*)jsdval->props.next;
533 if(jsdprop == (JSDProperty*)&jsdval->props)
534 return NULL;
535 *iterp = (JSDProperty*)jsdprop->links.next;
537 JS_ASSERT(jsdprop);
538 jsdprop->nref++;
539 return jsdprop;
542 JSDProperty*
543 jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
545 JSContext* cx = jsdc->dumbContext;
546 JSDProperty* jsdprop;
547 JSDProperty* iter = NULL;
548 JSObject* obj;
549 uintN attrs = 0;
550 JSBool found;
551 JSPropertyDesc pd;
552 const jschar * nameChars;
553 size_t nameLen;
554 jsval val, nameval;
555 jsid nameid;
556 JSCrossCompartmentCall *call = NULL;
558 if(!jsd_IsValueObject(jsdc, jsdval))
559 return NULL;
561 /* If we already have the prop, then return it */
562 while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
564 JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
565 if(propName && !JS_CompareStrings(propName, name))
566 return jsdprop;
567 JSD_DropProperty(jsdc, jsdprop);
569 /* Not found in property list, look it up explicitly */
571 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
572 return NULL;
574 nameChars = JS_GetStringChars(name);
575 nameLen = JS_GetStringLength(name);
577 JS_BeginRequest(cx);
578 call = JS_EnterCrossCompartmentCall(cx, obj);
579 if(!call) {
580 JS_EndRequest(cx);
582 return NULL;
585 JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
586 if (!found)
588 JS_LeaveCrossCompartmentCall(call);
589 JS_EndRequest(cx);
590 return NULL;
593 JS_ClearPendingException(cx);
595 if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
597 if (JS_IsExceptionPending(cx))
599 if (!JS_GetPendingException(cx, &pd.value))
601 JS_LeaveCrossCompartmentCall(call);
602 JS_EndRequest(cx);
603 return NULL;
605 pd.flags = JSPD_EXCEPTION;
607 else
609 pd.flags = JSPD_ERROR;
610 pd.value = JSVAL_VOID;
613 else
615 pd.value = val;
618 JS_LeaveCrossCompartmentCall(call);
619 JS_EndRequest(cx);
621 nameval = STRING_TO_JSVAL(name);
622 if (!JS_ValueToId(cx, nameval, &nameid) ||
623 !JS_IdToValue(cx, nameid, &pd.id)) {
624 return NULL;
627 pd.slot = pd.spare = 0;
628 pd.alias = JSVAL_NULL;
629 pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
630 | (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0
631 | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
633 return _newProperty(jsdc, &pd, JSDPD_HINTED);
637 JSDValue*
638 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
640 JSCrossCompartmentCall *call = NULL;
642 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
644 JSObject* obj;
645 JSObject* proto;
646 JS_ASSERT(!jsdval->proto);
647 SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
648 if(!JSVAL_IS_OBJECT(jsdval->val))
649 return NULL;
650 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
651 return NULL;
652 JS_BeginRequest(jsdc->dumbContext);
653 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
654 if(!call) {
655 JS_EndRequest(jsdc->dumbContext);
657 return NULL;
659 proto = JS_GetPrototype(jsdc->dumbContext, obj);
660 JS_LeaveCrossCompartmentCall(call);
661 JS_EndRequest(jsdc->dumbContext);
662 if(!proto)
663 return NULL;
664 jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
666 if(jsdval->proto)
667 jsdval->proto->nref++;
668 return jsdval->proto;
671 JSDValue*
672 jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
674 JSCrossCompartmentCall *call = NULL;
676 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
678 JSObject* obj;
679 JSObject* parent;
680 JS_ASSERT(!jsdval->parent);
681 SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
682 if(!JSVAL_IS_OBJECT(jsdval->val))
683 return NULL;
684 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
685 return NULL;
686 JS_BeginRequest(jsdc->dumbContext);
687 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
688 if(!call) {
689 JS_EndRequest(jsdc->dumbContext);
691 return NULL;
693 parent = JS_GetParent(jsdc->dumbContext,obj);
694 JS_LeaveCrossCompartmentCall(call);
695 JS_EndRequest(jsdc->dumbContext);
696 if(!parent)
697 return NULL;
698 jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
700 if(jsdval->parent)
701 jsdval->parent->nref++;
702 return jsdval->parent;
705 JSDValue*
706 jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
708 JSCrossCompartmentCall *call = NULL;
710 if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
712 JSObject* obj;
713 JSObject* proto;
714 JSObject* ctor;
715 JS_ASSERT(!jsdval->ctor);
716 SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
717 if(!JSVAL_IS_OBJECT(jsdval->val))
718 return NULL;
719 if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
720 return NULL;
721 JS_BeginRequest(jsdc->dumbContext);
722 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
723 if(!call) {
724 JS_EndRequest(jsdc->dumbContext);
726 return NULL;
728 proto = JS_GetPrototype(jsdc->dumbContext,obj);
729 if(!proto)
731 JS_LeaveCrossCompartmentCall(call);
732 JS_EndRequest(jsdc->dumbContext);
733 return NULL;
735 ctor = JS_GetConstructor(jsdc->dumbContext,proto);
736 JS_LeaveCrossCompartmentCall(call);
737 JS_EndRequest(jsdc->dumbContext);
738 if(!ctor)
739 return NULL;
740 jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
742 if(jsdval->ctor)
743 jsdval->ctor->nref++;
744 return jsdval->ctor;
747 const char*
748 jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
750 jsval val = jsdval->val;
751 JSCrossCompartmentCall *call = NULL;
753 if(!jsdval->className && JSVAL_IS_OBJECT(val))
755 JSObject* obj;
756 if(!(obj = JSVAL_TO_OBJECT(val)))
757 return NULL;
758 JS_BeginRequest(jsdc->dumbContext);
759 call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
760 if(!call) {
761 JS_EndRequest(jsdc->dumbContext);
763 return NULL;
765 if(JS_GET_CLASS(jsdc->dumbContext, obj))
766 jsdval->className = JS_GET_CLASS(jsdc->dumbContext, obj)->name;
767 JS_LeaveCrossCompartmentCall(call);
768 JS_EndRequest(jsdc->dumbContext);
770 return jsdval->className;
773 JSDScript*
774 jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
776 JSContext* cx = jsdc->dumbContext;
777 jsval val = jsdval->val;
778 JSFunction* fun = NULL;
779 JSExceptionState* exceptionState;
780 JSScript* script = NULL;
781 JSDScript* jsdscript;
782 JSCrossCompartmentCall *call = NULL;
784 if (!jsd_IsValueFunction(jsdc, jsdval))
785 return NULL;
787 JS_BeginRequest(cx);
788 call = JS_EnterCrossCompartmentCall(cx, JSVAL_TO_OBJECT(val));
789 if (!call) {
790 JS_EndRequest(cx);
792 return NULL;
795 exceptionState = JS_SaveExceptionState(cx);
796 fun = JS_ValueToFunction(cx, val);
797 JS_RestoreExceptionState(cx, exceptionState);
798 if (fun)
799 script = JS_GetFunctionScript(cx, fun);
800 JS_LeaveCrossCompartmentCall(call);
801 JS_EndRequest(cx);
803 if (!script)
804 return NULL;
806 JSD_LOCK_SCRIPTS(jsdc);
807 jsdscript = jsd_FindJSDScript(jsdc, script);
808 JSD_UNLOCK_SCRIPTS(jsdc);
809 return jsdscript;
813 /***************************************************************************/
814 /***************************************************************************/
816 JSDValue*
817 jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
819 jsdprop->name->nref++;
820 return jsdprop->name;
823 JSDValue*
824 jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
826 jsdprop->val->nref++;
827 return jsdprop->val;
830 JSDValue*
831 jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
833 if(jsdprop->alias)
834 jsdprop->alias->nref++;
835 return jsdprop->alias;
838 uintN
839 jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
841 return jsdprop->flags;
844 uintN
845 jsd_GetPropertyVarArgSlot(JSDContext* jsdc, JSDProperty* jsdprop)
847 return jsdprop->slot;
850 void
851 jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
853 JS_ASSERT(jsdprop->nref > 0);
854 if(0 == --jsdprop->nref)
856 JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
857 DROP_CLEAR_VALUE(jsdc, jsdprop->val);
858 DROP_CLEAR_VALUE(jsdc, jsdprop->name);
859 DROP_CLEAR_VALUE(jsdc, jsdprop->alias);
860 free(jsdprop);