~ubuntu-branches/ubuntu/hardy/avidemux/hardy

« back to all changes in this revision

Viewing changes to avidemux/ADM_libraries/ADM_smjs/jsapi.c

  • Committer: Bazaar Package Importer
  • Author(s): Matvey Kozhev
  • Date: 2007-12-18 13:53:04 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20071218135304-cdqec2lg2bglyz15
Tags: 1:2.4~preview3-0.0ubuntu1
* Upload to Ubuntu. (LP: #163287, LP: #126572)
* debian/changelog: re-added Ubuntu releases.
* debian/control:
  - Require debhelper >= 5.0.51 (for dh_icons) and imagemagick.
  - Build-depend on libsdl1.2-dev instead of libsdl-dev.
  - Build against newer libx264-dev. (LP: #138854)
  - Removed libamrnb-dev, not in Ubuntu yet.
* debian/rules:
  - Install all icon sizes, using convert (upstream installs none).
  - Added missing calls to dh_installmenu, dh_installman, dh_icons and
    dh_desktop.
* debian/menu, debian/avidemux-qt.menu:
  - Corrected package and executable names.
* debian/avidemux-common.install: Install icons.
* debian/avidemux.common.manpages: Install man/avidemux.1.
* debian/links, debian/avidemux-cli.links, debian/avidemux-gtk.links:
  - Link manpages to avidemux.1.gz.
* debian/install, debian/avidemux-qt.install, debian/avidemux-gtk.desktop,
  debian/avidemux-qt.desktop: Install desktop files.

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
 * vim: set ts=8 sw=4 et tw=80:
 
3
 *
 
4
 * ***** BEGIN LICENSE BLOCK *****
 
5
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
6
 *
 
7
 * The contents of this file are subject to the Mozilla Public License Version
 
8
 * 1.1 (the "License"); you may not use this file except in compliance with
 
9
 * the License. You may obtain a copy of the License at
 
10
 * http://www.mozilla.org/MPL/
 
11
 *
 
12
 * Software distributed under the License is distributed on an "AS IS" basis,
 
13
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
14
 * for the specific language governing rights and limitations under the
 
15
 * License.
 
16
 *
 
17
 * The Original Code is Mozilla Communicator client code, released
 
18
 * March 31, 1998.
 
19
 *
 
20
 * The Initial Developer of the Original Code is
 
21
 * Netscape Communications Corporation.
 
22
 * Portions created by the Initial Developer are Copyright (C) 1998
 
23
 * the Initial Developer. All Rights Reserved.
 
24
 *
 
25
 * Contributor(s):
 
26
 *
 
27
 * Alternatively, the contents of this file may be used under the terms of
 
28
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 
29
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
30
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
31
 * of those above. If you wish to allow use of your version of this file only
 
32
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
33
 * use your version of this file under the terms of the MPL, indicate your
 
34
 * decision by deleting the provisions above and replace them with the notice
 
35
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
36
 * the provisions above, a recipient may use your version of this file under
 
37
 * the terms of any one of the MPL, the GPL or the LGPL.
 
38
 *
 
39
 * ***** END LICENSE BLOCK ***** */
 
40
 
 
41
/*
 
42
 * JavaScript API.
 
43
 */
 
44
#include "jsstddef.h"
 
45
#include <ctype.h>
 
46
#include <stdarg.h>
 
47
#include <stdlib.h>
 
48
#include <string.h>
 
49
#include "jstypes.h"
 
50
#include "jsarena.h" /* Added by JSIFY */
 
51
#include "jsutil.h" /* Added by JSIFY */
 
52
#include "jsclist.h"
 
53
#include "jsdhash.h"
 
54
#include "jsprf.h"
 
55
#include "jsapi.h"
 
56
#include "jsarray.h"
 
57
#include "jsatom.h"
 
58
#include "jsbool.h"
 
59
#include "jscntxt.h"
 
60
#include "jsconfig.h"
 
61
#include "jsdate.h"
 
62
#include "jsdtoa.h"
 
63
#include "jsemit.h"
 
64
#include "jsexn.h"
 
65
#include "jsfun.h"
 
66
#include "jsgc.h"
 
67
#include "jsinterp.h"
 
68
#include "jslock.h"
 
69
#include "jsmath.h"
 
70
#include "jsnum.h"
 
71
#include "jsobj.h"
 
72
#include "jsopcode.h"
 
73
#include "jsparse.h"
 
74
#include "jsregexp.h"
 
75
#include "jsscan.h"
 
76
#include "jsscope.h"
 
77
#include "jsscript.h"
 
78
#include "jsstr.h"
 
79
#include "prmjtime.h"
 
80
 
 
81
#if JS_HAS_FILE_OBJECT
 
82
#include "jsfile.h"
 
83
#endif
 
84
 
 
85
#if JS_HAS_XML_SUPPORT
 
86
#include "jsxml.h"
 
87
#endif
 
88
 
 
89
#ifdef HAVE_VA_LIST_AS_ARRAY
 
90
#define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
 
91
#else
 
92
#define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
 
93
#endif
 
94
 
 
95
#if defined(JS_PARANOID_REQUEST) && defined(JS_THREADSAFE)
 
96
#define CHECK_REQUEST(cx)       JS_ASSERT(cx->requestDepth)
 
97
#else
 
98
#define CHECK_REQUEST(cx)       ((void)0)
 
99
#endif
 
100
 
 
101
JS_PUBLIC_API(int64)
 
102
JS_Now()
 
103
{
 
104
    return PRMJ_Now();
 
105
}
 
106
 
 
107
JS_PUBLIC_API(jsval)
 
108
JS_GetNaNValue(JSContext *cx)
 
109
{
 
110
    return DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
 
111
}
 
112
 
 
113
JS_PUBLIC_API(jsval)
 
114
JS_GetNegativeInfinityValue(JSContext *cx)
 
115
{
 
116
    return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
 
117
}
 
118
 
 
119
JS_PUBLIC_API(jsval)
 
120
JS_GetPositiveInfinityValue(JSContext *cx)
 
121
{
 
122
    return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
 
123
}
 
124
 
 
125
JS_PUBLIC_API(jsval)
 
126
JS_GetEmptyStringValue(JSContext *cx)
 
127
{
 
128
    return STRING_TO_JSVAL(cx->runtime->emptyString);
 
129
}
 
130
 
 
131
static JSBool
 
132
TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS,
 
133
                     jsval **vpp, va_list *app)
 
134
{
 
135
    const char *format;
 
136
    JSArgumentFormatMap *map;
 
137
 
 
138
    format = *formatp;
 
139
    for (map = cx->argumentFormatMap; map; map = map->next) {
 
140
        if (!strncmp(format, map->format, map->length)) {
 
141
            *formatp = format + map->length;
 
142
            return map->formatter(cx, format, fromJS, vpp, app);
 
143
        }
 
144
    }
 
145
    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
 
146
    return JS_FALSE;
 
147
}
 
148
 
 
149
JS_PUBLIC_API(JSBool)
 
150
JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
 
151
                    ...)
 
152
{
 
153
    va_list ap;
 
154
    JSBool ok;
 
155
 
 
156
    va_start(ap, format);
 
157
    ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
 
158
    va_end(ap);
 
159
    return ok;
 
160
}
 
161
 
 
162
JS_PUBLIC_API(JSBool)
 
163
JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
 
164
                      const char *format, va_list ap)
 
165
{
 
166
    jsval *sp;
 
167
    JSBool required;
 
168
    char c;
 
169
    JSFunction *fun;
 
170
    jsdouble d;
 
171
    JSString *str;
 
172
    JSObject *obj;
 
173
 
 
174
    CHECK_REQUEST(cx);
 
175
    sp = argv;
 
176
    required = JS_TRUE;
 
177
    while ((c = *format++) != '\0') {
 
178
        if (isspace(c))
 
179
            continue;
 
180
        if (c == '/') {
 
181
            required = JS_FALSE;
 
182
            continue;
 
183
        }
 
184
        if (sp == argv + argc) {
 
185
            if (required) {
 
186
                fun = js_ValueToFunction(cx, &argv[-2], 0);
 
187
                if (fun) {
 
188
                    char numBuf[12];
 
189
                    JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
 
190
                    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
 
191
                                         JSMSG_MORE_ARGS_NEEDED,
 
192
                                         JS_GetFunctionName(fun), numBuf,
 
193
                                         (argc == 1) ? "" : "s");
 
194
                }
 
195
                return JS_FALSE;
 
196
            }
 
197
            break;
 
198
        }
 
199
        switch (c) {
 
200
          case 'b':
 
201
            if (!js_ValueToBoolean(cx, *sp, va_arg(ap, JSBool *)))
 
202
                return JS_FALSE;
 
203
            break;
 
204
          case 'c':
 
205
            if (!js_ValueToUint16(cx, *sp, va_arg(ap, uint16 *)))
 
206
                return JS_FALSE;
 
207
            break;
 
208
          case 'i':
 
209
            if (!js_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
 
210
                return JS_FALSE;
 
211
            break;
 
212
          case 'u':
 
213
            if (!js_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
 
214
                return JS_FALSE;
 
215
            break;
 
216
          case 'j':
 
217
            if (!js_ValueToInt32(cx, *sp, va_arg(ap, int32 *)))
 
218
                return JS_FALSE;
 
219
            break;
 
220
          case 'd':
 
221
            if (!js_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
 
222
                return JS_FALSE;
 
223
            break;
 
224
          case 'I':
 
225
            if (!js_ValueToNumber(cx, *sp, &d))
 
226
                return JS_FALSE;
 
227
            *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
 
228
            break;
 
229
          case 's':
 
230
          case 'S':
 
231
          case 'W':
 
232
            str = js_ValueToString(cx, *sp);
 
233
            if (!str)
 
234
                return JS_FALSE;
 
235
            *sp = STRING_TO_JSVAL(str);
 
236
            if (c == 's')
 
237
                *va_arg(ap, char **) = JS_GetStringBytes(str);
 
238
            else if (c == 'W')
 
239
                *va_arg(ap, jschar **) = JS_GetStringChars(str);
 
240
            else
 
241
                *va_arg(ap, JSString **) = str;
 
242
            break;
 
243
          case 'o':
 
244
            if (!js_ValueToObject(cx, *sp, &obj))
 
245
                return JS_FALSE;
 
246
            *sp = OBJECT_TO_JSVAL(obj);
 
247
            *va_arg(ap, JSObject **) = obj;
 
248
            break;
 
249
          case 'f':
 
250
            obj = js_ValueToFunctionObject(cx, sp, 0);
 
251
            if (!obj)
 
252
                return JS_FALSE;
 
253
            *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj);
 
254
            break;
 
255
          case 'v':
 
256
            *va_arg(ap, jsval *) = *sp;
 
257
            break;
 
258
          case '*':
 
259
            break;
 
260
          default:
 
261
            format--;
 
262
            if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
 
263
                                      JS_ADDRESSOF_VA_LIST(ap))) {
 
264
                return JS_FALSE;
 
265
            }
 
266
            /* NB: the formatter already updated sp, so we continue here. */
 
267
            continue;
 
268
        }
 
269
        sp++;
 
270
    }
 
271
    return JS_TRUE;
 
272
}
 
273
 
 
274
JS_PUBLIC_API(jsval *)
 
275
JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
 
276
{
 
277
    va_list ap;
 
278
    jsval *argv;
 
279
 
 
280
    va_start(ap, format);
 
281
    argv = JS_PushArgumentsVA(cx, markp, format, ap);
 
282
    va_end(ap);
 
283
    return argv;
 
284
}
 
285
 
 
286
JS_PUBLIC_API(jsval *)
 
287
JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
 
288
{
 
289
    uintN argc;
 
290
    jsval *argv, *sp;
 
291
    char c;
 
292
    const char *cp;
 
293
    JSString *str;
 
294
    JSFunction *fun;
 
295
    JSStackHeader *sh;
 
296
 
 
297
    CHECK_REQUEST(cx);
 
298
    *markp = NULL;
 
299
    argc = 0;
 
300
    for (cp = format; (c = *cp) != '\0'; cp++) {
 
301
        /*
 
302
         * Count non-space non-star characters as individual jsval arguments.
 
303
         * This may over-allocate stack, but we'll fix below.
 
304
         */
 
305
        if (isspace(c) || c == '*')
 
306
            continue;
 
307
        argc++;
 
308
    }
 
309
    sp = js_AllocStack(cx, argc, markp);
 
310
    if (!sp)
 
311
        return NULL;
 
312
    argv = sp;
 
313
    while ((c = *format++) != '\0') {
 
314
        if (isspace(c) || c == '*')
 
315
            continue;
 
316
        switch (c) {
 
317
          case 'b':
 
318
            *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int));
 
319
            break;
 
320
          case 'c':
 
321
            *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int));
 
322
            break;
 
323
          case 'i':
 
324
          case 'j':
 
325
            if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
 
326
                goto bad;
 
327
            break;
 
328
          case 'u':
 
329
            if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
 
330
                goto bad;
 
331
            break;
 
332
          case 'd':
 
333
          case 'I':
 
334
            if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
 
335
                goto bad;
 
336
            break;
 
337
          case 's':
 
338
            str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
 
339
            if (!str)
 
340
                goto bad;
 
341
            *sp = STRING_TO_JSVAL(str);
 
342
            break;
 
343
          case 'W':
 
344
            str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
 
345
            if (!str)
 
346
                goto bad;
 
347
            *sp = STRING_TO_JSVAL(str);
 
348
            break;
 
349
          case 'S':
 
350
            str = va_arg(ap, JSString *);
 
351
            *sp = STRING_TO_JSVAL(str);
 
352
            break;
 
353
          case 'o':
 
354
            *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
 
355
            break;
 
356
          case 'f':
 
357
            fun = va_arg(ap, JSFunction *);
 
358
            *sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
 
359
            break;
 
360
          case 'v':
 
361
            *sp = va_arg(ap, jsval);
 
362
            break;
 
363
          default:
 
364
            format--;
 
365
            if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp,
 
366
                                      JS_ADDRESSOF_VA_LIST(ap))) {
 
367
                goto bad;
 
368
            }
 
369
            /* NB: the formatter already updated sp, so we continue here. */
 
370
            continue;
 
371
        }
 
372
        sp++;
 
373
    }
 
374
 
 
375
    /*
 
376
     * We may have overallocated stack due to a multi-character format code
 
377
     * handled by a JSArgumentFormatter.  Give back that stack space!
 
378
     */
 
379
    JS_ASSERT(sp <= argv + argc);
 
380
    if (sp < argv + argc) {
 
381
        /* Return slots not pushed to the current stack arena. */
 
382
        cx->stackPool.current->avail = (jsuword)sp;
 
383
 
 
384
        /* Reduce the count of slots the GC will scan in this stack segment. */
 
385
        sh = cx->stackHeaders;
 
386
        JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc);
 
387
        sh->nslots -= argc - (sp - argv);
 
388
    }
 
389
    return argv;
 
390
 
 
391
bad:
 
392
    js_FreeStack(cx, *markp);
 
393
    return NULL;
 
394
}
 
395
 
 
396
JS_PUBLIC_API(void)
 
397
JS_PopArguments(JSContext *cx, void *mark)
 
398
{
 
399
    CHECK_REQUEST(cx);
 
400
    js_FreeStack(cx, mark);
 
401
}
 
402
 
 
403
JS_PUBLIC_API(JSBool)
 
404
JS_AddArgumentFormatter(JSContext *cx, const char *format,
 
405
                        JSArgumentFormatter formatter)
 
406
{
 
407
    size_t length;
 
408
    JSArgumentFormatMap **mpp, *map;
 
409
 
 
410
    length = strlen(format);
 
411
    mpp = &cx->argumentFormatMap;
 
412
    while ((map = *mpp) != NULL) {
 
413
        /* Insert before any shorter string to match before prefixes. */
 
414
        if (map->length < length)
 
415
            break;
 
416
        if (map->length == length && !strcmp(map->format, format))
 
417
            goto out;
 
418
        mpp = &map->next;
 
419
    }
 
420
    map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map);
 
421
    if (!map)
 
422
        return JS_FALSE;
 
423
    map->format = format;
 
424
    map->length = length;
 
425
    map->next = *mpp;
 
426
    *mpp = map;
 
427
out:
 
428
    map->formatter = formatter;
 
429
    return JS_TRUE;
 
430
}
 
431
 
 
432
JS_PUBLIC_API(void)
 
433
JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
 
434
{
 
435
    size_t length;
 
436
    JSArgumentFormatMap **mpp, *map;
 
437
 
 
438
    length = strlen(format);
 
439
    mpp = &cx->argumentFormatMap;
 
440
    while ((map = *mpp) != NULL) {
 
441
        if (map->length == length && !strcmp(map->format, format)) {
 
442
            *mpp = map->next;
 
443
            JS_free(cx, map);
 
444
            return;
 
445
        }
 
446
        mpp = &map->next;
 
447
    }
 
448
}
 
449
 
 
450
JS_PUBLIC_API(JSBool)
 
451
JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
 
452
{
 
453
    JSBool ok, b;
 
454
    JSObject *obj;
 
455
    JSString *str;
 
456
    jsdouble d, *dp;
 
457
 
 
458
    CHECK_REQUEST(cx);
 
459
    switch (type) {
 
460
      case JSTYPE_VOID:
 
461
        *vp = JSVAL_VOID;
 
462
        ok = JS_TRUE;
 
463
        break;
 
464
      case JSTYPE_OBJECT:
 
465
        ok = js_ValueToObject(cx, v, &obj);
 
466
        if (ok)
 
467
            *vp = OBJECT_TO_JSVAL(obj);
 
468
        break;
 
469
      case JSTYPE_FUNCTION:
 
470
        *vp = v;
 
471
        obj = js_ValueToFunctionObject(cx, vp, JSV2F_SEARCH_STACK);
 
472
        ok = (obj != NULL);
 
473
        break;
 
474
      case JSTYPE_STRING:
 
475
        str = js_ValueToString(cx, v);
 
476
        ok = (str != NULL);
 
477
        if (ok)
 
478
            *vp = STRING_TO_JSVAL(str);
 
479
        break;
 
480
      case JSTYPE_NUMBER:
 
481
        ok = js_ValueToNumber(cx, v, &d);
 
482
        if (ok) {
 
483
            dp = js_NewDouble(cx, d, 0);
 
484
            ok = (dp != NULL);
 
485
            if (ok)
 
486
                *vp = DOUBLE_TO_JSVAL(dp);
 
487
        }
 
488
        break;
 
489
      case JSTYPE_BOOLEAN:
 
490
        ok = js_ValueToBoolean(cx, v, &b);
 
491
        if (ok)
 
492
            *vp = BOOLEAN_TO_JSVAL(b);
 
493
        break;
 
494
      default: {
 
495
        char numBuf[12];
 
496
        JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
 
497
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE,
 
498
                             numBuf);
 
499
        ok = JS_FALSE;
 
500
        break;
 
501
      }
 
502
    }
 
503
    return ok;
 
504
}
 
505
 
 
506
JS_PUBLIC_API(JSBool)
 
507
JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
 
508
{
 
509
    CHECK_REQUEST(cx);
 
510
    return js_ValueToObject(cx, v, objp);
 
511
}
 
512
 
 
513
JS_PUBLIC_API(JSFunction *)
 
514
JS_ValueToFunction(JSContext *cx, jsval v)
 
515
{
 
516
    CHECK_REQUEST(cx);
 
517
    return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
 
518
}
 
519
 
 
520
JS_PUBLIC_API(JSFunction *)
 
521
JS_ValueToConstructor(JSContext *cx, jsval v)
 
522
{
 
523
    CHECK_REQUEST(cx);
 
524
    return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
 
525
}
 
526
 
 
527
JS_PUBLIC_API(JSString *)
 
528
JS_ValueToString(JSContext *cx, jsval v)
 
529
{
 
530
    CHECK_REQUEST(cx);
 
531
    return js_ValueToString(cx, v);
 
532
}
 
533
 
 
534
JS_PUBLIC_API(JSBool)
 
535
JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
 
536
{
 
537
    CHECK_REQUEST(cx);
 
538
    return js_ValueToNumber(cx, v, dp);
 
539
}
 
540
 
 
541
JS_PUBLIC_API(JSBool)
 
542
JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
 
543
{
 
544
    CHECK_REQUEST(cx);
 
545
    return js_ValueToECMAInt32(cx, v, ip);
 
546
}
 
547
 
 
548
JS_PUBLIC_API(JSBool)
 
549
JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
 
550
{
 
551
    CHECK_REQUEST(cx);
 
552
    return js_ValueToECMAUint32(cx, v, ip);
 
553
}
 
554
 
 
555
JS_PUBLIC_API(JSBool)
 
556
JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
 
557
{
 
558
    CHECK_REQUEST(cx);
 
559
    return js_ValueToInt32(cx, v, ip);
 
560
}
 
561
 
 
562
JS_PUBLIC_API(JSBool)
 
563
JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
 
564
{
 
565
    CHECK_REQUEST(cx);
 
566
    return js_ValueToUint16(cx, v, ip);
 
567
}
 
568
 
 
569
JS_PUBLIC_API(JSBool)
 
570
JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
 
571
{
 
572
    CHECK_REQUEST(cx);
 
573
    return js_ValueToBoolean(cx, v, bp);
 
574
}
 
575
 
 
576
JS_PUBLIC_API(JSType)
 
577
JS_TypeOfValue(JSContext *cx, jsval v)
 
578
{
 
579
    JSType type;
 
580
    JSObject *obj;
 
581
    JSObjectOps *ops;
 
582
    JSClass *clasp;
 
583
 
 
584
    CHECK_REQUEST(cx);
 
585
    if (JSVAL_IS_OBJECT(v)) {
 
586
        type = JSTYPE_OBJECT;           /* XXXbe JSTYPE_NULL for JS2 */
 
587
        obj = JSVAL_TO_OBJECT(v);
 
588
        if (obj) {
 
589
            ops = obj->map->ops;
 
590
#if JS_HAS_XML_SUPPORT
 
591
            if (ops == &js_XMLObjectOps.base) {
 
592
                type = JSTYPE_XML;
 
593
            } else
 
594
#endif
 
595
            {
 
596
                /*
 
597
                 * ECMA 262, 11.4.3 says that any native object that implements
 
598
                 * [[Call]] should be of type "function". Note that RegExp and
 
599
                 * Script are both of type "function" for compatibility with
 
600
                 * older SpiderMonkeys.
 
601
                 */
 
602
                clasp = OBJ_GET_CLASS(cx, obj);
 
603
                if ((ops == &js_ObjectOps)
 
604
                    ? (clasp->call
 
605
                       ? (clasp == &js_RegExpClass || clasp == &js_ScriptClass)
 
606
                       : clasp == &js_FunctionClass)
 
607
                    : ops->call != NULL) {
 
608
                    type = JSTYPE_FUNCTION;
 
609
                } else {
 
610
#ifdef NARCISSUS
 
611
                    if (!OBJ_GET_PROPERTY(cx, obj,
 
612
                                          ATOM_TO_JSID(cx->runtime->atomState
 
613
                                                       .callAtom),
 
614
                                          &v)) {
 
615
                        JS_ClearPendingException(cx);
 
616
                    } else if (JSVAL_IS_FUNCTION(cx, v)) {
 
617
                        type = JSTYPE_FUNCTION;
 
618
                    }
 
619
#endif
 
620
                }
 
621
            }
 
622
        }
 
623
    } else if (JSVAL_IS_NUMBER(v)) {
 
624
        type = JSTYPE_NUMBER;
 
625
    } else if (JSVAL_IS_STRING(v)) {
 
626
        type = JSTYPE_STRING;
 
627
    } else if (JSVAL_IS_BOOLEAN(v)) {
 
628
        type = JSTYPE_BOOLEAN;
 
629
    } else {
 
630
        type = JSTYPE_VOID;
 
631
    }
 
632
    return type;
 
633
}
 
634
 
 
635
JS_PUBLIC_API(const char *)
 
636
JS_GetTypeName(JSContext *cx, JSType type)
 
637
{
 
638
    if ((uintN)type >= (uintN)JSTYPE_LIMIT)
 
639
        return NULL;
 
640
    return js_type_str[type];
 
641
}
 
642
 
 
643
/************************************************************************/
 
644
 
 
645
JS_PUBLIC_API(JSRuntime *)
 
646
JS_NewRuntime(uint32 maxbytes)
 
647
{
 
648
    JSRuntime *rt;
 
649
 
 
650
#ifdef DEBUG
 
651
    JS_BEGIN_MACRO
 
652
    /*
 
653
     * This code asserts that the numbers associated with the error names in
 
654
     * jsmsg.def are monotonically increasing.  It uses values for the error
 
655
     * names enumerated in jscntxt.c.  It's not a compiletime check, but it's
 
656
     * better than nothing.
 
657
     */
 
658
    int errorNumber = 0;
 
659
#define MSG_DEF(name, number, count, exception, format) \
 
660
    JS_ASSERT(name == errorNumber++);
 
661
#include "js.msg"
 
662
#undef MSG_DEF
 
663
    JS_END_MACRO;
 
664
#endif /* DEBUG */
 
665
 
 
666
    if (!js_InitStringGlobals())
 
667
        return NULL;
 
668
    rt = (JSRuntime *) malloc(sizeof(JSRuntime));
 
669
    if (!rt)
 
670
        return NULL;
 
671
 
 
672
    /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
 
673
    memset(rt, 0, sizeof(JSRuntime));
 
674
    JS_INIT_CLIST(&rt->contextList);
 
675
    JS_INIT_CLIST(&rt->trapList);
 
676
    JS_INIT_CLIST(&rt->watchPointList);
 
677
 
 
678
    if (!js_InitGC(rt, maxbytes))
 
679
        goto bad;
 
680
#ifdef JS_THREADSAFE
 
681
    rt->gcLock = JS_NEW_LOCK();
 
682
    if (!rt->gcLock)
 
683
        goto bad;
 
684
    rt->gcDone = JS_NEW_CONDVAR(rt->gcLock);
 
685
    if (!rt->gcDone)
 
686
        goto bad;
 
687
    rt->requestDone = JS_NEW_CONDVAR(rt->gcLock);
 
688
    if (!rt->requestDone)
 
689
        goto bad;
 
690
    /* this is asymmetric with JS_ShutDown: */
 
691
    if (!js_SetupLocks(8, 16))
 
692
        goto bad;
 
693
    rt->rtLock = JS_NEW_LOCK();
 
694
    if (!rt->rtLock)
 
695
        goto bad;
 
696
    rt->stateChange = JS_NEW_CONDVAR(rt->gcLock);
 
697
    if (!rt->stateChange)
 
698
        goto bad;
 
699
    rt->setSlotLock = JS_NEW_LOCK();
 
700
    if (!rt->setSlotLock)
 
701
        goto bad;
 
702
    rt->setSlotDone = JS_NEW_CONDVAR(rt->setSlotLock);
 
703
    if (!rt->setSlotDone)
 
704
        goto bad;
 
705
    rt->scopeSharingDone = JS_NEW_CONDVAR(rt->gcLock);
 
706
    if (!rt->scopeSharingDone)
 
707
        goto bad;
 
708
    rt->scopeSharingTodo = NO_SCOPE_SHARING_TODO;
 
709
#endif
 
710
    rt->propertyCache.empty = JS_TRUE;
 
711
    if (!js_InitPropertyTree(rt))
 
712
        goto bad;
 
713
    return rt;
 
714
 
 
715
bad:
 
716
    JS_DestroyRuntime(rt);
 
717
    return NULL;
 
718
}
 
719
 
 
720
JS_PUBLIC_API(void)
 
721
JS_DestroyRuntime(JSRuntime *rt)
 
722
{
 
723
#ifdef DEBUG
 
724
    /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
 
725
    if (!JS_CLIST_IS_EMPTY(&rt->contextList)) {
 
726
        JSContext *cx, *iter = NULL;
 
727
        uintN cxcount = 0;
 
728
        while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL)
 
729
            cxcount++;
 
730
        fprintf(stderr,
 
731
"JS API usage error: %u contexts left in runtime upon JS_DestroyRuntime.\n",
 
732
                cxcount);
 
733
    }
 
734
#endif
 
735
 
 
736
    js_FreeRuntimeScriptState(rt);
 
737
    js_FinishAtomState(&rt->atomState);
 
738
    js_FinishGC(rt);
 
739
#ifdef JS_THREADSAFE
 
740
    if (rt->gcLock)
 
741
        JS_DESTROY_LOCK(rt->gcLock);
 
742
    if (rt->gcDone)
 
743
        JS_DESTROY_CONDVAR(rt->gcDone);
 
744
    if (rt->requestDone)
 
745
        JS_DESTROY_CONDVAR(rt->requestDone);
 
746
    if (rt->rtLock)
 
747
        JS_DESTROY_LOCK(rt->rtLock);
 
748
    if (rt->stateChange)
 
749
        JS_DESTROY_CONDVAR(rt->stateChange);
 
750
    if (rt->setSlotLock)
 
751
        JS_DESTROY_LOCK(rt->setSlotLock);
 
752
    if (rt->setSlotDone)
 
753
        JS_DESTROY_CONDVAR(rt->setSlotDone);
 
754
    if (rt->scopeSharingDone)
 
755
        JS_DESTROY_CONDVAR(rt->scopeSharingDone);
 
756
#endif
 
757
    js_FinishPropertyTree(rt);
 
758
    free(rt);
 
759
}
 
760
 
 
761
JS_PUBLIC_API(void)
 
762
JS_ShutDown(void)
 
763
{
 
764
    JS_ArenaShutDown();
 
765
    js_FinishDtoa();
 
766
    js_FreeStringGlobals();
 
767
#ifdef JS_THREADSAFE
 
768
    js_CleanupLocks();
 
769
#endif
 
770
}
 
771
 
 
772
JS_PUBLIC_API(void *)
 
773
JS_GetRuntimePrivate(JSRuntime *rt)
 
774
{
 
775
    return rt->data;
 
776
}
 
777
 
 
778
JS_PUBLIC_API(void)
 
779
JS_SetRuntimePrivate(JSRuntime *rt, void *data)
 
780
{
 
781
    rt->data = data;
 
782
}
 
783
 
 
784
#ifdef JS_THREADSAFE
 
785
 
 
786
JS_PUBLIC_API(void)
 
787
JS_BeginRequest(JSContext *cx)
 
788
{
 
789
    JSRuntime *rt;
 
790
 
 
791
    JS_ASSERT(cx->thread);
 
792
    if (!cx->requestDepth) {
 
793
        /* Wait until the GC is finished. */
 
794
        rt = cx->runtime;
 
795
        JS_LOCK_GC(rt);
 
796
 
 
797
        /* NB: we use cx->thread here, not js_CurrentThreadId(). */
 
798
        if (rt->gcThread != cx->thread) {
 
799
            while (rt->gcLevel > 0)
 
800
                JS_AWAIT_GC_DONE(rt);
 
801
        }
 
802
 
 
803
        /* Indicate that a request is running. */
 
804
        rt->requestCount++;
 
805
        cx->requestDepth = 1;
 
806
        JS_UNLOCK_GC(rt);
 
807
        return;
 
808
    }
 
809
    cx->requestDepth++;
 
810
}
 
811
 
 
812
JS_PUBLIC_API(void)
 
813
JS_EndRequest(JSContext *cx)
 
814
{
 
815
    JSRuntime *rt;
 
816
    JSScope *scope, **todop;
 
817
    uintN nshares;
 
818
 
 
819
    CHECK_REQUEST(cx);
 
820
    JS_ASSERT(cx->requestDepth > 0);
 
821
    if (cx->requestDepth == 1) {
 
822
        /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
 
823
        rt = cx->runtime;
 
824
        JS_LOCK_GC(rt);
 
825
        cx->requestDepth = 0;
 
826
 
 
827
        /* See whether cx has any single-threaded scopes to start sharing. */
 
828
        todop = &rt->scopeSharingTodo;
 
829
        nshares = 0;
 
830
        while ((scope = *todop) != NO_SCOPE_SHARING_TODO) {
 
831
            if (scope->ownercx != cx) {
 
832
                todop = &scope->u.link;
 
833
                continue;
 
834
            }
 
835
            *todop = scope->u.link;
 
836
            scope->u.link = NULL;       /* null u.link for sanity ASAP */
 
837
 
 
838
            /*
 
839
             * If js_DropObjectMap returns null, we held the last ref to scope.
 
840
             * The waiting thread(s) must have been killed, after which the GC
 
841
             * collected the object that held this scope.  Unlikely, because it
 
842
             * requires that the GC ran (e.g., from a branch callback) during
 
843
             * this request, but possible.
 
844
             */
 
845
            if (js_DropObjectMap(cx, &scope->map, NULL)) {
 
846
                js_InitLock(&scope->lock);
 
847
                scope->u.count = 0;                 /* NULL may not pun as 0 */
 
848
                js_FinishSharingScope(rt, scope);   /* set ownercx = NULL */
 
849
                nshares++;
 
850
            }
 
851
        }
 
852
        if (nshares)
 
853
            JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone);
 
854
 
 
855
        /* Give the GC a chance to run if this was the last request running. */
 
856
        JS_ASSERT(rt->requestCount > 0);
 
857
        rt->requestCount--;
 
858
        if (rt->requestCount == 0)
 
859
            JS_NOTIFY_REQUEST_DONE(rt);
 
860
 
 
861
        JS_UNLOCK_GC(rt);
 
862
        return;
 
863
    }
 
864
 
 
865
    cx->requestDepth--;
 
866
}
 
867
 
 
868
/* Yield to pending GC operations, regardless of request depth */
 
869
JS_PUBLIC_API(void)
 
870
JS_YieldRequest(JSContext *cx)
 
871
{
 
872
    JSRuntime *rt;
 
873
 
 
874
    JS_ASSERT(cx->thread);
 
875
    CHECK_REQUEST(cx);
 
876
 
 
877
    rt = cx->runtime;
 
878
    JS_LOCK_GC(rt);
 
879
    JS_ASSERT(rt->requestCount > 0);
 
880
    rt->requestCount--;
 
881
    if (rt->requestCount == 0)
 
882
        JS_NOTIFY_REQUEST_DONE(rt);
 
883
    JS_UNLOCK_GC(rt);
 
884
    /* XXXbe give the GC or another request calling it a chance to run here?
 
885
             Assumes FIFO scheduling */
 
886
    JS_LOCK_GC(rt);
 
887
    rt->requestCount++;
 
888
    JS_UNLOCK_GC(rt);
 
889
}
 
890
 
 
891
JS_PUBLIC_API(jsrefcount)
 
892
JS_SuspendRequest(JSContext *cx)
 
893
{
 
894
    jsrefcount saveDepth = cx->requestDepth;
 
895
 
 
896
    while (cx->requestDepth)
 
897
        JS_EndRequest(cx);
 
898
    return saveDepth;
 
899
}
 
900
 
 
901
JS_PUBLIC_API(void)
 
902
JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
 
903
{
 
904
    JS_ASSERT(!cx->requestDepth);
 
905
    while (--saveDepth >= 0)
 
906
        JS_BeginRequest(cx);
 
907
}
 
908
 
 
909
#endif /* JS_THREADSAFE */
 
910
 
 
911
JS_PUBLIC_API(void)
 
912
JS_Lock(JSRuntime *rt)
 
913
{
 
914
    JS_LOCK_RUNTIME(rt);
 
915
}
 
916
 
 
917
JS_PUBLIC_API(void)
 
918
JS_Unlock(JSRuntime *rt)
 
919
{
 
920
    JS_UNLOCK_RUNTIME(rt);
 
921
}
 
922
 
 
923
JS_PUBLIC_API(JSContext *)
 
924
JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
 
925
{
 
926
    return js_NewContext(rt, stackChunkSize);
 
927
}
 
928
 
 
929
JS_PUBLIC_API(void)
 
930
JS_DestroyContext(JSContext *cx)
 
931
{
 
932
    js_DestroyContext(cx, JS_FORCE_GC);
 
933
}
 
934
 
 
935
JS_PUBLIC_API(void)
 
936
JS_DestroyContextNoGC(JSContext *cx)
 
937
{
 
938
    js_DestroyContext(cx, JS_NO_GC);
 
939
}
 
940
 
 
941
JS_PUBLIC_API(void)
 
942
JS_DestroyContextMaybeGC(JSContext *cx)
 
943
{
 
944
    js_DestroyContext(cx, JS_MAYBE_GC);
 
945
}
 
946
 
 
947
JS_PUBLIC_API(void *)
 
948
JS_GetContextPrivate(JSContext *cx)
 
949
{
 
950
    return cx->data;
 
951
}
 
952
 
 
953
JS_PUBLIC_API(void)
 
954
JS_SetContextPrivate(JSContext *cx, void *data)
 
955
{
 
956
    cx->data = data;
 
957
}
 
958
 
 
959
JS_PUBLIC_API(JSRuntime *)
 
960
JS_GetRuntime(JSContext *cx)
 
961
{
 
962
    return cx->runtime;
 
963
}
 
964
 
 
965
JS_PUBLIC_API(JSContext *)
 
966
JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
 
967
{
 
968
    return js_ContextIterator(rt, JS_TRUE, iterp);
 
969
}
 
970
 
 
971
JS_PUBLIC_API(JSVersion)
 
972
JS_GetVersion(JSContext *cx)
 
973
{
 
974
    return cx->version & JSVERSION_MASK;
 
975
}
 
976
 
 
977
JS_PUBLIC_API(JSVersion)
 
978
JS_SetVersion(JSContext *cx, JSVersion version)
 
979
{
 
980
    JSVersion oldVersion;
 
981
 
 
982
    JS_ASSERT(version != JSVERSION_UNKNOWN);
 
983
    JS_ASSERT((version & ~JSVERSION_MASK) == 0);
 
984
 
 
985
    oldVersion = cx->version & JSVERSION_MASK;
 
986
    if (version == oldVersion)
 
987
        return oldVersion;
 
988
 
 
989
    cx->version = (cx->version & ~JSVERSION_MASK) | version;
 
990
    js_OnVersionChange(cx);
 
991
    return oldVersion;
 
992
}
 
993
 
 
994
static struct v2smap {
 
995
    JSVersion   version;
 
996
    const char  *string;
 
997
} v2smap[] = {
 
998
    {JSVERSION_1_0,     "1.0"},
 
999
    {JSVERSION_1_1,     "1.1"},
 
1000
    {JSVERSION_1_2,     "1.2"},
 
1001
    {JSVERSION_1_3,     "1.3"},
 
1002
    {JSVERSION_1_4,     "1.4"},
 
1003
    {JSVERSION_ECMA_3,  "ECMAv3"},
 
1004
    {JSVERSION_1_5,     "1.5"},
 
1005
    {JSVERSION_1_6,     "1.6"},
 
1006
    {JSVERSION_DEFAULT, js_default_str},
 
1007
    {JSVERSION_UNKNOWN, NULL},          /* must be last, NULL is sentinel */
 
1008
};
 
1009
 
 
1010
JS_PUBLIC_API(const char *)
 
1011
JS_VersionToString(JSVersion version)
 
1012
{
 
1013
    int i;
 
1014
 
 
1015
    for (i = 0; v2smap[i].string; i++)
 
1016
        if (v2smap[i].version == version)
 
1017
            return v2smap[i].string;
 
1018
    return "unknown";
 
1019
}
 
1020
 
 
1021
JS_PUBLIC_API(JSVersion)
 
1022
JS_StringToVersion(const char *string)
 
1023
{
 
1024
    int i;
 
1025
 
 
1026
    for (i = 0; v2smap[i].string; i++)
 
1027
        if (strcmp(v2smap[i].string, string) == 0)
 
1028
            return v2smap[i].version;
 
1029
    return JSVERSION_UNKNOWN;
 
1030
}
 
1031
 
 
1032
JS_PUBLIC_API(uint32)
 
1033
JS_GetOptions(JSContext *cx)
 
1034
{
 
1035
    return cx->options;
 
1036
}
 
1037
 
 
1038
#define SYNC_OPTIONS_TO_VERSION(cx)                                           \
 
1039
    JS_BEGIN_MACRO                                                            \
 
1040
        if ((cx)->options & JSOPTION_XML)                                     \
 
1041
            (cx)->version |= JSVERSION_HAS_XML;                               \
 
1042
        else                                                                  \
 
1043
            (cx)->version &= ~JSVERSION_HAS_XML;                              \
 
1044
    JS_END_MACRO
 
1045
 
 
1046
JS_PUBLIC_API(uint32)
 
1047
JS_SetOptions(JSContext *cx, uint32 options)
 
1048
{
 
1049
    uint32 oldopts = cx->options;
 
1050
    cx->options = options;
 
1051
    SYNC_OPTIONS_TO_VERSION(cx);
 
1052
    return oldopts;
 
1053
}
 
1054
 
 
1055
JS_PUBLIC_API(uint32)
 
1056
JS_ToggleOptions(JSContext *cx, uint32 options)
 
1057
{
 
1058
    uint32 oldopts = cx->options;
 
1059
    cx->options ^= options;
 
1060
    SYNC_OPTIONS_TO_VERSION(cx);
 
1061
    return oldopts;
 
1062
}
 
1063
 
 
1064
JS_PUBLIC_API(const char *)
 
1065
JS_GetImplementationVersion(void)
 
1066
{
 
1067
    return "JavaScript-C 1.6.1 2007-04-01";
 
1068
}
 
1069
 
 
1070
 
 
1071
JS_PUBLIC_API(JSObject *)
 
1072
JS_GetGlobalObject(JSContext *cx)
 
1073
{
 
1074
    return cx->globalObject;
 
1075
}
 
1076
 
 
1077
JS_PUBLIC_API(void)
 
1078
JS_SetGlobalObject(JSContext *cx, JSObject *obj)
 
1079
{
 
1080
    cx->globalObject = obj;
 
1081
#if JS_HAS_XML_SUPPORT
 
1082
    cx->xmlSettingFlags = 0;
 
1083
#endif
 
1084
}
 
1085
 
 
1086
static JSObject *
 
1087
InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
 
1088
{
 
1089
    JSDHashTable *table;
 
1090
    JSBool resolving;
 
1091
    JSRuntime *rt;
 
1092
    JSResolvingKey key;
 
1093
    JSResolvingEntry *entry;
 
1094
    JSObject *fun_proto, *obj_proto;
 
1095
 
 
1096
    /* If cx has no global object, use obj so prototypes can be found. */
 
1097
    if (!cx->globalObject)
 
1098
        JS_SetGlobalObject(cx, obj);
 
1099
 
 
1100
    /* Record Function and Object in cx->resolvingTable, if we are resolving. */
 
1101
    table = cx->resolvingTable;
 
1102
    resolving = (table && table->entryCount);
 
1103
    if (resolving) {
 
1104
        rt = cx->runtime;
 
1105
        key.obj = obj;
 
1106
        key.id = ATOM_TO_JSID(rt->atomState.FunctionAtom);
 
1107
        entry = (JSResolvingEntry *)
 
1108
                JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
 
1109
        if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) {
 
1110
            /* Already resolving Function, record Object too. */
 
1111
            JS_ASSERT(entry->key.obj == obj);
 
1112
            key.id = ATOM_TO_JSID(rt->atomState.ObjectAtom);
 
1113
            entry = (JSResolvingEntry *)
 
1114
                    JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
 
1115
        }
 
1116
        if (!entry) {
 
1117
            JS_ReportOutOfMemory(cx);
 
1118
            return NULL;
 
1119
        }
 
1120
        JS_ASSERT(!entry->key.obj && entry->flags == 0);
 
1121
        entry->key = key;
 
1122
        entry->flags = JSRESFLAG_LOOKUP;
 
1123
    }
 
1124
 
 
1125
    /* Initialize the function class first so constructors can be made. */
 
1126
    fun_proto = js_InitFunctionClass(cx, obj);
 
1127
    if (!fun_proto)
 
1128
        goto out;
 
1129
 
 
1130
    /* Initialize the object class next so Object.prototype works. */
 
1131
    obj_proto = js_InitObjectClass(cx, obj);
 
1132
    if (!obj_proto) {
 
1133
        fun_proto = NULL;
 
1134
        goto out;
 
1135
    }
 
1136
 
 
1137
    /* Function.prototype and the global object delegate to Object.prototype. */
 
1138
    OBJ_SET_PROTO(cx, fun_proto, obj_proto);
 
1139
    if (!OBJ_GET_PROTO(cx, obj))
 
1140
        OBJ_SET_PROTO(cx, obj, obj_proto);
 
1141
 
 
1142
out:
 
1143
    /* If resolving, remove the other entry (Object or Function) from table. */
 
1144
    if (resolving)
 
1145
        JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
 
1146
    return fun_proto;
 
1147
}
 
1148
 
 
1149
JS_PUBLIC_API(JSBool)
 
1150
JS_InitStandardClasses(JSContext *cx, JSObject *obj)
 
1151
{
 
1152
    CHECK_REQUEST(cx);
 
1153
 
 
1154
#if JS_HAS_UNDEFINED
 
1155
{
 
1156
    /* Define a top-level property 'undefined' with the undefined value. */
 
1157
    JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
 
1158
    if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
 
1159
                             NULL, NULL, JSPROP_PERMANENT, NULL)) {
 
1160
        return JS_FALSE;
 
1161
    }
 
1162
}
 
1163
#endif
 
1164
 
 
1165
    /* Function and Object require cooperative bootstrapping magic. */
 
1166
    if (!InitFunctionAndObjectClasses(cx, obj))
 
1167
        return JS_FALSE;
 
1168
 
 
1169
    /* Initialize the rest of the standard objects and functions. */
 
1170
    return js_InitArrayClass(cx, obj) &&
 
1171
           js_InitBooleanClass(cx, obj) &&
 
1172
           js_InitMathClass(cx, obj) &&
 
1173
           js_InitNumberClass(cx, obj) &&
 
1174
           js_InitStringClass(cx, obj) &&
 
1175
#if JS_HAS_CALL_OBJECT
 
1176
           js_InitCallClass(cx, obj) &&
 
1177
#endif
 
1178
#if JS_HAS_REGEXPS
 
1179
           js_InitRegExpClass(cx, obj) &&
 
1180
#endif
 
1181
#if JS_HAS_SCRIPT_OBJECT
 
1182
           js_InitScriptClass(cx, obj) &&
 
1183
#endif
 
1184
#if JS_HAS_ERROR_EXCEPTIONS
 
1185
           js_InitExceptionClasses(cx, obj) &&
 
1186
#endif
 
1187
#if JS_HAS_XML_SUPPORT
 
1188
           js_InitXMLClasses(cx, obj) &&
 
1189
#endif
 
1190
#if JS_HAS_FILE_OBJECT
 
1191
           js_InitFileClass(cx, obj) &&
 
1192
#endif
 
1193
           js_InitDateClass(cx, obj);
 
1194
}
 
1195
 
 
1196
#define ATOM_OFFSET(name)       offsetof(JSAtomState, name##Atom)
 
1197
#define OFFSET_TO_ATOM(rt,off)  (*(JSAtom **)((char*)&(rt)->atomState + (off)))
 
1198
 
 
1199
/*
 
1200
 * Table of class initializers and their atom offsets in rt->atomState.
 
1201
 * If you add a "standard" class, remember to update this table.
 
1202
 */
 
1203
static struct {
 
1204
    JSObjectOp  init;
 
1205
    size_t      atomOffset;
 
1206
} standard_class_atoms[] = {
 
1207
    {InitFunctionAndObjectClasses,  ATOM_OFFSET(Function)},
 
1208
    {InitFunctionAndObjectClasses,  ATOM_OFFSET(Object)},
 
1209
    {js_InitArrayClass,             ATOM_OFFSET(Array)},
 
1210
    {js_InitBooleanClass,           ATOM_OFFSET(Boolean)},
 
1211
    {js_InitDateClass,              ATOM_OFFSET(Date)},
 
1212
    {js_InitMathClass,              ATOM_OFFSET(Math)},
 
1213
    {js_InitNumberClass,            ATOM_OFFSET(Number)},
 
1214
    {js_InitStringClass,            ATOM_OFFSET(String)},
 
1215
#if JS_HAS_CALL_OBJECT
 
1216
    {js_InitCallClass,              ATOM_OFFSET(Call)},
 
1217
#endif
 
1218
#if JS_HAS_ERROR_EXCEPTIONS
 
1219
    {js_InitExceptionClasses,       ATOM_OFFSET(Error)},
 
1220
#endif
 
1221
#if JS_HAS_REGEXPS
 
1222
    {js_InitRegExpClass,            ATOM_OFFSET(RegExp)},
 
1223
#endif
 
1224
#if JS_HAS_SCRIPT_OBJECT
 
1225
    {js_InitScriptClass,            ATOM_OFFSET(Script)},
 
1226
#endif
 
1227
#if JS_HAS_XML_SUPPORT
 
1228
    {js_InitXMLClass,               ATOM_OFFSET(XML)},
 
1229
    {js_InitNamespaceClass,         ATOM_OFFSET(Namespace)},
 
1230
    {js_InitQNameClass,             ATOM_OFFSET(QName)},
 
1231
#endif
 
1232
#if JS_HAS_FILE_OBJECT
 
1233
    {js_InitFileClass,              ATOM_OFFSET(File)},
 
1234
#endif
 
1235
    {NULL,                          0}
 
1236
};
 
1237
 
 
1238
/*
 
1239
 * Table of top-level function and constant names and their init functions.
 
1240
 * If you add a "standard" global function or property, remember to update
 
1241
 * this table.
 
1242
 */
 
1243
typedef struct JSStdName {
 
1244
    JSObjectOp  init;
 
1245
    size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
 
1246
    const char  *name;          /* null if atom is pre-pinned, else name */
 
1247
} JSStdName;
 
1248
 
 
1249
static JSAtom *
 
1250
StdNameToAtom(JSContext *cx, JSStdName *stdn)
 
1251
{
 
1252
    size_t offset;
 
1253
    JSAtom *atom;
 
1254
    const char *name;
 
1255
 
 
1256
    offset = stdn->atomOffset;
 
1257
    atom = OFFSET_TO_ATOM(cx->runtime, offset);
 
1258
    if (!atom) {
 
1259
        name = stdn->name;
 
1260
        if (name) {
 
1261
            atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED);
 
1262
            OFFSET_TO_ATOM(cx->runtime, offset) = atom;
 
1263
        }
 
1264
    }
 
1265
    return atom;
 
1266
}
 
1267
 
 
1268
#define EAGERLY_PINNED_ATOM(name)   ATOM_OFFSET(name), NULL
 
1269
#define LAZILY_PINNED_ATOM(name)    ATOM_OFFSET(lazy.name), js_##name##_str
 
1270
 
 
1271
static JSStdName standard_class_names[] = {
 
1272
    /* ECMA requires that eval be a direct property of the global object. */
 
1273
    {js_InitObjectClass,        EAGERLY_PINNED_ATOM(eval)},
 
1274
 
 
1275
    /* Global properties and functions defined by the Number class. */
 
1276
    {js_InitNumberClass,        LAZILY_PINNED_ATOM(NaN)},
 
1277
    {js_InitNumberClass,        LAZILY_PINNED_ATOM(Infinity)},
 
1278
    {js_InitNumberClass,        LAZILY_PINNED_ATOM(isNaN)},
 
1279
    {js_InitNumberClass,        LAZILY_PINNED_ATOM(isFinite)},
 
1280
    {js_InitNumberClass,        LAZILY_PINNED_ATOM(parseFloat)},
 
1281
    {js_InitNumberClass,        LAZILY_PINNED_ATOM(parseInt)},
 
1282
 
 
1283
    /* String global functions. */
 
1284
    {js_InitStringClass,        LAZILY_PINNED_ATOM(escape)},
 
1285
    {js_InitStringClass,        LAZILY_PINNED_ATOM(unescape)},
 
1286
    {js_InitStringClass,        LAZILY_PINNED_ATOM(decodeURI)},
 
1287
    {js_InitStringClass,        LAZILY_PINNED_ATOM(encodeURI)},
 
1288
    {js_InitStringClass,        LAZILY_PINNED_ATOM(decodeURIComponent)},
 
1289
    {js_InitStringClass,        LAZILY_PINNED_ATOM(encodeURIComponent)},
 
1290
#if JS_HAS_UNEVAL
 
1291
    {js_InitStringClass,        LAZILY_PINNED_ATOM(uneval)},
 
1292
#endif
 
1293
 
 
1294
    /* Exception constructors. */
 
1295
#if JS_HAS_ERROR_EXCEPTIONS
 
1296
    {js_InitExceptionClasses,   EAGERLY_PINNED_ATOM(Error)},
 
1297
    {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(InternalError)},
 
1298
    {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(EvalError)},
 
1299
    {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(RangeError)},
 
1300
    {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(ReferenceError)},
 
1301
    {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(SyntaxError)},
 
1302
    {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(TypeError)},
 
1303
    {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(URIError)},
 
1304
#endif
 
1305
 
 
1306
#if JS_HAS_XML_SUPPORT
 
1307
    {js_InitAnyNameClass,       LAZILY_PINNED_ATOM(AnyName)},
 
1308
    {js_InitAttributeNameClass, LAZILY_PINNED_ATOM(AttributeName)},
 
1309
    {js_InitXMLClass,           LAZILY_PINNED_ATOM(XMLList)},
 
1310
    {js_InitXMLClass,           LAZILY_PINNED_ATOM(isXMLName)},
 
1311
#endif
 
1312
 
 
1313
    {NULL,                      0, NULL}
 
1314
};
 
1315
 
 
1316
static JSStdName object_prototype_names[] = {
 
1317
    /* Object.prototype properties (global delegates to Object.prototype). */
 
1318
    {js_InitObjectClass,        EAGERLY_PINNED_ATOM(proto)},
 
1319
    {js_InitObjectClass,        EAGERLY_PINNED_ATOM(parent)},
 
1320
    {js_InitObjectClass,        EAGERLY_PINNED_ATOM(count)},
 
1321
#if JS_HAS_TOSOURCE
 
1322
    {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toSource)},
 
1323
#endif
 
1324
    {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toString)},
 
1325
    {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toLocaleString)},
 
1326
    {js_InitObjectClass,        EAGERLY_PINNED_ATOM(valueOf)},
 
1327
#if JS_HAS_OBJ_WATCHPOINT
 
1328
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(watch)},
 
1329
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(unwatch)},
 
1330
#endif
 
1331
#if JS_HAS_NEW_OBJ_METHODS
 
1332
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(hasOwnProperty)},
 
1333
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(isPrototypeOf)},
 
1334
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(propertyIsEnumerable)},
 
1335
#endif
 
1336
#if JS_HAS_GETTER_SETTER
 
1337
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(defineGetter)},
 
1338
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(defineSetter)},
 
1339
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(lookupGetter)},
 
1340
    {js_InitObjectClass,        LAZILY_PINNED_ATOM(lookupSetter)},
 
1341
#endif
 
1342
 
 
1343
    {NULL,                      0, NULL}
 
1344
};
 
1345
 
 
1346
#undef EAGERLY_PINNED_ATOM
 
1347
#undef LAZILY_PINNED_ATOM
 
1348
 
 
1349
JS_PUBLIC_API(JSBool)
 
1350
JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
 
1351
                        JSBool *resolved)
 
1352
{
 
1353
    JSString *idstr;
 
1354
    JSRuntime *rt;
 
1355
    JSAtom *atom;
 
1356
    JSObjectOp init;
 
1357
    uintN i;
 
1358
 
 
1359
    CHECK_REQUEST(cx);
 
1360
    *resolved = JS_FALSE;
 
1361
 
 
1362
    if (!JSVAL_IS_STRING(id))
 
1363
        return JS_TRUE;
 
1364
    idstr = JSVAL_TO_STRING(id);
 
1365
    rt = cx->runtime;
 
1366
 
 
1367
#if JS_HAS_UNDEFINED
 
1368
    /* Check whether we're resolving 'undefined', and define it if so. */
 
1369
    atom = rt->atomState.typeAtoms[JSTYPE_VOID];
 
1370
    if (idstr == ATOM_TO_STRING(atom)) {
 
1371
        *resolved = JS_TRUE;
 
1372
        return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
 
1373
                                   NULL, NULL, JSPROP_PERMANENT, NULL);
 
1374
    }
 
1375
#endif
 
1376
 
 
1377
    /* Try for class constructors/prototypes named by well-known atoms. */
 
1378
    init = NULL;
 
1379
    for (i = 0; standard_class_atoms[i].init; i++) {
 
1380
        atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
 
1381
        if (idstr == ATOM_TO_STRING(atom)) {
 
1382
            init = standard_class_atoms[i].init;
 
1383
            break;
 
1384
        }
 
1385
    }
 
1386
 
 
1387
    if (!init) {
 
1388
        /* Try less frequently used top-level functions and constants. */
 
1389
        for (i = 0; standard_class_names[i].init; i++) {
 
1390
            atom = StdNameToAtom(cx, &standard_class_names[i]);
 
1391
            if (!atom)
 
1392
                return JS_FALSE;
 
1393
            if (idstr == ATOM_TO_STRING(atom)) {
 
1394
                init = standard_class_names[i].init;
 
1395
                break;
 
1396
            }
 
1397
        }
 
1398
 
 
1399
        if (!init && !OBJ_GET_PROTO(cx, obj)) {
 
1400
            /*
 
1401
             * Try even less frequently used names delegated from the global
 
1402
             * object to Object.prototype, but only if the Object class hasn't
 
1403
             * yet been initialized.
 
1404
             */
 
1405
            for (i = 0; object_prototype_names[i].init; i++) {
 
1406
                atom = StdNameToAtom(cx, &object_prototype_names[i]);
 
1407
                if (!atom)
 
1408
                    return JS_FALSE;
 
1409
                if (idstr == ATOM_TO_STRING(atom)) {
 
1410
                    init = standard_class_names[i].init;
 
1411
                    break;
 
1412
                }
 
1413
            }
 
1414
        }
 
1415
    }
 
1416
 
 
1417
    if (init) {
 
1418
        if (!init(cx, obj))
 
1419
            return JS_FALSE;
 
1420
        *resolved = JS_TRUE;
 
1421
    }
 
1422
    return JS_TRUE;
 
1423
}
 
1424
 
 
1425
static JSBool
 
1426
AlreadyHasOwnProperty(JSObject *obj, JSAtom *atom)
 
1427
{
 
1428
    JS_ASSERT(OBJ_IS_NATIVE(obj));
 
1429
    return SCOPE_GET_PROPERTY(OBJ_SCOPE(obj), ATOM_TO_JSID(atom)) != NULL;
 
1430
}
 
1431
 
 
1432
JS_PUBLIC_API(JSBool)
 
1433
JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
 
1434
{
 
1435
    JSRuntime *rt;
 
1436
    JSAtom *atom;
 
1437
    uintN i;
 
1438
 
 
1439
    CHECK_REQUEST(cx);
 
1440
    rt = cx->runtime;
 
1441
 
 
1442
#if JS_HAS_UNDEFINED
 
1443
    /* Check whether we need to bind 'undefined' and define it if so. */
 
1444
    atom = rt->atomState.typeAtoms[JSTYPE_VOID];
 
1445
    if (!AlreadyHasOwnProperty(obj, atom) &&
 
1446
        !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
 
1447
                             NULL, NULL, JSPROP_PERMANENT, NULL)) {
 
1448
        return JS_FALSE;
 
1449
    }
 
1450
#endif
 
1451
 
 
1452
    /* Initialize any classes that have not been resolved yet. */
 
1453
    for (i = 0; standard_class_atoms[i].init; i++) {
 
1454
        atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
 
1455
        if (!AlreadyHasOwnProperty(obj, atom) &&
 
1456
            !standard_class_atoms[i].init(cx, obj)) {
 
1457
            return JS_FALSE;
 
1458
        }
 
1459
    }
 
1460
 
 
1461
    return JS_TRUE;
 
1462
}
 
1463
 
 
1464
static JSIdArray *
 
1465
AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip)
 
1466
{
 
1467
    jsint i, length;
 
1468
    
 
1469
    i = *ip;
 
1470
    length = ida->length;
 
1471
    if (i >= length) {
 
1472
        ida = js_SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8));
 
1473
        if (!ida)
 
1474
            return NULL;
 
1475
        JS_ASSERT(i < ida->length);
 
1476
    }
 
1477
    ida->vector[i] = ATOM_TO_JSID(atom);
 
1478
    *ip = i + 1;
 
1479
    return ida;
 
1480
}
 
1481
 
 
1482
static JSIdArray *
 
1483
EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
 
1484
                    jsint *ip, JSBool *foundp)
 
1485
{
 
1486
    *foundp = AlreadyHasOwnProperty(obj, atom);
 
1487
    if (*foundp)
 
1488
        ida = AddAtomToArray(cx, atom, ida, ip);
 
1489
    return ida;
 
1490
}
 
1491
 
 
1492
JS_PUBLIC_API(JSIdArray *)
 
1493
JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
 
1494
                                    JSIdArray *ida)
 
1495
{
 
1496
    JSRuntime *rt;
 
1497
    jsint i, j, k;
 
1498
    JSAtom *atom;
 
1499
    JSBool found;
 
1500
    JSObjectOp init;
 
1501
 
 
1502
    CHECK_REQUEST(cx);
 
1503
    rt = cx->runtime;
 
1504
    if (ida) {
 
1505
        i = ida->length;
 
1506
    } else {
 
1507
        ida = js_NewIdArray(cx, 8);
 
1508
        if (!ida)
 
1509
            return NULL;
 
1510
        i = 0;
 
1511
    }
 
1512
 
 
1513
#if JS_HAS_UNDEFINED
 
1514
    /* Check whether 'undefined' has been resolved and enumerate it if so. */
 
1515
    atom = rt->atomState.typeAtoms[JSTYPE_VOID];
 
1516
    ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
 
1517
    if (!ida)
 
1518
        return NULL;
 
1519
#endif
 
1520
 
 
1521
    /* Enumerate only classes that *have* been resolved. */
 
1522
    for (j = 0; standard_class_atoms[j].init; j++) {
 
1523
        atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
 
1524
        ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
 
1525
        if (!ida)
 
1526
            return NULL;
 
1527
 
 
1528
        if (found) {
 
1529
            init = standard_class_atoms[j].init;
 
1530
 
 
1531
            for (k = 0; standard_class_names[k].init; k++) {
 
1532
                if (standard_class_names[k].init == init) {
 
1533
                    atom = StdNameToAtom(cx, &standard_class_names[k]);
 
1534
                    ida = AddAtomToArray(cx, atom, ida, &i);
 
1535
                    if (!ida)
 
1536
                        return NULL;
 
1537
                }
 
1538
            }
 
1539
 
 
1540
            if (init == js_InitObjectClass) {
 
1541
                for (k = 0; object_prototype_names[k].init; k++) {
 
1542
                    atom = StdNameToAtom(cx, &object_prototype_names[k]);
 
1543
                    ida = AddAtomToArray(cx, atom, ida, &i);
 
1544
                    if (!ida)
 
1545
                        return NULL;
 
1546
                }
 
1547
            }
 
1548
        }
 
1549
    }
 
1550
 
 
1551
    /* Trim to exact length via js_SetIdArrayLength. */
 
1552
    return js_SetIdArrayLength(cx, ida, i);
 
1553
}
 
1554
 
 
1555
#undef ATOM_OFFSET
 
1556
#undef OFFSET_TO_ATOM
 
1557
 
 
1558
JS_PUBLIC_API(JSObject *)
 
1559
JS_GetScopeChain(JSContext *cx)
 
1560
{
 
1561
    return cx->fp ? cx->fp->scopeChain : NULL;
 
1562
}
 
1563
 
 
1564
JS_PUBLIC_API(void *)
 
1565
JS_malloc(JSContext *cx, size_t nbytes)
 
1566
{
 
1567
    void *p;
 
1568
 
 
1569
    JS_ASSERT(nbytes != 0);
 
1570
    if (nbytes == 0)
 
1571
        nbytes = 1;
 
1572
    cx->runtime->gcMallocBytes += nbytes;
 
1573
    p = malloc(nbytes);
 
1574
    if (!p)
 
1575
        JS_ReportOutOfMemory(cx);
 
1576
    return p;
 
1577
}
 
1578
 
 
1579
JS_PUBLIC_API(void *)
 
1580
JS_realloc(JSContext *cx, void *p, size_t nbytes)
 
1581
{
 
1582
    p = realloc(p, nbytes);
 
1583
    if (!p)
 
1584
        JS_ReportOutOfMemory(cx);
 
1585
    return p;
 
1586
}
 
1587
 
 
1588
JS_PUBLIC_API(void)
 
1589
JS_free(JSContext *cx, void *p)
 
1590
{
 
1591
    if (p)
 
1592
        free(p);
 
1593
}
 
1594
 
 
1595
JS_PUBLIC_API(char *)
 
1596
JS_strdup(JSContext *cx, const char *s)
 
1597
{
 
1598
    size_t n;
 
1599
    void *p;
 
1600
 
 
1601
    n = strlen(s) + 1;
 
1602
    p = JS_malloc(cx, n);
 
1603
    if (!p)
 
1604
        return NULL;
 
1605
    return (char *)memcpy(p, s, n);
 
1606
}
 
1607
 
 
1608
JS_PUBLIC_API(jsdouble *)
 
1609
JS_NewDouble(JSContext *cx, jsdouble d)
 
1610
{
 
1611
    CHECK_REQUEST(cx);
 
1612
    return js_NewDouble(cx, d, 0);
 
1613
}
 
1614
 
 
1615
JS_PUBLIC_API(JSBool)
 
1616
JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
 
1617
{
 
1618
    CHECK_REQUEST(cx);
 
1619
    return js_NewDoubleValue(cx, d, rval);
 
1620
}
 
1621
 
 
1622
JS_PUBLIC_API(JSBool)
 
1623
JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
 
1624
{
 
1625
    CHECK_REQUEST(cx);
 
1626
    return js_NewNumberValue(cx, d, rval);
 
1627
}
 
1628
 
 
1629
#undef JS_AddRoot
 
1630
JS_PUBLIC_API(JSBool)
 
1631
JS_AddRoot(JSContext *cx, void *rp)
 
1632
{
 
1633
    CHECK_REQUEST(cx);
 
1634
    return js_AddRoot(cx, rp, NULL);
 
1635
}
 
1636
 
 
1637
JS_PUBLIC_API(JSBool)
 
1638
JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name)
 
1639
{
 
1640
    return js_AddRootRT(rt, rp, name);
 
1641
}
 
1642
 
 
1643
JS_PUBLIC_API(JSBool)
 
1644
JS_RemoveRoot(JSContext *cx, void *rp)
 
1645
{
 
1646
    CHECK_REQUEST(cx);
 
1647
    return js_RemoveRoot(cx->runtime, rp);
 
1648
}
 
1649
 
 
1650
JS_PUBLIC_API(JSBool)
 
1651
JS_RemoveRootRT(JSRuntime *rt, void *rp)
 
1652
{
 
1653
    return js_RemoveRoot(rt, rp);
 
1654
}
 
1655
 
 
1656
JS_PUBLIC_API(JSBool)
 
1657
JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
 
1658
{
 
1659
    CHECK_REQUEST(cx);
 
1660
    return js_AddRoot(cx, rp, name);
 
1661
}
 
1662
 
 
1663
JS_PUBLIC_API(void)
 
1664
JS_ClearNewbornRoots(JSContext *cx)
 
1665
{
 
1666
    JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
 
1667
}
 
1668
 
 
1669
JS_PUBLIC_API(JSBool)
 
1670
JS_EnterLocalRootScope(JSContext *cx)
 
1671
{
 
1672
    CHECK_REQUEST(cx);
 
1673
    return js_EnterLocalRootScope(cx);
 
1674
}
 
1675
 
 
1676
JS_PUBLIC_API(void)
 
1677
JS_LeaveLocalRootScope(JSContext *cx)
 
1678
{
 
1679
    CHECK_REQUEST(cx);
 
1680
    js_LeaveLocalRootScope(cx);
 
1681
}
 
1682
 
 
1683
JS_PUBLIC_API(void)
 
1684
JS_ForgetLocalRoot(JSContext *cx, void *thing)
 
1685
{
 
1686
    CHECK_REQUEST(cx);
 
1687
    js_ForgetLocalRoot(cx, (jsval) thing);
 
1688
}
 
1689
 
 
1690
#include "jshash.h" /* Added by JSIFY */
 
1691
 
 
1692
#ifdef DEBUG
 
1693
 
 
1694
typedef struct NamedRootDumpArgs {
 
1695
    void (*dump)(const char *name, void *rp, void *data);
 
1696
    void *data;
 
1697
} NamedRootDumpArgs;
 
1698
 
 
1699
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
 
1700
js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
 
1701
                     void *arg)
 
1702
{
 
1703
    NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;
 
1704
    JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
 
1705
 
 
1706
    if (rhe->name)
 
1707
        args->dump(rhe->name, rhe->root, args->data);
 
1708
    return JS_DHASH_NEXT;
 
1709
}
 
1710
 
 
1711
JS_PUBLIC_API(void)
 
1712
JS_DumpNamedRoots(JSRuntime *rt,
 
1713
                  void (*dump)(const char *name, void *rp, void *data),
 
1714
                  void *data)
 
1715
{
 
1716
    NamedRootDumpArgs args;
 
1717
 
 
1718
    args.dump = dump;
 
1719
    args.data = data;
 
1720
    JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);
 
1721
}
 
1722
 
 
1723
#endif /* DEBUG */
 
1724
 
 
1725
typedef struct GCRootMapArgs {
 
1726
    JSGCRootMapFun map;
 
1727
    void *data;
 
1728
} GCRootMapArgs;
 
1729
 
 
1730
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
 
1731
js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
 
1732
                 void *arg)
 
1733
{
 
1734
    GCRootMapArgs *args = (GCRootMapArgs *) arg;
 
1735
    JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
 
1736
    intN mapflags;
 
1737
    JSDHashOperator op;
 
1738
 
 
1739
    mapflags = args->map(rhe->root, rhe->name, args->data);
 
1740
 
 
1741
#if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT &&                                     \
 
1742
    JS_MAP_GCROOT_STOP == JS_DHASH_STOP &&                                     \
 
1743
    JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE
 
1744
    op = (JSDHashOperator)mapflags;
 
1745
#else
 
1746
    op = JS_DHASH_NEXT;
 
1747
    if (mapflags & JS_MAP_GCROOT_STOP)
 
1748
        op |= JS_DHASH_STOP;
 
1749
    if (mapflags & JS_MAP_GCROOT_REMOVE)
 
1750
        op |= JS_DHASH_REMOVE;
 
1751
#endif
 
1752
 
 
1753
    return op;
 
1754
}
 
1755
 
 
1756
JS_PUBLIC_API(uint32)
 
1757
JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
 
1758
{
 
1759
    GCRootMapArgs args;
 
1760
    uint32 rv;
 
1761
 
 
1762
    args.map = map;
 
1763
    args.data = data;
 
1764
    JS_LOCK_GC(rt);
 
1765
    rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args);
 
1766
    JS_UNLOCK_GC(rt);
 
1767
    return rv;
 
1768
}
 
1769
 
 
1770
JS_PUBLIC_API(JSBool)
 
1771
JS_LockGCThing(JSContext *cx, void *thing)
 
1772
{
 
1773
    JSBool ok;
 
1774
 
 
1775
    CHECK_REQUEST(cx);
 
1776
    ok = js_LockGCThing(cx, thing);
 
1777
    if (!ok)
 
1778
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_LOCK);
 
1779
    return ok;
 
1780
}
 
1781
 
 
1782
JS_PUBLIC_API(JSBool)
 
1783
JS_LockGCThingRT(JSRuntime *rt, void *thing)
 
1784
{
 
1785
    return js_LockGCThingRT(rt, thing);
 
1786
}
 
1787
 
 
1788
JS_PUBLIC_API(JSBool)
 
1789
JS_UnlockGCThing(JSContext *cx, void *thing)
 
1790
{
 
1791
    JSBool ok;
 
1792
 
 
1793
    CHECK_REQUEST(cx);
 
1794
    ok = js_UnlockGCThingRT(cx->runtime, thing);
 
1795
    if (!ok)
 
1796
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK);
 
1797
    return ok;
 
1798
}
 
1799
 
 
1800
JS_PUBLIC_API(JSBool)
 
1801
JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
 
1802
{
 
1803
    return js_UnlockGCThingRT(rt, thing);
 
1804
}
 
1805
 
 
1806
JS_PUBLIC_API(void)
 
1807
JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
 
1808
{
 
1809
    JS_ASSERT(cx->runtime->gcLevel > 0);
 
1810
#ifdef JS_THREADSAFE
 
1811
    JS_ASSERT(cx->runtime->gcThread == js_CurrentThreadId());
 
1812
#endif
 
1813
 
 
1814
    GC_MARK(cx, thing, name, arg);
 
1815
}
 
1816
 
 
1817
JS_PUBLIC_API(void)
 
1818
JS_GC(JSContext *cx)
 
1819
{
 
1820
    /* Don't nuke active arenas if executing or compiling. */
 
1821
    if (cx->stackPool.current == &cx->stackPool.first)
 
1822
        JS_FinishArenaPool(&cx->stackPool);
 
1823
    if (cx->tempPool.current == &cx->tempPool.first)
 
1824
        JS_FinishArenaPool(&cx->tempPool);
 
1825
    js_ForceGC(cx, 0);
 
1826
}
 
1827
 
 
1828
JS_PUBLIC_API(void)
 
1829
JS_MaybeGC(JSContext *cx)
 
1830
{
 
1831
#ifdef WAY_TOO_MUCH_GC
 
1832
    JS_GC(cx);
 
1833
#else
 
1834
    JSRuntime *rt;
 
1835
    uint32 bytes, lastBytes;
 
1836
 
 
1837
    rt = cx->runtime;
 
1838
    bytes = rt->gcBytes;
 
1839
    lastBytes = rt->gcLastBytes;
 
1840
    if ((bytes > 8192 && bytes > lastBytes + lastBytes / 2) ||
 
1841
        rt->gcMallocBytes > rt->gcMaxMallocBytes) {
 
1842
        /*
 
1843
         * Run the GC if we have half again as many bytes of GC-things as
 
1844
         * the last time we GC'd, or if we have malloc'd more bytes through
 
1845
         * JS_malloc than we were told to allocate by JS_NewRuntime.
 
1846
         */
 
1847
        JS_GC(cx);
 
1848
    }
 
1849
#endif
 
1850
}
 
1851
 
 
1852
JS_PUBLIC_API(JSGCCallback)
 
1853
JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
 
1854
{
 
1855
    return JS_SetGCCallbackRT(cx->runtime, cb);
 
1856
}
 
1857
 
 
1858
JS_PUBLIC_API(JSGCCallback)
 
1859
JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
 
1860
{
 
1861
    JSGCCallback oldcb;
 
1862
 
 
1863
    oldcb = rt->gcCallback;
 
1864
    rt->gcCallback = cb;
 
1865
    return oldcb;
 
1866
}
 
1867
 
 
1868
JS_PUBLIC_API(JSBool)
 
1869
JS_IsAboutToBeFinalized(JSContext *cx, void *thing)
 
1870
{
 
1871
    JS_ASSERT(thing);
 
1872
    return js_IsAboutToBeFinalized(cx, thing);
 
1873
}
 
1874
 
 
1875
JS_PUBLIC_API(void)
 
1876
JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value)
 
1877
{
 
1878
    switch (key) {
 
1879
      case JSGC_MAX_BYTES:
 
1880
        rt->gcMaxBytes = value;
 
1881
        break;
 
1882
      case JSGC_MAX_MALLOC_BYTES:
 
1883
        rt->gcMaxMallocBytes = value;
 
1884
        break;
 
1885
    }
 
1886
}
 
1887
 
 
1888
JS_PUBLIC_API(intN)
 
1889
JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
 
1890
{
 
1891
    return js_ChangeExternalStringFinalizer(NULL, finalizer);
 
1892
}
 
1893
 
 
1894
JS_PUBLIC_API(intN)
 
1895
JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
 
1896
{
 
1897
    return js_ChangeExternalStringFinalizer(finalizer, NULL);
 
1898
}
 
1899
 
 
1900
JS_PUBLIC_API(JSString *)
 
1901
JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
 
1902
{
 
1903
    JSString *str;
 
1904
 
 
1905
    CHECK_REQUEST(cx);
 
1906
    JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES);
 
1907
 
 
1908
    str = (JSString *) js_NewGCThing(cx, (uintN) type, sizeof(JSString));
 
1909
    if (!str)
 
1910
        return NULL;
 
1911
    str->length = length;
 
1912
    str->chars = chars;
 
1913
    return str;
 
1914
}
 
1915
 
 
1916
JS_PUBLIC_API(intN)
 
1917
JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
 
1918
{
 
1919
    uint8 type = (uint8) (*js_GetGCThingFlags(str) & GCF_TYPEMASK);
 
1920
 
 
1921
    if (type >= GCX_EXTERNAL_STRING)
 
1922
        return (intN)type;
 
1923
    JS_ASSERT(type == GCX_STRING || type == GCX_MUTABLE_STRING);
 
1924
    return -1;
 
1925
}
 
1926
 
 
1927
JS_PUBLIC_API(void)
 
1928
JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
 
1929
{
 
1930
#if JS_STACK_GROWTH_DIRECTION > 0
 
1931
    if (limitAddr == 0)
 
1932
        limitAddr = (jsuword)-1;
 
1933
#endif
 
1934
    cx->stackLimit = limitAddr;
 
1935
}
 
1936
 
 
1937
/************************************************************************/
 
1938
 
 
1939
JS_PUBLIC_API(void)
 
1940
JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
 
1941
{
 
1942
    JS_free(cx, ida);
 
1943
}
 
1944
 
 
1945
JS_PUBLIC_API(JSBool)
 
1946
JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
 
1947
{
 
1948
    JSAtom *atom;
 
1949
 
 
1950
    CHECK_REQUEST(cx);
 
1951
    if (JSVAL_IS_INT(v)) {
 
1952
        *idp = v;
 
1953
    } else {
 
1954
        atom = js_ValueToStringAtom(cx, v);
 
1955
        if (!atom)
 
1956
            return JS_FALSE;
 
1957
        *idp = ATOM_TO_JSID(atom);
 
1958
    }
 
1959
    return JS_TRUE;
 
1960
}
 
1961
 
 
1962
JS_PUBLIC_API(JSBool)
 
1963
JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
 
1964
{
 
1965
    CHECK_REQUEST(cx);
 
1966
    *vp = ID_TO_VALUE(id);
 
1967
    return JS_TRUE;
 
1968
}
 
1969
 
 
1970
JS_PUBLIC_API(JSBool)
 
1971
JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 
1972
{
 
1973
    return JS_TRUE;
 
1974
}
 
1975
 
 
1976
JS_PUBLIC_API(JSBool)
 
1977
JS_EnumerateStub(JSContext *cx, JSObject *obj)
 
1978
{
 
1979
    return JS_TRUE;
 
1980
}
 
1981
 
 
1982
JS_PUBLIC_API(JSBool)
 
1983
JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id)
 
1984
{
 
1985
    return JS_TRUE;
 
1986
}
 
1987
 
 
1988
JS_PUBLIC_API(JSBool)
 
1989
JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
 
1990
{
 
1991
#if JS_BUG_EAGER_TOSTRING
 
1992
    if (type == JSTYPE_STRING)
 
1993
        return JS_TRUE;
 
1994
#endif
 
1995
    js_TryValueOf(cx, obj, type, vp);
 
1996
    return JS_TRUE;
 
1997
}
 
1998
 
 
1999
JS_PUBLIC_API(void)
 
2000
JS_FinalizeStub(JSContext *cx, JSObject *obj)
 
2001
{
 
2002
}
 
2003
 
 
2004
JS_PUBLIC_API(JSObject *)
 
2005
JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
 
2006
             JSClass *clasp, JSNative constructor, uintN nargs,
 
2007
             JSPropertySpec *ps, JSFunctionSpec *fs,
 
2008
             JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
 
2009
{
 
2010
    JSAtom *atom;
 
2011
    JSObject *proto, *ctor;
 
2012
    JSTempValueRooter tvr;
 
2013
    jsval cval, rval;
 
2014
    JSBool named;
 
2015
    JSFunction *fun;
 
2016
 
 
2017
    CHECK_REQUEST(cx);
 
2018
    atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
 
2019
    if (!atom)
 
2020
        return NULL;
 
2021
 
 
2022
    /* Create a prototype object for this class. */
 
2023
    proto = js_NewObject(cx, clasp, parent_proto, obj);
 
2024
    if (!proto)
 
2025
        return NULL;
 
2026
 
 
2027
    /* After this point, control must exit via label bad or out. */
 
2028
    JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(proto), &tvr);
 
2029
 
 
2030
    if (!constructor) {
 
2031
        /* Lacking a constructor, name the prototype (e.g., Math). */
 
2032
        named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
 
2033
                                    OBJECT_TO_JSVAL(proto),
 
2034
                                    NULL, NULL, 0, NULL);
 
2035
        if (!named)
 
2036
            goto bad;
 
2037
        ctor = proto;
 
2038
    } else {
 
2039
        /* Define the constructor function in obj's scope. */
 
2040
        fun = js_DefineFunction(cx, obj, atom, constructor, nargs, 0);
 
2041
        named = (fun != NULL);
 
2042
        if (!fun)
 
2043
            goto bad;
 
2044
 
 
2045
        /*
 
2046
         * Remember the class this function is a constructor for so that
 
2047
         * we know to create an object of this class when we call the
 
2048
         * constructor.
 
2049
         */
 
2050
        fun->clasp = clasp;
 
2051
 
 
2052
        /*
 
2053
         * Optionally construct the prototype object, before the class has
 
2054
         * been fully initialized.  Allow the ctor to replace proto with a
 
2055
         * different object, as is done for operator new -- and as at least
 
2056
         * XML support requires.
 
2057
         */
 
2058
        ctor = fun->object;
 
2059
        if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
 
2060
            cval = OBJECT_TO_JSVAL(ctor);
 
2061
            if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))
 
2062
                goto bad;
 
2063
            if (!JSVAL_IS_PRIMITIVE(rval) && JSVAL_TO_OBJECT(rval) != proto)
 
2064
                proto = JSVAL_TO_OBJECT(rval);
 
2065
        }
 
2066
 
 
2067
        /* Connect constructor and prototype by named properties. */
 
2068
        if (!js_SetClassPrototype(cx, ctor, proto,
 
2069
                                  JSPROP_READONLY | JSPROP_PERMANENT)) {
 
2070
            goto bad;
 
2071
        }
 
2072
 
 
2073
        /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
 
2074
        if (OBJ_GET_CLASS(cx, ctor) == clasp) {
 
2075
            /* XXXMLM - this fails in framesets that are writing over
 
2076
             *           themselves!
 
2077
             * JS_ASSERT(!OBJ_GET_PROTO(cx, ctor));
 
2078
             */
 
2079
            OBJ_SET_PROTO(cx, ctor, proto);
 
2080
        }
 
2081
    }
 
2082
 
 
2083
    /* Add properties and methods to the prototype and the constructor. */
 
2084
    if ((ps && !JS_DefineProperties(cx, proto, ps)) ||
 
2085
        (fs && !JS_DefineFunctions(cx, proto, fs)) ||
 
2086
        (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||
 
2087
        (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {
 
2088
        goto bad;
 
2089
    }
 
2090
 
 
2091
out:
 
2092
    JS_POP_TEMP_ROOT(cx, &tvr);
 
2093
    return proto;
 
2094
 
 
2095
bad:
 
2096
    if (named)
 
2097
        (void) OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &rval);
 
2098
    proto = NULL;
 
2099
    goto out;
 
2100
}
 
2101
 
 
2102
#ifdef JS_THREADSAFE
 
2103
JS_PUBLIC_API(JSClass *)
 
2104
JS_GetClass(JSContext *cx, JSObject *obj)
 
2105
{
 
2106
    return (JSClass *)
 
2107
        JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS));
 
2108
}
 
2109
#else
 
2110
JS_PUBLIC_API(JSClass *)
 
2111
JS_GetClass(JSObject *obj)
 
2112
{
 
2113
    return LOCKED_OBJ_GET_CLASS(obj);
 
2114
}
 
2115
#endif
 
2116
 
 
2117
JS_PUBLIC_API(JSBool)
 
2118
JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
 
2119
{
 
2120
    JSFunction *fun;
 
2121
 
 
2122
    CHECK_REQUEST(cx);
 
2123
    if (OBJ_GET_CLASS(cx, obj) == clasp)
 
2124
        return JS_TRUE;
 
2125
    if (argv) {
 
2126
        fun = js_ValueToFunction(cx, &argv[-2], 0);
 
2127
        if (fun) {
 
2128
            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
 
2129
                                 JSMSG_INCOMPATIBLE_PROTO,
 
2130
                                 clasp->name, JS_GetFunctionName(fun),
 
2131
                                 OBJ_GET_CLASS(cx, obj)->name);
 
2132
        }
 
2133
    }
 
2134
    return JS_FALSE;
 
2135
}
 
2136
 
 
2137
JS_PUBLIC_API(JSBool)
 
2138
JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
 
2139
{
 
2140
    return js_HasInstance(cx, obj, v, bp);
 
2141
}
 
2142
 
 
2143
JS_PUBLIC_API(void *)
 
2144
JS_GetPrivate(JSContext *cx, JSObject *obj)
 
2145
{
 
2146
    jsval v;
 
2147
 
 
2148
    JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
 
2149
    v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
 
2150
    if (!JSVAL_IS_INT(v))
 
2151
        return NULL;
 
2152
    return JSVAL_TO_PRIVATE(v);
 
2153
}
 
2154
 
 
2155
JS_PUBLIC_API(JSBool)
 
2156
JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
 
2157
{
 
2158
    JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
 
2159
    OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(data));
 
2160
    return JS_TRUE;
 
2161
}
 
2162
 
 
2163
JS_PUBLIC_API(void *)
 
2164
JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
 
2165
                      jsval *argv)
 
2166
{
 
2167
    if (!JS_InstanceOf(cx, obj, clasp, argv))
 
2168
        return NULL;
 
2169
    return JS_GetPrivate(cx, obj);
 
2170
}
 
2171
 
 
2172
JS_PUBLIC_API(JSObject *)
 
2173
JS_GetPrototype(JSContext *cx, JSObject *obj)
 
2174
{
 
2175
    JSObject *proto;
 
2176
 
 
2177
    CHECK_REQUEST(cx);
 
2178
    proto = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PROTO));
 
2179
 
 
2180
    /* Beware ref to dead object (we may be called from obj's finalizer). */
 
2181
    return proto && proto->map ? proto : NULL;
 
2182
}
 
2183
 
 
2184
JS_PUBLIC_API(JSBool)
 
2185
JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
 
2186
{
 
2187
    CHECK_REQUEST(cx);
 
2188
    if (obj->map->ops->setProto)
 
2189
        return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto);
 
2190
    OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto));
 
2191
    return JS_TRUE;
 
2192
}
 
2193
 
 
2194
JS_PUBLIC_API(JSObject *)
 
2195
JS_GetParent(JSContext *cx, JSObject *obj)
 
2196
{
 
2197
    JSObject *parent;
 
2198
 
 
2199
    parent = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PARENT));
 
2200
 
 
2201
    /* Beware ref to dead object (we may be called from obj's finalizer). */
 
2202
    return parent && parent->map ? parent : NULL;
 
2203
}
 
2204
 
 
2205
JS_PUBLIC_API(JSBool)
 
2206
JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
 
2207
{
 
2208
    CHECK_REQUEST(cx);
 
2209
    if (obj->map->ops->setParent)
 
2210
        return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent);
 
2211
    OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent));
 
2212
    return JS_TRUE;
 
2213
}
 
2214
 
 
2215
JS_PUBLIC_API(JSObject *)
 
2216
JS_GetConstructor(JSContext *cx, JSObject *proto)
 
2217
{
 
2218
    jsval cval;
 
2219
 
 
2220
    CHECK_REQUEST(cx);
 
2221
    if (!OBJ_GET_PROPERTY(cx, proto,
 
2222
                          ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
 
2223
                          &cval)) {
 
2224
        return NULL;
 
2225
    }
 
2226
    if (!JSVAL_IS_FUNCTION(cx, cval)) {
 
2227
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
 
2228
                             OBJ_GET_CLASS(cx, proto)->name);
 
2229
        return NULL;
 
2230
    }
 
2231
    return JSVAL_TO_OBJECT(cval);
 
2232
}
 
2233
 
 
2234
JS_PUBLIC_API(JSBool)
 
2235
JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
 
2236
{
 
2237
    JS_ASSERT(((jsid)obj & JSID_TAGMASK) == 0);
 
2238
    *idp = OBJECT_TO_JSID(obj);
 
2239
    return JS_TRUE;
 
2240
}
 
2241
 
 
2242
JS_PUBLIC_API(JSObject *)
 
2243
JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
 
2244
{
 
2245
    CHECK_REQUEST(cx);
 
2246
    if (!clasp)
 
2247
        clasp = &js_ObjectClass;    /* default class is Object */
 
2248
    return js_NewObject(cx, clasp, proto, parent);
 
2249
}
 
2250
 
 
2251
JS_PUBLIC_API(JSBool)
 
2252
JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
 
2253
{
 
2254
    JSScope *scope;
 
2255
    JSIdArray *ida;
 
2256
    uint32 nslots;
 
2257
    jsval v, *vp, *end;
 
2258
 
 
2259
    if (!OBJ_IS_NATIVE(obj)) {
 
2260
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
 
2261
                             JSMSG_CANT_SEAL_OBJECT,
 
2262
                             OBJ_GET_CLASS(cx, obj)->name);
 
2263
        return JS_FALSE;
 
2264
    }
 
2265
 
 
2266
    scope = OBJ_SCOPE(obj);
 
2267
 
 
2268
#if defined JS_THREADSAFE && defined DEBUG
 
2269
    /* Insist on scope being used exclusively by cx's thread. */
 
2270
    if (scope->ownercx != cx) {
 
2271
        JS_LOCK_OBJ(cx, obj);
 
2272
        JS_ASSERT(OBJ_SCOPE(obj) == scope);
 
2273
        JS_ASSERT(scope->ownercx == cx);
 
2274
        JS_UNLOCK_SCOPE(cx, scope);
 
2275
    }
 
2276
#endif
 
2277
 
 
2278
    /* Nothing to do if obj's scope is already sealed. */
 
2279
    if (SCOPE_IS_SEALED(scope))
 
2280
        return JS_TRUE;
 
2281
 
 
2282
    /* XXX Enumerate lazy properties now, as they can't be added later. */
 
2283
    ida = JS_Enumerate(cx, obj);
 
2284
    if (!ida)
 
2285
        return JS_FALSE;
 
2286
    JS_DestroyIdArray(cx, ida);
 
2287
 
 
2288
    /* Ensure that obj has its own, mutable scope, and seal that scope. */
 
2289
    JS_LOCK_OBJ(cx, obj);
 
2290
    scope = js_GetMutableScope(cx, obj);
 
2291
    if (scope)
 
2292
        SCOPE_SET_SEALED(scope);
 
2293
    JS_UNLOCK_SCOPE(cx, scope);
 
2294
    if (!scope)
 
2295
        return JS_FALSE;
 
2296
 
 
2297
    /* If we are not sealing an entire object graph, we're done. */
 
2298
    if (!deep)
 
2299
        return JS_TRUE;
 
2300
 
 
2301
    /* Walk obj->slots and if any value is a non-null object, seal it. */
 
2302
    nslots = JS_MIN(scope->map.freeslot, scope->map.nslots);
 
2303
    for (vp = obj->slots, end = vp + nslots; vp < end; vp++) {
 
2304
        v = *vp;
 
2305
        if (JSVAL_IS_PRIMITIVE(v))
 
2306
            continue;
 
2307
        if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep))
 
2308
            return JS_FALSE;
 
2309
    }
 
2310
    return JS_TRUE;
 
2311
}
 
2312
 
 
2313
JS_PUBLIC_API(JSObject *)
 
2314
JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
 
2315
                   JSObject *parent)
 
2316
{
 
2317
    CHECK_REQUEST(cx);
 
2318
    if (!clasp)
 
2319
        clasp = &js_ObjectClass;    /* default class is Object */
 
2320
    return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
 
2321
}
 
2322
 
 
2323
JS_PUBLIC_API(JSObject *)
 
2324
JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
 
2325
                                JSObject *parent, uintN argc, jsval *argv)
 
2326
{
 
2327
    CHECK_REQUEST(cx);
 
2328
    if (!clasp)
 
2329
        clasp = &js_ObjectClass;    /* default class is Object */
 
2330
    return js_ConstructObject(cx, clasp, proto, parent, argc, argv);
 
2331
}
 
2332
 
 
2333
static JSBool
 
2334
DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
 
2335
               JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
 
2336
               uintN flags, intN tinyid)
 
2337
{
 
2338
    jsid id;
 
2339
    JSAtom *atom;
 
2340
 
 
2341
    if (attrs & JSPROP_INDEX) {
 
2342
        id = INT_TO_JSID(JS_PTR_TO_INT32(name));
 
2343
        atom = NULL;
 
2344
        attrs &= ~JSPROP_INDEX;
 
2345
    } else {
 
2346
        atom = js_Atomize(cx, name, strlen(name), 0);
 
2347
        if (!atom)
 
2348
            return JS_FALSE;
 
2349
        id = ATOM_TO_JSID(atom);
 
2350
    }
 
2351
    if (flags != 0 && OBJ_IS_NATIVE(obj)) {
 
2352
        return js_DefineNativeProperty(cx, obj, id, value, getter, setter,
 
2353
                                       attrs, flags, tinyid, NULL);
 
2354
    }
 
2355
    return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
 
2356
                               NULL);
 
2357
}
 
2358
 
 
2359
#define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
 
2360
 
 
2361
static JSBool
 
2362
DefineUCProperty(JSContext *cx, JSObject *obj,
 
2363
                 const jschar *name, size_t namelen, jsval value,
 
2364
                 JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
 
2365
                 uintN flags, intN tinyid)
 
2366
{
 
2367
    JSAtom *atom;
 
2368
 
 
2369
    atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
 
2370
    if (!atom)
 
2371
        return JS_FALSE;
 
2372
    if (flags != 0 && OBJ_IS_NATIVE(obj)) {
 
2373
        return js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
 
2374
                                       getter, setter, attrs, flags, tinyid,
 
2375
                                       NULL);
 
2376
    }
 
2377
    return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), value,
 
2378
                               getter, setter, attrs, NULL);
 
2379
}
 
2380
 
 
2381
JS_PUBLIC_API(JSObject *)
 
2382
JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
 
2383
                JSObject *proto, uintN attrs)
 
2384
{
 
2385
    JSObject *nobj;
 
2386
 
 
2387
    CHECK_REQUEST(cx);
 
2388
    if (!clasp)
 
2389
        clasp = &js_ObjectClass;    /* default class is Object */
 
2390
    nobj = js_NewObject(cx, clasp, proto, obj);
 
2391
    if (!nobj)
 
2392
        return NULL;
 
2393
    if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
 
2394
                        0, 0)) {
 
2395
        cx->weakRoots.newborn[GCX_OBJECT] = NULL;
 
2396
        return NULL;
 
2397
    }
 
2398
    return nobj;
 
2399
}
 
2400
 
 
2401
JS_PUBLIC_API(JSBool)
 
2402
JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
 
2403
{
 
2404
    JSBool ok;
 
2405
    jsval value;
 
2406
    uintN flags;
 
2407
 
 
2408
    CHECK_REQUEST(cx);
 
2409
    for (ok = JS_TRUE; cds->name; cds++) {
 
2410
        ok = js_NewNumberValue(cx, cds->dval, &value);
 
2411
        if (!ok)
 
2412
            break;
 
2413
        flags = cds->flags;
 
2414
        if (!flags)
 
2415
            flags = JSPROP_READONLY | JSPROP_PERMANENT;
 
2416
        ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0);
 
2417
        if (!ok)
 
2418
            break;
 
2419
    }
 
2420
    return ok;
 
2421
}
 
2422
 
 
2423
JS_PUBLIC_API(JSBool)
 
2424
JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
 
2425
{
 
2426
    JSBool ok;
 
2427
 
 
2428
    CHECK_REQUEST(cx);
 
2429
    for (ok = JS_TRUE; ps->name; ps++) {
 
2430
        ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID,
 
2431
                            ps->getter, ps->setter, ps->flags,
 
2432
                            SPROP_HAS_SHORTID, ps->tinyid);
 
2433
        if (!ok)
 
2434
            break;
 
2435
    }
 
2436
    return ok;
 
2437
}
 
2438
 
 
2439
JS_PUBLIC_API(JSBool)
 
2440
JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
 
2441
                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
 
2442
{
 
2443
    CHECK_REQUEST(cx);
 
2444
    return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
 
2445
}
 
2446
 
 
2447
JS_PUBLIC_API(JSBool)
 
2448
JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
 
2449
                            int8 tinyid, jsval value,
 
2450
                            JSPropertyOp getter, JSPropertyOp setter,
 
2451
                            uintN attrs)
 
2452
{
 
2453
    CHECK_REQUEST(cx);
 
2454
    return DefineProperty(cx, obj, name, value, getter, setter, attrs,
 
2455
                          SPROP_HAS_SHORTID, tinyid);
 
2456
}
 
2457
 
 
2458
static JSBool
 
2459
LookupProperty(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
 
2460
               JSProperty **propp)
 
2461
{
 
2462
    JSAtom *atom;
 
2463
 
 
2464
    atom = js_Atomize(cx, name, strlen(name), 0);
 
2465
    if (!atom)
 
2466
        return JS_FALSE;
 
2467
    return OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), objp, propp);
 
2468
}
 
2469
 
 
2470
static JSBool
 
2471
LookupUCProperty(JSContext *cx, JSObject *obj,
 
2472
                 const jschar *name, size_t namelen,
 
2473
                 JSObject **objp, JSProperty **propp)
 
2474
{
 
2475
    JSAtom *atom;
 
2476
 
 
2477
    atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
 
2478
    if (!atom)
 
2479
        return JS_FALSE;
 
2480
    return OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), objp, propp);
 
2481
}
 
2482
 
 
2483
JS_PUBLIC_API(JSBool)
 
2484
JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
 
2485
                 const char *alias)
 
2486
{
 
2487
    JSObject *obj2;
 
2488
    JSProperty *prop;
 
2489
    JSAtom *atom;
 
2490
    JSBool ok;
 
2491
    JSScopeProperty *sprop;
 
2492
 
 
2493
    CHECK_REQUEST(cx);
 
2494
    if (!LookupProperty(cx, obj, name, &obj2, &prop))
 
2495
        return JS_FALSE;
 
2496
    if (!prop) {
 
2497
        js_ReportIsNotDefined(cx, name);
 
2498
        return JS_FALSE;
 
2499
    }
 
2500
    if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
 
2501
        OBJ_DROP_PROPERTY(cx, obj2, prop);
 
2502
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
 
2503
                             alias, name, OBJ_GET_CLASS(cx, obj2)->name);
 
2504
        return JS_FALSE;
 
2505
    }
 
2506
    atom = js_Atomize(cx, alias, strlen(alias), 0);
 
2507
    if (!atom) {
 
2508
        ok = JS_FALSE;
 
2509
    } else {
 
2510
        sprop = (JSScopeProperty *)prop;
 
2511
        ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom),
 
2512
                                   sprop->getter, sprop->setter, sprop->slot,
 
2513
                                   sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
 
2514
                                   sprop->shortid)
 
2515
              != NULL);
 
2516
    }
 
2517
    OBJ_DROP_PROPERTY(cx, obj, prop);
 
2518
    return ok;
 
2519
}
 
2520
 
 
2521
static jsval
 
2522
LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
 
2523
{
 
2524
    JSScopeProperty *sprop;
 
2525
    jsval rval;
 
2526
 
 
2527
    if (!prop) {
 
2528
        /* XXX bad API: no way to tell "not defined" from "void value" */
 
2529
        return JSVAL_VOID;
 
2530
    }
 
2531
    if (OBJ_IS_NATIVE(obj2)) {
 
2532
        /* Peek at the native property's slot value, without doing a Get. */
 
2533
        sprop = (JSScopeProperty *)prop;
 
2534
        rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
 
2535
               ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
 
2536
               : JSVAL_TRUE;
 
2537
    } else {
 
2538
        /* XXX bad API: no way to return "defined but value unknown" */
 
2539
        rval = JSVAL_TRUE;
 
2540
    }
 
2541
    OBJ_DROP_PROPERTY(cx, obj2, prop);
 
2542
    return rval;
 
2543
}
 
2544
 
 
2545
static JSBool
 
2546
GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
 
2547
                      uintN *attrsp, JSBool *foundp,
 
2548
                      JSPropertyOp *getterp, JSPropertyOp *setterp)
 
2549
{
 
2550
    JSObject *obj2;
 
2551
    JSProperty *prop;
 
2552
    JSBool ok;
 
2553
 
 
2554
    if (!atom)
 
2555
        return JS_FALSE;
 
2556
    if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop))
 
2557
        return JS_FALSE;
 
2558
 
 
2559
    if (!prop || obj != obj2) {
 
2560
        *attrsp = 0;
 
2561
        *foundp = JS_FALSE;
 
2562
        if (getterp)
 
2563
            *getterp = NULL;
 
2564
        if (setterp)
 
2565
            *setterp = NULL;
 
2566
        if (prop)
 
2567
            OBJ_DROP_PROPERTY(cx, obj2, prop);
 
2568
        return JS_TRUE;
 
2569
    }
 
2570
 
 
2571
    *foundp = JS_TRUE;
 
2572
    ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, attrsp);
 
2573
    if (ok && OBJ_IS_NATIVE(obj)) {
 
2574
        JSScopeProperty *sprop = (JSScopeProperty *) prop;
 
2575
 
 
2576
        if (getterp)
 
2577
            *getterp = sprop->getter;
 
2578
        if (setterp)
 
2579
            *setterp = sprop->setter;
 
2580
    }
 
2581
    OBJ_DROP_PROPERTY(cx, obj, prop);
 
2582
    return ok;
 
2583
}
 
2584
 
 
2585
static JSBool
 
2586
SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
 
2587
                      uintN attrs, JSBool *foundp)
 
2588
{
 
2589
    JSObject *obj2;
 
2590
    JSProperty *prop;
 
2591
    JSBool ok;
 
2592
 
 
2593
    if (!atom)
 
2594
        return JS_FALSE;
 
2595
    if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop))
 
2596
        return JS_FALSE;
 
2597
    if (!prop || obj != obj2) {
 
2598
        *foundp = JS_FALSE;
 
2599
        if (prop)
 
2600
            OBJ_DROP_PROPERTY(cx, obj2, prop);
 
2601
        return JS_TRUE;
 
2602
    }
 
2603
 
 
2604
    *foundp = JS_TRUE;
 
2605
    ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs);
 
2606
    OBJ_DROP_PROPERTY(cx, obj, prop);
 
2607
    return ok;
 
2608
}
 
2609
 
 
2610
JS_PUBLIC_API(JSBool)
 
2611
JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
 
2612
                         uintN *attrsp, JSBool *foundp)
 
2613
{
 
2614
    CHECK_REQUEST(cx);
 
2615
    return GetPropertyAttributes(cx, obj,
 
2616
                                 js_Atomize(cx, name, strlen(name), 0),
 
2617
                                 attrsp, foundp, NULL, NULL);
 
2618
}
 
2619
 
 
2620
JS_PUBLIC_API(JSBool)
 
2621
JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
 
2622
                                   const char *name,
 
2623
                                   uintN *attrsp, JSBool *foundp,
 
2624
                                   JSPropertyOp *getterp,
 
2625
                                   JSPropertyOp *setterp)
 
2626
{
 
2627
    CHECK_REQUEST(cx);
 
2628
    return GetPropertyAttributes(cx, obj,
 
2629
                                 js_Atomize(cx, name, strlen(name), 0),
 
2630
                                 attrsp, foundp, getterp, setterp);
 
2631
}
 
2632
 
 
2633
JS_PUBLIC_API(JSBool)
 
2634
JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
 
2635
                         uintN attrs, JSBool *foundp)
 
2636
{
 
2637
    CHECK_REQUEST(cx);
 
2638
    return SetPropertyAttributes(cx, obj,
 
2639
                                 js_Atomize(cx, name, strlen(name), 0),
 
2640
                                 attrs, foundp);
 
2641
}
 
2642
 
 
2643
JS_PUBLIC_API(JSBool)
 
2644
JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
 
2645
{
 
2646
    JSBool ok;
 
2647
    JSObject *obj2;
 
2648
    JSProperty *prop;
 
2649
 
 
2650
    CHECK_REQUEST(cx);
 
2651
    ok = LookupProperty(cx, obj, name, &obj2, &prop);
 
2652
    if (ok) {
 
2653
        *foundp = (prop != NULL);
 
2654
        if (prop)
 
2655
            OBJ_DROP_PROPERTY(cx, obj2, prop);
 
2656
    }
 
2657
    return ok;
 
2658
}
 
2659
 
 
2660
JS_PUBLIC_API(JSBool)
 
2661
JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
 
2662
{
 
2663
    JSBool ok;
 
2664
    JSObject *obj2;
 
2665
    JSProperty *prop;
 
2666
 
 
2667
    CHECK_REQUEST(cx);
 
2668
    ok = LookupProperty(cx, obj, name, &obj2, &prop);
 
2669
    if (ok)
 
2670
        *vp = LookupResult(cx, obj, obj2, prop);
 
2671
    return ok;
 
2672
}
 
2673
 
 
2674
JS_PUBLIC_API(JSBool)
 
2675
JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
 
2676
                           uintN flags, jsval *vp)
 
2677
{
 
2678
    JSAtom *atom;
 
2679
    JSBool ok;
 
2680
    JSObject *obj2;
 
2681
    JSProperty *prop;
 
2682
 
 
2683
    CHECK_REQUEST(cx);
 
2684
    atom = js_Atomize(cx, name, strlen(name), 0);
 
2685
    if (!atom)
 
2686
        return JS_FALSE;
 
2687
    ok = OBJ_IS_NATIVE(obj)
 
2688
         ? js_LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(atom), flags,
 
2689
                                      &obj2, &prop)
 
2690
         : OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop);
 
2691
    if (ok)
 
2692
        *vp = LookupResult(cx, obj, obj2, prop);
 
2693
    return ok;
 
2694
}
 
2695
 
 
2696
JS_PUBLIC_API(JSBool)
 
2697
JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
 
2698
{
 
2699
    JSAtom *atom;
 
2700
 
 
2701
    CHECK_REQUEST(cx);
 
2702
    atom = js_Atomize(cx, name, strlen(name), 0);
 
2703
    if (!atom)
 
2704
        return JS_FALSE;
 
2705
    return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
 
2706
}
 
2707
 
 
2708
JS_PUBLIC_API(JSBool)
 
2709
JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
 
2710
             jsval *vp)
 
2711
{
 
2712
    JSAtom *atom;
 
2713
    jsid id;
 
2714
 
 
2715
    CHECK_REQUEST(cx);
 
2716
    atom = js_Atomize(cx, name, strlen(name), 0);
 
2717
    if (!atom)
 
2718
        return JS_FALSE;
 
2719
    id = ATOM_TO_JSID(atom);
 
2720
 
 
2721
#if JS_HAS_XML_SUPPORT
 
2722
    if (OBJECT_IS_XML(cx, obj)) {
 
2723
        JSXMLObjectOps *ops;
 
2724
 
 
2725
        ops = (JSXMLObjectOps *) obj->map->ops;
 
2726
        obj = ops->getMethod(cx, obj, id, vp);
 
2727
        if (!obj)
 
2728
            return JS_FALSE;
 
2729
    } else
 
2730
#endif
 
2731
    {
 
2732
        if (!OBJ_GET_PROPERTY(cx, obj, id, vp))
 
2733
            return JS_FALSE;
 
2734
    }
 
2735
 
 
2736
    *objp = obj;
 
2737
    return JS_TRUE;
 
2738
}
 
2739
 
 
2740
JS_PUBLIC_API(JSBool)
 
2741
JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
 
2742
{
 
2743
    JSAtom *atom;
 
2744
 
 
2745
    CHECK_REQUEST(cx);
 
2746
    atom = js_Atomize(cx, name, strlen(name), 0);
 
2747
    if (!atom)
 
2748
        return JS_FALSE;
 
2749
    return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
 
2750
}
 
2751
 
 
2752
JS_PUBLIC_API(JSBool)
 
2753
JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
 
2754
{
 
2755
    jsval junk;
 
2756
 
 
2757
    CHECK_REQUEST(cx);
 
2758
    return JS_DeleteProperty2(cx, obj, name, &junk);
 
2759
}
 
2760
 
 
2761
JS_PUBLIC_API(JSBool)
 
2762
JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
 
2763
                   jsval *rval)
 
2764
{
 
2765
    JSAtom *atom;
 
2766
 
 
2767
    CHECK_REQUEST(cx);
 
2768
    atom = js_Atomize(cx, name, strlen(name), 0);
 
2769
    if (!atom)
 
2770
        return JS_FALSE;
 
2771
    return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
 
2772
}
 
2773
 
 
2774
JS_PUBLIC_API(JSBool)
 
2775
JS_DefineUCProperty(JSContext *cx, JSObject *obj,
 
2776
                    const jschar *name, size_t namelen, jsval value,
 
2777
                    JSPropertyOp getter, JSPropertyOp setter,
 
2778
                    uintN attrs)
 
2779
{
 
2780
    CHECK_REQUEST(cx);
 
2781
    return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
 
2782
                            attrs, 0, 0);
 
2783
}
 
2784
 
 
2785
JS_PUBLIC_API(JSBool)
 
2786
JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
 
2787
                           const jschar *name, size_t namelen,
 
2788
                           uintN *attrsp, JSBool *foundp)
 
2789
{
 
2790
    CHECK_REQUEST(cx);
 
2791
    return GetPropertyAttributes(cx, obj,
 
2792
                    js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
 
2793
                    attrsp, foundp, NULL, NULL);
 
2794
}
 
2795
 
 
2796
JS_PUBLIC_API(JSBool)
 
2797
JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
 
2798
                                     const jschar *name, size_t namelen,
 
2799
                                     uintN *attrsp, JSBool *foundp,
 
2800
                                     JSPropertyOp *getterp,
 
2801
                                     JSPropertyOp *setterp)
 
2802
{
 
2803
    CHECK_REQUEST(cx);
 
2804
    return GetPropertyAttributes(cx, obj,
 
2805
                    js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
 
2806
                    attrsp, foundp, getterp, setterp);
 
2807
}
 
2808
 
 
2809
JS_PUBLIC_API(JSBool)
 
2810
JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
 
2811
                           const jschar *name, size_t namelen,
 
2812
                           uintN attrs, JSBool *foundp)
 
2813
{
 
2814
    CHECK_REQUEST(cx);
 
2815
    return SetPropertyAttributes(cx, obj,
 
2816
                    js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
 
2817
                    attrs, foundp);
 
2818
}
 
2819
 
 
2820
JS_PUBLIC_API(JSBool)
 
2821
JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
 
2822
                              const jschar *name, size_t namelen,
 
2823
                              int8 tinyid, jsval value,
 
2824
                              JSPropertyOp getter, JSPropertyOp setter,
 
2825
                              uintN attrs)
 
2826
{
 
2827
    CHECK_REQUEST(cx);
 
2828
    return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
 
2829
                            attrs, SPROP_HAS_SHORTID, tinyid);
 
2830
}
 
2831
 
 
2832
JS_PUBLIC_API(JSBool)
 
2833
JS_HasUCProperty(JSContext *cx, JSObject *obj,
 
2834
                 const jschar *name, size_t namelen,
 
2835
                 JSBool *vp)
 
2836
{
 
2837
    JSBool ok;
 
2838
    JSObject *obj2;
 
2839
    JSProperty *prop;
 
2840
 
 
2841
    CHECK_REQUEST(cx);
 
2842
    ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
 
2843
    if (ok) {
 
2844
        *vp = (prop != NULL);
 
2845
        if (prop)
 
2846
            OBJ_DROP_PROPERTY(cx, obj2, prop);
 
2847
    }
 
2848
    return ok;
 
2849
}
 
2850
 
 
2851
JS_PUBLIC_API(JSBool)
 
2852
JS_LookupUCProperty(JSContext *cx, JSObject *obj,
 
2853
                    const jschar *name, size_t namelen,
 
2854
                    jsval *vp)
 
2855
{
 
2856
    JSBool ok;
 
2857
    JSObject *obj2;
 
2858
    JSProperty *prop;
 
2859
 
 
2860
    CHECK_REQUEST(cx);
 
2861
    ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
 
2862
    if (ok)
 
2863
        *vp = LookupResult(cx, obj, obj2, prop);
 
2864
    return ok;
 
2865
}
 
2866
 
 
2867
JS_PUBLIC_API(JSBool)
 
2868
JS_GetUCProperty(JSContext *cx, JSObject *obj,
 
2869
                 const jschar *name, size_t namelen,
 
2870
                 jsval *vp)
 
2871
{
 
2872
    JSAtom *atom;
 
2873
 
 
2874
    CHECK_REQUEST(cx);
 
2875
    atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
 
2876
    if (!atom)
 
2877
        return JS_FALSE;
 
2878
    return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
 
2879
}
 
2880
 
 
2881
JS_PUBLIC_API(JSBool)
 
2882
JS_SetUCProperty(JSContext *cx, JSObject *obj,
 
2883
                 const jschar *name, size_t namelen,
 
2884
                 jsval *vp)
 
2885
{
 
2886
    JSAtom *atom;
 
2887
 
 
2888
    CHECK_REQUEST(cx);
 
2889
    atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
 
2890
    if (!atom)
 
2891
        return JS_FALSE;
 
2892
    return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
 
2893
}
 
2894
 
 
2895
JS_PUBLIC_API(JSBool)
 
2896
JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
 
2897
                     const jschar *name, size_t namelen,
 
2898
                     jsval *rval)
 
2899
{
 
2900
    JSAtom *atom;
 
2901
 
 
2902
    CHECK_REQUEST(cx);
 
2903
    atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
 
2904
    if (!atom)
 
2905
        return JS_FALSE;
 
2906
    return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
 
2907
}
 
2908
 
 
2909
JS_PUBLIC_API(JSObject *)
 
2910
JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
 
2911
{
 
2912
    CHECK_REQUEST(cx);
 
2913
    /* NB: jsuint cast does ToUint32. */
 
2914
    return js_NewArrayObject(cx, (jsuint)length, vector);
 
2915
}
 
2916
 
 
2917
JS_PUBLIC_API(JSBool)
 
2918
JS_IsArrayObject(JSContext *cx, JSObject *obj)
 
2919
{
 
2920
    return OBJ_GET_CLASS(cx, obj) == &js_ArrayClass;
 
2921
}
 
2922
 
 
2923
JS_PUBLIC_API(JSBool)
 
2924
JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
 
2925
{
 
2926
    CHECK_REQUEST(cx);
 
2927
    return js_GetLengthProperty(cx, obj, lengthp);
 
2928
}
 
2929
 
 
2930
JS_PUBLIC_API(JSBool)
 
2931
JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
 
2932
{
 
2933
    CHECK_REQUEST(cx);
 
2934
    return js_SetLengthProperty(cx, obj, length);
 
2935
}
 
2936
 
 
2937
JS_PUBLIC_API(JSBool)
 
2938
JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
 
2939
{
 
2940
    CHECK_REQUEST(cx);
 
2941
    return js_HasLengthProperty(cx, obj, lengthp);
 
2942
}
 
2943
 
 
2944
JS_PUBLIC_API(JSBool)
 
2945
JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
 
2946
                 JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
 
2947
{
 
2948
    CHECK_REQUEST(cx);
 
2949
    return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(index), value,
 
2950
                               getter, setter, attrs, NULL);
 
2951
}
 
2952
 
 
2953
JS_PUBLIC_API(JSBool)
 
2954
JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
 
2955
{
 
2956
    JSObject *obj2;
 
2957
    JSProperty *prop;
 
2958
    JSScopeProperty *sprop;
 
2959
    JSBool ok;
 
2960
 
 
2961
    CHECK_REQUEST(cx);
 
2962
    if (!LookupProperty(cx, obj, name, &obj2, &prop))
 
2963
        return JS_FALSE;
 
2964
    if (!prop) {
 
2965
        js_ReportIsNotDefined(cx, name);
 
2966
        return JS_FALSE;
 
2967
    }
 
2968
    if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
 
2969
        char numBuf[12];
 
2970
        OBJ_DROP_PROPERTY(cx, obj2, prop);
 
2971
        JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
 
2972
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
 
2973
                             numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
 
2974
        return JS_FALSE;
 
2975
    }
 
2976
    sprop = (JSScopeProperty *)prop;
 
2977
    ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias),
 
2978
                               sprop->getter, sprop->setter, sprop->slot,
 
2979
                               sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
 
2980
                               sprop->shortid)
 
2981
          != NULL);
 
2982
    OBJ_DROP_PROPERTY(cx, obj, prop);
 
2983
    return ok;
 
2984
}
 
2985
 
 
2986
JS_PUBLIC_API(JSBool)
 
2987
JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
 
2988
{
 
2989
    JSBool ok;
 
2990
    JSObject *obj2;
 
2991
    JSProperty *prop;
 
2992
 
 
2993
    CHECK_REQUEST(cx);
 
2994
    ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSID(index), &obj2, &prop);
 
2995
    if (ok) {
 
2996
        *foundp = (prop != NULL);
 
2997
        if (prop)
 
2998
            OBJ_DROP_PROPERTY(cx, obj2, prop);
 
2999
    }
 
3000
    return ok;
 
3001
}
 
3002
 
 
3003
JS_PUBLIC_API(JSBool)
 
3004
JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
 
3005
{
 
3006
    JSBool ok;
 
3007
    JSObject *obj2;
 
3008
    JSProperty *prop;
 
3009
 
 
3010
    CHECK_REQUEST(cx);
 
3011
    ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSID(index), &obj2, &prop);
 
3012
    if (ok)
 
3013
        *vp = LookupResult(cx, obj, obj2, prop);
 
3014
    return ok;
 
3015
}
 
3016
 
 
3017
JS_PUBLIC_API(JSBool)
 
3018
JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
 
3019
{
 
3020
    CHECK_REQUEST(cx);
 
3021
    return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
 
3022
}
 
3023
 
 
3024
JS_PUBLIC_API(JSBool)
 
3025
JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
 
3026
{
 
3027
    CHECK_REQUEST(cx);
 
3028
    return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
 
3029
}
 
3030
 
 
3031
JS_PUBLIC_API(JSBool)
 
3032
JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index)
 
3033
{
 
3034
    jsval junk;
 
3035
 
 
3036
    CHECK_REQUEST(cx);
 
3037
    return JS_DeleteElement2(cx, obj, index, &junk);
 
3038
}
 
3039
 
 
3040
JS_PUBLIC_API(JSBool)
 
3041
JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
 
3042
{
 
3043
    CHECK_REQUEST(cx);
 
3044
    return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSID(index), rval);
 
3045
}
 
3046
 
 
3047
JS_PUBLIC_API(void)
 
3048
JS_ClearScope(JSContext *cx, JSObject *obj)
 
3049
{
 
3050
    CHECK_REQUEST(cx);
 
3051
 
 
3052
    if (obj->map->ops->clear)
 
3053
        obj->map->ops->clear(cx, obj);
 
3054
}
 
3055
 
 
3056
JS_PUBLIC_API(JSIdArray *)
 
3057
JS_Enumerate(JSContext *cx, JSObject *obj)
 
3058
{
 
3059
    jsint i, n;
 
3060
    jsval iter_state, num_properties;
 
3061
    jsid id;
 
3062
    JSIdArray *ida;
 
3063
    jsval *vector;
 
3064
 
 
3065
    CHECK_REQUEST(cx);
 
3066
 
 
3067
    ida = NULL;
 
3068
    iter_state = JSVAL_NULL;
 
3069
 
 
3070
    /* Get the number of properties to enumerate. */
 
3071
    if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties))
 
3072
        goto error;
 
3073
    if (!JSVAL_IS_INT(num_properties)) {
 
3074
        JS_ASSERT(0);
 
3075
        goto error;
 
3076
    }
 
3077
 
 
3078
    /* Grow as needed if we don't know the exact amount ahead of time. */
 
3079
    n = JSVAL_TO_INT(num_properties);
 
3080
    if (n <= 0)
 
3081
        n = 8;
 
3082
 
 
3083
    /* Create an array of jsids large enough to hold all the properties */
 
3084
    ida = js_NewIdArray(cx, n);
 
3085
    if (!ida)
 
3086
        goto error;
 
3087
 
 
3088
    i = 0;
 
3089
    vector = &ida->vector[0];
 
3090
    for (;;) {
 
3091
        if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id))
 
3092
            goto error;
 
3093
 
 
3094
        /* No more jsid's to enumerate ? */
 
3095
        if (iter_state == JSVAL_NULL)
 
3096
            break;
 
3097
 
 
3098
        if (i == ida->length) {
 
3099
            ida = js_SetIdArrayLength(cx, ida, ida->length * 2);
 
3100
            if (!ida)
 
3101
                goto error;
 
3102
            vector = &ida->vector[0];
 
3103
        }
 
3104
        vector[i++] = id;
 
3105
    }
 
3106
    return js_SetIdArrayLength(cx, ida, i);
 
3107
 
 
3108
error:
 
3109
    if (iter_state != JSVAL_NULL)
 
3110
        OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
 
3111
    if (ida)
 
3112
        JS_DestroyIdArray(cx, ida);
 
3113
    return NULL;
 
3114
}
 
3115
 
 
3116
/*
 
3117
 * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
 
3118
 *     prop_iterator_class somehow...
 
3119
 * + preserve the OBJ_ENUMERATE API while optimizing the native object case
 
3120
 * + native case here uses a JSScopeProperty *, but that iterates in reverse!
 
3121
 * + so we make non-native match, by reverse-iterating after JS_Enumerating
 
3122
 */
 
3123
#define JSSLOT_ITER_INDEX       (JSSLOT_PRIVATE + 1)
 
3124
 
 
3125
#if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS
 
3126
# error "JSSLOT_ITER_INDEX botch!"
 
3127
#endif
 
3128
 
 
3129
static void
 
3130
prop_iter_finalize(JSContext *cx, JSObject *obj)
 
3131
{
 
3132
    jsval v;
 
3133
    jsint i;
 
3134
    JSIdArray *ida;
 
3135
 
 
3136
    v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX);
 
3137
    if (JSVAL_IS_VOID(v))
 
3138
        return;
 
3139
 
 
3140
    i = JSVAL_TO_INT(v);
 
3141
    if (i >= 0) {
 
3142
        /* Non-native case: destroy the ida enumerated when obj was created. */
 
3143
        ida = (JSIdArray *) JS_GetPrivate(cx, obj);
 
3144
        if (ida)
 
3145
            JS_DestroyIdArray(cx, ida);
 
3146
    }
 
3147
}
 
3148
 
 
3149
static uint32
 
3150
prop_iter_mark(JSContext *cx, JSObject *obj, void *arg)
 
3151
{
 
3152
    jsval v;
 
3153
    jsint i, n;
 
3154
    JSScopeProperty *sprop;
 
3155
    JSIdArray *ida;
 
3156
    jsid id;
 
3157
 
 
3158
    v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
 
3159
    JS_ASSERT(!JSVAL_IS_VOID(v));
 
3160
 
 
3161
    i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX));
 
3162
    if (i < 0) {
 
3163
        /* Native case: just mark the next property to visit. */
 
3164
        sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v);
 
3165
        if (sprop)
 
3166
            MARK_SCOPE_PROPERTY(cx, sprop);
 
3167
    } else {
 
3168
        /* Non-native case: mark each id in the JSIdArray private. */
 
3169
        ida = (JSIdArray *) JSVAL_TO_PRIVATE(v);
 
3170
        for (i = 0, n = ida->length; i < n; i++) {
 
3171
            id = ida->vector[i];
 
3172
            MARK_ID(cx, id);
 
3173
        }
 
3174
    }
 
3175
    return 0;
 
3176
}
 
3177
 
 
3178
static JSClass prop_iter_class = {
 
3179
    "PropertyIterator",
 
3180
    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
 
3181
    JS_PropertyStub,  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
3182
    JS_EnumerateStub, JS_ResolveStub,  JS_ConvertStub,  prop_iter_finalize,
 
3183
    NULL,             NULL,            NULL,            NULL,
 
3184
    NULL,             NULL,            prop_iter_mark,  NULL
 
3185
};
 
3186
 
 
3187
JS_PUBLIC_API(JSObject *)
 
3188
JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
 
3189
{
 
3190
    JSObject *iterobj;
 
3191
    JSScope *scope;
 
3192
    void *pdata;
 
3193
    jsint index;
 
3194
    JSIdArray *ida;
 
3195
    
 
3196
    CHECK_REQUEST(cx);
 
3197
    iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj);
 
3198
    if (!iterobj)
 
3199
        return NULL;
 
3200
 
 
3201
    if (OBJ_IS_NATIVE(obj)) {
 
3202
        /* Native case: start with the last property in obj's own scope. */
 
3203
        scope = OBJ_SCOPE(obj);
 
3204
        pdata = (scope->object == obj) ? scope->lastProp : NULL;
 
3205
        index = -1;
 
3206
    } else {
 
3207
        JSTempValueRooter tvr;
 
3208
 
 
3209
        /*
 
3210
         * Non-native case: enumerate a JSIdArray and keep it via private.
 
3211
         *
 
3212
         * Note: we have to make sure that we root obj around the call to
 
3213
         * JS_Enumerate to protect against multiple allocations under it.
 
3214
         */
 
3215
        JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(iterobj), &tvr);
 
3216
        ida = JS_Enumerate(cx, obj);
 
3217
        JS_POP_TEMP_ROOT(cx, &tvr);
 
3218
        if (!ida)
 
3219
            goto bad;
 
3220
        pdata = ida;
 
3221
        index = ida->length;
 
3222
    }
 
3223
 
 
3224
    /* iterobj can not escape to other threads here. */
 
3225
    iterobj->slots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(pdata);
 
3226
    iterobj->slots[JSSLOT_ITER_INDEX] = INT_TO_JSVAL(index);
 
3227
    return iterobj;
 
3228
 
 
3229
  bad:
 
3230
    cx->weakRoots.newborn[GCX_OBJECT] = NULL;
 
3231
    return NULL;
 
3232
}
 
3233
 
 
3234
JS_PUBLIC_API(JSBool)
 
3235
JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
 
3236
{
 
3237
    jsint i;
 
3238
    JSObject *obj;
 
3239
    JSScope *scope;
 
3240
    JSScopeProperty *sprop;
 
3241
    JSIdArray *ida;
 
3242
 
 
3243
    CHECK_REQUEST(cx);
 
3244
    i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX));
 
3245
    if (i < 0) {
 
3246
        /* Native case: private data is a property tree node pointer. */
 
3247
        obj = OBJ_GET_PARENT(cx, iterobj);
 
3248
        JS_ASSERT(OBJ_IS_NATIVE(obj));
 
3249
        scope = OBJ_SCOPE(obj);
 
3250
        JS_ASSERT(scope->object == obj);
 
3251
        sprop = (JSScopeProperty *) JS_GetPrivate(cx, iterobj);
 
3252
 
 
3253
        /*
 
3254
         * If the next property mapped by scope in the property tree ancestor
 
3255
         * line is not enumerable, or it's an alias, or one or more properties
 
3256
         * were deleted from the "middle" of the scope-mapped ancestor line
 
3257
         * and the next property was among those deleted, skip it and keep on
 
3258
         * trying to find an enumerable property that is still in scope.
 
3259
         */
 
3260
        while (sprop &&
 
3261
               (!(sprop->attrs & JSPROP_ENUMERATE) ||
 
3262
                (sprop->flags & SPROP_IS_ALIAS) ||
 
3263
                (SCOPE_HAD_MIDDLE_DELETE(scope) &&
 
3264
                 !SCOPE_HAS_PROPERTY(scope, sprop)))) {
 
3265
            sprop = sprop->parent;
 
3266
        }
 
3267
 
 
3268
        if (!sprop) {
 
3269
            *idp = JSVAL_VOID;
 
3270
        } else {
 
3271
            if (!JS_SetPrivate(cx, iterobj, sprop->parent))
 
3272
                return JS_FALSE;
 
3273
            *idp = sprop->id;
 
3274
        }
 
3275
    } else {
 
3276
        /* Non-native case: use the ida enumerated when iterobj was created. */
 
3277
        ida = (JSIdArray *) JS_GetPrivate(cx, iterobj);
 
3278
        JS_ASSERT(i <= ida->length);
 
3279
        if (i == 0) {
 
3280
            *idp = JSVAL_VOID; 
 
3281
        } else {
 
3282
            *idp = ida->vector[--i];
 
3283
            OBJ_SET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(i));
 
3284
        }
 
3285
    }
 
3286
    return JS_TRUE;
 
3287
}
 
3288
 
 
3289
JS_PUBLIC_API(JSBool)
 
3290
JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
 
3291
               jsval *vp, uintN *attrsp)
 
3292
{
 
3293
    CHECK_REQUEST(cx);
 
3294
    return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp);
 
3295
}
 
3296
 
 
3297
JS_PUBLIC_API(JSCheckAccessOp)
 
3298
JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb)
 
3299
{
 
3300
    JSCheckAccessOp oldacb;
 
3301
 
 
3302
    oldacb = rt->checkObjectAccess;
 
3303
    rt->checkObjectAccess = acb;
 
3304
    return oldacb;
 
3305
}
 
3306
 
 
3307
static JSBool
 
3308
ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
 
3309
                    uint32 index, uint32 limit)
 
3310
{
 
3311
    /* Check the computed, possibly per-instance, upper bound. */
 
3312
    if (clasp->reserveSlots)
 
3313
        JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj));
 
3314
    if (index >= limit) {
 
3315
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
 
3316
                             JSMSG_RESERVED_SLOT_RANGE);
 
3317
        return JS_FALSE;
 
3318
    }
 
3319
    return JS_TRUE;
 
3320
}
 
3321
 
 
3322
JS_PUBLIC_API(JSBool)
 
3323
JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
 
3324
{
 
3325
    JSClass *clasp;
 
3326
    uint32 limit, slot;
 
3327
 
 
3328
    CHECK_REQUEST(cx);
 
3329
    clasp = OBJ_GET_CLASS(cx, obj);
 
3330
    limit = JSCLASS_RESERVED_SLOTS(clasp);
 
3331
    if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
 
3332
        return JS_FALSE;
 
3333
    slot = JSSLOT_START(clasp) + index;
 
3334
    *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
 
3335
    return JS_TRUE;
 
3336
}
 
3337
 
 
3338
JS_PUBLIC_API(JSBool)
 
3339
JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
 
3340
{
 
3341
    JSClass *clasp;
 
3342
    uint32 limit, slot;
 
3343
 
 
3344
    CHECK_REQUEST(cx);
 
3345
    clasp = OBJ_GET_CLASS(cx, obj);
 
3346
    limit = JSCLASS_RESERVED_SLOTS(clasp);
 
3347
    if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
 
3348
        return JS_FALSE;
 
3349
    slot = JSSLOT_START(clasp) + index;
 
3350
    return OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
 
3351
}
 
3352
 
 
3353
#ifdef JS_THREADSAFE
 
3354
JS_PUBLIC_API(jsrefcount)
 
3355
JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
 
3356
{
 
3357
    return JS_ATOMIC_INCREMENT(&principals->refcount);
 
3358
}
 
3359
 
 
3360
JS_PUBLIC_API(jsrefcount)
 
3361
JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
 
3362
{
 
3363
    jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount);
 
3364
    if (rc == 0)
 
3365
        principals->destroy(cx, principals);
 
3366
    return rc;
 
3367
}
 
3368
#endif
 
3369
 
 
3370
JS_PUBLIC_API(JSPrincipalsTranscoder)
 
3371
JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px)
 
3372
{
 
3373
    JSPrincipalsTranscoder oldpx;
 
3374
 
 
3375
    oldpx = rt->principalsTranscoder;
 
3376
    rt->principalsTranscoder = px;
 
3377
    return oldpx;
 
3378
}
 
3379
 
 
3380
JS_PUBLIC_API(JSObjectPrincipalsFinder)
 
3381
JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop)
 
3382
{
 
3383
    JSObjectPrincipalsFinder oldfop;
 
3384
 
 
3385
    oldfop = rt->findObjectPrincipals;
 
3386
    rt->findObjectPrincipals = fop;
 
3387
    return oldfop;
 
3388
}
 
3389
 
 
3390
JS_PUBLIC_API(JSFunction *)
 
3391
JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
 
3392
               JSObject *parent, const char *name)
 
3393
{
 
3394
    JSAtom *atom;
 
3395
 
 
3396
    CHECK_REQUEST(cx);
 
3397
 
 
3398
    if (!name) {
 
3399
        atom = NULL;
 
3400
    } else {
 
3401
        atom = js_Atomize(cx, name, strlen(name), 0);
 
3402
        if (!atom)
 
3403
            return NULL;
 
3404
    }
 
3405
    return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
 
3406
}
 
3407
 
 
3408
JS_PUBLIC_API(JSObject *)
 
3409
JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
 
3410
{
 
3411
    CHECK_REQUEST(cx);
 
3412
    if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {
 
3413
        /* Indicate we cannot clone this object. */
 
3414
        return funobj;
 
3415
    }
 
3416
    return js_CloneFunctionObject(cx, funobj, parent);
 
3417
}
 
3418
 
 
3419
JS_PUBLIC_API(JSObject *)
 
3420
JS_GetFunctionObject(JSFunction *fun)
 
3421
{
 
3422
    return fun->object;
 
3423
}
 
3424
 
 
3425
JS_PUBLIC_API(const char *)
 
3426
JS_GetFunctionName(JSFunction *fun)
 
3427
{
 
3428
    return fun->atom
 
3429
           ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
 
3430
           : js_anonymous_str;
 
3431
}
 
3432
 
 
3433
JS_PUBLIC_API(JSString *)
 
3434
JS_GetFunctionId(JSFunction *fun)
 
3435
{
 
3436
    return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
 
3437
}
 
3438
 
 
3439
JS_PUBLIC_API(uintN)
 
3440
JS_GetFunctionFlags(JSFunction *fun)
 
3441
{
 
3442
    return fun->flags;
 
3443
}
 
3444
 
 
3445
JS_PUBLIC_API(uint16)
 
3446
JS_GetFunctionArity(JSFunction *fun)
 
3447
{
 
3448
    return fun->nargs;
 
3449
}
 
3450
 
 
3451
JS_PUBLIC_API(JSBool)
 
3452
JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
 
3453
{
 
3454
    return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
 
3455
}
 
3456
 
 
3457
JS_STATIC_DLL_CALLBACK(JSBool)
 
3458
js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
 
3459
                                    uintN argc, jsval *argv, jsval *rval)
 
3460
{
 
3461
    jsval fsv;
 
3462
    JSFunctionSpec *fs;
 
3463
    JSObject *tmp;
 
3464
 
 
3465
    if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), 0, &fsv))
 
3466
        return JS_FALSE;
 
3467
    fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
 
3468
 
 
3469
    /*
 
3470
     * We know that argv[0] is valid because JS_DefineFunctions, which is our
 
3471
     * only (indirect) referrer, defined us as requiring at least one argument
 
3472
     * (notice how it passes fs->nargs + 1 as the next-to-last argument to
 
3473
     * JS_DefineFunction).
 
3474
     */
 
3475
    if (JSVAL_IS_PRIMITIVE(argv[0])) {
 
3476
        /*
 
3477
         * Make sure that this is an object or null, as required by the generic
 
3478
         * functions.
 
3479
         */
 
3480
        if (!js_ValueToObject(cx, argv[0], &tmp))
 
3481
            return JS_FALSE;
 
3482
        argv[0] = OBJECT_TO_JSVAL(tmp);
 
3483
    }
 
3484
 
 
3485
    /*
 
3486
     * Copy all actual (argc) and required but missing (fs->nargs + 1 - argc)
 
3487
     * args down over our |this| parameter, argv[-1], which is almost always
 
3488
     * the class constructor object, e.g. Array.  Then call the corresponding
 
3489
     * prototype native method with our first argument passed as |this|.
 
3490
     */
 
3491
    memmove(argv - 1, argv, JS_MAX(fs->nargs + 1U, argc) * sizeof(jsval));
 
3492
 
 
3493
    /*
 
3494
     * Follow Function.prototype.apply and .call by using the global object as
 
3495
     * the 'this' param if no args.
 
3496
     */
 
3497
    JS_ASSERT(cx->fp->argv == argv);
 
3498
    if (!js_ComputeThis(cx, JSVAL_TO_OBJECT(argv[-1]), cx->fp))
 
3499
        return JS_FALSE;
 
3500
 
 
3501
    /*
 
3502
     * Protect against argc - 1 underflowing below. By calling js_ComputeThis,
 
3503
     * we made it as if the static was called with one parameter.
 
3504
     */
 
3505
    if (argc == 0)
 
3506
        argc = 1;
 
3507
 
 
3508
    return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc - 1, argv, rval);
 
3509
}
 
3510
 
 
3511
JS_PUBLIC_API(JSBool)
 
3512
JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
 
3513
{
 
3514
    uintN flags;
 
3515
    JSObject *ctor;
 
3516
    JSFunction *fun;
 
3517
 
 
3518
    CHECK_REQUEST(cx);
 
3519
    ctor = NULL;
 
3520
    for (; fs->name; fs++) {
 
3521
        flags = fs->flags;
 
3522
 
 
3523
        /*
 
3524
         * Define a generic arity N+1 static method for the arity N prototype
 
3525
         * method if flags contains JSFUN_GENERIC_NATIVE.
 
3526
         */
 
3527
        if (flags & JSFUN_GENERIC_NATIVE) {
 
3528
            if (!ctor) {
 
3529
                ctor = JS_GetConstructor(cx, obj);
 
3530
                if (!ctor)
 
3531
                    return JS_FALSE;
 
3532
            }
 
3533
 
 
3534
            flags &= ~JSFUN_GENERIC_NATIVE;
 
3535
            fun = JS_DefineFunction(cx, ctor, fs->name,
 
3536
                                    js_generic_native_method_dispatcher,
 
3537
                                    fs->nargs + 1, flags);
 
3538
            if (!fun)
 
3539
                return JS_FALSE;
 
3540
            fun->extra = fs->extra;
 
3541
 
 
3542
            /*
 
3543
             * As jsapi.h notes, fs must point to storage that lives as long
 
3544
             * as fun->object lives.
 
3545
             */
 
3546
            if (!JS_SetReservedSlot(cx, fun->object, 0, PRIVATE_TO_JSVAL(fs)))
 
3547
                return JS_FALSE;
 
3548
        }
 
3549
 
 
3550
        fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
 
3551
        if (!fun)
 
3552
            return JS_FALSE;
 
3553
        fun->extra = fs->extra;
 
3554
    }
 
3555
    return JS_TRUE;
 
3556
}
 
3557
 
 
3558
JS_PUBLIC_API(JSFunction *)
 
3559
JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
 
3560
                  uintN nargs, uintN attrs)
 
3561
{
 
3562
    JSAtom *atom;
 
3563
 
 
3564
    CHECK_REQUEST(cx);
 
3565
    atom = js_Atomize(cx, name, strlen(name), 0);
 
3566
    if (!atom)
 
3567
        return NULL;
 
3568
    return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
 
3569
}
 
3570
 
 
3571
JS_PUBLIC_API(JSFunction *)
 
3572
JS_DefineUCFunction(JSContext *cx, JSObject *obj,
 
3573
                    const jschar *name, size_t namelen, JSNative call,
 
3574
                    uintN nargs, uintN attrs)
 
3575
{
 
3576
    JSAtom *atom;
 
3577
 
 
3578
    atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
 
3579
    if (!atom)
 
3580
        return NULL;
 
3581
    return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
 
3582
}
 
3583
 
 
3584
static JSScript *
 
3585
CompileTokenStream(JSContext *cx, JSObject *obj, JSTokenStream *ts,
 
3586
                   void *tempMark, JSBool *eofp)
 
3587
{
 
3588
    JSBool eof;
 
3589
    JSArenaPool codePool, notePool;
 
3590
    JSCodeGenerator cg;
 
3591
    JSScript *script;
 
3592
 
 
3593
    CHECK_REQUEST(cx);
 
3594
    eof = JS_FALSE;
 
3595
    JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
 
3596
    JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));
 
3597
    if (!js_InitCodeGenerator(cx, &cg, &codePool, &notePool,
 
3598
                              ts->filename, ts->lineno,
 
3599
                              ts->principals)) {
 
3600
        script = NULL;
 
3601
    } else if (!js_CompileTokenStream(cx, obj, ts, &cg)) {
 
3602
        script = NULL;
 
3603
        eof = (ts->flags & TSF_EOF) != 0;
 
3604
    } else {
 
3605
        script = js_NewScriptFromCG(cx, &cg, NULL);
 
3606
    }
 
3607
    if (eofp)
 
3608
        *eofp = eof;
 
3609
    if (!js_CloseTokenStream(cx, ts)) {
 
3610
        if (script)
 
3611
            js_DestroyScript(cx, script);
 
3612
        script = NULL;
 
3613
    }
 
3614
    cg.tempMark = tempMark;
 
3615
    js_FinishCodeGenerator(cx, &cg);
 
3616
    JS_FinishArenaPool(&codePool);
 
3617
    JS_FinishArenaPool(&notePool);
 
3618
    return script;
 
3619
}
 
3620
 
 
3621
JS_PUBLIC_API(JSScript *)
 
3622
JS_CompileScript(JSContext *cx, JSObject *obj,
 
3623
                 const char *bytes, size_t length,
 
3624
                 const char *filename, uintN lineno)
 
3625
{
 
3626
    jschar *chars;
 
3627
    JSScript *script;
 
3628
 
 
3629
    CHECK_REQUEST(cx);
 
3630
    chars = js_InflateString(cx, bytes, &length);
 
3631
    if (!chars)
 
3632
        return NULL;
 
3633
    script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno);
 
3634
    JS_free(cx, chars);
 
3635
    return script;
 
3636
}
 
3637
 
 
3638
JS_PUBLIC_API(JSScript *)
 
3639
JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
 
3640
                              JSPrincipals *principals,
 
3641
                              const char *bytes, size_t length,
 
3642
                              const char *filename, uintN lineno)
 
3643
{
 
3644
    jschar *chars;
 
3645
    JSScript *script;
 
3646
 
 
3647
    CHECK_REQUEST(cx);
 
3648
    chars = js_InflateString(cx, bytes, &length);
 
3649
    if (!chars)
 
3650
        return NULL;
 
3651
    script = JS_CompileUCScriptForPrincipals(cx, obj, principals,
 
3652
                                             chars, length, filename, lineno);
 
3653
    JS_free(cx, chars);
 
3654
    return script;
 
3655
}
 
3656
 
 
3657
JS_PUBLIC_API(JSScript *)
 
3658
JS_CompileUCScript(JSContext *cx, JSObject *obj,
 
3659
                   const jschar *chars, size_t length,
 
3660
                   const char *filename, uintN lineno)
 
3661
{
 
3662
    CHECK_REQUEST(cx);
 
3663
    return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length,
 
3664
                                           filename, lineno);
 
3665
}
 
3666
 
 
3667
#if JS_HAS_EXCEPTIONS
 
3668
# define LAST_FRAME_EXCEPTION_CHECK(cx,result)                                \
 
3669
    JS_BEGIN_MACRO                                                            \
 
3670
        if (!(result))                                                        \
 
3671
            js_ReportUncaughtException(cx);                                   \
 
3672
    JS_END_MACRO
 
3673
#else
 
3674
# define LAST_FRAME_EXCEPTION_CHECK(cx,result)  /* nothing */
 
3675
#endif
 
3676
 
 
3677
#define LAST_FRAME_CHECKS(cx,result)                                          \
 
3678
    JS_BEGIN_MACRO                                                            \
 
3679
        if (!(cx)->fp) {                                                      \
 
3680
            (cx)->weakRoots.lastInternalResult = JSVAL_NULL;                  \
 
3681
            LAST_FRAME_EXCEPTION_CHECK(cx, result);                           \
 
3682
        }                                                                     \
 
3683
    JS_END_MACRO
 
3684
 
 
3685
JS_PUBLIC_API(JSScript *)
 
3686
JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
 
3687
                                JSPrincipals *principals,
 
3688
                                const jschar *chars, size_t length,
 
3689
                                const char *filename, uintN lineno)
 
3690
{
 
3691
    void *mark;
 
3692
    JSTokenStream *ts;
 
3693
    JSScript *script;
 
3694
 
 
3695
    CHECK_REQUEST(cx);
 
3696
    mark = JS_ARENA_MARK(&cx->tempPool);
 
3697
    ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
 
3698
    if (!ts)
 
3699
        return NULL;
 
3700
    script = CompileTokenStream(cx, obj, ts, mark, NULL);
 
3701
    LAST_FRAME_CHECKS(cx, script);
 
3702
    return script;
 
3703
}
 
3704
 
 
3705
JS_PUBLIC_API(JSBool)
 
3706
JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
 
3707
                          const char *bytes, size_t length)
 
3708
{
 
3709
    jschar *chars;
 
3710
    JSBool result;
 
3711
    JSExceptionState *exnState;
 
3712
    void *tempMark;
 
3713
    JSTokenStream *ts;
 
3714
    JSErrorReporter older;
 
3715
 
 
3716
    CHECK_REQUEST(cx);
 
3717
    chars = js_InflateString(cx, bytes, &length);
 
3718
    if (!chars)
 
3719
        return JS_TRUE;
 
3720
 
 
3721
    /*
 
3722
     * Return true on any out-of-memory error, so our caller doesn't try to
 
3723
     * collect more buffered source.
 
3724
     */
 
3725
    result = JS_TRUE;
 
3726
    exnState = JS_SaveExceptionState(cx);
 
3727
    tempMark = JS_ARENA_MARK(&cx->tempPool);
 
3728
    ts = js_NewTokenStream(cx, chars, length, NULL, 0, NULL);
 
3729
    if (ts) {
 
3730
        older = JS_SetErrorReporter(cx, NULL);
 
3731
        if (!js_ParseTokenStream(cx, obj, ts) &&
 
3732
            (ts->flags & TSF_UNEXPECTED_EOF)) {
 
3733
            /*
 
3734
             * We ran into an error.  If it was because we ran out of source,
 
3735
             * we return false, so our caller will know to try to collect more
 
3736
             * buffered source.
 
3737
             */
 
3738
            result = JS_FALSE;
 
3739
        }
 
3740
 
 
3741
        JS_SetErrorReporter(cx, older);
 
3742
        js_CloseTokenStream(cx, ts);
 
3743
        JS_ARENA_RELEASE(&cx->tempPool, tempMark);
 
3744
    }
 
3745
 
 
3746
    JS_free(cx, chars);
 
3747
    JS_RestoreExceptionState(cx, exnState);
 
3748
    return result;
 
3749
}
 
3750
 
 
3751
JS_PUBLIC_API(JSScript *)
 
3752
JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
 
3753
{
 
3754
    void *mark;
 
3755
    JSTokenStream *ts;
 
3756
    JSScript *script;
 
3757
 
 
3758
    CHECK_REQUEST(cx);
 
3759
    mark = JS_ARENA_MARK(&cx->tempPool);
 
3760
    ts = js_NewFileTokenStream(cx, filename, stdin);
 
3761
    if (!ts)
 
3762
        return NULL;
 
3763
    script = CompileTokenStream(cx, obj, ts, mark, NULL);
 
3764
    LAST_FRAME_CHECKS(cx, script);
 
3765
    return script;
 
3766
}
 
3767
 
 
3768
JS_PUBLIC_API(JSScript *)
 
3769
JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
 
3770
                     FILE *file)
 
3771
{
 
3772
    return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
 
3773
}
 
3774
 
 
3775
JS_PUBLIC_API(JSScript *)
 
3776
JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
 
3777
                                  const char *filename, FILE *file,
 
3778
                                  JSPrincipals *principals)
 
3779
{
 
3780
    void *mark;
 
3781
    JSTokenStream *ts;
 
3782
    JSScript *script;
 
3783
 
 
3784
    CHECK_REQUEST(cx);
 
3785
    mark = JS_ARENA_MARK(&cx->tempPool);
 
3786
    ts = js_NewFileTokenStream(cx, NULL, file);
 
3787
    if (!ts)
 
3788
        return NULL;
 
3789
    ts->filename = filename;
 
3790
    /* XXXshaver js_NewFileTokenStream should do this, because it drops */
 
3791
    if (principals) {
 
3792
        ts->principals = principals;
 
3793
        JSPRINCIPALS_HOLD(cx, ts->principals);
 
3794
    }
 
3795
    script = CompileTokenStream(cx, obj, ts, mark, NULL);
 
3796
    LAST_FRAME_CHECKS(cx, script);
 
3797
    return script;
 
3798
}
 
3799
 
 
3800
JS_PUBLIC_API(JSObject *)
 
3801
JS_NewScriptObject(JSContext *cx, JSScript *script)
 
3802
{
 
3803
    JSObject *obj;
 
3804
 
 
3805
    obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
 
3806
    if (!obj)
 
3807
        return NULL;
 
3808
 
 
3809
    if (script) {
 
3810
        if (!JS_SetPrivate(cx, obj, script))
 
3811
            return NULL;
 
3812
        script->object = obj;
 
3813
    }
 
3814
    return obj;
 
3815
}
 
3816
 
 
3817
JS_PUBLIC_API(JSObject *)
 
3818
JS_GetScriptObject(JSScript *script)
 
3819
{
 
3820
    return script->object;
 
3821
}
 
3822
 
 
3823
JS_PUBLIC_API(void)
 
3824
JS_DestroyScript(JSContext *cx, JSScript *script)
 
3825
{
 
3826
    CHECK_REQUEST(cx);
 
3827
    js_DestroyScript(cx, script);
 
3828
}
 
3829
 
 
3830
JS_PUBLIC_API(JSFunction *)
 
3831
JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
 
3832
                   uintN nargs, const char **argnames,
 
3833
                   const char *bytes, size_t length,
 
3834
                   const char *filename, uintN lineno)
 
3835
{
 
3836
    jschar *chars;
 
3837
    JSFunction *fun;
 
3838
 
 
3839
    CHECK_REQUEST(cx);
 
3840
    chars = js_InflateString(cx, bytes, &length);
 
3841
    if (!chars)
 
3842
        return NULL;
 
3843
    fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length,
 
3844
                               filename, lineno);
 
3845
    JS_free(cx, chars);
 
3846
    return fun;
 
3847
}
 
3848
 
 
3849
JS_PUBLIC_API(JSFunction *)
 
3850
JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
 
3851
                                JSPrincipals *principals, const char *name,
 
3852
                                uintN nargs, const char **argnames,
 
3853
                                const char *bytes, size_t length,
 
3854
                                const char *filename, uintN lineno)
 
3855
{
 
3856
    jschar *chars;
 
3857
    JSFunction *fun;
 
3858
 
 
3859
    CHECK_REQUEST(cx);
 
3860
    chars = js_InflateString(cx, bytes, &length);
 
3861
    if (!chars)
 
3862
        return NULL;
 
3863
    fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
 
3864
                                            nargs, argnames, chars, length,
 
3865
                                            filename, lineno);
 
3866
    JS_free(cx, chars);
 
3867
    return fun;
 
3868
}
 
3869
 
 
3870
JS_PUBLIC_API(JSFunction *)
 
3871
JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
 
3872
                     uintN nargs, const char **argnames,
 
3873
                     const jschar *chars, size_t length,
 
3874
                     const char *filename, uintN lineno)
 
3875
{
 
3876
    CHECK_REQUEST(cx);
 
3877
    return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name,
 
3878
                                             nargs, argnames,
 
3879
                                             chars, length,
 
3880
                                             filename, lineno);
 
3881
}
 
3882
 
 
3883
JS_PUBLIC_API(JSFunction *)
 
3884
JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
 
3885
                                  JSPrincipals *principals, const char *name,
 
3886
                                  uintN nargs, const char **argnames,
 
3887
                                  const jschar *chars, size_t length,
 
3888
                                  const char *filename, uintN lineno)
 
3889
{
 
3890
    void *mark;
 
3891
    JSTokenStream *ts;
 
3892
    JSFunction *fun;
 
3893
    JSAtom *funAtom, *argAtom;
 
3894
    uintN i;
 
3895
 
 
3896
    CHECK_REQUEST(cx);
 
3897
    mark = JS_ARENA_MARK(&cx->tempPool);
 
3898
    ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
 
3899
    if (!ts) {
 
3900
        fun = NULL;
 
3901
        goto out;
 
3902
    }
 
3903
    if (!name) {
 
3904
        funAtom = NULL;
 
3905
    } else {
 
3906
        funAtom = js_Atomize(cx, name, strlen(name), 0);
 
3907
        if (!funAtom) {
 
3908
            fun = NULL;
 
3909
            goto out;
 
3910
        }
 
3911
    }
 
3912
    fun = js_NewFunction(cx, NULL, NULL, nargs, 0, obj, funAtom);
 
3913
    if (!fun)
 
3914
        goto out;
 
3915
    if (nargs) {
 
3916
        for (i = 0; i < nargs; i++) {
 
3917
            argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
 
3918
            if (!argAtom)
 
3919
                break;
 
3920
            if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(argAtom),
 
3921
                                      js_GetArgument, js_SetArgument,
 
3922
                                      SPROP_INVALID_SLOT,
 
3923
                                      JSPROP_PERMANENT | JSPROP_SHARED,
 
3924
                                      SPROP_HAS_SHORTID, i)) {
 
3925
                break;
 
3926
            }
 
3927
        }
 
3928
        if (i < nargs) {
 
3929
            fun = NULL;
 
3930
            goto out;
 
3931
        }
 
3932
    }
 
3933
    if (!js_CompileFunctionBody(cx, ts, fun)) {
 
3934
        fun = NULL;
 
3935
        goto out;
 
3936
    }
 
3937
    if (obj && funAtom) {
 
3938
        if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom),
 
3939
                                 OBJECT_TO_JSVAL(fun->object),
 
3940
                                 NULL, NULL, JSPROP_ENUMERATE, NULL)) {
 
3941
            return NULL;
 
3942
        }
 
3943
    }
 
3944
out:
 
3945
    if (ts)
 
3946
        js_CloseTokenStream(cx, ts);
 
3947
    JS_ARENA_RELEASE(&cx->tempPool, mark);
 
3948
    LAST_FRAME_CHECKS(cx, fun);
 
3949
    return fun;
 
3950
}
 
3951
 
 
3952
JS_PUBLIC_API(JSString *)
 
3953
JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
 
3954
                   uintN indent)
 
3955
{
 
3956
    JSPrinter *jp;
 
3957
    JSString *str;
 
3958
 
 
3959
    CHECK_REQUEST(cx);
 
3960
    jp = js_NewPrinter(cx, name,
 
3961
                       indent & ~JS_DONT_PRETTY_PRINT,
 
3962
                       !(indent & JS_DONT_PRETTY_PRINT));
 
3963
    if (!jp)
 
3964
        return NULL;
 
3965
    if (js_DecompileScript(jp, script))
 
3966
        str = js_GetPrinterOutput(jp);
 
3967
    else
 
3968
        str = NULL;
 
3969
    js_DestroyPrinter(jp);
 
3970
    return str;
 
3971
}
 
3972
 
 
3973
JS_PUBLIC_API(JSString *)
 
3974
JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
 
3975
{
 
3976
    JSPrinter *jp;
 
3977
    JSString *str;
 
3978
 
 
3979
    CHECK_REQUEST(cx);
 
3980
    jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
 
3981
                       indent & ~JS_DONT_PRETTY_PRINT,
 
3982
                       !(indent & JS_DONT_PRETTY_PRINT));
 
3983
    if (!jp)
 
3984
        return NULL;
 
3985
    if (js_DecompileFunction(jp, fun))
 
3986
        str = js_GetPrinterOutput(jp);
 
3987
    else
 
3988
        str = NULL;
 
3989
    js_DestroyPrinter(jp);
 
3990
    return str;
 
3991
}
 
3992
 
 
3993
JS_PUBLIC_API(JSString *)
 
3994
JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
 
3995
{
 
3996
    JSPrinter *jp;
 
3997
    JSString *str;
 
3998
 
 
3999
    CHECK_REQUEST(cx);
 
4000
    jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
 
4001
                       indent & ~JS_DONT_PRETTY_PRINT,
 
4002
                       !(indent & JS_DONT_PRETTY_PRINT));
 
4003
    if (!jp)
 
4004
        return NULL;
 
4005
    if (js_DecompileFunctionBody(jp, fun))
 
4006
        str = js_GetPrinterOutput(jp);
 
4007
    else
 
4008
        str = NULL;
 
4009
    js_DestroyPrinter(jp);
 
4010
    return str;
 
4011
}
 
4012
 
 
4013
JS_PUBLIC_API(JSBool)
 
4014
JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
 
4015
{
 
4016
    JSBool ok;
 
4017
 
 
4018
    CHECK_REQUEST(cx);
 
4019
    ok = js_Execute(cx, obj, script, NULL, 0, rval);
 
4020
    LAST_FRAME_CHECKS(cx, ok);
 
4021
    return ok;
 
4022
}
 
4023
 
 
4024
JS_PUBLIC_API(JSBool)
 
4025
JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
 
4026
                     JSExecPart part, jsval *rval)
 
4027
{
 
4028
    JSScript tmp;
 
4029
    JSRuntime *rt;
 
4030
    JSBool ok;
 
4031
 
 
4032
    /* Make a temporary copy of the JSScript structure and farble it a bit. */
 
4033
    tmp = *script;
 
4034
    if (part == JSEXEC_PROLOG) {
 
4035
        tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode);
 
4036
    } else {
 
4037
        tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode);
 
4038
        tmp.code = tmp.main;
 
4039
    }
 
4040
 
 
4041
    /* Tell the debugger about our temporary copy of the script structure. */
 
4042
    rt = cx->runtime;
 
4043
    if (rt->newScriptHook) {
 
4044
        rt->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL,
 
4045
                          rt->newScriptHookData);
 
4046
    }
 
4047
 
 
4048
    /* Execute the farbled struct and tell the debugger to forget about it. */
 
4049
    ok = JS_ExecuteScript(cx, obj, &tmp, rval);
 
4050
    if (rt->destroyScriptHook)
 
4051
        rt->destroyScriptHook(cx, &tmp, rt->destroyScriptHookData);
 
4052
    return ok;
 
4053
}
 
4054
 
 
4055
JS_PUBLIC_API(JSBool)
 
4056
JS_EvaluateScript(JSContext *cx, JSObject *obj,
 
4057
                  const char *bytes, uintN nbytes,
 
4058
                  const char *filename, uintN lineno,
 
4059
                  jsval *rval)
 
4060
{
 
4061
    size_t length = nbytes;
 
4062
    jschar *chars;
 
4063
    JSBool ok;
 
4064
 
 
4065
    CHECK_REQUEST(cx);
 
4066
    chars = js_InflateString(cx, bytes, &length);
 
4067
    if (!chars)
 
4068
        return JS_FALSE;
 
4069
    ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval);
 
4070
    JS_free(cx, chars);
 
4071
    return ok;
 
4072
}
 
4073
 
 
4074
JS_PUBLIC_API(JSBool)
 
4075
JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
 
4076
                               JSPrincipals *principals,
 
4077
                               const char *bytes, uintN nbytes,
 
4078
                               const char *filename, uintN lineno,
 
4079
                               jsval *rval)
 
4080
{
 
4081
    size_t length = nbytes;
 
4082
    jschar *chars;
 
4083
    JSBool ok;
 
4084
 
 
4085
    CHECK_REQUEST(cx);
 
4086
    chars = js_InflateString(cx, bytes, &length);
 
4087
    if (!chars)
 
4088
        return JS_FALSE;
 
4089
    ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
 
4090
                                          filename, lineno, rval);
 
4091
    JS_free(cx, chars);
 
4092
    return ok;
 
4093
}
 
4094
 
 
4095
JS_PUBLIC_API(JSBool)
 
4096
JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
 
4097
                    const jschar *chars, uintN length,
 
4098
                    const char *filename, uintN lineno,
 
4099
                    jsval *rval)
 
4100
{
 
4101
    CHECK_REQUEST(cx);
 
4102
    return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length,
 
4103
                                            filename, lineno, rval);
 
4104
}
 
4105
 
 
4106
JS_PUBLIC_API(JSBool)
 
4107
JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
 
4108
                                 JSPrincipals *principals,
 
4109
                                 const jschar *chars, uintN length,
 
4110
                                 const char *filename, uintN lineno,
 
4111
                                 jsval *rval)
 
4112
{
 
4113
    uint32 options;
 
4114
    JSScript *script;
 
4115
    JSBool ok;
 
4116
 
 
4117
    CHECK_REQUEST(cx);
 
4118
    options = cx->options;
 
4119
    cx->options = options | JSOPTION_COMPILE_N_GO;
 
4120
    script = JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length,
 
4121
                                             filename, lineno);
 
4122
    cx->options = options;
 
4123
    if (!script)
 
4124
        return JS_FALSE;
 
4125
    ok = js_Execute(cx, obj, script, NULL, 0, rval);
 
4126
    LAST_FRAME_CHECKS(cx, ok);
 
4127
    JS_DestroyScript(cx, script);
 
4128
    return ok;
 
4129
}
 
4130
 
 
4131
JS_PUBLIC_API(JSBool)
 
4132
JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
 
4133
                jsval *argv, jsval *rval)
 
4134
{
 
4135
    JSBool ok;
 
4136
 
 
4137
    CHECK_REQUEST(cx);
 
4138
    ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv,
 
4139
                         rval);
 
4140
    LAST_FRAME_CHECKS(cx, ok);
 
4141
    return ok;
 
4142
}
 
4143
 
 
4144
JS_PUBLIC_API(JSBool)
 
4145
JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
 
4146
                    jsval *argv, jsval *rval)
 
4147
{
 
4148
    JSBool ok;
 
4149
    jsval fval;
 
4150
 
 
4151
    CHECK_REQUEST(cx);
 
4152
#if JS_HAS_XML_SUPPORT
 
4153
    if (OBJECT_IS_XML(cx, obj)) {
 
4154
        JSXMLObjectOps *ops;
 
4155
        JSAtom *atom;
 
4156
 
 
4157
        ops = (JSXMLObjectOps *) obj->map->ops;
 
4158
        atom = js_Atomize(cx, name, strlen(name), 0);
 
4159
        if (!atom)
 
4160
            return JS_FALSE;
 
4161
        obj = ops->getMethod(cx, obj, ATOM_TO_JSID(atom), &fval);
 
4162
        if (!obj)
 
4163
            return JS_FALSE;
 
4164
    } else
 
4165
#endif
 
4166
    if (!JS_GetProperty(cx, obj, name, &fval))
 
4167
        return JS_FALSE;
 
4168
    ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
 
4169
    LAST_FRAME_CHECKS(cx, ok);
 
4170
    return ok;
 
4171
}
 
4172
 
 
4173
JS_PUBLIC_API(JSBool)
 
4174
JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
 
4175
                     jsval *argv, jsval *rval)
 
4176
{
 
4177
    JSBool ok;
 
4178
 
 
4179
    CHECK_REQUEST(cx);
 
4180
    ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
 
4181
    LAST_FRAME_CHECKS(cx, ok);
 
4182
    return ok;
 
4183
}
 
4184
 
 
4185
JS_PUBLIC_API(JSBranchCallback)
 
4186
JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb)
 
4187
{
 
4188
    JSBranchCallback oldcb;
 
4189
 
 
4190
    oldcb = cx->branchCallback;
 
4191
    cx->branchCallback = cb;
 
4192
    return oldcb;
 
4193
}
 
4194
 
 
4195
JS_PUBLIC_API(JSBool)
 
4196
JS_IsRunning(JSContext *cx)
 
4197
{
 
4198
    return cx->fp != NULL;
 
4199
}
 
4200
 
 
4201
JS_PUBLIC_API(JSBool)
 
4202
JS_IsConstructing(JSContext *cx)
 
4203
{
 
4204
    return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
 
4205
}
 
4206
 
 
4207
JS_FRIEND_API(JSBool)
 
4208
JS_IsAssigning(JSContext *cx)
 
4209
{
 
4210
    JSStackFrame *fp;
 
4211
    jsbytecode *pc;
 
4212
 
 
4213
    for (fp = cx->fp; fp && !fp->script; fp = fp->down)
 
4214
        continue;
 
4215
    if (!fp || !(pc = fp->pc))
 
4216
        return JS_FALSE;
 
4217
    return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0;
 
4218
}
 
4219
 
 
4220
JS_PUBLIC_API(void)
 
4221
JS_SetCallReturnValue2(JSContext *cx, jsval v)
 
4222
{
 
4223
#if JS_HAS_LVALUE_RETURN
 
4224
    cx->rval2 = v;
 
4225
    cx->rval2set = JS_TRUE;
 
4226
#endif
 
4227
}
 
4228
 
 
4229
/************************************************************************/
 
4230
 
 
4231
JS_PUBLIC_API(JSString *)
 
4232
JS_NewString(JSContext *cx, char *bytes, size_t length)
 
4233
{
 
4234
    jschar *chars;
 
4235
    JSString *str;
 
4236
    size_t charsLength = length;
 
4237
 
 
4238
    CHECK_REQUEST(cx);
 
4239
    /* Make a Unicode vector from the 8-bit char codes in bytes. */
 
4240
    chars = js_InflateString(cx, bytes, &charsLength);
 
4241
    if (!chars)
 
4242
        return NULL;
 
4243
 
 
4244
    /* Free chars (but not bytes, which caller frees on error) if we fail. */
 
4245
    str = js_NewString(cx, chars, charsLength, 0);
 
4246
    if (!str) {
 
4247
        JS_free(cx, chars);
 
4248
        return NULL;
 
4249
    }
 
4250
 
 
4251
    /* Hand off bytes to the deflated string cache, if possible. */
 
4252
    if (!js_SetStringBytes(str, bytes, length))
 
4253
        JS_free(cx, bytes);
 
4254
    return str;
 
4255
}
 
4256
 
 
4257
JS_PUBLIC_API(JSString *)
 
4258
JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
 
4259
{
 
4260
    jschar *js;
 
4261
    JSString *str;
 
4262
 
 
4263
    CHECK_REQUEST(cx);
 
4264
    js = js_InflateString(cx, s, &n);
 
4265
    if (!js)
 
4266
        return NULL;
 
4267
    str = js_NewString(cx, js, n, 0);
 
4268
    if (!str)
 
4269
        JS_free(cx, js);
 
4270
    return str;
 
4271
}
 
4272
 
 
4273
JS_PUBLIC_API(JSString *)
 
4274
JS_NewStringCopyZ(JSContext *cx, const char *s)
 
4275
{
 
4276
    size_t n;
 
4277
    jschar *js;
 
4278
    JSString *str;
 
4279
 
 
4280
    CHECK_REQUEST(cx);
 
4281
    if (!s)
 
4282
        return cx->runtime->emptyString;
 
4283
    n = strlen(s);
 
4284
    js = js_InflateString(cx, s, &n);
 
4285
    if (!js)
 
4286
        return NULL;
 
4287
    str = js_NewString(cx, js, n, 0);
 
4288
    if (!str)
 
4289
        JS_free(cx, js);
 
4290
    return str;
 
4291
}
 
4292
 
 
4293
JS_PUBLIC_API(JSString *)
 
4294
JS_InternString(JSContext *cx, const char *s)
 
4295
{
 
4296
    JSAtom *atom;
 
4297
 
 
4298
    CHECK_REQUEST(cx);
 
4299
    atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
 
4300
    if (!atom)
 
4301
        return NULL;
 
4302
    return ATOM_TO_STRING(atom);
 
4303
}
 
4304
 
 
4305
JS_PUBLIC_API(JSString *)
 
4306
JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
 
4307
{
 
4308
    CHECK_REQUEST(cx);
 
4309
    return js_NewString(cx, chars, length, 0);
 
4310
}
 
4311
 
 
4312
JS_PUBLIC_API(JSString *)
 
4313
JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
 
4314
{
 
4315
    CHECK_REQUEST(cx);
 
4316
    return js_NewStringCopyN(cx, s, n, 0);
 
4317
}
 
4318
 
 
4319
JS_PUBLIC_API(JSString *)
 
4320
JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
 
4321
{
 
4322
    CHECK_REQUEST(cx);
 
4323
    if (!s)
 
4324
        return cx->runtime->emptyString;
 
4325
    return js_NewStringCopyZ(cx, s, 0);
 
4326
}
 
4327
 
 
4328
JS_PUBLIC_API(JSString *)
 
4329
JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
 
4330
{
 
4331
    JSAtom *atom;
 
4332
 
 
4333
    CHECK_REQUEST(cx);
 
4334
    atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
 
4335
    if (!atom)
 
4336
        return NULL;
 
4337
    return ATOM_TO_STRING(atom);
 
4338
}
 
4339
 
 
4340
JS_PUBLIC_API(JSString *)
 
4341
JS_InternUCString(JSContext *cx, const jschar *s)
 
4342
{
 
4343
    return JS_InternUCStringN(cx, s, js_strlen(s));
 
4344
}
 
4345
 
 
4346
JS_PUBLIC_API(char *)
 
4347
JS_GetStringBytes(JSString *str)
 
4348
{
 
4349
    char *bytes;
 
4350
 
 
4351
    bytes = js_GetStringBytes(str);
 
4352
    return bytes ? bytes : "";
 
4353
}
 
4354
 
 
4355
JS_PUBLIC_API(jschar *)
 
4356
JS_GetStringChars(JSString *str)
 
4357
{
 
4358
    /*
 
4359
     * API botch (again, shades of JS_GetStringBytes): we have no cx to pass
 
4360
     * to js_UndependString (called by js_GetStringChars) for out-of-memory
 
4361
     * error reports, so js_UndependString passes NULL and suppresses errors.
 
4362
     * If it fails to convert a dependent string into an independent one, our
 
4363
     * caller will not be guaranteed a \u0000 terminator as a backstop.  This
 
4364
     * may break some clients who already misbehave on embedded NULs.
 
4365
     *
 
4366
     * The gain of dependent strings, which cure quadratic and cubic growth
 
4367
     * rate bugs in string concatenation, is worth this slight loss in API
 
4368
     * compatibility.
 
4369
     */
 
4370
    jschar *chars;
 
4371
 
 
4372
    chars = js_GetStringChars(str);
 
4373
    return chars ? chars : JSSTRING_CHARS(str);
 
4374
}
 
4375
 
 
4376
JS_PUBLIC_API(size_t)
 
4377
JS_GetStringLength(JSString *str)
 
4378
{
 
4379
    return JSSTRING_LENGTH(str);
 
4380
}
 
4381
 
 
4382
JS_PUBLIC_API(intN)
 
4383
JS_CompareStrings(JSString *str1, JSString *str2)
 
4384
{
 
4385
    return js_CompareStrings(str1, str2);
 
4386
}
 
4387
 
 
4388
JS_PUBLIC_API(JSString *)
 
4389
JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
 
4390
{
 
4391
    CHECK_REQUEST(cx);
 
4392
    return js_NewString(cx, chars, length, GCF_MUTABLE);
 
4393
}
 
4394
 
 
4395
JS_PUBLIC_API(JSString *)
 
4396
JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
 
4397
                      size_t length)
 
4398
{
 
4399
    CHECK_REQUEST(cx);
 
4400
    return js_NewDependentString(cx, str, start, length, 0);
 
4401
}
 
4402
 
 
4403
JS_PUBLIC_API(JSString *)
 
4404
JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
 
4405
{
 
4406
    CHECK_REQUEST(cx);
 
4407
    return js_ConcatStrings(cx, left, right);
 
4408
}
 
4409
 
 
4410
JS_PUBLIC_API(const jschar *)
 
4411
JS_UndependString(JSContext *cx, JSString *str)
 
4412
{
 
4413
    CHECK_REQUEST(cx);
 
4414
    return js_UndependString(cx, str);
 
4415
}
 
4416
 
 
4417
JS_PUBLIC_API(JSBool)
 
4418
JS_MakeStringImmutable(JSContext *cx, JSString *str)
 
4419
{
 
4420
    CHECK_REQUEST(cx);
 
4421
    if (!js_UndependString(cx, str))
 
4422
        return JS_FALSE;
 
4423
 
 
4424
    *js_GetGCThingFlags(str) &= ~GCF_MUTABLE;
 
4425
    return JS_TRUE;
 
4426
}
 
4427
 
 
4428
JS_PUBLIC_API(JSBool)
 
4429
JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
 
4430
                    size_t *dstlenp)
 
4431
{
 
4432
    return js_DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
 
4433
}
 
4434
 
 
4435
JS_PUBLIC_API(JSBool)
 
4436
JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
 
4437
               size_t *dstlenp)
 
4438
{
 
4439
    return js_InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
 
4440
}
 
4441
 
 
4442
JS_PUBLIC_API(JSBool)
 
4443
JS_StringsAreUTF8 ()
 
4444
{
 
4445
#ifdef JS_C_STRINGS_ARE_UTF8
 
4446
    return JS_TRUE;
 
4447
#else
 
4448
    return JS_FALSE;
 
4449
#endif
 
4450
}
 
4451
 
 
4452
/************************************************************************/
 
4453
 
 
4454
JS_PUBLIC_API(void)
 
4455
JS_ReportError(JSContext *cx, const char *format, ...)
 
4456
{
 
4457
    va_list ap;
 
4458
 
 
4459
    va_start(ap, format);
 
4460
    js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
 
4461
    va_end(ap);
 
4462
}
 
4463
 
 
4464
JS_PUBLIC_API(void)
 
4465
JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
 
4466
                     void *userRef, const uintN errorNumber, ...)
 
4467
{
 
4468
    va_list ap;
 
4469
 
 
4470
    va_start(ap, errorNumber);
 
4471
    js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
 
4472
                           errorNumber, JS_TRUE, ap);
 
4473
    va_end(ap);
 
4474
}
 
4475
 
 
4476
JS_PUBLIC_API(void)
 
4477
JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
 
4478
                     void *userRef, const uintN errorNumber, ...)
 
4479
{
 
4480
    va_list ap;
 
4481
 
 
4482
    va_start(ap, errorNumber);
 
4483
    js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
 
4484
                           errorNumber, JS_FALSE, ap);
 
4485
    va_end(ap);
 
4486
}
 
4487
 
 
4488
JS_PUBLIC_API(JSBool)
 
4489
JS_ReportWarning(JSContext *cx, const char *format, ...)
 
4490
{
 
4491
    va_list ap;
 
4492
    JSBool ok;
 
4493
 
 
4494
    va_start(ap, format);
 
4495
    ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
 
4496
    va_end(ap);
 
4497
    return ok;
 
4498
}
 
4499
 
 
4500
JS_PUBLIC_API(JSBool)
 
4501
JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
 
4502
                             JSErrorCallback errorCallback, void *userRef,
 
4503
                             const uintN errorNumber, ...)
 
4504
{
 
4505
    va_list ap;
 
4506
    JSBool ok;
 
4507
 
 
4508
    va_start(ap, errorNumber);
 
4509
    ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
 
4510
                                errorNumber, JS_TRUE, ap);
 
4511
    va_end(ap);
 
4512
    return ok;
 
4513
}
 
4514
 
 
4515
JS_PUBLIC_API(JSBool)
 
4516
JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
 
4517
                               JSErrorCallback errorCallback, void *userRef,
 
4518
                               const uintN errorNumber, ...)
 
4519
{
 
4520
    va_list ap;
 
4521
    JSBool ok;
 
4522
 
 
4523
    va_start(ap, errorNumber);
 
4524
    ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
 
4525
                                errorNumber, JS_FALSE, ap);
 
4526
    va_end(ap);
 
4527
    return ok;
 
4528
}
 
4529
 
 
4530
JS_PUBLIC_API(void)
 
4531
JS_ReportOutOfMemory(JSContext *cx)
 
4532
{
 
4533
    js_ReportOutOfMemory(cx, js_GetErrorMessage);
 
4534
}
 
4535
 
 
4536
JS_PUBLIC_API(JSErrorReporter)
 
4537
JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
 
4538
{
 
4539
    JSErrorReporter older;
 
4540
 
 
4541
    older = cx->errorReporter;
 
4542
    cx->errorReporter = er;
 
4543
    return older;
 
4544
}
 
4545
 
 
4546
/************************************************************************/
 
4547
 
 
4548
/*
 
4549
 * Regular Expressions.
 
4550
 */
 
4551
JS_PUBLIC_API(JSObject *)
 
4552
JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
 
4553
{
 
4554
#if JS_HAS_REGEXPS
 
4555
    jschar *chars;
 
4556
    JSObject *obj;
 
4557
 
 
4558
    CHECK_REQUEST(cx);
 
4559
    chars = js_InflateString(cx, bytes, &length);
 
4560
    if (!chars)
 
4561
        return NULL;
 
4562
    obj = js_NewRegExpObject(cx, NULL, chars, length, flags);
 
4563
    JS_free(cx, chars);
 
4564
    return obj;
 
4565
#else
 
4566
    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS);
 
4567
    return NULL;
 
4568
#endif
 
4569
}
 
4570
 
 
4571
JS_PUBLIC_API(JSObject *)
 
4572
JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
 
4573
{
 
4574
    CHECK_REQUEST(cx);
 
4575
#if JS_HAS_REGEXPS
 
4576
    return js_NewRegExpObject(cx, NULL, chars, length, flags);
 
4577
#else
 
4578
    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS);
 
4579
    return NULL;
 
4580
#endif
 
4581
}
 
4582
 
 
4583
JS_PUBLIC_API(void)
 
4584
JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
 
4585
{
 
4586
    JSRegExpStatics *res;
 
4587
 
 
4588
    CHECK_REQUEST(cx);
 
4589
    /* No locking required, cx is thread-private and input must be live. */
 
4590
    res = &cx->regExpStatics;
 
4591
    res->input = input;
 
4592
    res->multiline = multiline;
 
4593
    cx->runtime->gcPoke = JS_TRUE;
 
4594
}
 
4595
 
 
4596
JS_PUBLIC_API(void)
 
4597
JS_ClearRegExpStatics(JSContext *cx)
 
4598
{
 
4599
    JSRegExpStatics *res;
 
4600
 
 
4601
    /* No locking required, cx is thread-private and input must be live. */
 
4602
    res = &cx->regExpStatics;
 
4603
    res->input = NULL;
 
4604
    res->multiline = JS_FALSE;
 
4605
    res->parenCount = 0;
 
4606
    res->lastMatch = res->lastParen = js_EmptySubString;
 
4607
    res->leftContext = res->rightContext = js_EmptySubString;
 
4608
    cx->runtime->gcPoke = JS_TRUE;
 
4609
}
 
4610
 
 
4611
JS_PUBLIC_API(void)
 
4612
JS_ClearRegExpRoots(JSContext *cx)
 
4613
{
 
4614
    JSRegExpStatics *res;
 
4615
 
 
4616
    /* No locking required, cx is thread-private and input must be live. */
 
4617
    res = &cx->regExpStatics;
 
4618
    res->input = NULL;
 
4619
    cx->runtime->gcPoke = JS_TRUE;
 
4620
}
 
4621
 
 
4622
/* TODO: compile, execute, get/set other statics... */
 
4623
 
 
4624
/************************************************************************/
 
4625
 
 
4626
JS_PUBLIC_API(void)
 
4627
JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
 
4628
{
 
4629
    cx->localeCallbacks = callbacks;
 
4630
}
 
4631
 
 
4632
JS_PUBLIC_API(JSLocaleCallbacks *)
 
4633
JS_GetLocaleCallbacks(JSContext *cx)
 
4634
{
 
4635
    return cx->localeCallbacks;
 
4636
}
 
4637
 
 
4638
/************************************************************************/
 
4639
 
 
4640
JS_PUBLIC_API(JSBool)
 
4641
JS_IsExceptionPending(JSContext *cx)
 
4642
{
 
4643
#if JS_HAS_EXCEPTIONS
 
4644
    return (JSBool) cx->throwing;
 
4645
#else
 
4646
    return JS_FALSE;
 
4647
#endif
 
4648
}
 
4649
 
 
4650
JS_PUBLIC_API(JSBool)
 
4651
JS_GetPendingException(JSContext *cx, jsval *vp)
 
4652
{
 
4653
#if JS_HAS_EXCEPTIONS
 
4654
    CHECK_REQUEST(cx);
 
4655
    if (!cx->throwing)
 
4656
        return JS_FALSE;
 
4657
    *vp = cx->exception;
 
4658
    return JS_TRUE;
 
4659
#else
 
4660
    return JS_FALSE;
 
4661
#endif
 
4662
}
 
4663
 
 
4664
JS_PUBLIC_API(void)
 
4665
JS_SetPendingException(JSContext *cx, jsval v)
 
4666
{
 
4667
    CHECK_REQUEST(cx);
 
4668
#if JS_HAS_EXCEPTIONS
 
4669
    cx->throwing = JS_TRUE;
 
4670
    cx->exception = v;
 
4671
#endif
 
4672
}
 
4673
 
 
4674
JS_PUBLIC_API(void)
 
4675
JS_ClearPendingException(JSContext *cx)
 
4676
{
 
4677
#if JS_HAS_EXCEPTIONS
 
4678
    cx->throwing = JS_FALSE;
 
4679
    cx->exception = JSVAL_VOID;
 
4680
#endif
 
4681
}
 
4682
 
 
4683
JS_PUBLIC_API(JSBool)
 
4684
JS_ReportPendingException(JSContext *cx)
 
4685
{
 
4686
#if JS_HAS_EXCEPTIONS
 
4687
    JSBool save, ok;
 
4688
 
 
4689
    CHECK_REQUEST(cx);
 
4690
 
 
4691
    /*
 
4692
     * Set cx->creatingException to suppress the standard error-to-exception
 
4693
     * conversion done by all {js,JS}_Report* functions except for OOM.  The
 
4694
     * cx->creatingException flag was added to suppress recursive divergence
 
4695
     * under js_ErrorToException, but it serves for our purposes here too.
 
4696
     */
 
4697
    save = cx->creatingException;
 
4698
    cx->creatingException = JS_TRUE;
 
4699
    ok = js_ReportUncaughtException(cx);
 
4700
    cx->creatingException = save;
 
4701
    return ok;
 
4702
#else
 
4703
    return JS_TRUE;
 
4704
#endif
 
4705
}
 
4706
 
 
4707
#if JS_HAS_EXCEPTIONS
 
4708
struct JSExceptionState {
 
4709
    JSBool throwing;
 
4710
    jsval  exception;
 
4711
};
 
4712
#endif
 
4713
 
 
4714
JS_PUBLIC_API(JSExceptionState *)
 
4715
JS_SaveExceptionState(JSContext *cx)
 
4716
{
 
4717
#if JS_HAS_EXCEPTIONS
 
4718
    JSExceptionState *state;
 
4719
 
 
4720
    CHECK_REQUEST(cx);
 
4721
    state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState));
 
4722
    if (state) {
 
4723
        state->throwing = JS_GetPendingException(cx, &state->exception);
 
4724
        if (state->throwing && JSVAL_IS_GCTHING(state->exception))
 
4725
            js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
 
4726
    }
 
4727
    return state;
 
4728
#else
 
4729
    return NULL;
 
4730
#endif
 
4731
}
 
4732
 
 
4733
JS_PUBLIC_API(void)
 
4734
JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
 
4735
{
 
4736
#if JS_HAS_EXCEPTIONS
 
4737
    CHECK_REQUEST(cx);
 
4738
    if (state) {
 
4739
        if (state->throwing)
 
4740
            JS_SetPendingException(cx, state->exception);
 
4741
        else
 
4742
            JS_ClearPendingException(cx);
 
4743
        JS_DropExceptionState(cx, state);
 
4744
    }
 
4745
#endif
 
4746
}
 
4747
 
 
4748
JS_PUBLIC_API(void)
 
4749
JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
 
4750
{
 
4751
#if JS_HAS_EXCEPTIONS
 
4752
    CHECK_REQUEST(cx);
 
4753
    if (state) {
 
4754
        if (state->throwing && JSVAL_IS_GCTHING(state->exception))
 
4755
            JS_RemoveRoot(cx, &state->exception);
 
4756
        JS_free(cx, state);
 
4757
    }
 
4758
#endif
 
4759
}
 
4760
 
 
4761
JS_PUBLIC_API(JSErrorReport *)
 
4762
JS_ErrorFromException(JSContext *cx, jsval v)
 
4763
{
 
4764
#if JS_HAS_ERROR_EXCEPTIONS
 
4765
    CHECK_REQUEST(cx);
 
4766
    return js_ErrorFromException(cx, v);
 
4767
#else
 
4768
    return NULL;
 
4769
#endif
 
4770
}
 
4771
 
 
4772
JS_PUBLIC_API(JSBool)
 
4773
JS_ThrowReportedError(JSContext *cx, const char *message,
 
4774
                      JSErrorReport *reportp)
 
4775
{
 
4776
    return js_ErrorToException(cx, message, reportp);
 
4777
}
 
4778
 
 
4779
#ifdef JS_THREADSAFE
 
4780
JS_PUBLIC_API(jsword)
 
4781
JS_GetContextThread(JSContext *cx)
 
4782
{
 
4783
    return cx->thread;
 
4784
}
 
4785
 
 
4786
JS_PUBLIC_API(jsword)
 
4787
JS_SetContextThread(JSContext *cx)
 
4788
{
 
4789
    jsword old = cx->thread;
 
4790
    cx->thread = js_CurrentThreadId();
 
4791
    return old;
 
4792
}
 
4793
 
 
4794
JS_PUBLIC_API(jsword)
 
4795
JS_ClearContextThread(JSContext *cx)
 
4796
{
 
4797
    jsword old = cx->thread;
 
4798
    cx->thread = 0;
 
4799
    return old;
 
4800
}
 
4801
#endif
 
4802
 
 
4803
/************************************************************************/
 
4804
 
 
4805
#if defined(XP_WIN)
 
4806
#include <windows.h>
 
4807
/*
 
4808
 * Initialization routine for the JS DLL...
 
4809
 */
 
4810
 
 
4811
/*
 
4812
 * Global Instance handle...
 
4813
 * In Win32 this is the module handle of the DLL.
 
4814
 *
 
4815
 * In Win16 this is the instance handle of the application
 
4816
 * which loaded the DLL.
 
4817
 */
 
4818
 
 
4819
#ifdef _WIN32
 
4820
BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
 
4821
{
 
4822
    return TRUE;
 
4823
}
 
4824
 
 
4825
#else  /* !_WIN32 */
 
4826
 
 
4827
int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
 
4828
                      WORD cbHeapSize, LPSTR lpszCmdLine )
 
4829
{
 
4830
    return TRUE;
 
4831
}
 
4832
 
 
4833
BOOL CALLBACK __loadds WEP(BOOL fSystemExit)
 
4834
{
 
4835
    return TRUE;
 
4836
}
 
4837
 
 
4838
#endif /* !_WIN32 */
 
4839
#endif /* XP_WIN */