Code

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