~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/js/jsd/jsd_val.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Netscape Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/NPL/
 
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 NPL, 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 NPL, 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
 
 
44
#ifdef DEBUG
 
45
void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
 
46
{
 
47
    JS_ASSERT(jsdval);
 
48
    JS_ASSERT(jsdval->nref > 0);
 
49
    if(!JS_CLIST_IS_EMPTY(&jsdval->props))
 
50
    {
 
51
        JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
 
52
        JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
 
53
    }
 
54
 
 
55
    if(jsdval->proto)
 
56
    {
 
57
        JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
 
58
        JS_ASSERT(jsdval->proto->nref > 0);
 
59
    }
 
60
    if(jsdval->parent)
 
61
    {
 
62
        JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
 
63
        JS_ASSERT(jsdval->parent->nref > 0);
 
64
    }
 
65
    if(jsdval->ctor)
 
66
    {
 
67
        JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
 
68
        JS_ASSERT(jsdval->ctor->nref > 0);
 
69
    }
 
70
}
 
71
 
 
72
void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
 
73
{
 
74
    JS_ASSERT(jsdprop);
 
75
    JS_ASSERT(jsdprop->name);
 
76
    JS_ASSERT(jsdprop->name->nref > 0);
 
77
    JS_ASSERT(jsdprop->val);
 
78
    JS_ASSERT(jsdprop->val->nref > 0);
 
79
    if(jsdprop->alias)
 
80
        JS_ASSERT(jsdprop->alias->nref > 0);
 
81
}
 
82
#endif
 
83
 
 
84
 
 
85
JSBool
 
86
jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
 
87
{
 
88
    return JSVAL_IS_OBJECT(jsdval->val);
 
89
}
 
90
 
 
91
JSBool
 
92
jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
 
93
{
 
94
    return JSVAL_IS_NUMBER(jsdval->val);
 
95
}
 
96
 
 
97
JSBool
 
98
jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
 
99
{
 
100
    return JSVAL_IS_INT(jsdval->val);
 
101
}
 
102
 
 
103
JSBool
 
104
jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
 
105
{
 
106
    return JSVAL_IS_DOUBLE(jsdval->val);
 
107
}
 
108
 
 
109
JSBool
 
110
jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
 
111
{
 
112
    return JSVAL_IS_STRING(jsdval->val);
 
113
}
 
114
 
 
115
JSBool
 
116
jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
 
117
{
 
118
    return JSVAL_IS_BOOLEAN(jsdval->val);
 
119
}
 
120
 
 
121
JSBool
 
122
jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
 
123
{
 
124
    return JSVAL_IS_NULL(jsdval->val);
 
125
}
 
126
 
 
127
JSBool
 
128
jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
 
129
{
 
130
    return JSVAL_IS_VOID(jsdval->val);
 
131
}
 
132
 
 
133
JSBool
 
134
jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
 
135
{
 
136
    return JSVAL_IS_PRIMITIVE(jsdval->val);
 
137
}
 
138
 
 
139
JSBool
 
140
jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
 
141
{
 
142
    return JSVAL_IS_FUNCTION(jsdc->dumbContext, jsdval->val);
 
143
}
 
144
 
 
145
JSBool
 
146
jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
 
147
{
 
148
    JSContext* cx = jsdc->dumbContext;
 
149
    jsval val = jsdval->val;
 
150
    JSFunction* fun;
 
151
    JSExceptionState* exceptionState;
 
152
 
 
153
    if(!JSVAL_IS_OBJECT(val))
 
154
        return JS_FALSE;
 
155
 
 
156
    if(JSVAL_IS_FUNCTION(cx, val))
 
157
    {
 
158
        exceptionState = JS_SaveExceptionState(cx);
 
159
        fun = JS_ValueToFunction(cx, val);
 
160
        JS_RestoreExceptionState(cx, exceptionState);
 
161
        if(!fun)
 
162
        {
 
163
            JS_ASSERT(0);
 
164
            return JS_FALSE;
 
165
        }
 
166
        return JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
 
167
    }
 
168
    return JSVAL_TO_OBJECT(val) && OBJ_IS_NATIVE(JSVAL_TO_OBJECT(val));
 
169
}
 
170
 
 
171
/***************************************************************************/
 
172
 
 
173
JSBool
 
174
jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
 
175
{
 
176
    jsval val = jsdval->val;
 
177
    if(!JSVAL_IS_BOOLEAN(val))
 
178
        return JS_FALSE;
 
179
    return JSVAL_TO_BOOLEAN(val);
 
180
}
 
181
 
 
182
int32
 
183
jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
 
184
{
 
185
    jsval val = jsdval->val;
 
186
    if(!JSVAL_IS_INT(val))
 
187
        return 0;
 
188
    return JSVAL_TO_INT(val);
 
189
}
 
190
 
 
191
jsdouble*
 
192
jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
 
193
{
 
194
    jsval val = jsdval->val;
 
195
    if(!JSVAL_IS_DOUBLE(val))
 
196
        return 0;
 
197
    return JSVAL_TO_DOUBLE(val);
 
198
}
 
199
 
 
200
JSString*
 
201
jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
 
202
{
 
203
    JSContext* cx = jsdc->dumbContext;
 
204
    JSExceptionState* exceptionState;
 
205
 
 
206
    if(!jsdval->string)
 
207
    {
 
208
        /* if the jsval is a string, then we don't need to double root it */
 
209
        if(JSVAL_IS_STRING(jsdval->val))
 
210
            jsdval->string = JSVAL_TO_STRING(jsdval->val);
 
211
        else
 
212
        {
 
213
            exceptionState = JS_SaveExceptionState(cx);
 
214
            jsdval->string = JS_ValueToString(cx, jsdval->val);
 
215
            JS_RestoreExceptionState(cx, exceptionState);
 
216
            if(jsdval->string)
 
217
            {
 
218
                if(!JS_AddNamedRoot(cx, &jsdval->string, "ValueString"))
 
219
                    jsdval->string = NULL;
 
220
            }
 
221
        }
 
222
    }
 
223
    return jsdval->string;
 
224
}
 
225
 
 
226
const char*
 
227
jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
 
228
{
 
229
    JSContext* cx = jsdc->dumbContext;
 
230
    jsval val = jsdval->val;
 
231
    JSFunction* fun;
 
232
    JSExceptionState* exceptionState;
 
233
 
 
234
    if(!jsdval->funName && JSVAL_IS_FUNCTION(cx, val))
 
235
    {
 
236
        exceptionState = JS_SaveExceptionState(cx);
 
237
        fun = JS_ValueToFunction(cx, val);
 
238
        JS_RestoreExceptionState(cx, exceptionState);
 
239
        if(!fun)
 
240
            return NULL;
 
241
        jsdval->funName = JS_GetFunctionName(fun);
 
242
    }
 
243
    return jsdval->funName;
 
244
}
 
245
 
 
246
/***************************************************************************/
 
247
 
 
248
JSDValue*
 
249
jsd_NewValue(JSDContext* jsdc, jsval val)
 
250
{
 
251
    JSDValue* jsdval;
 
252
 
 
253
    if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
 
254
        return NULL;
 
255
 
 
256
    if(JSVAL_IS_GCTHING(val))
 
257
    {
 
258
        if(!JS_AddNamedRoot(jsdc->dumbContext, &jsdval->val, "JSDValue"))
 
259
        {
 
260
            free(jsdval);
 
261
            return NULL;
 
262
        }
 
263
    }
 
264
    jsdval->val  = val;
 
265
    jsdval->nref = 1;
 
266
    JS_INIT_CLIST(&jsdval->props);
 
267
 
 
268
    return jsdval;
 
269
}
 
270
 
 
271
void
 
272
jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
 
273
{
 
274
    JS_ASSERT(jsdval->nref > 0);
 
275
    if(0 == --jsdval->nref)
 
276
    {
 
277
        jsd_RefreshValue(jsdc, jsdval);
 
278
        if(JSVAL_IS_GCTHING(jsdval->val))
 
279
            JS_RemoveRoot(jsdc->dumbContext, &jsdval->val);
 
280
        free(jsdval);
 
281
    }
 
282
}
 
283
 
 
284
jsval
 
285
jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
 
286
{
 
287
    return jsdval->val;
 
288
}
 
289
 
 
290
static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
 
291
                                 uintN additionalFlags)
 
292
{
 
293
    JSDProperty* jsdprop;
 
294
 
 
295
    if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
 
296
        return NULL;
 
297
 
 
298
    JS_INIT_CLIST(&jsdprop->links);
 
299
    jsdprop->nref = 1;
 
300
    jsdprop->flags = pd->flags | additionalFlags;
 
301
    jsdprop->slot = pd->slot;
 
302
 
 
303
    if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
 
304
        goto new_prop_fail;
 
305
 
 
306
    if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
 
307
        goto new_prop_fail;
 
308
 
 
309
    if((jsdprop->flags & JSDPD_ALIAS) &&
 
310
       !(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
 
311
        goto new_prop_fail;
 
312
 
 
313
    return jsdprop;
 
314
new_prop_fail:
 
315
    jsd_DropProperty(jsdc, jsdprop);
 
316
    return NULL;
 
317
}
 
318
 
 
319
static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
 
320
{
 
321
    JSDProperty* jsdprop;
 
322
 
 
323
    while(jsdprop = (JSDProperty*)jsdval->props.next,
 
324
          jsdprop != (JSDProperty*)&jsdval->props)
 
325
    {
 
326
        JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
 
327
        jsd_DropProperty(jsdc, jsdprop);
 
328
    }
 
329
    JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
 
330
    CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
 
331
}
 
332
 
 
333
static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
 
334
{
 
335
    JSContext* cx = jsdc->dumbContext;
 
336
    JSPropertyDescArray pda;
 
337
    uintN i;
 
338
 
 
339
    JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
 
340
    JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
 
341
    JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
 
342
 
 
343
    if(!JSVAL_IS_OBJECT(jsdval->val) || JSVAL_IS_NULL(jsdval->val))
 
344
        return JS_FALSE;
 
345
 
 
346
    if(!JS_GetPropertyDescArray(cx, JSVAL_TO_OBJECT(jsdval->val), &pda))
 
347
        return JS_FALSE;
 
348
 
 
349
    for(i = 0; i < pda.length; i++)
 
350
    {
 
351
        JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
 
352
        if(!prop)
 
353
        {
 
354
            _freeProps(jsdc, jsdval);
 
355
            break;
 
356
        }
 
357
        JS_APPEND_LINK(&prop->links, &jsdval->props);
 
358
    }
 
359
    JS_PutPropertyDescArray(cx, &pda);
 
360
    SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
 
361
    return !JS_CLIST_IS_EMPTY(&jsdval->props);
 
362
}
 
363
 
 
364
#undef  DROP_CLEAR_VALUE
 
365
#define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
 
366
 
 
367
void
 
368
jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
 
369
{
 
370
    JSContext* cx = jsdc->dumbContext;
 
371
 
 
372
    if(jsdval->string)
 
373
    {
 
374
        /* if the jsval is a string, then we didn't need to root the string */
 
375
        if(!JSVAL_IS_STRING(jsdval->val))
 
376
            JS_RemoveRoot(cx, &jsdval->string);
 
377
        jsdval->string = NULL;
 
378
    }
 
379
 
 
380
    jsdval->funName = NULL;
 
381
    jsdval->className = NULL;
 
382
    DROP_CLEAR_VALUE(jsdc, jsdval->proto);
 
383
    DROP_CLEAR_VALUE(jsdc, jsdval->parent);
 
384
    DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
 
385
    _freeProps(jsdc, jsdval);
 
386
    jsdval->flags = 0;
 
387
}
 
388
 
 
389
/***************************************************************************/
 
390
 
 
391
uintN
 
392
jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
 
393
{
 
394
    JSDProperty* jsdprop;
 
395
    uintN count = 0;
 
396
 
 
397
    if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
 
398
        if(!_buildProps(jsdc, jsdval))
 
399
            return 0;
 
400
 
 
401
    for(jsdprop = (JSDProperty*)jsdval->props.next;
 
402
        jsdprop != (JSDProperty*)&jsdval->props;
 
403
        jsdprop = (JSDProperty*)jsdprop->links.next)
 
404
    {
 
405
        count++;
 
406
    }
 
407
    return count;
 
408
}
 
409
 
 
410
JSDProperty*
 
411
jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
 
412
{
 
413
    JSDProperty* jsdprop = *iterp;
 
414
    if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
 
415
    {
 
416
        JS_ASSERT(!jsdprop);
 
417
        if(!_buildProps(jsdc, jsdval))
 
418
            return NULL;
 
419
    }
 
420
 
 
421
    if(!jsdprop)
 
422
        jsdprop = (JSDProperty*)jsdval->props.next;
 
423
    if(jsdprop == (JSDProperty*)&jsdval->props)
 
424
        return NULL;
 
425
    *iterp = (JSDProperty*)jsdprop->links.next;
 
426
 
 
427
    JS_ASSERT(jsdprop);
 
428
    jsdprop->nref++;
 
429
    return jsdprop;
 
430
}
 
431
 
 
432
JSDProperty*
 
433
jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
 
434
{
 
435
    JSContext* cx = jsdc->dumbContext;
 
436
    JSDProperty* jsdprop;
 
437
    JSDProperty* iter = NULL;
 
438
    JSObject* obj;
 
439
    uintN  attrs = 0;
 
440
    JSBool found;
 
441
    JSPropertyDesc pd;
 
442
    const jschar * nameChars;
 
443
    size_t nameLen;
 
444
    jsval val;
 
445
 
 
446
    if(!jsd_IsValueObject(jsdc, jsdval))
 
447
        return NULL;
 
448
 
 
449
    /* If we already have the prop, then return it */
 
450
    while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
 
451
    {
 
452
        JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
 
453
        if(propName && !JS_CompareStrings(propName, name))
 
454
            return jsdprop;
 
455
        JSD_DropProperty(jsdc, jsdprop);
 
456
    }
 
457
    /* Not found in property list, look it up explicitly */
 
458
 
 
459
    if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
 
460
        return NULL;
 
461
 
 
462
    nameChars = JS_GetStringChars(name);
 
463
    nameLen   = JS_GetStringLength(name);
 
464
 
 
465
    JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
 
466
    if (!found)
 
467
        return NULL;
 
468
 
 
469
    JS_ClearPendingException(cx);
 
470
 
 
471
    if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
 
472
    {
 
473
        if (JS_IsExceptionPending(cx))
 
474
        {
 
475
            if (!JS_GetPendingException(cx, &pd.value))
 
476
                return NULL;
 
477
            pd.flags = JSPD_EXCEPTION;
 
478
        }
 
479
        else
 
480
        {
 
481
            pd.flags = JSPD_ERROR;
 
482
            pd.value = JSVAL_VOID;
 
483
        }
 
484
    }
 
485
    else
 
486
    {
 
487
        pd.value = val;
 
488
    }
 
489
 
 
490
    pd.id = STRING_TO_JSVAL(name);
 
491
    pd.alias = pd.slot = pd.spare = 0;
 
492
    pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
 
493
        | (attrs & JSPROP_READONLY)  ? JSPD_READONLY  : 0
 
494
        | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
 
495
 
 
496
    return _newProperty(jsdc, &pd, JSDPD_HINTED);
 
497
}
 
498
 
 
499
 
 
500
JSDValue*
 
501
jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
 
502
{
 
503
    if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
 
504
    {
 
505
        JSObject* obj;
 
506
        JSObject* proto;
 
507
        JS_ASSERT(!jsdval->proto);
 
508
        SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
 
509
        if(!JSVAL_IS_OBJECT(jsdval->val))
 
510
            return NULL;
 
511
        if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
 
512
            return NULL;
 
513
        if(!(proto = OBJ_GET_PROTO(jsdc->dumbContext,obj)))
 
514
            return NULL;
 
515
        jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
 
516
    }
 
517
    if(jsdval->proto)
 
518
        jsdval->proto->nref++;
 
519
    return jsdval->proto;
 
520
}
 
521
 
 
522
JSDValue*
 
523
jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
 
524
{
 
525
    if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
 
526
    {
 
527
        JSObject* obj;
 
528
        JSObject* parent;
 
529
        JS_ASSERT(!jsdval->parent);
 
530
        SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
 
531
        if(!JSVAL_IS_OBJECT(jsdval->val))
 
532
            return NULL;
 
533
        if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
 
534
            return NULL;
 
535
        if(!(parent = OBJ_GET_PARENT(jsdc->dumbContext,obj)))
 
536
            return NULL;
 
537
        jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
 
538
    }
 
539
    if(jsdval->parent)
 
540
        jsdval->parent->nref++;
 
541
    return jsdval->parent;
 
542
}
 
543
 
 
544
JSDValue*
 
545
jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
 
546
{
 
547
    if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
 
548
    {
 
549
        JSObject* obj;
 
550
        JSObject* proto;
 
551
        JSObject* ctor;
 
552
        JS_ASSERT(!jsdval->ctor);
 
553
        SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
 
554
        if(!JSVAL_IS_OBJECT(jsdval->val))
 
555
            return NULL;
 
556
        if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
 
557
            return NULL;
 
558
        if(!(proto = OBJ_GET_PROTO(jsdc->dumbContext,obj)))
 
559
            return NULL;
 
560
        if(!(ctor = JS_GetConstructor(jsdc->dumbContext,proto)))
 
561
            return NULL;
 
562
        jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
 
563
    }
 
564
    if(jsdval->ctor)
 
565
        jsdval->ctor->nref++;
 
566
    return jsdval->ctor;
 
567
}
 
568
 
 
569
const char*
 
570
jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
 
571
{
 
572
    jsval val = jsdval->val;
 
573
    if(!jsdval->className && JSVAL_IS_OBJECT(val))
 
574
    {
 
575
        JSObject* obj;
 
576
        if(!(obj = JSVAL_TO_OBJECT(val)))
 
577
            return NULL;
 
578
        if(OBJ_GET_CLASS(jsdc->dumbContext, obj))
 
579
            jsdval->className = OBJ_GET_CLASS(jsdc->dumbContext, obj)->name;
 
580
    }
 
581
    return jsdval->className;
 
582
}
 
583
 
 
584
/***************************************************************************/
 
585
/***************************************************************************/
 
586
 
 
587
JSDValue*
 
588
jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
 
589
{
 
590
    jsdprop->name->nref++;
 
591
    return jsdprop->name;
 
592
}
 
593
 
 
594
JSDValue*
 
595
jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
 
596
{
 
597
    jsdprop->val->nref++;
 
598
    return jsdprop->val;
 
599
}
 
600
 
 
601
JSDValue*
 
602
jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
 
603
{
 
604
    if(jsdprop->alias)
 
605
        jsdprop->alias->nref++;
 
606
    return jsdprop->alias;
 
607
}
 
608
 
 
609
uintN
 
610
jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
 
611
{
 
612
    return jsdprop->flags;
 
613
}
 
614
 
 
615
uintN
 
616
jsd_GetPropertyVarArgSlot(JSDContext* jsdc, JSDProperty* jsdprop)
 
617
{
 
618
    return jsdprop->slot;
 
619
}
 
620
 
 
621
void
 
622
jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
 
623
{
 
624
    JS_ASSERT(jsdprop->nref > 0);
 
625
    if(0 == --jsdprop->nref)
 
626
    {
 
627
        JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
 
628
        DROP_CLEAR_VALUE(jsdc, jsdprop->val);
 
629
        DROP_CLEAR_VALUE(jsdc, jsdprop->name);
 
630
        DROP_CLEAR_VALUE(jsdc, jsdprop->alias);
 
631
        free(jsdprop);
 
632
    }
 
633
}