Code

r11451@tres: ted | 2006-04-17 22:21:33 -0700
[inkscape.git] / src / dom / js / jsapi.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * ***** BEGIN LICENSE BLOCK *****
4  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is Mozilla Communicator client code, released
17  * March 31, 1998.
18  *
19  * The Initial Developer of the Original Code is
20  * Netscape Communications Corporation.
21  * Portions created by the Initial Developer are Copyright (C) 1998
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either of the GNU General Public License Version 2 or later (the "GPL"),
28  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
40 /*
41  * JavaScript API.
42  */
43 #include "jsstddef.h"
44 #include <ctype.h>
45 #include <stdarg.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include "jstypes.h"
49 #include "jsarena.h" /* Added by JSIFY */
50 #include "jsutil.h" /* Added by JSIFY */
51 #include "jsclist.h"
52 #include "jsdhash.h"
53 #include "jsprf.h"
54 #include "jsapi.h"
55 #include "jsarray.h"
56 #include "jsatom.h"
57 #include "jsbool.h"
58 #include "jscntxt.h"
59 #include "jsconfig.h"
60 #include "jsdate.h"
61 #include "jsdtoa.h"
62 #include "jsemit.h"
63 #include "jsexn.h"
64 #include "jsfun.h"
65 #include "jsgc.h"
66 #include "jsinterp.h"
67 #include "jslock.h"
68 #include "jsmath.h"
69 #include "jsnum.h"
70 #include "jsobj.h"
71 #include "jsopcode.h"
72 #include "jsparse.h"
73 #include "jsregexp.h"
74 #include "jsscan.h"
75 #include "jsscope.h"
76 #include "jsscript.h"
77 #include "jsstr.h"
78 #include "prmjtime.h"
80 #if JS_HAS_FILE_OBJECT
81 #include "jsfile.h"
82 #endif
84 #ifdef HAVE_VA_LIST_AS_ARRAY
85 #define JS_ADDRESSOF_VA_LIST(ap) (ap)
86 #else
87 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
88 #endif
90 #if defined(JS_PARANOID_REQUEST) && defined(JS_THREADSAFE)
91 #define CHECK_REQUEST(cx)       JS_ASSERT(cx->requestDepth)
92 #else
93 #define CHECK_REQUEST(cx)       ((void)0)
94 #endif
96 JS_PUBLIC_API(int64)
97 JS_Now()
98 {
99     return PRMJ_Now();
102 JS_PUBLIC_API(jsval)
103 JS_GetNaNValue(JSContext *cx)
105     return DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
108 JS_PUBLIC_API(jsval)
109 JS_GetNegativeInfinityValue(JSContext *cx)
111     return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
114 JS_PUBLIC_API(jsval)
115 JS_GetPositiveInfinityValue(JSContext *cx)
117     return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
120 JS_PUBLIC_API(jsval)
121 JS_GetEmptyStringValue(JSContext *cx)
123     return STRING_TO_JSVAL(cx->runtime->emptyString);
126 static JSBool
127 TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS,
128                      jsval **vpp, va_list *app)
130     const char *format;
131     JSArgumentFormatMap *map;
133     format = *formatp;
134     for (map = cx->argumentFormatMap; map; map = map->next) {
135         if (!strncmp(format, map->format, map->length)) {
136             *formatp = format + map->length;
137             return map->formatter(cx, format, fromJS, vpp, app);
138         }
139     }
140     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
141     return JS_FALSE;
144 JS_PUBLIC_API(JSBool)
145 JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
146                     ...)
148     va_list ap;
149     JSBool ok;
151     va_start(ap, format);
152     ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
153     va_end(ap);
154     return ok;
157 JS_PUBLIC_API(JSBool)
158 JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
159                       const char *format, va_list ap)
161     jsval *sp;
162     JSBool required;
163     char c;
164     JSFunction *fun;
165     jsdouble d;
166     JSString *str;
167     JSObject *obj;
169     CHECK_REQUEST(cx);
170     sp = argv;
171     required = JS_TRUE;
172     while ((c = *format++) != '\0') {
173         if (isspace(c))
174             continue;
175         if (c == '/') {
176             required = JS_FALSE;
177             continue;
178         }
179         if (sp == argv + argc) {
180             if (required) {
181                 fun = js_ValueToFunction(cx, &argv[-2], 0);
182                 if (fun) {
183                     char numBuf[12];
184                     JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
185                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
186                                          JSMSG_MORE_ARGS_NEEDED,
187                                          JS_GetFunctionName(fun), numBuf,
188                                          (argc == 1) ? "" : "s");
189                 }
190                 return JS_FALSE;
191             }
192             break;
193         }
194         switch (c) {
195           case 'b':
196             if (!js_ValueToBoolean(cx, *sp, va_arg(ap, JSBool *)))
197                 return JS_FALSE;
198             break;
199           case 'c':
200             if (!js_ValueToUint16(cx, *sp, va_arg(ap, uint16 *)))
201                 return JS_FALSE;
202             break;
203           case 'i':
204             if (!js_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
205                 return JS_FALSE;
206             break;
207           case 'u':
208             if (!js_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
209                 return JS_FALSE;
210             break;
211           case 'j':
212             if (!js_ValueToInt32(cx, *sp, va_arg(ap, int32 *)))
213                 return JS_FALSE;
214             break;
215           case 'd':
216             if (!js_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
217                 return JS_FALSE;
218             break;
219           case 'I':
220             if (!js_ValueToNumber(cx, *sp, &d))
221                 return JS_FALSE;
222             *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
223             break;
224           case 's':
225           case 'S':
226           case 'W':
227             str = js_ValueToString(cx, *sp);
228             if (!str)
229                 return JS_FALSE;
230             *sp = STRING_TO_JSVAL(str);
231             if (c == 's')
232                 *va_arg(ap, char **) = JS_GetStringBytes(str);
233             else if (c == 'W')
234                 *va_arg(ap, jschar **) = JS_GetStringChars(str);
235             else
236                 *va_arg(ap, JSString **) = str;
237             break;
238           case 'o':
239             if (!js_ValueToObject(cx, *sp, &obj))
240                 return JS_FALSE;
241             *sp = OBJECT_TO_JSVAL(obj);
242             *va_arg(ap, JSObject **) = obj;
243             break;
244           case 'f':
245             /*
246              * Don't convert a cloned function object to its shared private
247              * data, then follow fun->object back to the clone-parent.
248              */
249             if (JSVAL_IS_FUNCTION(cx, *sp)) {
250                 fun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(*sp));
251             } else {
252                 fun = js_ValueToFunction(cx, sp, 0);
253                 if (!fun)
254                     return JS_FALSE;
255                 *sp = OBJECT_TO_JSVAL(fun->object);
256             }
257             *va_arg(ap, JSFunction **) = fun;
258             break;
259           case 'v':
260             *va_arg(ap, jsval *) = *sp;
261             break;
262           case '*':
263             break;
264           default:
265             format--;
266             if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
267                                       JS_ADDRESSOF_VA_LIST(ap))) {
268                 return JS_FALSE;
269             }
270             /* NB: the formatter already updated sp, so we continue here. */
271             continue;
272         }
273         sp++;
274     }
275     return JS_TRUE;
278 JS_PUBLIC_API(jsval *)
279 JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
281     va_list ap;
282     jsval *argv;
284     va_start(ap, format);
285     argv = JS_PushArgumentsVA(cx, markp, format, ap);
286     va_end(ap);
287     return argv;
290 JS_PUBLIC_API(jsval *)
291 JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
293     uintN argc;
294     jsval *argv, *sp;
295     char c;
296     const char *cp;
297     JSString *str;
298     JSFunction *fun;
299     JSStackHeader *sh;
301     CHECK_REQUEST(cx);
302     *markp = NULL;
303     argc = 0;
304     for (cp = format; (c = *cp) != '\0'; cp++) {
305         /*
306          * Count non-space non-star characters as individual jsval arguments.
307          * This may over-allocate stack, but we'll fix below.
308          */
309         if (isspace(c) || c == '*')
310             continue;
311         argc++;
312     }
313     sp = js_AllocStack(cx, argc, markp);
314     if (!sp)
315         return NULL;
316     argv = sp;
317     while ((c = *format++) != '\0') {
318         if (isspace(c) || c == '*')
319             continue;
320         switch (c) {
321           case 'b':
322             *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int));
323             break;
324           case 'c':
325             *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int));
326             break;
327           case 'i':
328           case 'j':
329             if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
330                 goto bad;
331             break;
332           case 'u':
333             if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
334                 goto bad;
335             break;
336           case 'd':
337           case 'I':
338             if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
339                 goto bad;
340             break;
341           case 's':
342             str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
343             if (!str)
344                 goto bad;
345             *sp = STRING_TO_JSVAL(str);
346             break;
347           case 'W':
348             str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
349             if (!str)
350                 goto bad;
351             *sp = STRING_TO_JSVAL(str);
352             break;
353           case 'S':
354             str = va_arg(ap, JSString *);
355             *sp = STRING_TO_JSVAL(str);
356             break;
357           case 'o':
358             *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
359             break;
360           case 'f':
361             fun = va_arg(ap, JSFunction *);
362             *sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
363             break;
364           case 'v':
365             *sp = va_arg(ap, jsval);
366             break;
367           default:
368             format--;
369             if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp,
370                                       JS_ADDRESSOF_VA_LIST(ap))) {
371                 goto bad;
372             }
373             /* NB: the formatter already updated sp, so we continue here. */
374             continue;
375         }
376         sp++;
377     }
379     /*
380      * We may have overallocated stack due to a multi-character format code
381      * handled by a JSArgumentFormatter.  Give back that stack space!
382      */
383     JS_ASSERT(sp <= argv + argc);
384     if (sp < argv + argc) {
385         /* Return slots not pushed to the current stack arena. */
386         cx->stackPool.current->avail = (jsuword)sp;
388         /* Reduce the count of slots the GC will scan in this stack segment. */
389         sh = cx->stackHeaders;
390         JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc);
391         sh->nslots -= argc - (sp - argv);
392     }
393     return argv;
395 bad:
396     js_FreeStack(cx, *markp);
397     return NULL;
400 JS_PUBLIC_API(void)
401 JS_PopArguments(JSContext *cx, void *mark)
403     CHECK_REQUEST(cx);
404     js_FreeStack(cx, mark);
407 JS_PUBLIC_API(JSBool)
408 JS_AddArgumentFormatter(JSContext *cx, const char *format,
409                         JSArgumentFormatter formatter)
411     size_t length;
412     JSArgumentFormatMap **mpp, *map;
414     length = strlen(format);
415     mpp = &cx->argumentFormatMap;
416     while ((map = *mpp) != NULL) {
417         /* Insert before any shorter string to match before prefixes. */
418         if (map->length < length)
419             break;
420         if (map->length == length && !strcmp(map->format, format))
421             goto out;
422         mpp = &map->next;
423     }
424     map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map);
425     if (!map)
426         return JS_FALSE;
427     map->format = format;
428     map->length = length;
429     map->next = *mpp;
430     *mpp = map;
431 out:
432     map->formatter = formatter;
433     return JS_TRUE;
436 JS_PUBLIC_API(void)
437 JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
439     size_t length;
440     JSArgumentFormatMap **mpp, *map;
442     length = strlen(format);
443     mpp = &cx->argumentFormatMap;
444     while ((map = *mpp) != NULL) {
445         if (map->length == length && !strcmp(map->format, format)) {
446             *mpp = map->next;
447             JS_free(cx, map);
448             return;
449         }
450         mpp = &map->next;
451     }
454 JS_PUBLIC_API(JSBool)
455 JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
457     JSBool ok, b;
458     JSObject *obj;
459     JSFunction *fun;
460     JSString *str;
461     jsdouble d, *dp;
463     CHECK_REQUEST(cx);
464     switch (type) {
465       case JSTYPE_VOID:
466         *vp = JSVAL_VOID;
467         ok = JS_TRUE;
468         break;
469       case JSTYPE_OBJECT:
470         ok = js_ValueToObject(cx, v, &obj);
471         if (ok)
472             *vp = OBJECT_TO_JSVAL(obj);
473         break;
474       case JSTYPE_FUNCTION:
475         /*
476          * Don't convert a cloned function object to its shared private data,
477          * then follow fun->object back to the clone-parent.
478          */
479         if (JSVAL_IS_FUNCTION(cx, v)) {
480             ok = JS_TRUE;
481             *vp = v;
482         } else {
483             fun = js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
484             ok = (fun != NULL);
485             if (ok)
486                 *vp = OBJECT_TO_JSVAL(fun->object);
487         }
488         break;
489       case JSTYPE_STRING:
490         str = js_ValueToString(cx, v);
491         ok = (str != NULL);
492         if (ok)
493             *vp = STRING_TO_JSVAL(str);
494         break;
495       case JSTYPE_NUMBER:
496         ok = js_ValueToNumber(cx, v, &d);
497         if (ok) {
498             dp = js_NewDouble(cx, d);
499             ok = (dp != NULL);
500             if (ok)
501                 *vp = DOUBLE_TO_JSVAL(dp);
502         }
503         break;
504       case JSTYPE_BOOLEAN:
505         ok = js_ValueToBoolean(cx, v, &b);
506         if (ok)
507             *vp = BOOLEAN_TO_JSVAL(b);
508         break;
509       default: {
510         char numBuf[12];
511         JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
512         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE,
513                              numBuf);
514         ok = JS_FALSE;
515         break;
516       }
517     }
518     return ok;
521 JS_PUBLIC_API(JSBool)
522 JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
524     CHECK_REQUEST(cx);
525     return js_ValueToObject(cx, v, objp);
528 JS_PUBLIC_API(JSFunction *)
529 JS_ValueToFunction(JSContext *cx, jsval v)
531     CHECK_REQUEST(cx);
532     return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
535 JS_PUBLIC_API(JSFunction *)
536 JS_ValueToConstructor(JSContext *cx, jsval v)
538     CHECK_REQUEST(cx);
539     return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
542 JS_PUBLIC_API(JSString *)
543 JS_ValueToString(JSContext *cx, jsval v)
545     CHECK_REQUEST(cx);
546     return js_ValueToString(cx, v);
549 JS_PUBLIC_API(JSBool)
550 JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
552     CHECK_REQUEST(cx);
553     return js_ValueToNumber(cx, v, dp);
556 JS_PUBLIC_API(JSBool)
557 JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
559     CHECK_REQUEST(cx);
560     return js_ValueToECMAInt32(cx, v, ip);
563 JS_PUBLIC_API(JSBool)
564 JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
566     CHECK_REQUEST(cx);
567     return js_ValueToECMAUint32(cx, v, ip);
570 JS_PUBLIC_API(JSBool)
571 JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
573     CHECK_REQUEST(cx);
574     return js_ValueToInt32(cx, v, ip);
577 JS_PUBLIC_API(JSBool)
578 JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
580     CHECK_REQUEST(cx);
581     return js_ValueToUint16(cx, v, ip);
584 JS_PUBLIC_API(JSBool)
585 JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
587     CHECK_REQUEST(cx);
588     return js_ValueToBoolean(cx, v, bp);
591 JS_PUBLIC_API(JSType)
592 JS_TypeOfValue(JSContext *cx, jsval v)
594     JSType type;
595     JSObject *obj;
596     JSObjectOps *ops;
597     JSClass *clasp;
599     CHECK_REQUEST(cx);
600     if (JSVAL_IS_OBJECT(v)) {
601         /* XXX JSVAL_IS_OBJECT(v) is true for null too! Can we change ECMA? */
602         obj = JSVAL_TO_OBJECT(v);
603         if (obj &&
604             (ops = obj->map->ops,
605              ops == &js_ObjectOps
606              ? (clasp = OBJ_GET_CLASS(cx, obj),
607                 clasp->call || clasp == &js_FunctionClass)
608              : ops->call != NULL)) {
609             type = JSTYPE_FUNCTION;
610         } else {
611 #ifdef NARCISSUS
612             if (obj) {
613                 /* XXX suppress errors/exceptions */
614                 OBJ_GET_PROPERTY(cx, obj,
615                                  (jsid)cx->runtime->atomState.callAtom,
616                                  &v);
617                 if (JSVAL_IS_FUNCTION(cx, v))
618                     return JSTYPE_FUNCTION;
619             }
620 #endif
621             type = JSTYPE_OBJECT;
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;
635 JS_PUBLIC_API(const char *)
636 JS_GetTypeName(JSContext *cx, JSType type)
638     if ((uintN)type >= (uintN)JSTYPE_LIMIT)
639         return NULL;
640     return js_type_str[type];
643 /************************************************************************/
645 JS_PUBLIC_API(JSRuntime *)
646 JS_NewRuntime(uint32 maxbytes)
648     JSRuntime *rt;
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 */
666     if (!js_InitStringGlobals())
667         return NULL;
668     rt = (JSRuntime *) malloc(sizeof(JSRuntime));
669     if (!rt)
670         return NULL;
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);
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     js_SetupLocks(8, 16);       /* this is asymmetric with JS_ShutDown. */
691     rt->rtLock = JS_NEW_LOCK();
692     if (!rt->rtLock)
693         goto bad;
694     rt->stateChange = JS_NEW_CONDVAR(rt->gcLock);
695     if (!rt->stateChange)
696         goto bad;
697     rt->setSlotLock = JS_NEW_LOCK();
698     if (!rt->setSlotLock)
699         goto bad;
700     rt->setSlotDone = JS_NEW_CONDVAR(rt->setSlotLock);
701     if (!rt->setSlotDone)
702         goto bad;
703     rt->scopeSharingDone = JS_NEW_CONDVAR(rt->gcLock);
704     if (!rt->scopeSharingDone)
705         goto bad;
706     rt->scopeSharingTodo = NO_SCOPE_SHARING_TODO;
707 #endif
708     rt->propertyCache.empty = JS_TRUE;
709     if (!js_InitPropertyTree(rt))
710         goto bad;
711     return rt;
713 bad:
714     JS_DestroyRuntime(rt);
715     return NULL;
718 JS_PUBLIC_API(void)
719 JS_DestroyRuntime(JSRuntime *rt)
721 #ifdef DEBUG
722     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
723     if (!JS_CLIST_IS_EMPTY(&rt->contextList)) {
724         JSContext *cx, *iter = NULL;
725         uintN cxcount = 0;
726         while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL)
727             cxcount++;
728         fprintf(stderr,
729 "JS API usage error: %u contexts left in runtime upon JS_DestroyRuntime.\n",
730                 cxcount);
731     }
732 #endif
734     js_FinishAtomState(&rt->atomState);
735     js_FinishGC(rt);
736 #ifdef JS_THREADSAFE
737     if (rt->gcLock)
738         JS_DESTROY_LOCK(rt->gcLock);
739     if (rt->gcDone)
740         JS_DESTROY_CONDVAR(rt->gcDone);
741     if (rt->requestDone)
742         JS_DESTROY_CONDVAR(rt->requestDone);
743     if (rt->rtLock)
744         JS_DESTROY_LOCK(rt->rtLock);
745     if (rt->stateChange)
746         JS_DESTROY_CONDVAR(rt->stateChange);
747     if (rt->setSlotLock)
748         JS_DESTROY_LOCK(rt->setSlotLock);
749     if (rt->setSlotDone)
750         JS_DESTROY_CONDVAR(rt->setSlotDone);
751     if (rt->scopeSharingDone)
752         JS_DESTROY_CONDVAR(rt->scopeSharingDone);
753 #endif
754     js_FinishPropertyTree(rt);
755     free(rt);
758 JS_PUBLIC_API(void)
759 JS_ShutDown(void)
761     JS_ArenaShutDown();
762     js_FinishDtoa();
763     js_FreeStringGlobals();
764 #ifdef JS_THREADSAFE
765     js_CleanupLocks();
766 #endif
769 JS_PUBLIC_API(void *)
770 JS_GetRuntimePrivate(JSRuntime *rt)
772     return rt->data;
775 JS_PUBLIC_API(void)
776 JS_SetRuntimePrivate(JSRuntime *rt, void *data)
778     rt->data = data;
781 #ifdef JS_THREADSAFE
783 JS_PUBLIC_API(void)
784 JS_BeginRequest(JSContext *cx)
786     JSRuntime *rt;
788     JS_ASSERT(cx->thread);
789     if (!cx->requestDepth) {
790         /* Wait until the GC is finished. */
791         rt = cx->runtime;
792         JS_LOCK_GC(rt);
794         /* NB: we use cx->thread here, not js_CurrentThreadId(). */
795         if (rt->gcThread != cx->thread) {
796             while (rt->gcLevel > 0)
797                 JS_AWAIT_GC_DONE(rt);
798         }
800         /* Indicate that a request is running. */
801         rt->requestCount++;
802         cx->requestDepth = 1;
803         JS_UNLOCK_GC(rt);
804         return;
805     }
806     cx->requestDepth++;
809 JS_PUBLIC_API(void)
810 JS_EndRequest(JSContext *cx)
812     JSRuntime *rt;
813     JSScope *scope, **todop;
814     uintN nshares;
816     CHECK_REQUEST(cx);
817     JS_ASSERT(cx->requestDepth > 0);
818     if (cx->requestDepth == 1) {
819         /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
820         rt = cx->runtime;
821         JS_LOCK_GC(rt);
822         cx->requestDepth = 0;
824         /* See whether cx has any single-threaded scopes to start sharing. */
825         todop = &rt->scopeSharingTodo;
826         nshares = 0;
827         while ((scope = *todop) != NO_SCOPE_SHARING_TODO) {
828             if (scope->ownercx != cx) {
829                 todop = &scope->u.link;
830                 continue;
831             }
832             *todop = scope->u.link;
833             scope->u.link = NULL;       /* null u.link for sanity ASAP */
835             /*
836              * If js_DropObjectMap returns null, we held the last ref to scope.
837              * The waiting thread(s) must have been killed, after which the GC
838              * collected the object that held this scope.  Unlikely, because it
839              * requires that the GC ran (e.g., from a branch callback) during
840              * this request, but possible.
841              */
842             if (js_DropObjectMap(cx, &scope->map, NULL)) {
843                 js_InitLock(&scope->lock);
844                 scope->u.count = 0;                 /* NULL may not pun as 0 */
845                 js_FinishSharingScope(rt, scope);   /* set ownercx = NULL */
846                 nshares++;
847             }
848         }
849         if (nshares)
850             JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone);
852         /* Give the GC a chance to run if this was the last request running. */
853         JS_ASSERT(rt->requestCount > 0);
854         rt->requestCount--;
855         if (rt->requestCount == 0)
856             JS_NOTIFY_REQUEST_DONE(rt);
858         JS_UNLOCK_GC(rt);
859         return;
860     }
862     cx->requestDepth--;
865 /* Yield to pending GC operations, regardless of request depth */
866 JS_PUBLIC_API(void)
867 JS_YieldRequest(JSContext *cx)
869     JSRuntime *rt;
871     JS_ASSERT(cx->thread);
872     CHECK_REQUEST(cx);
874     rt = cx->runtime;
875     JS_LOCK_GC(rt);
876     JS_ASSERT(rt->requestCount > 0);
877     rt->requestCount--;
878     if (rt->requestCount == 0)
879         JS_NOTIFY_REQUEST_DONE(rt);
880     JS_UNLOCK_GC(rt);
881     /* XXXbe give the GC or another request calling it a chance to run here?
882              Assumes FIFO scheduling */
883     JS_LOCK_GC(rt);
884     rt->requestCount++;
885     JS_UNLOCK_GC(rt);
888 JS_PUBLIC_API(jsrefcount)
889 JS_SuspendRequest(JSContext *cx)
891     jsrefcount saveDepth = cx->requestDepth;
893     while (cx->requestDepth)
894         JS_EndRequest(cx);
895     return saveDepth;
898 JS_PUBLIC_API(void)
899 JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
901     JS_ASSERT(!cx->requestDepth);
902     while (--saveDepth >= 0)
903         JS_BeginRequest(cx);
906 #endif /* JS_THREADSAFE */
908 JS_PUBLIC_API(void)
909 JS_Lock(JSRuntime *rt)
911     JS_LOCK_RUNTIME(rt);
914 JS_PUBLIC_API(void)
915 JS_Unlock(JSRuntime *rt)
917     JS_UNLOCK_RUNTIME(rt);
920 JS_PUBLIC_API(JSContext *)
921 JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
923     return js_NewContext(rt, stackChunkSize);
926 JS_PUBLIC_API(void)
927 JS_DestroyContext(JSContext *cx)
929     js_DestroyContext(cx, JS_FORCE_GC);
932 JS_PUBLIC_API(void)
933 JS_DestroyContextNoGC(JSContext *cx)
935     js_DestroyContext(cx, JS_NO_GC);
938 JS_PUBLIC_API(void)
939 JS_DestroyContextMaybeGC(JSContext *cx)
941     js_DestroyContext(cx, JS_MAYBE_GC);
944 JS_PUBLIC_API(void *)
945 JS_GetContextPrivate(JSContext *cx)
947     return cx->data;
950 JS_PUBLIC_API(void)
951 JS_SetContextPrivate(JSContext *cx, void *data)
953     cx->data = data;
956 JS_PUBLIC_API(JSRuntime *)
957 JS_GetRuntime(JSContext *cx)
959     return cx->runtime;
962 JS_PUBLIC_API(JSContext *)
963 JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
965     return js_ContextIterator(rt, JS_TRUE, iterp);
968 JS_PUBLIC_API(JSVersion)
969 JS_GetVersion(JSContext *cx)
971     return cx->version;
974 JS_PUBLIC_API(JSVersion)
975 JS_SetVersion(JSContext *cx, JSVersion version)
977     JSVersion oldVersion;
979     oldVersion = cx->version;
980     if (version == oldVersion)
981         return oldVersion;
983     cx->version = version;
985 #if !JS_BUG_FALLIBLE_EQOPS
986     if (cx->version == JSVERSION_1_2) {
987         cx->jsop_eq = JSOP_NEW_EQ;
988         cx->jsop_ne = JSOP_NEW_NE;
989     } else {
990         cx->jsop_eq = JSOP_EQ;
991         cx->jsop_ne = JSOP_NE;
992     }
993 #endif /* !JS_BUG_FALLIBLE_EQOPS */
995     return oldVersion;
998 static struct v2smap {
999     JSVersion   version;
1000     const char  *string;
1001 } v2smap[] = {
1002     {JSVERSION_1_0,     "1.0"},
1003     {JSVERSION_1_1,     "1.1"},
1004     {JSVERSION_1_2,     "1.2"},
1005     {JSVERSION_1_3,     "1.3"},
1006     {JSVERSION_1_4,     "1.4"},
1007     {JSVERSION_ECMA_3,  "ECMAv3"},
1008     {JSVERSION_1_5,     "1.5"},
1009     {JSVERSION_DEFAULT, "default"},
1010     {JSVERSION_UNKNOWN, NULL},          /* must be last, NULL is sentinel */
1011 };
1013 JS_PUBLIC_API(const char *)
1014 JS_VersionToString(JSVersion version)
1016     int i;
1018     for (i = 0; v2smap[i].string; i++)
1019         if (v2smap[i].version == version)
1020             return v2smap[i].string;
1021     return "unknown";
1024 JS_PUBLIC_API(JSVersion)
1025 JS_StringToVersion(const char *string)
1027     int i;
1029     for (i = 0; v2smap[i].string; i++)
1030         if (strcmp(v2smap[i].string, string) == 0)
1031             return v2smap[i].version;
1032     return JSVERSION_UNKNOWN;
1035 JS_PUBLIC_API(uint32)
1036 JS_GetOptions(JSContext *cx)
1038     return cx->options;
1041 JS_PUBLIC_API(uint32)
1042 JS_SetOptions(JSContext *cx, uint32 options)
1044     uint32 oldopts = cx->options;
1045     cx->options = options;
1046     return oldopts;
1049 JS_PUBLIC_API(uint32)
1050 JS_ToggleOptions(JSContext *cx, uint32 options)
1052     uint32 oldopts = cx->options;
1053     cx->options ^= options;
1054     return oldopts;
1057 JS_PUBLIC_API(const char *)
1058 JS_GetImplementationVersion(void)
1060     return "JavaScript-C 1.5 2004-09-24";
1064 JS_PUBLIC_API(JSObject *)
1065 JS_GetGlobalObject(JSContext *cx)
1067     return cx->globalObject;
1070 JS_PUBLIC_API(void)
1071 JS_SetGlobalObject(JSContext *cx, JSObject *obj)
1073     cx->globalObject = obj;
1076 static JSObject *
1077 InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
1079     JSDHashTable *table;
1080     JSBool resolving;
1081     JSRuntime *rt;
1082     JSResolvingKey key;
1083     JSResolvingEntry *entry;
1084     JSObject *fun_proto, *obj_proto;
1086     /* If cx has no global object, use obj so prototypes can be found. */
1087     if (!cx->globalObject)
1088         cx->globalObject = obj;
1090     /* Record Function and Object in cx->resolvingTable, if we are resolving. */
1091     table = cx->resolvingTable;
1092     resolving = (table && table->entryCount);
1093     if (resolving) {
1094         rt = cx->runtime;
1095         key.obj = obj;
1096         key.id = (jsid) rt->atomState.FunctionAtom;
1097         entry = (JSResolvingEntry *)
1098                 JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
1099         if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) {
1100             /* Already resolving Function, record Object too. */
1101             JS_ASSERT(entry->key.obj == obj);
1102             key.id = (jsid) rt->atomState.ObjectAtom;
1103             entry = (JSResolvingEntry *)
1104                     JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
1105         }
1106         if (!entry) {
1107             JS_ReportOutOfMemory(cx);
1108             return NULL;
1109         }
1110         JS_ASSERT(!entry->key.obj && entry->flags == 0);
1111         entry->key = key;
1112         entry->flags = JSRESFLAG_LOOKUP;
1113     }
1115     /* Initialize the function class first so constructors can be made. */
1116     fun_proto = js_InitFunctionClass(cx, obj);
1117     if (!fun_proto)
1118         goto out;
1120     /* Initialize the object class next so Object.prototype works. */
1121     obj_proto = js_InitObjectClass(cx, obj);
1122     if (!obj_proto) {
1123         fun_proto = NULL;
1124         goto out;
1125     }
1127     /* Function.prototype and the global object delegate to Object.prototype. */
1128     OBJ_SET_PROTO(cx, fun_proto, obj_proto);
1129     if (!OBJ_GET_PROTO(cx, obj))
1130         OBJ_SET_PROTO(cx, obj, obj_proto);
1132 out:
1133     /* If resolving, remove the other entry (Object or Function) from table. */
1134     if (resolving)
1135         JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
1136     return fun_proto;
1139 JS_PUBLIC_API(JSBool)
1140 JS_InitStandardClasses(JSContext *cx, JSObject *obj)
1142     CHECK_REQUEST(cx);
1144 #if JS_HAS_UNDEFINED
1146     /* Define a top-level property 'undefined' with the undefined value. */
1147     JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
1148     if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
1149                              JSPROP_PERMANENT, NULL)) {
1150         return JS_FALSE;
1151     }
1153 #endif
1155     /* Function and Object require cooperative bootstrapping magic. */
1156     if (!InitFunctionAndObjectClasses(cx, obj))
1157         return JS_FALSE;
1159     /* Initialize the rest of the standard objects and functions. */
1160     return js_InitArrayClass(cx, obj) &&
1161            js_InitBooleanClass(cx, obj) &&
1162            js_InitMathClass(cx, obj) &&
1163            js_InitNumberClass(cx, obj) &&
1164            js_InitStringClass(cx, obj) &&
1165 #if JS_HAS_CALL_OBJECT
1166            js_InitCallClass(cx, obj) &&
1167 #endif
1168 #if JS_HAS_REGEXPS
1169            js_InitRegExpClass(cx, obj) &&
1170 #endif
1171 #if JS_HAS_SCRIPT_OBJECT
1172            js_InitScriptClass(cx, obj) &&
1173 #endif
1174 #if JS_HAS_ERROR_EXCEPTIONS
1175            js_InitExceptionClasses(cx, obj) &&
1176 #endif
1177 #if JS_HAS_FILE_OBJECT
1178            js_InitFileClass(cx, obj, JS_TRUE) &&
1179 #endif
1180            js_InitDateClass(cx, obj);
1183 #define ATOM_OFFSET(name)       offsetof(JSAtomState, name##Atom)
1184 #define OFFSET_TO_ATOM(rt,off)  (*(JSAtom **)((char*)&(rt)->atomState + (off)))
1186 /*
1187  * Table of class initializers and their atom offsets in rt->atomState.
1188  * If you add a "standard" class, remember to update this table.
1189  */
1190 static struct {
1191     JSObjectOp  init;
1192     size_t      atomOffset;
1193 } standard_class_atoms[] = {
1194     {InitFunctionAndObjectClasses,  ATOM_OFFSET(Function)},
1195     {InitFunctionAndObjectClasses,  ATOM_OFFSET(Object)},
1196     {js_InitArrayClass,             ATOM_OFFSET(Array)},
1197     {js_InitBooleanClass,           ATOM_OFFSET(Boolean)},
1198     {js_InitDateClass,              ATOM_OFFSET(Date)},
1199     {js_InitMathClass,              ATOM_OFFSET(Math)},
1200     {js_InitNumberClass,            ATOM_OFFSET(Number)},
1201     {js_InitStringClass,            ATOM_OFFSET(String)},
1202 #if JS_HAS_CALL_OBJECT
1203     {js_InitCallClass,              ATOM_OFFSET(Call)},
1204 #endif
1205 #if JS_HAS_ERROR_EXCEPTIONS
1206     {js_InitExceptionClasses,       ATOM_OFFSET(Error)},
1207 #endif
1208 #if JS_HAS_REGEXPS
1209     {js_InitRegExpClass,            ATOM_OFFSET(RegExp)},
1210 #endif
1211 #if JS_HAS_SCRIPT_OBJECT
1212     {js_InitScriptClass,            ATOM_OFFSET(Script)},
1213 #endif
1214     {NULL,                          0}
1215 };
1217 /*
1218  * Table of top-level function and constant names and their init functions.
1219  * If you add a "standard" global function or property, remember to update
1220  * this table.
1221  */
1222 typedef struct JSStdName {
1223     JSObjectOp  init;
1224     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
1225     const char  *name;          /* null if atom is pre-pinned, else name */
1226 } JSStdName;
1228 static JSAtom *
1229 StdNameToAtom(JSContext *cx, JSStdName *stdn)
1231     size_t offset;
1232     JSAtom *atom;
1233     const char *name;
1235     offset = stdn->atomOffset;
1236     atom = OFFSET_TO_ATOM(cx->runtime, offset);
1237     if (!atom) {
1238         name = stdn->name;
1239         if (name) {
1240             atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED);
1241             OFFSET_TO_ATOM(cx->runtime, offset) = atom;
1242         }
1243     }
1244     return atom;
1247 #define EAGERLY_PINNED_ATOM(name)   ATOM_OFFSET(name), NULL
1248 #define LAZILY_PINNED_ATOM(name)    ATOM_OFFSET(lazy.name), js_##name##_str
1250 static JSStdName standard_class_names[] = {
1251     /* ECMA requires that eval be a direct property of the global object. */
1252     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(eval)},
1254     /* Global properties and functions defined by the Number class. */
1255     {js_InitNumberClass,        LAZILY_PINNED_ATOM(NaN)},
1256     {js_InitNumberClass,        LAZILY_PINNED_ATOM(Infinity)},
1257     {js_InitNumberClass,        LAZILY_PINNED_ATOM(isNaN)},
1258     {js_InitNumberClass,        LAZILY_PINNED_ATOM(isFinite)},
1259     {js_InitNumberClass,        LAZILY_PINNED_ATOM(parseFloat)},
1260     {js_InitNumberClass,        LAZILY_PINNED_ATOM(parseInt)},
1262     /* String global functions. */
1263     {js_InitStringClass,        LAZILY_PINNED_ATOM(escape)},
1264     {js_InitStringClass,        LAZILY_PINNED_ATOM(unescape)},
1265     {js_InitStringClass,        LAZILY_PINNED_ATOM(decodeURI)},
1266     {js_InitStringClass,        LAZILY_PINNED_ATOM(encodeURI)},
1267     {js_InitStringClass,        LAZILY_PINNED_ATOM(decodeURIComponent)},
1268     {js_InitStringClass,        LAZILY_PINNED_ATOM(encodeURIComponent)},
1269 #if JS_HAS_UNEVAL
1270     {js_InitStringClass,        LAZILY_PINNED_ATOM(uneval)},
1271 #endif
1273     /* Exception constructors. */
1274 #if JS_HAS_ERROR_EXCEPTIONS
1275     {js_InitExceptionClasses,   EAGERLY_PINNED_ATOM(Error)},
1276     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(InternalError)},
1277     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(EvalError)},
1278     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(RangeError)},
1279     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(ReferenceError)},
1280     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(SyntaxError)},
1281     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(TypeError)},
1282     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(URIError)},
1283 #endif
1285     {NULL,                      0, NULL}
1286 };
1288 static JSStdName object_prototype_names[] = {
1289     /* Object.prototype properties (global delegates to Object.prototype). */
1290     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(proto)},
1291     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(parent)},
1292     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(count)},
1293 #if JS_HAS_TOSOURCE
1294     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toSource)},
1295 #endif
1296     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toString)},
1297     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toLocaleString)},
1298     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(valueOf)},
1299 #if JS_HAS_OBJ_WATCHPOINT
1300     {js_InitObjectClass,        LAZILY_PINNED_ATOM(watch)},
1301     {js_InitObjectClass,        LAZILY_PINNED_ATOM(unwatch)},
1302 #endif
1303 #if JS_HAS_NEW_OBJ_METHODS
1304     {js_InitObjectClass,        LAZILY_PINNED_ATOM(hasOwnProperty)},
1305     {js_InitObjectClass,        LAZILY_PINNED_ATOM(isPrototypeOf)},
1306     {js_InitObjectClass,        LAZILY_PINNED_ATOM(propertyIsEnumerable)},
1307 #endif
1308 #if JS_HAS_GETTER_SETTER
1309     {js_InitObjectClass,        LAZILY_PINNED_ATOM(defineGetter)},
1310     {js_InitObjectClass,        LAZILY_PINNED_ATOM(defineSetter)},
1311     {js_InitObjectClass,        LAZILY_PINNED_ATOM(lookupGetter)},
1312     {js_InitObjectClass,        LAZILY_PINNED_ATOM(lookupSetter)},
1313 #endif
1315     {NULL,                      0, NULL}
1316 };
1318 #undef EAGERLY_PINNED_ATOM
1319 #undef LAZILY_PINNED_ATOM
1321 JS_PUBLIC_API(JSBool)
1322 JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
1323                         JSBool *resolved)
1325     JSString *idstr;
1326     JSRuntime *rt;
1327     JSAtom *atom;
1328     JSObjectOp init;
1329     uintN i;
1331     CHECK_REQUEST(cx);
1332     *resolved = JS_FALSE;
1334     if (!JSVAL_IS_STRING(id))
1335         return JS_TRUE;
1336     idstr = JSVAL_TO_STRING(id);
1337     rt = cx->runtime;
1339 #if JS_HAS_UNDEFINED
1340     /* See if we're resolving 'undefined', and define it if so. */
1341     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1342     if (idstr == ATOM_TO_STRING(atom)) {
1343         *resolved = JS_TRUE;
1344         return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
1345                                    JSPROP_PERMANENT, NULL);
1346     }
1347 #endif
1349     /* Try for class constructors/prototypes named by well-known atoms. */
1350     init = NULL;
1351     for (i = 0; standard_class_atoms[i].init; i++) {
1352         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
1353         if (idstr == ATOM_TO_STRING(atom)) {
1354             init = standard_class_atoms[i].init;
1355             break;
1356         }
1357     }
1359     if (!init) {
1360         /* Try less frequently used top-level functions and constants. */
1361         for (i = 0; standard_class_names[i].init; i++) {
1362             atom = StdNameToAtom(cx, &standard_class_names[i]);
1363             if (!atom)
1364                 return JS_FALSE;
1365             if (idstr == ATOM_TO_STRING(atom)) {
1366                 init = standard_class_names[i].init;
1367                 break;
1368             }
1369         }
1371         if (!init && !OBJ_GET_PROTO(cx, obj)) {
1372             /*
1373              * Try even less frequently used names delegated from the global
1374              * object to Object.prototype, but only if the Object class hasn't
1375              * yet been initialized.
1376              */
1377             for (i = 0; object_prototype_names[i].init; i++) {
1378                 atom = StdNameToAtom(cx, &object_prototype_names[i]);
1379                 if (!atom)
1380                     return JS_FALSE;
1381                 if (idstr == ATOM_TO_STRING(atom)) {
1382                     init = standard_class_names[i].init;
1383                     break;
1384                 }
1385             }
1386         }
1387     }
1389     if (init) {
1390         if (!init(cx, obj))
1391             return JS_FALSE;
1392         *resolved = JS_TRUE;
1393     }
1394     return JS_TRUE;
1397 static JSBool
1398 HasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom, JSBool *ownp)
1400     JSObject *pobj;
1401     JSProperty *prop;
1403     if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &pobj, &prop))
1404         return JS_FALSE;
1405     if (prop)
1406         OBJ_DROP_PROPERTY(cx, pobj, prop);
1407     *ownp = (pobj == obj && prop);
1408     return JS_TRUE;
1411 JS_PUBLIC_API(JSBool)
1412 JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
1414     JSRuntime *rt;
1415     JSAtom *atom;
1416     JSBool found;
1417     uintN i;
1419     CHECK_REQUEST(cx);
1420     rt = cx->runtime;
1422 #if JS_HAS_UNDEFINED
1423     /* See if we need to bind 'undefined' and define it if so. */
1424     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1425     if (!HasOwnProperty(cx, obj, atom, &found))
1426         return JS_FALSE;
1427     if (!found &&
1428         !OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
1429                             JSPROP_PERMANENT, NULL)) {
1430         return JS_FALSE;
1431     }
1432 #endif
1434     /* Initialize any classes that have not been resolved yet. */
1435     for (i = 0; standard_class_atoms[i].init; i++) {
1436         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
1437         if (!HasOwnProperty(cx, obj, atom, &found))
1438             return JS_FALSE;
1439         if (!found && !standard_class_atoms[i].init(cx, obj))
1440             return JS_FALSE;
1441     }
1443     return JS_TRUE;
1446 #undef ATOM_OFFSET
1447 #undef OFFSET_TO_ATOM
1449 JS_PUBLIC_API(JSObject *)
1450 JS_GetScopeChain(JSContext *cx)
1452     return cx->fp ? cx->fp->scopeChain : NULL;
1455 JS_PUBLIC_API(void *)
1456 JS_malloc(JSContext *cx, size_t nbytes)
1458     void *p;
1460     JS_ASSERT(nbytes != 0);
1461     if (nbytes == 0)
1462         nbytes = 1;
1463     cx->runtime->gcMallocBytes += nbytes;
1464     p = malloc(nbytes);
1465     if (!p)
1466         JS_ReportOutOfMemory(cx);
1467     return p;
1470 JS_PUBLIC_API(void *)
1471 JS_realloc(JSContext *cx, void *p, size_t nbytes)
1473     p = realloc(p, nbytes);
1474     if (!p)
1475         JS_ReportOutOfMemory(cx);
1476     return p;
1479 JS_PUBLIC_API(void)
1480 JS_free(JSContext *cx, void *p)
1482     if (p)
1483         free(p);
1486 JS_PUBLIC_API(char *)
1487 JS_strdup(JSContext *cx, const char *s)
1489     size_t n;
1490     void *p;
1492     n = strlen(s) + 1;
1493     p = JS_malloc(cx, n);
1494     if (!p)
1495         return NULL;
1496     return (char *)memcpy(p, s, n);
1499 JS_PUBLIC_API(jsdouble *)
1500 JS_NewDouble(JSContext *cx, jsdouble d)
1502     CHECK_REQUEST(cx);
1503     return js_NewDouble(cx, d);
1506 JS_PUBLIC_API(JSBool)
1507 JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
1509     CHECK_REQUEST(cx);
1510     return js_NewDoubleValue(cx, d, rval);
1513 JS_PUBLIC_API(JSBool)
1514 JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
1516     CHECK_REQUEST(cx);
1517     return js_NewNumberValue(cx, d, rval);
1520 #undef JS_AddRoot
1521 JS_PUBLIC_API(JSBool)
1522 JS_AddRoot(JSContext *cx, void *rp)
1524     CHECK_REQUEST(cx);
1525     return js_AddRoot(cx, rp, NULL);
1528 JS_PUBLIC_API(JSBool)
1529 JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name)
1531     return js_AddRootRT(rt, rp, name);
1534 JS_PUBLIC_API(JSBool)
1535 JS_RemoveRoot(JSContext *cx, void *rp)
1537     CHECK_REQUEST(cx);
1538     return js_RemoveRoot(cx->runtime, rp);
1541 JS_PUBLIC_API(JSBool)
1542 JS_RemoveRootRT(JSRuntime *rt, void *rp)
1544     return js_RemoveRoot(rt, rp);
1547 JS_PUBLIC_API(JSBool)
1548 JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
1550     CHECK_REQUEST(cx);
1551     return js_AddRoot(cx, rp, name);
1554 JS_PUBLIC_API(void)
1555 JS_ClearNewbornRoots(JSContext *cx)
1557     uintN i;
1559     for (i = 0; i < GCX_NTYPES; i++)
1560         cx->newborn[i] = NULL;
1561     cx->lastAtom = NULL;
1564 JS_PUBLIC_API(JSBool)
1565 JS_EnterLocalRootScope(JSContext *cx)
1567     CHECK_REQUEST(cx);
1568     return js_EnterLocalRootScope(cx);
1571 JS_PUBLIC_API(void)
1572 JS_LeaveLocalRootScope(JSContext *cx)
1574     CHECK_REQUEST(cx);
1575     js_LeaveLocalRootScope(cx);
1578 JS_PUBLIC_API(void)
1579 JS_ForgetLocalRoot(JSContext *cx, void *thing)
1581     CHECK_REQUEST(cx);
1582     js_ForgetLocalRoot(cx, (jsval) thing);
1585 #include "jshash.h" /* Added by JSIFY */
1587 #ifdef DEBUG
1589 typedef struct NamedRootDumpArgs {
1590     void (*dump)(const char *name, void *rp, void *data);
1591     void *data;
1592 } NamedRootDumpArgs;
1594 JS_STATIC_DLL_CALLBACK(JSDHashOperator)
1595 js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
1596                      void *arg)
1598     NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;
1599     JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
1601     if (rhe->name)
1602         args->dump(rhe->name, rhe->root, args->data);
1603     return JS_DHASH_NEXT;
1606 JS_PUBLIC_API(void)
1607 JS_DumpNamedRoots(JSRuntime *rt,
1608                   void (*dump)(const char *name, void *rp, void *data),
1609                   void *data)
1611     NamedRootDumpArgs args;
1613     args.dump = dump;
1614     args.data = data;
1615     JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);
1618 #endif /* DEBUG */
1620 typedef struct GCRootMapArgs {
1621     JSGCRootMapFun map;
1622     void *data;
1623 } GCRootMapArgs;
1625 JS_STATIC_DLL_CALLBACK(JSDHashOperator)
1626 js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
1627                  void *arg)
1629     GCRootMapArgs *args = (GCRootMapArgs *) arg;
1630     JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
1631     intN mapflags;
1632     JSDHashOperator op;
1634     mapflags = args->map(rhe->root, rhe->name, args->data);
1636 #if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT &&                                     \
1637     JS_MAP_GCROOT_STOP == JS_DHASH_STOP &&                                     \
1638     JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE
1639     op = (JSDHashOperator)mapflags;
1640 #else
1641     op = JS_DHASH_NEXT;
1642     if (mapflags & JS_MAP_GCROOT_STOP)
1643         op |= JS_DHASH_STOP;
1644     if (mapflags & JS_MAP_GCROOT_REMOVE)
1645         op |= JS_DHASH_REMOVE;
1646 #endif
1648     return op;
1651 JS_PUBLIC_API(uint32)
1652 JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
1654     GCRootMapArgs args;
1655     uint32 rv;
1657     args.map = map;
1658     args.data = data;
1659     JS_LOCK_GC(rt);
1660     rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args);
1661     JS_UNLOCK_GC(rt);
1662     return rv;
1665 JS_PUBLIC_API(JSBool)
1666 JS_LockGCThing(JSContext *cx, void *thing)
1668     JSBool ok;
1670     CHECK_REQUEST(cx);
1671     ok = js_LockGCThing(cx, thing);
1672     if (!ok)
1673         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_LOCK);
1674     return ok;
1677 JS_PUBLIC_API(JSBool)
1678 JS_LockGCThingRT(JSRuntime *rt, void *thing)
1680     return js_LockGCThingRT(rt, thing);
1683 JS_PUBLIC_API(JSBool)
1684 JS_UnlockGCThing(JSContext *cx, void *thing)
1686     JSBool ok;
1688     CHECK_REQUEST(cx);
1689     ok = js_UnlockGCThingRT(cx->runtime, thing);
1690     if (!ok)
1691         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK);
1692     return ok;
1695 JS_PUBLIC_API(JSBool)
1696 JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
1698     return js_UnlockGCThingRT(rt, thing);
1701 JS_PUBLIC_API(void)
1702 JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
1704     JS_ASSERT(cx->runtime->gcLevel > 0);
1705 #ifdef JS_THREADSAFE
1706     JS_ASSERT(cx->runtime->gcThread == js_CurrentThreadId());
1707 #endif
1709     GC_MARK(cx, thing, name, arg);
1712 JS_PUBLIC_API(void)
1713 JS_GC(JSContext *cx)
1715     /* Don't nuke active arenas if executing or compiling. */
1716     if (cx->stackPool.current == &cx->stackPool.first)
1717         JS_FinishArenaPool(&cx->stackPool);
1718     if (cx->tempPool.current == &cx->tempPool.first)
1719         JS_FinishArenaPool(&cx->tempPool);
1720     js_ForceGC(cx, 0);
1723 JS_PUBLIC_API(void)
1724 JS_MaybeGC(JSContext *cx)
1726     JSRuntime *rt;
1727     uint32 bytes, lastBytes;
1729     rt = cx->runtime;
1730     bytes = rt->gcBytes;
1731     lastBytes = rt->gcLastBytes;
1732     if ((bytes > 8192 && bytes > lastBytes + lastBytes / 2) ||
1733         rt->gcMallocBytes > rt->gcMaxBytes) {
1734         /*
1735          * Run the GC if we have half again as many bytes of GC-things as
1736          * the last time we GC'd, or if we have malloc'd more bytes through
1737          * JS_malloc than we were told to allocate by JS_NewRuntime.
1738          */
1739         JS_GC(cx);
1740     }
1743 JS_PUBLIC_API(JSGCCallback)
1744 JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
1746     return JS_SetGCCallbackRT(cx->runtime, cb);
1749 JS_PUBLIC_API(JSGCCallback)
1750 JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
1752     JSGCCallback oldcb;
1754     oldcb = rt->gcCallback;
1755     rt->gcCallback = cb;
1756     return oldcb;
1759 JS_PUBLIC_API(JSBool)
1760 JS_IsAboutToBeFinalized(JSContext *cx, void *thing)
1762     JS_ASSERT(thing);
1763     return js_IsAboutToBeFinalized(cx, thing);
1766 JS_PUBLIC_API(intN)
1767 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
1769     return js_ChangeExternalStringFinalizer(NULL, finalizer);
1772 JS_PUBLIC_API(intN)
1773 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
1775     return js_ChangeExternalStringFinalizer(finalizer, NULL);
1778 JS_PUBLIC_API(JSString *)
1779 JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
1781     JSString *str;
1783     CHECK_REQUEST(cx);
1784     JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES);
1786     str = (JSString *) js_AllocGCThing(cx, (uintN) type);
1787     if (!str)
1788         return NULL;
1789     str->length = length;
1790     str->chars = chars;
1791     return str;
1794 JS_PUBLIC_API(intN)
1795 JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
1797     uint8 type = (uint8) (*js_GetGCThingFlags(str) & GCF_TYPEMASK);
1799     if (type >= GCX_EXTERNAL_STRING)
1800         return (intN)type;
1801     JS_ASSERT(type == GCX_STRING || type == GCX_MUTABLE_STRING);
1802     return -1;
1805 #ifdef DEBUG
1806 /* FIXME: 242518 static */ void
1807 CheckStackGrowthDirection(int *dummy1addr, jsuword limitAddr)
1809     int dummy2;
1811 #if JS_STACK_GROWTH_DIRECTION > 0
1812     JS_ASSERT(dummy1addr < &dummy2);
1813     JS_ASSERT((jsuword)&dummy2 < limitAddr);
1814 #else
1815     /* Stack grows downward, the common case on modern architectures. */
1816     JS_ASSERT(&dummy2 < dummy1addr);
1817     JS_ASSERT(limitAddr < (jsuword)&dummy2);
1818 #endif
1820 #endif
1822 JS_PUBLIC_API(void)
1823 JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
1825 #ifdef DEBUG
1826     int dummy1;
1828     CheckStackGrowthDirection(&dummy1, limitAddr);
1829 #endif
1831 #if JS_STACK_GROWTH_DIRECTION > 0
1832     if (limitAddr == 0)
1833         limitAddr = (jsuword)-1;
1834 #endif
1835     cx->stackLimit = limitAddr;
1838 /************************************************************************/
1840 JS_PUBLIC_API(void)
1841 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
1843     JS_free(cx, ida);
1846 JS_PUBLIC_API(JSBool)
1847 JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
1849     JSAtom *atom;
1851     CHECK_REQUEST(cx);
1852     if (JSVAL_IS_INT(v)) {
1853         *idp = v;
1854     } else {
1855         atom = js_ValueToStringAtom(cx, v);
1856         if (!atom)
1857             return JS_FALSE;
1858         *idp = (jsid)atom;
1859     }
1860     return JS_TRUE;
1863 JS_PUBLIC_API(JSBool)
1864 JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
1866     CHECK_REQUEST(cx);
1867     *vp = ID_TO_VALUE(id);
1868     return JS_TRUE;
1871 JS_PUBLIC_API(JSBool)
1872 JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
1874     return JS_TRUE;
1877 JS_PUBLIC_API(JSBool)
1878 JS_EnumerateStub(JSContext *cx, JSObject *obj)
1880     return JS_TRUE;
1883 JS_PUBLIC_API(JSBool)
1884 JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id)
1886     return JS_TRUE;
1889 JS_PUBLIC_API(JSBool)
1890 JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
1892 #if JS_BUG_EAGER_TOSTRING
1893     if (type == JSTYPE_STRING)
1894         return JS_TRUE;
1895 #endif
1896     return js_TryValueOf(cx, obj, type, vp);
1899 JS_PUBLIC_API(void)
1900 JS_FinalizeStub(JSContext *cx, JSObject *obj)
1904 JS_PUBLIC_API(JSObject *)
1905 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
1906              JSClass *clasp, JSNative constructor, uintN nargs,
1907              JSPropertySpec *ps, JSFunctionSpec *fs,
1908              JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
1910     JSAtom *atom;
1911     JSObject *proto, *ctor;
1912     JSBool named;
1913     JSFunction *fun;
1914     jsval junk;
1916     CHECK_REQUEST(cx);
1917     atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
1918     if (!atom)
1919         return NULL;
1921     /* Create a prototype object for this class. */
1922     proto = js_NewObject(cx, clasp, parent_proto, obj);
1923     if (!proto)
1924         return NULL;
1926     if (!constructor) {
1927         /* Lacking a constructor, name the prototype (e.g., Math). */
1928         named = OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, OBJECT_TO_JSVAL(proto),
1929                                     NULL, NULL, 0, NULL);
1930         if (!named)
1931             goto bad;
1932         ctor = proto;
1933     } else {
1934         /* Define the constructor function in obj's scope. */
1935         fun = js_DefineFunction(cx, obj, atom, constructor, nargs, 0);
1936         named = (fun != NULL);
1937         if (!fun)
1938             goto bad;
1940         /*
1941          * Remember the class this function is a constructor for so that
1942          * we know to create an object of this class when we call the
1943          * constructor.
1944          */
1945         fun->clasp = clasp;
1947         /* Connect constructor and prototype by named properties. */
1948         ctor = fun->object;
1949         if (!js_SetClassPrototype(cx, ctor, proto,
1950                                   JSPROP_READONLY | JSPROP_PERMANENT)) {
1951             goto bad;
1952         }
1954         /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
1955         if (OBJ_GET_CLASS(cx, ctor) == clasp) {
1956             /* XXXMLM - this fails in framesets that are writing over
1957              *           themselves!
1958              * JS_ASSERT(!OBJ_GET_PROTO(cx, ctor));
1959              */
1960             OBJ_SET_PROTO(cx, ctor, proto);
1961         }
1962     }
1964     /* Add properties and methods to the prototype and the constructor. */
1965     if ((ps && !JS_DefineProperties(cx, proto, ps)) ||
1966         (fs && !JS_DefineFunctions(cx, proto, fs)) ||
1967         (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||
1968         (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {
1969         goto bad;
1970     }
1971     return proto;
1973 bad:
1974     if (named)
1975         (void) OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, &junk);
1976     cx->newborn[GCX_OBJECT] = NULL;
1977     return NULL;
1980 #ifdef JS_THREADSAFE
1981 JS_PUBLIC_API(JSClass *)
1982 JS_GetClass(JSContext *cx, JSObject *obj)
1984     return (JSClass *)
1985         JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS));
1987 #else
1988 JS_PUBLIC_API(JSClass *)
1989 JS_GetClass(JSObject *obj)
1991     return LOCKED_OBJ_GET_CLASS(obj);
1993 #endif
1995 JS_PUBLIC_API(JSBool)
1996 JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
1998     JSFunction *fun;
2000     CHECK_REQUEST(cx);
2001     if (OBJ_GET_CLASS(cx, obj) == clasp)
2002         return JS_TRUE;
2003     if (argv) {
2004         fun = js_ValueToFunction(cx, &argv[-2], 0);
2005         if (fun) {
2006             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2007                                  JSMSG_INCOMPATIBLE_PROTO,
2008                                  clasp->name, JS_GetFunctionName(fun),
2009                                  OBJ_GET_CLASS(cx, obj)->name);
2010         }
2011     }
2012     return JS_FALSE;
2015 JS_PUBLIC_API(void *)
2016 JS_GetPrivate(JSContext *cx, JSObject *obj)
2018     jsval v;
2020     JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
2021     v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
2022     if (!JSVAL_IS_INT(v))
2023         return NULL;
2024     return JSVAL_TO_PRIVATE(v);
2027 JS_PUBLIC_API(JSBool)
2028 JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
2030     JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
2031     OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(data));
2032     return JS_TRUE;
2035 JS_PUBLIC_API(void *)
2036 JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
2037                       jsval *argv)
2039     if (!JS_InstanceOf(cx, obj, clasp, argv))
2040         return NULL;
2041     return JS_GetPrivate(cx, obj);
2044 JS_PUBLIC_API(JSObject *)
2045 JS_GetPrototype(JSContext *cx, JSObject *obj)
2047     JSObject *proto;
2049     CHECK_REQUEST(cx);
2050     proto = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PROTO));
2052     /* Beware ref to dead object (we may be called from obj's finalizer). */
2053     return proto && proto->map ? proto : NULL;
2056 JS_PUBLIC_API(JSBool)
2057 JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
2059     CHECK_REQUEST(cx);
2060     if (obj->map->ops->setProto)
2061         return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto);
2062     OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto));
2063     return JS_TRUE;
2066 JS_PUBLIC_API(JSObject *)
2067 JS_GetParent(JSContext *cx, JSObject *obj)
2069     JSObject *parent;
2071     parent = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PARENT));
2073     /* Beware ref to dead object (we may be called from obj's finalizer). */
2074     return parent && parent->map ? parent : NULL;
2077 JS_PUBLIC_API(JSBool)
2078 JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
2080     CHECK_REQUEST(cx);
2081     if (obj->map->ops->setParent)
2082         return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent);
2083     OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent));
2084     return JS_TRUE;
2087 JS_PUBLIC_API(JSObject *)
2088 JS_GetConstructor(JSContext *cx, JSObject *proto)
2090     jsval cval;
2092     CHECK_REQUEST(cx);
2093     if (!OBJ_GET_PROPERTY(cx, proto,
2094                           (jsid)cx->runtime->atomState.constructorAtom,
2095                           &cval)) {
2096         return NULL;
2097     }
2098     if (!JSVAL_IS_FUNCTION(cx, cval)) {
2099         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
2100                              OBJ_GET_CLASS(cx, proto)->name);
2101         return NULL;
2102     }
2103     return JSVAL_TO_OBJECT(cval);
2106 JS_PUBLIC_API(JSBool)
2107 JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
2109     JS_ASSERT(((jsid)obj & JSVAL_TAGMASK) == 0);
2110     *idp = (jsid) obj | JSVAL_INT;
2111     return JS_TRUE;
2114 JS_PUBLIC_API(JSObject *)
2115 JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
2117     CHECK_REQUEST(cx);
2118     if (!clasp)
2119         clasp = &js_ObjectClass;    /* default class is Object */
2120     return js_NewObject(cx, clasp, proto, parent);
2123 JS_PUBLIC_API(JSBool)
2124 JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
2126     JSScope *scope;
2127     JSIdArray *ida;
2128     uint32 nslots;
2129     jsval v, *vp, *end;
2131     if (!OBJ_IS_NATIVE(obj)) {
2132         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2133                              JSMSG_CANT_SEAL_OBJECT,
2134                              OBJ_GET_CLASS(cx, obj)->name);
2135         return JS_FALSE;
2136     }
2138     scope = OBJ_SCOPE(obj);
2140 #if defined JS_THREADSAFE && defined DEBUG
2141     /* Insist on scope being used exclusively by cx's thread. */
2142     if (scope->ownercx != cx) {
2143         JS_LOCK_OBJ(cx, obj);
2144         JS_ASSERT(OBJ_SCOPE(obj) == scope);
2145         JS_ASSERT(scope->ownercx == cx);
2146         JS_UNLOCK_SCOPE(cx, scope);
2147     }
2148 #endif
2150     /* Nothing to do if obj's scope is already sealed. */
2151     if (SCOPE_IS_SEALED(scope))
2152         return JS_TRUE;
2154     /* XXX Enumerate lazy properties now, as they can't be added later. */
2155     ida = JS_Enumerate(cx, obj);
2156     if (!ida)
2157         return JS_FALSE;
2158     JS_DestroyIdArray(cx, ida);
2160     /* Ensure that obj has its own, mutable scope, and seal that scope. */
2161     JS_LOCK_OBJ(cx, obj);
2162     scope = js_GetMutableScope(cx, obj);
2163     if (scope)
2164         SCOPE_SET_SEALED(scope);
2165     JS_UNLOCK_SCOPE(cx, scope);
2166     if (!scope)
2167         return JS_FALSE;
2169     /* If we are not sealing an entire object graph, we're done. */
2170     if (!deep)
2171         return JS_TRUE;
2173     /* Walk obj->slots and if any value is a non-null object, seal it. */
2174     nslots = JS_MIN(scope->map.freeslot, scope->map.nslots);
2175     for (vp = obj->slots, end = vp + nslots; vp < end; vp++) {
2176         v = *vp;
2177         if (JSVAL_IS_PRIMITIVE(v))
2178             continue;
2179         if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep))
2180             return JS_FALSE;
2181     }
2182     return JS_TRUE;
2185 JS_PUBLIC_API(JSObject *)
2186 JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
2187                    JSObject *parent)
2189     CHECK_REQUEST(cx);
2190     if (!clasp)
2191         clasp = &js_ObjectClass;    /* default class is Object */
2192     return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
2195 JS_PUBLIC_API(JSObject *)
2196 JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
2197                                 JSObject *parent, uintN argc, jsval *argv)
2199     CHECK_REQUEST(cx);
2200     if (!clasp)
2201         clasp = &js_ObjectClass;    /* default class is Object */
2202     return js_ConstructObject(cx, clasp, proto, parent, argc, argv);
2205 static JSBool
2206 DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
2207                JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
2208                uintN flags, intN tinyid)
2210     jsid id;
2211     JSAtom *atom;
2213     if (attrs & JSPROP_INDEX) {
2214         id = INT_TO_JSVAL((jsint)name);
2215         atom = NULL;
2216         attrs &= ~JSPROP_INDEX;
2217     } else {
2218         atom = js_Atomize(cx, name, strlen(name), 0);
2219         if (!atom)
2220             return JS_FALSE;
2221         id = (jsid)atom;
2222     }
2223     if (flags != 0 && OBJ_IS_NATIVE(obj)) {
2224         return js_DefineNativeProperty(cx, obj, id, value, getter, setter,
2225                                        attrs, flags, tinyid, NULL);
2226     }
2227     return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
2228                                NULL);
2231 #define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
2233 static JSBool
2234 DefineUCProperty(JSContext *cx, JSObject *obj,
2235                  const jschar *name, size_t namelen, jsval value,
2236                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
2237                  uintN flags, intN tinyid)
2239     JSAtom *atom;
2241     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2242     if (!atom)
2243         return JS_FALSE;
2244     if (flags != 0 && OBJ_IS_NATIVE(obj)) {
2245         return js_DefineNativeProperty(cx, obj, (jsid)atom, value,
2246                                        getter, setter, attrs, flags, tinyid,
2247                                        NULL);
2248     }
2249     return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, value, getter, setter,
2250                                attrs, NULL);
2253 JS_PUBLIC_API(JSObject *)
2254 JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
2255                 JSObject *proto, uintN attrs)
2257     JSObject *nobj;
2259     CHECK_REQUEST(cx);
2260     if (!clasp)
2261         clasp = &js_ObjectClass;    /* default class is Object */
2262     nobj = js_NewObject(cx, clasp, proto, obj);
2263     if (!nobj)
2264         return NULL;
2265     if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
2266                         0, 0)) {
2267         cx->newborn[GCX_OBJECT] = NULL;
2268         return NULL;
2269     }
2270     return nobj;
2273 JS_PUBLIC_API(JSBool)
2274 JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
2276     JSBool ok;
2277     jsval value;
2278     uintN flags;
2280     CHECK_REQUEST(cx);
2281     for (ok = JS_TRUE; cds->name; cds++) {
2282         ok = js_NewNumberValue(cx, cds->dval, &value);
2283         if (!ok)
2284             break;
2285         flags = cds->flags;
2286         if (!flags)
2287             flags = JSPROP_READONLY | JSPROP_PERMANENT;
2288         ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0);
2289         if (!ok)
2290             break;
2291     }
2292     return ok;
2295 JS_PUBLIC_API(JSBool)
2296 JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
2298     JSBool ok;
2300     CHECK_REQUEST(cx);
2301     for (ok = JS_TRUE; ps->name; ps++) {
2302         ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID,
2303                             ps->getter, ps->setter, ps->flags,
2304                             SPROP_HAS_SHORTID, ps->tinyid);
2305         if (!ok)
2306             break;
2307     }
2308     return ok;
2311 JS_PUBLIC_API(JSBool)
2312 JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
2313                   JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
2315     CHECK_REQUEST(cx);
2316     return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
2319 JS_PUBLIC_API(JSBool)
2320 JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
2321                             int8 tinyid, jsval value,
2322                             JSPropertyOp getter, JSPropertyOp setter,
2323                             uintN attrs)
2325     CHECK_REQUEST(cx);
2326     return DefineProperty(cx, obj, name, value, getter, setter, attrs,
2327                           SPROP_HAS_SHORTID, tinyid);
2330 static JSBool
2331 LookupProperty(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
2332                JSProperty **propp)
2334     JSAtom *atom;
2336     atom = js_Atomize(cx, name, strlen(name), 0);
2337     if (!atom)
2338         return JS_FALSE;
2339     return OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, objp, propp);
2342 static JSBool
2343 LookupUCProperty(JSContext *cx, JSObject *obj,
2344                  const jschar *name, size_t namelen,
2345                  JSObject **objp, JSProperty **propp)
2347     JSAtom *atom;
2349     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2350     if (!atom)
2351         return JS_FALSE;
2352     return OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, objp, propp);
2355 JS_PUBLIC_API(JSBool)
2356 JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
2357                  const char *alias)
2359     JSObject *obj2;
2360     JSProperty *prop;
2361     JSAtom *atom;
2362     JSBool ok;
2363     JSScopeProperty *sprop;
2365     CHECK_REQUEST(cx);
2366     if (!LookupProperty(cx, obj, name, &obj2, &prop))
2367         return JS_FALSE;
2368     if (!prop) {
2369         js_ReportIsNotDefined(cx, name);
2370         return JS_FALSE;
2371     }
2372     if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
2373         OBJ_DROP_PROPERTY(cx, obj2, prop);
2374         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
2375                              alias, name, OBJ_GET_CLASS(cx, obj2)->name);
2376         return JS_FALSE;
2377     }
2378     atom = js_Atomize(cx, alias, strlen(alias), 0);
2379     if (!atom) {
2380         ok = JS_FALSE;
2381     } else {
2382         sprop = (JSScopeProperty *)prop;
2383         ok = (js_AddNativeProperty(cx, obj, (jsid)atom,
2384                                    sprop->getter, sprop->setter, sprop->slot,
2385                                    sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
2386                                    sprop->shortid)
2387               != NULL);
2388     }
2389     OBJ_DROP_PROPERTY(cx, obj, prop);
2390     return ok;
2393 static jsval
2394 LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
2396     JSScopeProperty *sprop;
2397     jsval rval;
2399     if (!prop) {
2400         /* XXX bad API: no way to tell "not defined" from "void value" */
2401         return JSVAL_VOID;
2402     }
2403     if (OBJ_IS_NATIVE(obj2)) {
2404         /* Peek at the native property's slot value, without doing a Get. */
2405         sprop = (JSScopeProperty *)prop;
2406         rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
2407                ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
2408                : JSVAL_TRUE;
2409     } else {
2410         /* XXX bad API: no way to return "defined but value unknown" */
2411         rval = JSVAL_TRUE;
2412     }
2413     OBJ_DROP_PROPERTY(cx, obj2, prop);
2414     return rval;
2417 static JSBool
2418 GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
2419                       uintN *attrsp, JSBool *foundp)
2421     JSObject *obj2;
2422     JSProperty *prop;
2423     JSBool ok;
2425     if (!atom)
2426         return JS_FALSE;
2427     if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop))
2428         return JS_FALSE;
2429     if (!prop || obj != obj2) {
2430         *foundp = JS_FALSE;
2431         if (prop)
2432             OBJ_DROP_PROPERTY(cx, obj2, prop);
2433         return JS_TRUE;
2434     }
2436     *foundp = JS_TRUE;
2437     ok = OBJ_GET_ATTRIBUTES(cx, obj, (jsid)atom, prop, attrsp);
2438     OBJ_DROP_PROPERTY(cx, obj, prop);
2439     return ok;
2442 static JSBool
2443 SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
2444                       uintN attrs, JSBool *foundp)
2446     JSObject *obj2;
2447     JSProperty *prop;
2448     JSBool ok;
2450     if (!atom)
2451         return JS_FALSE;
2452     if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop))
2453         return JS_FALSE;
2454     if (!prop || obj != obj2) {
2455         *foundp = JS_FALSE;
2456         if (prop)
2457             OBJ_DROP_PROPERTY(cx, obj2, prop);
2458         return JS_TRUE;
2459     }
2461     *foundp = JS_TRUE;
2462     ok = OBJ_SET_ATTRIBUTES(cx, obj, (jsid)atom, prop, &attrs);
2463     OBJ_DROP_PROPERTY(cx, obj, prop);
2464     return ok;
2468 JS_PUBLIC_API(JSBool)
2469 JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
2470                          uintN *attrsp, JSBool *foundp)
2472     CHECK_REQUEST(cx);
2473     return GetPropertyAttributes(cx, obj,
2474                                  js_Atomize(cx, name, strlen(name), 0),
2475                                  attrsp, foundp);
2478 JS_PUBLIC_API(JSBool)
2479 JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
2480                          uintN attrs, JSBool *foundp)
2482     CHECK_REQUEST(cx);
2483     return SetPropertyAttributes(cx, obj,
2484                                  js_Atomize(cx, name, strlen(name), 0),
2485                                  attrs, foundp);
2488 JS_PUBLIC_API(JSBool)
2489 JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
2491     JSBool ok;
2492     JSObject *obj2;
2493     JSProperty *prop;
2495     CHECK_REQUEST(cx);
2496     ok = LookupProperty(cx, obj, name, &obj2, &prop);
2497     if (ok) {
2498         *foundp = (prop != NULL);
2499         if (prop)
2500             OBJ_DROP_PROPERTY(cx, obj2, prop);
2501     }
2502     return ok;
2505 JS_PUBLIC_API(JSBool)
2506 JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
2508     JSBool ok;
2509     JSObject *obj2;
2510     JSProperty *prop;
2512     CHECK_REQUEST(cx);
2513     ok = LookupProperty(cx, obj, name, &obj2, &prop);
2514     if (ok)
2515         *vp = LookupResult(cx, obj, obj2, prop);
2516     return ok;
2519 JS_PUBLIC_API(JSBool)
2520 JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
2521                            uintN flags, jsval *vp)
2523     JSAtom *atom;
2524     JSBool ok;
2525     JSObject *obj2;
2526     JSProperty *prop;
2528     CHECK_REQUEST(cx);
2529     atom = js_Atomize(cx, name, strlen(name), 0);
2530     if (!atom)
2531         return JS_FALSE;
2532     ok = OBJ_IS_NATIVE(obj)
2533          ? js_LookupPropertyWithFlags(cx, obj, (jsid)atom, flags, &obj2, &prop
2534 #if defined JS_THREADSAFE && defined DEBUG
2535                                       , __FILE__, __LINE__
2536 #endif
2537                                       )
2538          : OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop);
2539     if (ok)
2540         *vp = LookupResult(cx, obj, obj2, prop);
2541     return ok;
2544 JS_PUBLIC_API(JSBool)
2545 JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
2547     JSAtom *atom;
2549     CHECK_REQUEST(cx);
2550     atom = js_Atomize(cx, name, strlen(name), 0);
2551     if (!atom)
2552         return JS_FALSE;
2553     return OBJ_GET_PROPERTY(cx, obj, (jsid)atom, vp);
2556 JS_PUBLIC_API(JSBool)
2557 JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
2559     JSAtom *atom;
2561     CHECK_REQUEST(cx);
2562     atom = js_Atomize(cx, name, strlen(name), 0);
2563     if (!atom)
2564         return JS_FALSE;
2565     return OBJ_SET_PROPERTY(cx, obj, (jsid)atom, vp);
2568 JS_PUBLIC_API(JSBool)
2569 JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
2571     jsval junk;
2573     CHECK_REQUEST(cx);
2574     return JS_DeleteProperty2(cx, obj, name, &junk);
2577 JS_PUBLIC_API(JSBool)
2578 JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
2579                    jsval *rval)
2581     JSAtom *atom;
2583     CHECK_REQUEST(cx);
2584     atom = js_Atomize(cx, name, strlen(name), 0);
2585     if (!atom)
2586         return JS_FALSE;
2587     return OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, rval);
2590 JS_PUBLIC_API(JSBool)
2591 JS_DefineUCProperty(JSContext *cx, JSObject *obj,
2592                     const jschar *name, size_t namelen, jsval value,
2593                     JSPropertyOp getter, JSPropertyOp setter,
2594                     uintN attrs)
2596     CHECK_REQUEST(cx);
2597     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
2598                             attrs, 0, 0);
2601 JS_PUBLIC_API(JSBool)
2602 JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
2603                            const jschar *name, size_t namelen,
2604                            uintN *attrsp, JSBool *foundp)
2606     CHECK_REQUEST(cx);
2607     return GetPropertyAttributes(cx, obj,
2608                     js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
2609                     attrsp, foundp);
2612 JS_PUBLIC_API(JSBool)
2613 JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
2614                            const jschar *name, size_t namelen,
2615                            uintN attrs, JSBool *foundp)
2617     CHECK_REQUEST(cx);
2618     return SetPropertyAttributes(cx, obj,
2619                     js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
2620                     attrs, foundp);
2623 JS_PUBLIC_API(JSBool)
2624 JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
2625                               const jschar *name, size_t namelen,
2626                               int8 tinyid, jsval value,
2627                               JSPropertyOp getter, JSPropertyOp setter,
2628                               uintN attrs)
2630     CHECK_REQUEST(cx);
2631     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
2632                             attrs, SPROP_HAS_SHORTID, tinyid);
2635 JS_PUBLIC_API(JSBool)
2636 JS_HasUCProperty(JSContext *cx, JSObject *obj,
2637                  const jschar *name, size_t namelen,
2638                  JSBool *vp)
2640     JSBool ok;
2641     JSObject *obj2;
2642     JSProperty *prop;
2644     CHECK_REQUEST(cx);
2645     ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
2646     if (ok) {
2647         *vp = (prop != NULL);
2648         if (prop)
2649             OBJ_DROP_PROPERTY(cx, obj2, prop);
2650     }
2651     return ok;
2654 JS_PUBLIC_API(JSBool)
2655 JS_LookupUCProperty(JSContext *cx, JSObject *obj,
2656                     const jschar *name, size_t namelen,
2657                     jsval *vp)
2659     JSBool ok;
2660     JSObject *obj2;
2661     JSProperty *prop;
2663     CHECK_REQUEST(cx);
2664     ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
2665     if (ok)
2666         *vp = LookupResult(cx, obj, obj2, prop);
2667     return ok;
2670 JS_PUBLIC_API(JSBool)
2671 JS_GetUCProperty(JSContext *cx, JSObject *obj,
2672                  const jschar *name, size_t namelen,
2673                  jsval *vp)
2675     JSAtom *atom;
2677     CHECK_REQUEST(cx);
2678     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2679     if (!atom)
2680         return JS_FALSE;
2681     return OBJ_GET_PROPERTY(cx, obj, (jsid)atom, vp);
2684 JS_PUBLIC_API(JSBool)
2685 JS_SetUCProperty(JSContext *cx, JSObject *obj,
2686                  const jschar *name, size_t namelen,
2687                  jsval *vp)
2689     JSAtom *atom;
2691     CHECK_REQUEST(cx);
2692     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2693     if (!atom)
2694         return JS_FALSE;
2695     return OBJ_SET_PROPERTY(cx, obj, (jsid)atom, vp);
2698 JS_PUBLIC_API(JSBool)
2699 JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
2700                      const jschar *name, size_t namelen,
2701                      jsval *rval)
2703     JSAtom *atom;
2705     CHECK_REQUEST(cx);
2706     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2707     if (!atom)
2708         return JS_FALSE;
2709     return OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, rval);
2712 JS_PUBLIC_API(JSObject *)
2713 JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
2715     CHECK_REQUEST(cx);
2716     /* NB: jsuint cast does ToUint32. */
2717     return js_NewArrayObject(cx, (jsuint)length, vector);
2720 JS_PUBLIC_API(JSBool)
2721 JS_IsArrayObject(JSContext *cx, JSObject *obj)
2723     return OBJ_GET_CLASS(cx, obj) == &js_ArrayClass;
2726 JS_PUBLIC_API(JSBool)
2727 JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
2729     CHECK_REQUEST(cx);
2730     return js_GetLengthProperty(cx, obj, lengthp);
2733 JS_PUBLIC_API(JSBool)
2734 JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
2736     CHECK_REQUEST(cx);
2737     return js_SetLengthProperty(cx, obj, length);
2740 JS_PUBLIC_API(JSBool)
2741 JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
2743     CHECK_REQUEST(cx);
2744     return js_HasLengthProperty(cx, obj, lengthp);
2747 JS_PUBLIC_API(JSBool)
2748 JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
2749                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
2751     CHECK_REQUEST(cx);
2752     return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSVAL(index), value,
2753                                getter, setter, attrs, NULL);
2756 JS_PUBLIC_API(JSBool)
2757 JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
2759     JSObject *obj2;
2760     JSProperty *prop;
2761     JSScopeProperty *sprop;
2762     JSBool ok;
2764     CHECK_REQUEST(cx);
2765     if (!LookupProperty(cx, obj, name, &obj2, &prop))
2766         return JS_FALSE;
2767     if (!prop) {
2768         js_ReportIsNotDefined(cx, name);
2769         return JS_FALSE;
2770     }
2771     if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
2772         char numBuf[12];
2773         OBJ_DROP_PROPERTY(cx, obj2, prop);
2774         JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
2775         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
2776                              numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
2777         return JS_FALSE;
2778     }
2779     sprop = (JSScopeProperty *)prop;
2780     ok = (js_AddNativeProperty(cx, obj, INT_TO_JSVAL(alias),
2781                                sprop->getter, sprop->setter, sprop->slot,
2782                                sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
2783                                sprop->shortid)
2784           != NULL);
2785     OBJ_DROP_PROPERTY(cx, obj, prop);
2786     return ok;
2789 JS_PUBLIC_API(JSBool)
2790 JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
2792     JSBool ok;
2793     JSObject *obj2;
2794     JSProperty *prop;
2796     CHECK_REQUEST(cx);
2797     ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSVAL(index), &obj2, &prop);
2798     if (ok) {
2799         *foundp = (prop != NULL);
2800         if (prop)
2801             OBJ_DROP_PROPERTY(cx, obj2, prop);
2802     }
2803     return ok;
2806 JS_PUBLIC_API(JSBool)
2807 JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
2809     JSBool ok;
2810     JSObject *obj2;
2811     JSProperty *prop;
2813     CHECK_REQUEST(cx);
2814     ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSVAL(index), &obj2, &prop);
2815     if (ok)
2816         *vp = LookupResult(cx, obj, obj2, prop);
2817     return ok;
2820 JS_PUBLIC_API(JSBool)
2821 JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
2823     CHECK_REQUEST(cx);
2824     return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSVAL(index), vp);
2827 JS_PUBLIC_API(JSBool)
2828 JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
2830     CHECK_REQUEST(cx);
2831     return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSVAL(index), vp);
2834 JS_PUBLIC_API(JSBool)
2835 JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index)
2837     jsval junk;
2839     CHECK_REQUEST(cx);
2840     return JS_DeleteElement2(cx, obj, index, &junk);
2843 JS_PUBLIC_API(JSBool)
2844 JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
2846     CHECK_REQUEST(cx);
2847     return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSVAL(index), rval);
2850 JS_PUBLIC_API(void)
2851 JS_ClearScope(JSContext *cx, JSObject *obj)
2853     CHECK_REQUEST(cx);
2855     if (obj->map->ops->clear)
2856         obj->map->ops->clear(cx, obj);
2859 JS_PUBLIC_API(JSIdArray *)
2860 JS_Enumerate(JSContext *cx, JSObject *obj)
2862     jsint i, n;
2863     jsval iter_state, num_properties;
2864     jsid id;
2865     JSIdArray *ida;
2866     jsval *vector;
2868     CHECK_REQUEST(cx);
2870     ida = NULL;
2871     iter_state = JSVAL_NULL;
2873     /* Get the number of properties to enumerate. */
2874     if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties))
2875         goto error;
2876     if (!JSVAL_IS_INT(num_properties)) {
2877         JS_ASSERT(0);
2878         goto error;
2879     }
2881     /* Grow as needed if we don't know the exact amount ahead of time. */
2882     n = JSVAL_TO_INT(num_properties);
2883     if (n <= 0)
2884         n = 8;
2886     /* Create an array of jsids large enough to hold all the properties */
2887     ida = js_NewIdArray(cx, n);
2888     if (!ida)
2889         goto error;
2891     i = 0;
2892     vector = &ida->vector[0];
2893     for (;;) {
2894         if (i == ida->length) {
2895             /* Grow length by factor of 1.5 instead of doubling. */
2896             jsint newlen = ida->length + (((jsuint)ida->length + 1) >> 1);
2897             ida = js_GrowIdArray(cx, ida, newlen);
2898             if (!ida)
2899                 goto error;
2900             vector = &ida->vector[0];
2901         }
2903         if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id))
2904             goto error;
2906         /* No more jsid's to enumerate ? */
2907         if (iter_state == JSVAL_NULL)
2908             break;
2909         vector[i++] = id;
2910     }
2911     ida->length = i;
2912     return ida;
2914 error:
2915     if (iter_state != JSVAL_NULL)
2916         OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
2917     if (ida)
2918         JS_DestroyIdArray(cx, ida);
2919     return NULL;
2922 JS_PUBLIC_API(JSBool)
2923 JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
2924                jsval *vp, uintN *attrsp)
2926     CHECK_REQUEST(cx);
2927     return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp);
2930 JS_PUBLIC_API(JSCheckAccessOp)
2931 JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb)
2933     JSCheckAccessOp oldacb;
2935     oldacb = rt->checkObjectAccess;
2936     rt->checkObjectAccess = acb;
2937     return oldacb;
2940 static JSBool
2941 ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
2942                     uint32 index, uint32 limit)
2944     /* Check the computed, possibly per-instance, upper bound. */
2945     if (clasp->reserveSlots)
2946         JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj));
2947     if (index >= limit) {
2948         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2949                              JSMSG_RESERVED_SLOT_RANGE);
2950         return JS_FALSE;
2951     }
2952     return JS_TRUE;
2955 JS_PUBLIC_API(JSBool)
2956 JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
2958     JSClass *clasp;
2959     uint32 limit, slot;
2961     CHECK_REQUEST(cx);
2962     clasp = OBJ_GET_CLASS(cx, obj);
2963     limit = JSCLASS_RESERVED_SLOTS(clasp);
2964     if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
2965         return JS_FALSE;
2966     slot = JSSLOT_START(clasp) + index;
2967     *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
2968     return JS_TRUE;
2971 JS_PUBLIC_API(JSBool)
2972 JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
2974     JSClass *clasp;
2975     uint32 limit, slot;
2977     CHECK_REQUEST(cx);
2978     clasp = OBJ_GET_CLASS(cx, obj);
2979     limit = JSCLASS_RESERVED_SLOTS(clasp);
2980     if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
2981         return JS_FALSE;
2982     slot = JSSLOT_START(clasp) + index;
2983     return OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
2986 #ifdef JS_THREADSAFE
2987 JS_PUBLIC_API(jsrefcount)
2988 JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
2990     return JS_ATOMIC_INCREMENT(&principals->refcount);
2993 JS_PUBLIC_API(jsrefcount)
2994 JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
2996     jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount);
2997     if (rc == 0)
2998         principals->destroy(cx, principals);
2999     return rc;
3001 #endif
3003 JS_PUBLIC_API(JSPrincipalsTranscoder)
3004 JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px)
3006     JSPrincipalsTranscoder oldpx;
3008     oldpx = rt->principalsTranscoder;
3009     rt->principalsTranscoder = px;
3010     return oldpx;
3013 JS_PUBLIC_API(JSObjectPrincipalsFinder)
3014 JS_SetObjectPrincipalsFinder(JSContext *cx, JSObjectPrincipalsFinder fop)
3016     JSObjectPrincipalsFinder oldfop;
3018     oldfop = cx->findObjectPrincipals;
3019     cx->findObjectPrincipals = fop;
3020     return oldfop;
3023 JS_PUBLIC_API(JSFunction *)
3024 JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
3025                JSObject *parent, const char *name)
3027     JSAtom *atom;
3029     CHECK_REQUEST(cx);
3031     if (!name) {
3032         atom = NULL;
3033     } else {
3034         atom = js_Atomize(cx, name, strlen(name), 0);
3035         if (!atom)
3036             return NULL;
3037     }
3038     return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
3041 JS_PUBLIC_API(JSObject *)
3042 JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
3044     CHECK_REQUEST(cx);
3045     if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {
3046         /* Indicate we cannot clone this object. */
3047         return funobj;
3048     }
3049     return js_CloneFunctionObject(cx, funobj, parent);
3052 JS_PUBLIC_API(JSObject *)
3053 JS_GetFunctionObject(JSFunction *fun)
3055     return fun->object;
3058 JS_PUBLIC_API(const char *)
3059 JS_GetFunctionName(JSFunction *fun)
3061     return fun->atom
3062            ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
3063            : js_anonymous_str;
3066 JS_PUBLIC_API(JSString *)
3067 JS_GetFunctionId(JSFunction *fun)
3069     return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
3072 JS_PUBLIC_API(uintN)
3073 JS_GetFunctionFlags(JSFunction *fun)
3075     return fun->flags;
3078 JS_PUBLIC_API(JSBool)
3079 JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
3081     return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
3084 JS_PUBLIC_API(JSBool)
3085 JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
3087     JSFunction *fun;
3089     CHECK_REQUEST(cx);
3090     for (; fs->name; fs++) {
3091         fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs,
3092                                 fs->flags);
3093         if (!fun)
3094             return JS_FALSE;
3095         fun->extra = fs->extra;
3096     }
3097     return JS_TRUE;
3100 JS_PUBLIC_API(JSFunction *)
3101 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
3102                   uintN nargs, uintN attrs)
3104     JSAtom *atom;
3106     CHECK_REQUEST(cx);
3107     atom = js_Atomize(cx, name, strlen(name), 0);
3108     if (!atom)
3109         return NULL;
3110     return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
3113 JS_PUBLIC_API(JSFunction *)
3114 JS_DefineUCFunction(JSContext *cx, JSObject *obj,
3115                     const jschar *name, size_t namelen, JSNative call,
3116                     uintN nargs, uintN attrs)
3118     JSAtom *atom;
3120     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3121     if (!atom)
3122         return NULL;
3123     return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
3126 static JSScript *
3127 CompileTokenStream(JSContext *cx, JSObject *obj, JSTokenStream *ts,
3128                    void *tempMark, JSBool *eofp)
3130     JSBool eof;
3131     JSArenaPool codePool, notePool;
3132     JSCodeGenerator cg;
3133     JSScript *script;
3135     CHECK_REQUEST(cx);
3136     eof = JS_FALSE;
3137     JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
3138     JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));
3139     if (!js_InitCodeGenerator(cx, &cg, &codePool, &notePool,
3140                               ts->filename, ts->lineno,
3141                               ts->principals)) {
3142         script = NULL;
3143     } else if (!js_CompileTokenStream(cx, obj, ts, &cg)) {
3144         script = NULL;
3145         eof = (ts->flags & TSF_EOF) != 0;
3146     } else {
3147         script = js_NewScriptFromCG(cx, &cg, NULL);
3148     }
3149     if (eofp)
3150         *eofp = eof;
3151     if (!js_CloseTokenStream(cx, ts)) {
3152         if (script)
3153             js_DestroyScript(cx, script);
3154         script = NULL;
3155     }
3156     cg.tempMark = tempMark;
3157     js_FinishCodeGenerator(cx, &cg);
3158     JS_FinishArenaPool(&codePool);
3159     JS_FinishArenaPool(&notePool);
3160     return script;
3163 JS_PUBLIC_API(JSScript *)
3164 JS_CompileScript(JSContext *cx, JSObject *obj,
3165                  const char *bytes, size_t length,
3166                  const char *filename, uintN lineno)
3168     jschar *chars;
3169     JSScript *script;
3171     CHECK_REQUEST(cx);
3172     chars = js_InflateString(cx, bytes, length);
3173     if (!chars)
3174         return NULL;
3175     script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno);
3176     JS_free(cx, chars);
3177     return script;
3180 JS_PUBLIC_API(JSScript *)
3181 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
3182                               JSPrincipals *principals,
3183                               const char *bytes, size_t length,
3184                               const char *filename, uintN lineno)
3186     jschar *chars;
3187     JSScript *script;
3189     CHECK_REQUEST(cx);
3190     chars = js_InflateString(cx, bytes, length);
3191     if (!chars)
3192         return NULL;
3193     script = JS_CompileUCScriptForPrincipals(cx, obj, principals,
3194                                              chars, length, filename, lineno);
3195     JS_free(cx, chars);
3196     return script;
3199 JS_PUBLIC_API(JSScript *)
3200 JS_CompileUCScript(JSContext *cx, JSObject *obj,
3201                    const jschar *chars, size_t length,
3202                    const char *filename, uintN lineno)
3204     CHECK_REQUEST(cx);
3205     return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length,
3206                                            filename, lineno);
3209 JS_PUBLIC_API(JSScript *)
3210 JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
3211                                 JSPrincipals *principals,
3212                                 const jschar *chars, size_t length,
3213                                 const char *filename, uintN lineno)
3215     void *mark;
3216     JSTokenStream *ts;
3217     JSScript *script;
3219     CHECK_REQUEST(cx);
3220     mark = JS_ARENA_MARK(&cx->tempPool);
3221     ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
3222     if (!ts)
3223         return NULL;
3224     script = CompileTokenStream(cx, obj, ts, mark, NULL);
3225 #if JS_HAS_EXCEPTIONS
3226     if (!script && !cx->fp)
3227         js_ReportUncaughtException(cx);
3228 #endif
3229     return script;
3232 JS_PUBLIC_API(JSBool)
3233 JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
3234                           const char *bytes, size_t length)
3236     jschar *chars;
3237     JSBool result;
3238     JSExceptionState *exnState;
3239     void *tempMark;
3240     JSTokenStream *ts;
3241     JSErrorReporter older;
3243     CHECK_REQUEST(cx);
3244     chars = js_InflateString(cx, bytes, length);
3245     if (!chars)
3246         return JS_TRUE;
3248     /*
3249      * Return true on any out-of-memory error, so our caller doesn't try to
3250      * collect more buffered source.
3251      */
3252     result = JS_TRUE;
3253     exnState = JS_SaveExceptionState(cx);
3254     tempMark = JS_ARENA_MARK(&cx->tempPool);
3255     ts = js_NewTokenStream(cx, chars, length, NULL, 0, NULL);
3256     if (ts) {
3257         older = JS_SetErrorReporter(cx, NULL);
3258         if (!js_ParseTokenStream(cx, obj, ts)) {
3259             /*
3260              * We ran into an error.  If it was because we ran out of source,
3261              * we return false, so our caller will know to try to collect more
3262              * buffered source.
3263              */
3264             result = (ts->flags & TSF_EOF) == 0;
3265         }
3267         JS_SetErrorReporter(cx, older);
3268         js_CloseTokenStream(cx, ts);
3269         JS_ARENA_RELEASE(&cx->tempPool, tempMark);
3270     }
3272     JS_free(cx, chars);
3273     JS_RestoreExceptionState(cx, exnState);
3274     return result;
3277 JS_PUBLIC_API(JSScript *)
3278 JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
3280     void *mark;
3281     JSTokenStream *ts;
3282     JSScript *script;
3284     CHECK_REQUEST(cx);
3285     mark = JS_ARENA_MARK(&cx->tempPool);
3286     ts = js_NewFileTokenStream(cx, filename, stdin);
3287     if (!ts)
3288         return NULL;
3289     script = CompileTokenStream(cx, obj, ts, mark, NULL);
3290 #if JS_HAS_EXCEPTIONS
3291     if (!script && !cx->fp)
3292         js_ReportUncaughtException(cx);
3293 #endif
3294     return script;
3297 JS_PUBLIC_API(JSScript *)
3298 JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
3299                      FILE *file)
3301     return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
3304 JS_PUBLIC_API(JSScript *)
3305 JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
3306                                   const char *filename, FILE *file,
3307                                   JSPrincipals *principals)
3309     void *mark;
3310     JSTokenStream *ts;
3311     JSScript *script;
3313     CHECK_REQUEST(cx);
3314     mark = JS_ARENA_MARK(&cx->tempPool);
3315     ts = js_NewFileTokenStream(cx, NULL, file);
3316     if (!ts)
3317         return NULL;
3318     ts->filename = filename;
3319     /* XXXshaver js_NewFileTokenStream should do this, because it drops */
3320     if (principals) {
3321         ts->principals = principals;
3322         JSPRINCIPALS_HOLD(cx, ts->principals);
3323     }
3324     script = CompileTokenStream(cx, obj, ts, mark, NULL);
3325 #if JS_HAS_EXCEPTIONS
3326     if (!script && !cx->fp)
3327         js_ReportUncaughtException(cx);
3328 #endif
3329     return script;
3332 JS_PUBLIC_API(JSObject *)
3333 JS_NewScriptObject(JSContext *cx, JSScript *script)
3335     JSObject *obj;
3337     obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
3338     if (!obj)
3339         return NULL;
3341     if (script) {
3342         if (!JS_SetPrivate(cx, obj, script))
3343             return NULL;
3344         script->object = obj;
3345     }
3346     return obj;
3349 JS_PUBLIC_API(JSObject *)
3350 JS_GetScriptObject(JSScript *script)
3352     return script->object;
3355 JS_PUBLIC_API(void)
3356 JS_DestroyScript(JSContext *cx, JSScript *script)
3358     CHECK_REQUEST(cx);
3359     js_DestroyScript(cx, script);
3362 JS_PUBLIC_API(JSFunction *)
3363 JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
3364                    uintN nargs, const char **argnames,
3365                    const char *bytes, size_t length,
3366                    const char *filename, uintN lineno)
3368     jschar *chars;
3369     JSFunction *fun;
3371     CHECK_REQUEST(cx);
3372     chars = js_InflateString(cx, bytes, length);
3373     if (!chars)
3374         return NULL;
3375     fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length,
3376                                filename, lineno);
3377     JS_free(cx, chars);
3378     return fun;
3381 JS_PUBLIC_API(JSFunction *)
3382 JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
3383                                 JSPrincipals *principals, const char *name,
3384                                 uintN nargs, const char **argnames,
3385                                 const char *bytes, size_t length,
3386                                 const char *filename, uintN lineno)
3388     jschar *chars;
3389     JSFunction *fun;
3391     CHECK_REQUEST(cx);
3392     chars = js_InflateString(cx, bytes, length);
3393     if (!chars)
3394         return NULL;
3395     fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
3396                                             nargs, argnames, chars, length,
3397                                             filename, lineno);
3398     JS_free(cx, chars);
3399     return fun;
3402 JS_PUBLIC_API(JSFunction *)
3403 JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
3404                      uintN nargs, const char **argnames,
3405                      const jschar *chars, size_t length,
3406                      const char *filename, uintN lineno)
3408     CHECK_REQUEST(cx);
3409     return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name,
3410                                              nargs, argnames,
3411                                              chars, length,
3412                                              filename, lineno);
3415 JS_PUBLIC_API(JSFunction *)
3416 JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
3417                                   JSPrincipals *principals, const char *name,
3418                                   uintN nargs, const char **argnames,
3419                                   const jschar *chars, size_t length,
3420                                   const char *filename, uintN lineno)
3422     void *mark;
3423     JSTokenStream *ts;
3424     JSFunction *fun;
3425     JSAtom *funAtom, *argAtom;
3426     uintN i;
3428     CHECK_REQUEST(cx);
3429     mark = JS_ARENA_MARK(&cx->tempPool);
3430     ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
3431     if (!ts) {
3432         fun = NULL;
3433         goto out;
3434     }
3435     if (!name) {
3436         funAtom = NULL;
3437     } else {
3438         funAtom = js_Atomize(cx, name, strlen(name), 0);
3439         if (!funAtom) {
3440             fun = NULL;
3441             goto out;
3442         }
3443     }
3444     fun = js_NewFunction(cx, NULL, NULL, nargs, 0, obj, funAtom);
3445     if (!fun)
3446         goto out;
3447     if (nargs) {
3448         for (i = 0; i < nargs; i++) {
3449             argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
3450             if (!argAtom)
3451                 break;
3452             if (!js_AddNativeProperty(cx, fun->object, (jsid)argAtom,
3453                                       js_GetArgument, js_SetArgument,
3454                                       SPROP_INVALID_SLOT,
3455                                       JSPROP_ENUMERATE | JSPROP_PERMANENT |
3456                                       JSPROP_SHARED,
3457                                       SPROP_HAS_SHORTID, i)) {
3458                 break;
3459             }
3460         }
3461         if (i < nargs) {
3462             fun = NULL;
3463             goto out;
3464         }
3465     }
3466     if (!js_CompileFunctionBody(cx, ts, fun)) {
3467         fun = NULL;
3468         goto out;
3469     }
3470     if (obj && funAtom) {
3471         if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)funAtom,
3472                                  OBJECT_TO_JSVAL(fun->object),
3473                                  NULL, NULL, 0, NULL)) {
3474             return NULL;
3475         }
3476     }
3477 out:
3478     if (ts)
3479         js_CloseTokenStream(cx, ts);
3480     JS_ARENA_RELEASE(&cx->tempPool, mark);
3481 #if JS_HAS_EXCEPTIONS
3482     if (!fun && !cx->fp)
3483         js_ReportUncaughtException(cx);
3484 #endif
3485     return fun;
3488 JS_PUBLIC_API(JSString *)
3489 JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
3490                    uintN indent)
3492     JSPrinter *jp;
3493     JSString *str;
3495     CHECK_REQUEST(cx);
3496     jp = js_NewPrinter(cx, name,
3497                        indent & ~JS_DONT_PRETTY_PRINT,
3498                        !(indent & JS_DONT_PRETTY_PRINT));
3499     if (!jp)
3500         return NULL;
3501     if (js_DecompileScript(jp, script))
3502         str = js_GetPrinterOutput(jp);
3503     else
3504         str = NULL;
3505     js_DestroyPrinter(jp);
3506     return str;
3509 JS_PUBLIC_API(JSString *)
3510 JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
3512     JSPrinter *jp;
3513     JSString *str;
3515     CHECK_REQUEST(cx);
3516     jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
3517                        indent & ~JS_DONT_PRETTY_PRINT,
3518                        !(indent & JS_DONT_PRETTY_PRINT));
3519     if (!jp)
3520         return NULL;
3521     if (js_DecompileFunction(jp, fun))
3522         str = js_GetPrinterOutput(jp);
3523     else
3524         str = NULL;
3525     js_DestroyPrinter(jp);
3526     return str;
3529 JS_PUBLIC_API(JSString *)
3530 JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
3532     JSPrinter *jp;
3533     JSString *str;
3535     CHECK_REQUEST(cx);
3536     jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
3537                        indent & ~JS_DONT_PRETTY_PRINT,
3538                        !(indent & JS_DONT_PRETTY_PRINT));
3539     if (!jp)
3540         return NULL;
3541     if (js_DecompileFunctionBody(jp, fun))
3542         str = js_GetPrinterOutput(jp);
3543     else
3544         str = NULL;
3545     js_DestroyPrinter(jp);
3546     return str;
3549 JS_PUBLIC_API(JSBool)
3550 JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
3552     CHECK_REQUEST(cx);
3553     if (!js_Execute(cx, obj, script, NULL, 0, rval)) {
3554 #if JS_HAS_EXCEPTIONS
3555         if (!cx->fp)
3556             js_ReportUncaughtException(cx);
3557 #endif
3558         return JS_FALSE;
3559     }
3560     return JS_TRUE;
3563 JS_PUBLIC_API(JSBool)
3564 JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
3565                      JSExecPart part, jsval *rval)
3567     JSScript tmp;
3568     JSRuntime *rt;
3569     JSBool ok;
3571     /* Make a temporary copy of the JSScript structure and farble it a bit. */
3572     tmp = *script;
3573     if (part == JSEXEC_PROLOG) {
3574         tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode);
3575     } else {
3576         tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode);
3577         tmp.code = tmp.main;
3578     }
3580     /* Tell the debugger about our temporary copy of the script structure. */
3581     rt = cx->runtime;
3582     if (rt->newScriptHook) {
3583         rt->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL,
3584                           rt->newScriptHookData);
3585     }
3587     /* Execute the farbled struct and tell the debugger to forget about it. */
3588     ok = JS_ExecuteScript(cx, obj, &tmp, rval);
3589     if (rt->destroyScriptHook)
3590         rt->destroyScriptHook(cx, &tmp, rt->destroyScriptHookData);
3591     return ok;
3594 JS_PUBLIC_API(JSBool)
3595 JS_EvaluateScript(JSContext *cx, JSObject *obj,
3596                   const char *bytes, uintN length,
3597                   const char *filename, uintN lineno,
3598                   jsval *rval)
3600     jschar *chars;
3601     JSBool ok;
3603     CHECK_REQUEST(cx);
3604     chars = js_InflateString(cx, bytes, length);
3605     if (!chars)
3606         return JS_FALSE;
3607     ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval);
3608     JS_free(cx, chars);
3609     return ok;
3612 JS_PUBLIC_API(JSBool)
3613 JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
3614                                JSPrincipals *principals,
3615                                const char *bytes, uintN length,
3616                                const char *filename, uintN lineno,
3617                                jsval *rval)
3619     jschar *chars;
3620     JSBool ok;
3622     CHECK_REQUEST(cx);
3623     chars = js_InflateString(cx, bytes, length);
3624     if (!chars)
3625         return JS_FALSE;
3626     ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
3627                                           filename, lineno, rval);
3628     JS_free(cx, chars);
3629     return ok;
3632 JS_PUBLIC_API(JSBool)
3633 JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
3634                     const jschar *chars, uintN length,
3635                     const char *filename, uintN lineno,
3636                     jsval *rval)
3638     CHECK_REQUEST(cx);
3639     return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length,
3640                                             filename, lineno, rval);
3643 JS_PUBLIC_API(JSBool)
3644 JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
3645                                  JSPrincipals *principals,
3646                                  const jschar *chars, uintN length,
3647                                  const char *filename, uintN lineno,
3648                                  jsval *rval)
3650     uint32 options;
3651     JSScript *script;
3652     JSBool ok;
3654     CHECK_REQUEST(cx);
3655     options = cx->options;
3656     cx->options = options | JSOPTION_COMPILE_N_GO;
3657     script = JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length,
3658                                              filename, lineno);
3659     cx->options = options;
3660     if (!script)
3661         return JS_FALSE;
3662     ok = js_Execute(cx, obj, script, NULL, 0, rval);
3663 #if JS_HAS_EXCEPTIONS
3664     if (!ok && !cx->fp)
3665         js_ReportUncaughtException(cx);
3666 #endif
3667     JS_DestroyScript(cx, script);
3668     return ok;
3671 JS_PUBLIC_API(JSBool)
3672 JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
3673                 jsval *argv, jsval *rval)
3675     CHECK_REQUEST(cx);
3676     if (!js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv,
3677                          rval)) {
3678 #if JS_HAS_EXCEPTIONS
3679         if (!cx->fp)
3680             js_ReportUncaughtException(cx);
3681 #endif
3682         return JS_FALSE;
3683     }
3684     return JS_TRUE;
3687 JS_PUBLIC_API(JSBool)
3688 JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
3689                     jsval *argv, jsval *rval)
3691     jsval fval;
3693     CHECK_REQUEST(cx);
3694     if (!JS_GetProperty(cx, obj, name, &fval))
3695         return JS_FALSE;
3696     if (!js_InternalCall(cx, obj, fval, argc, argv, rval)) {
3697 #if JS_HAS_EXCEPTIONS
3698         if (!cx->fp)
3699             js_ReportUncaughtException(cx);
3700 #endif
3701         return JS_FALSE;
3702     }
3703     return JS_TRUE;
3706 JS_PUBLIC_API(JSBool)
3707 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
3708                      jsval *argv, jsval *rval)
3710     CHECK_REQUEST(cx);
3711     if (!js_InternalCall(cx, obj, fval, argc, argv, rval)) {
3712 #if JS_HAS_EXCEPTIONS
3713         if (!cx->fp)
3714             js_ReportUncaughtException(cx);
3715 #endif
3716         return JS_FALSE;
3717     }
3718     return JS_TRUE;
3721 JS_PUBLIC_API(JSBranchCallback)
3722 JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb)
3724     JSBranchCallback oldcb;
3726     oldcb = cx->branchCallback;
3727     cx->branchCallback = cb;
3728     return oldcb;
3731 JS_PUBLIC_API(JSBool)
3732 JS_IsRunning(JSContext *cx)
3734     return cx->fp != NULL;
3737 JS_PUBLIC_API(JSBool)
3738 JS_IsConstructing(JSContext *cx)
3740     return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
3743 JS_FRIEND_API(JSBool)
3744 JS_IsAssigning(JSContext *cx)
3746     JSStackFrame *fp;
3747     jsbytecode *pc;
3749     for (fp = cx->fp; fp && !fp->script; fp = fp->down)
3750         continue;
3751     if (!fp || !(pc = fp->pc))
3752         return JS_FALSE;
3753     return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0;
3756 JS_PUBLIC_API(void)
3757 JS_SetCallReturnValue2(JSContext *cx, jsval v)
3759 #if JS_HAS_LVALUE_RETURN
3760     cx->rval2 = v;
3761     cx->rval2set = JS_TRUE;
3762 #endif
3765 /************************************************************************/
3767 JS_PUBLIC_API(JSString *)
3768 JS_NewString(JSContext *cx, char *bytes, size_t length)
3770     jschar *chars;
3771     JSString *str;
3773     CHECK_REQUEST(cx);
3774     /* Make a Unicode vector from the 8-bit char codes in bytes. */
3775     chars = js_InflateString(cx, bytes, length);
3776     if (!chars)
3777         return NULL;
3779     /* Free chars (but not bytes, which caller frees on error) if we fail. */
3780     str = js_NewString(cx, chars, length, 0);
3781     if (!str) {
3782         JS_free(cx, chars);
3783         return NULL;
3784     }
3786     /* Hand off bytes to the deflated string cache, if possible. */
3787     if (!js_SetStringBytes(str, bytes, length))
3788         JS_free(cx, bytes);
3789     return str;
3792 JS_PUBLIC_API(JSString *)
3793 JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
3795     jschar *js;
3796     JSString *str;
3798     CHECK_REQUEST(cx);
3799     js = js_InflateString(cx, s, n);
3800     if (!js)
3801         return NULL;
3802     str = js_NewString(cx, js, n, 0);
3803     if (!str)
3804         JS_free(cx, js);
3805     return str;
3808 JS_PUBLIC_API(JSString *)
3809 JS_NewStringCopyZ(JSContext *cx, const char *s)
3811     size_t n;
3812     jschar *js;
3813     JSString *str;
3815     CHECK_REQUEST(cx);
3816     if (!s)
3817         return cx->runtime->emptyString;
3818     n = strlen(s);
3819     js = js_InflateString(cx, s, n);
3820     if (!js)
3821         return NULL;
3822     str = js_NewString(cx, js, n, 0);
3823     if (!str)
3824         JS_free(cx, js);
3825     return str;
3828 JS_PUBLIC_API(JSString *)
3829 JS_InternString(JSContext *cx, const char *s)
3831     JSAtom *atom;
3833     CHECK_REQUEST(cx);
3834     atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
3835     if (!atom)
3836         return NULL;
3837     return ATOM_TO_STRING(atom);
3840 JS_PUBLIC_API(JSString *)
3841 JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
3843     CHECK_REQUEST(cx);
3844     return js_NewString(cx, chars, length, 0);
3847 JS_PUBLIC_API(JSString *)
3848 JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
3850     CHECK_REQUEST(cx);
3851     return js_NewStringCopyN(cx, s, n, 0);
3854 JS_PUBLIC_API(JSString *)
3855 JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
3857     CHECK_REQUEST(cx);
3858     if (!s)
3859         return cx->runtime->emptyString;
3860     return js_NewStringCopyZ(cx, s, 0);
3863 JS_PUBLIC_API(JSString *)
3864 JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
3866     JSAtom *atom;
3868     CHECK_REQUEST(cx);
3869     atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
3870     if (!atom)
3871         return NULL;
3872     return ATOM_TO_STRING(atom);
3875 JS_PUBLIC_API(JSString *)
3876 JS_InternUCString(JSContext *cx, const jschar *s)
3878     return JS_InternUCStringN(cx, s, js_strlen(s));
3881 JS_PUBLIC_API(char *)
3882 JS_GetStringBytes(JSString *str)
3884     char *bytes;
3886     bytes = js_GetStringBytes(str);
3887     return bytes ? bytes : "";
3890 JS_PUBLIC_API(jschar *)
3891 JS_GetStringChars(JSString *str)
3893     /*
3894      * API botch (again, shades of JS_GetStringBytes): we have no cx to pass
3895      * to js_UndependString (called by js_GetStringChars) for out-of-memory
3896      * error reports, so js_UndependString passes NULL and suppresses errors.
3897      * If it fails to convert a dependent string into an independent one, our
3898      * caller will not be guaranteed a \u0000 terminator as a backstop.  This
3899      * may break some clients who already misbehave on embedded NULs.
3900      *
3901      * The gain of dependent strings, which cure quadratic and cubic growth
3902      * rate bugs in string concatenation, is worth this slight loss in API
3903      * compatibility.
3904      */
3905     jschar *chars;
3907     chars = js_GetStringChars(str);
3908     return chars ? chars : JSSTRING_CHARS(str);
3911 JS_PUBLIC_API(size_t)
3912 JS_GetStringLength(JSString *str)
3914     return JSSTRING_LENGTH(str);
3917 JS_PUBLIC_API(intN)
3918 JS_CompareStrings(JSString *str1, JSString *str2)
3920     return js_CompareStrings(str1, str2);
3923 JS_PUBLIC_API(JSString *)
3924 JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
3926     CHECK_REQUEST(cx);
3927     return js_NewString(cx, chars, length, GCF_MUTABLE);
3930 JS_PUBLIC_API(JSString *)
3931 JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
3932                       size_t length)
3934     CHECK_REQUEST(cx);
3935     return js_NewDependentString(cx, str, start, length, 0);
3938 JS_PUBLIC_API(JSString *)
3939 JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
3941     CHECK_REQUEST(cx);
3942     return js_ConcatStrings(cx, left, right);
3945 JS_PUBLIC_API(const jschar *)
3946 JS_UndependString(JSContext *cx, JSString *str)
3948     CHECK_REQUEST(cx);
3949     return js_UndependString(cx, str);
3952 JS_PUBLIC_API(JSBool)
3953 JS_MakeStringImmutable(JSContext *cx, JSString *str)
3955     CHECK_REQUEST(cx);
3956     if (!js_UndependString(cx, str))
3957         return JS_FALSE;
3959     *js_GetGCThingFlags(str) &= ~GCF_MUTABLE;
3960     return JS_TRUE;
3963 /************************************************************************/
3965 JS_PUBLIC_API(void)
3966 JS_ReportError(JSContext *cx, const char *format, ...)
3968     va_list ap;
3970     va_start(ap, format);
3971     js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
3972     va_end(ap);
3975 JS_PUBLIC_API(void)
3976 JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
3977                      void *userRef, const uintN errorNumber, ...)
3979     va_list ap;
3981     va_start(ap, errorNumber);
3982     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
3983                            errorNumber, JS_TRUE, ap);
3984     va_end(ap);
3987 JS_PUBLIC_API(void)
3988 JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
3989                      void *userRef, const uintN errorNumber, ...)
3991     va_list ap;
3993     va_start(ap, errorNumber);
3994     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
3995                            errorNumber, JS_FALSE, ap);
3996     va_end(ap);
3999 JS_PUBLIC_API(JSBool)
4000 JS_ReportWarning(JSContext *cx, const char *format, ...)
4002     va_list ap;
4003     JSBool ok;
4005     va_start(ap, format);
4006     ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
4007     va_end(ap);
4008     return ok;
4011 JS_PUBLIC_API(JSBool)
4012 JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
4013                              JSErrorCallback errorCallback, void *userRef,
4014                              const uintN errorNumber, ...)
4016     va_list ap;
4017     JSBool ok;
4019     va_start(ap, errorNumber);
4020     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
4021                                 errorNumber, JS_TRUE, ap);
4022     va_end(ap);
4023     return ok;
4026 JS_PUBLIC_API(JSBool)
4027 JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
4028                                JSErrorCallback errorCallback, void *userRef,
4029                                const uintN errorNumber, ...)
4031     va_list ap;
4032     JSBool ok;
4034     va_start(ap, errorNumber);
4035     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
4036                                 errorNumber, JS_FALSE, ap);
4037     va_end(ap);
4038     return ok;
4041 JS_PUBLIC_API(void)
4042 JS_ReportOutOfMemory(JSContext *cx)
4044     js_ReportOutOfMemory(cx, js_GetErrorMessage);
4047 JS_PUBLIC_API(JSErrorReporter)
4048 JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
4050     JSErrorReporter older;
4052     older = cx->errorReporter;
4053     cx->errorReporter = er;
4054     return older;
4057 /************************************************************************/
4059 /*
4060  * Regular Expressions.
4061  */
4062 JS_PUBLIC_API(JSObject *)
4063 JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
4065 #if JS_HAS_REGEXPS
4066     jschar *chars;
4067     JSObject *obj;
4069     CHECK_REQUEST(cx);
4070     chars = js_InflateString(cx, bytes, length);
4071     if (!chars)
4072         return NULL;
4073     obj = js_NewRegExpObject(cx, NULL, chars, length, flags);
4074     JS_free(cx, chars);
4075     return obj;
4076 #else
4077     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS);
4078     return NULL;
4079 #endif
4082 JS_PUBLIC_API(JSObject *)
4083 JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
4085     CHECK_REQUEST(cx);
4086 #if JS_HAS_REGEXPS
4087     return js_NewRegExpObject(cx, NULL, chars, length, flags);
4088 #else
4089     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS);
4090     return NULL;
4091 #endif
4094 JS_PUBLIC_API(void)
4095 JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
4097     JSRegExpStatics *res;
4099     CHECK_REQUEST(cx);
4100     /* No locking required, cx is thread-private and input must be live. */
4101     res = &cx->regExpStatics;
4102     res->input = input;
4103     res->multiline = multiline;
4104     cx->runtime->gcPoke = JS_TRUE;
4107 JS_PUBLIC_API(void)
4108 JS_ClearRegExpStatics(JSContext *cx)
4110     JSRegExpStatics *res;
4112     /* No locking required, cx is thread-private and input must be live. */
4113     res = &cx->regExpStatics;
4114     res->input = NULL;
4115     res->multiline = JS_FALSE;
4116     res->parenCount = 0;
4117     res->lastMatch = res->lastParen = js_EmptySubString;
4118     res->leftContext = res->rightContext = js_EmptySubString;
4119     cx->runtime->gcPoke = JS_TRUE;
4122 JS_PUBLIC_API(void)
4123 JS_ClearRegExpRoots(JSContext *cx)
4125     JSRegExpStatics *res;
4127     /* No locking required, cx is thread-private and input must be live. */
4128     res = &cx->regExpStatics;
4129     res->input = NULL;
4130     cx->runtime->gcPoke = JS_TRUE;
4133 /* TODO: compile, execute, get/set other statics... */
4135 /************************************************************************/
4137 JS_PUBLIC_API(void)
4138 JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
4140     cx->localeCallbacks = callbacks;
4143 JS_PUBLIC_API(JSLocaleCallbacks *)
4144 JS_GetLocaleCallbacks(JSContext *cx)
4146     return cx->localeCallbacks;
4149 /************************************************************************/
4151 JS_PUBLIC_API(JSBool)
4152 JS_IsExceptionPending(JSContext *cx)
4154 #if JS_HAS_EXCEPTIONS
4155     return (JSBool) cx->throwing;
4156 #else
4157     return JS_FALSE;
4158 #endif
4161 JS_PUBLIC_API(JSBool)
4162 JS_GetPendingException(JSContext *cx, jsval *vp)
4164 #if JS_HAS_EXCEPTIONS
4165     CHECK_REQUEST(cx);
4166     if (!cx->throwing)
4167         return JS_FALSE;
4168     *vp = cx->exception;
4169     return JS_TRUE;
4170 #else
4171     return JS_FALSE;
4172 #endif
4175 JS_PUBLIC_API(void)
4176 JS_SetPendingException(JSContext *cx, jsval v)
4178     CHECK_REQUEST(cx);
4179 #if JS_HAS_EXCEPTIONS
4180     cx->throwing = JS_TRUE;
4181     cx->exception = v;
4182 #endif
4185 JS_PUBLIC_API(void)
4186 JS_ClearPendingException(JSContext *cx)
4188 #if JS_HAS_EXCEPTIONS
4189     cx->throwing = JS_FALSE;
4190     cx->exception = JSVAL_VOID;
4191 #endif
4194 JS_PUBLIC_API(JSBool)
4195 JS_ReportPendingException(JSContext *cx)
4197 #if JS_HAS_EXCEPTIONS
4198     CHECK_REQUEST(cx);
4199     return js_ReportUncaughtException(cx);
4200 #else
4201     return JS_TRUE;
4202 #endif
4205 #if JS_HAS_EXCEPTIONS
4206 struct JSExceptionState {
4207     JSBool throwing;
4208     jsval  exception;
4209 };
4210 #endif
4212 JS_PUBLIC_API(JSExceptionState *)
4213 JS_SaveExceptionState(JSContext *cx)
4215 #if JS_HAS_EXCEPTIONS
4216     JSExceptionState *state;
4218     CHECK_REQUEST(cx);
4219     state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState));
4220     if (state) {
4221         state->throwing = JS_GetPendingException(cx, &state->exception);
4222         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
4223             js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
4224     }
4225     return state;
4226 #else
4227     return NULL;
4228 #endif
4231 JS_PUBLIC_API(void)
4232 JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
4234 #if JS_HAS_EXCEPTIONS
4235     CHECK_REQUEST(cx);
4236     if (state) {
4237         if (state->throwing)
4238             JS_SetPendingException(cx, state->exception);
4239         else
4240             JS_ClearPendingException(cx);
4241         JS_DropExceptionState(cx, state);
4242     }
4243 #endif
4246 JS_PUBLIC_API(void)
4247 JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
4249 #if JS_HAS_EXCEPTIONS
4250     CHECK_REQUEST(cx);
4251     if (state) {
4252         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
4253             JS_RemoveRoot(cx, &state->exception);
4254         JS_free(cx, state);
4255     }
4256 #endif
4259 JS_PUBLIC_API(JSErrorReport *)
4260 JS_ErrorFromException(JSContext *cx, jsval v)
4262 #if JS_HAS_EXCEPTIONS
4263     CHECK_REQUEST(cx);
4264     return js_ErrorFromException(cx, v);
4265 #else
4266     return NULL;
4267 #endif
4270 #ifdef JS_THREADSAFE
4271 JS_PUBLIC_API(jsword)
4272 JS_GetContextThread(JSContext *cx)
4274     return cx->thread;
4277 JS_PUBLIC_API(jsword)
4278 JS_SetContextThread(JSContext *cx)
4280     jsword old = cx->thread;
4281     cx->thread = js_CurrentThreadId();
4282     return old;
4285 JS_PUBLIC_API(jsword)
4286 JS_ClearContextThread(JSContext *cx)
4288     jsword old = cx->thread;
4289     cx->thread = 0;
4290     return old;
4292 #endif
4294 /************************************************************************/
4296 #if defined(XP_WIN)
4297 #include <windows.h>
4298 /*
4299  * Initialization routine for the JS DLL...
4300  */
4302 /*
4303  * Global Instance handle...
4304  * In Win32 this is the module handle of the DLL.
4305  *
4306  * In Win16 this is the instance handle of the application
4307  * which loaded the DLL.
4308  */
4310 #ifdef _WIN32
4311 BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
4313     return TRUE;
4316 #else  /* !_WIN32 */
4318 int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
4319                       WORD cbHeapSize, LPSTR lpszCmdLine )
4321     return TRUE;
4324 BOOL CALLBACK __loadds WEP(BOOL fSystemExit)
4326     return TRUE;
4329 #endif /* !_WIN32 */
4330 #endif /* XP_WIN */