OSSP CVS Repository

ossp - Check-in [5498]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 5498
Date: 2006-Jun-16 04:01:22 (local)
2006-Jun-16 02:01:22 (UTC)
User:rse
Branch:
Comment: Import new upstream version: Mozilla JavaScript 1.6-1.5.0.5-20060722
Tickets:
Inspections:
Files:
ossp-pkg/js/src/jsapi.c      1.1 -> 1.1.1.1    
ossp-pkg/js/src/jsapi.c      added-> 1.1
ossp-pkg/js/src/jsapi.h      ->removed
ossp-pkg/js/src/jsapi.h      ->removed

ossp-pkg/js/src/jsapi.c -> 1.1

*** /dev/null    Sat Nov 23 05:37:38 2024
--- -    Sat Nov 23 05:37:41 2024
***************
*** 0 ****
--- 1,4811 ----
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+  * vim: set ts=8 sw=4 et tw=80:
+  *
+  * ***** BEGIN LICENSE BLOCK *****
+  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+  *
+  * The contents of this file are subject to the Mozilla Public License Version
+  * 1.1 (the "License"); you may not use this file except in compliance with
+  * the License. You may obtain a copy of the License at
+  * http://www.mozilla.org/MPL/
+  *
+  * Software distributed under the License is distributed on an "AS IS" basis,
+  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  * for the specific language governing rights and limitations under the
+  * License.
+  *
+  * The Original Code is Mozilla Communicator client code, released
+  * March 31, 1998.
+  *
+  * The Initial Developer of the Original Code is
+  * Netscape Communications Corporation.
+  * Portions created by the Initial Developer are Copyright (C) 1998
+  * the Initial Developer. All Rights Reserved.
+  *
+  * Contributor(s):
+  *
+  * Alternatively, the contents of this file may be used under the terms of
+  * either of the GNU General Public License Version 2 or later (the "GPL"),
+  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  * in which case the provisions of the GPL or the LGPL are applicable instead
+  * of those above. If you wish to allow use of your version of this file only
+  * under the terms of either the GPL or the LGPL, and not to allow others to
+  * use your version of this file under the terms of the MPL, indicate your
+  * decision by deleting the provisions above and replace them with the notice
+  * and other provisions required by the GPL or the LGPL. If you do not delete
+  * the provisions above, a recipient may use your version of this file under
+  * the terms of any one of the MPL, the GPL or the LGPL.
+  *
+  * ***** END LICENSE BLOCK ***** */
+ 
+ /*
+  * JavaScript API.
+  */
+ #include "jsstddef.h"
+ #include <ctype.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "jstypes.h"
+ #include "jsarena.h" /* Added by JSIFY */
+ #include "jsutil.h" /* Added by JSIFY */
+ #include "jsclist.h"
+ #include "jsdhash.h"
+ #include "jsprf.h"
+ #include "jsapi.h"
+ #include "jsarray.h"
+ #include "jsatom.h"
+ #include "jsbool.h"
+ #include "jscntxt.h"
+ #include "jsconfig.h"
+ #include "jsdate.h"
+ #include "jsdtoa.h"
+ #include "jsemit.h"
+ #include "jsexn.h"
+ #include "jsfun.h"
+ #include "jsgc.h"
+ #include "jsinterp.h"
+ #include "jslock.h"
+ #include "jsmath.h"
+ #include "jsnum.h"
+ #include "jsobj.h"
+ #include "jsopcode.h"
+ #include "jsparse.h"
+ #include "jsregexp.h"
+ #include "jsscan.h"
+ #include "jsscope.h"
+ #include "jsscript.h"
+ #include "jsstr.h"
+ #include "prmjtime.h"
+ 
+ #if JS_HAS_FILE_OBJECT
+ #include "jsfile.h"
+ #endif
+ 
+ #if JS_HAS_XML_SUPPORT
+ #include "jsxml.h"
+ #endif
+ 
+ #ifdef HAVE_VA_LIST_AS_ARRAY
+ #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
+ #else
+ #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
+ #endif
+ 
+ #if defined(JS_PARANOID_REQUEST) && defined(JS_THREADSAFE)
+ #define CHECK_REQUEST(cx)       JS_ASSERT(cx->requestDepth)
+ #else
+ #define CHECK_REQUEST(cx)       ((void)0)
+ #endif
+ 
+ JS_PUBLIC_API(int64)
+ JS_Now()
+ {
+     return PRMJ_Now();
+ }
+ 
+ JS_PUBLIC_API(jsval)
+ JS_GetNaNValue(JSContext *cx)
+ {
+     return DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ }
+ 
+ JS_PUBLIC_API(jsval)
+ JS_GetNegativeInfinityValue(JSContext *cx)
+ {
+     return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
+ }
+ 
+ JS_PUBLIC_API(jsval)
+ JS_GetPositiveInfinityValue(JSContext *cx)
+ {
+     return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
+ }
+ 
+ JS_PUBLIC_API(jsval)
+ JS_GetEmptyStringValue(JSContext *cx)
+ {
+     return STRING_TO_JSVAL(cx->runtime->emptyString);
+ }
+ 
+ static JSBool
+ TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS,
+                      jsval **vpp, va_list *app)
+ {
+     const char *format;
+     JSArgumentFormatMap *map;
+ 
+     format = *formatp;
+     for (map = cx->argumentFormatMap; map; map = map->next) {
+         if (!strncmp(format, map->format, map->length)) {
+             *formatp = format + map->length;
+             return map->formatter(cx, format, fromJS, vpp, app);
+         }
+     }
+     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
+     return JS_FALSE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
+                     ...)
+ {
+     va_list ap;
+     JSBool ok;
+ 
+     va_start(ap, format);
+     ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
+     va_end(ap);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
+                       const char *format, va_list ap)
+ {
+     jsval *sp;
+     JSBool required;
+     char c;
+     JSFunction *fun;
+     jsdouble d;
+     JSString *str;
+     JSObject *obj;
+ 
+     CHECK_REQUEST(cx);
+     sp = argv;
+     required = JS_TRUE;
+     while ((c = *format++) != '\0') {
+         if (isspace(c))
+             continue;
+         if (c == '/') {
+             required = JS_FALSE;
+             continue;
+         }
+         if (sp == argv + argc) {
+             if (required) {
+                 fun = js_ValueToFunction(cx, &argv[-2], 0);
+                 if (fun) {
+                     char numBuf[12];
+                     JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
+                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+                                          JSMSG_MORE_ARGS_NEEDED,
+                                          JS_GetFunctionName(fun), numBuf,
+                                          (argc == 1) ? "" : "s");
+                 }
+                 return JS_FALSE;
+             }
+             break;
+         }
+         switch (c) {
+           case 'b':
+             if (!js_ValueToBoolean(cx, *sp, va_arg(ap, JSBool *)))
+                 return JS_FALSE;
+             break;
+           case 'c':
+             if (!js_ValueToUint16(cx, *sp, va_arg(ap, uint16 *)))
+                 return JS_FALSE;
+             break;
+           case 'i':
+             if (!js_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
+                 return JS_FALSE;
+             break;
+           case 'u':
+             if (!js_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
+                 return JS_FALSE;
+             break;
+           case 'j':
+             if (!js_ValueToInt32(cx, *sp, va_arg(ap, int32 *)))
+                 return JS_FALSE;
+             break;
+           case 'd':
+             if (!js_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
+                 return JS_FALSE;
+             break;
+           case 'I':
+             if (!js_ValueToNumber(cx, *sp, &d))
+                 return JS_FALSE;
+             *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
+             break;
+           case 's':
+           case 'S':
+           case 'W':
+             str = js_ValueToString(cx, *sp);
+             if (!str)
+                 return JS_FALSE;
+             *sp = STRING_TO_JSVAL(str);
+             if (c == 's')
+                 *va_arg(ap, char **) = JS_GetStringBytes(str);
+             else if (c == 'W')
+                 *va_arg(ap, jschar **) = JS_GetStringChars(str);
+             else
+                 *va_arg(ap, JSString **) = str;
+             break;
+           case 'o':
+             if (!js_ValueToObject(cx, *sp, &obj))
+                 return JS_FALSE;
+             *sp = OBJECT_TO_JSVAL(obj);
+             *va_arg(ap, JSObject **) = obj;
+             break;
+           case 'f':
+             obj = js_ValueToFunctionObject(cx, sp, 0);
+             if (!obj)
+                 return JS_FALSE;
+             *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj);
+             break;
+           case 'v':
+             *va_arg(ap, jsval *) = *sp;
+             break;
+           case '*':
+             break;
+           default:
+             format--;
+             if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
+                                       JS_ADDRESSOF_VA_LIST(ap))) {
+                 return JS_FALSE;
+             }
+             /* NB: the formatter already updated sp, so we continue here. */
+             continue;
+         }
+         sp++;
+     }
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(jsval *)
+ JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
+ {
+     va_list ap;
+     jsval *argv;
+ 
+     va_start(ap, format);
+     argv = JS_PushArgumentsVA(cx, markp, format, ap);
+     va_end(ap);
+     return argv;
+ }
+ 
+ JS_PUBLIC_API(jsval *)
+ JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
+ {
+     uintN argc;
+     jsval *argv, *sp;
+     char c;
+     const char *cp;
+     JSString *str;
+     JSFunction *fun;
+     JSStackHeader *sh;
+ 
+     CHECK_REQUEST(cx);
+     *markp = NULL;
+     argc = 0;
+     for (cp = format; (c = *cp) != '\0'; cp++) {
+         /*
+          * Count non-space non-star characters as individual jsval arguments.
+          * This may over-allocate stack, but we'll fix below.
+          */
+         if (isspace(c) || c == '*')
+             continue;
+         argc++;
+     }
+     sp = js_AllocStack(cx, argc, markp);
+     if (!sp)
+         return NULL;
+     argv = sp;
+     while ((c = *format++) != '\0') {
+         if (isspace(c) || c == '*')
+             continue;
+         switch (c) {
+           case 'b':
+             *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int));
+             break;
+           case 'c':
+             *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int));
+             break;
+           case 'i':
+           case 'j':
+             if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
+                 goto bad;
+             break;
+           case 'u':
+             if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
+                 goto bad;
+             break;
+           case 'd':
+           case 'I':
+             if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
+                 goto bad;
+             break;
+           case 's':
+             str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
+             if (!str)
+                 goto bad;
+             *sp = STRING_TO_JSVAL(str);
+             break;
+           case 'W':
+             str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
+             if (!str)
+                 goto bad;
+             *sp = STRING_TO_JSVAL(str);
+             break;
+           case 'S':
+             str = va_arg(ap, JSString *);
+             *sp = STRING_TO_JSVAL(str);
+             break;
+           case 'o':
+             *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
+             break;
+           case 'f':
+             fun = va_arg(ap, JSFunction *);
+             *sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
+             break;
+           case 'v':
+             *sp = va_arg(ap, jsval);
+             break;
+           default:
+             format--;
+             if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp,
+                                       JS_ADDRESSOF_VA_LIST(ap))) {
+                 goto bad;
+             }
+             /* NB: the formatter already updated sp, so we continue here. */
+             continue;
+         }
+         sp++;
+     }
+ 
+     /*
+      * We may have overallocated stack due to a multi-character format code
+      * handled by a JSArgumentFormatter.  Give back that stack space!
+      */
+     JS_ASSERT(sp <= argv + argc);
+     if (sp < argv + argc) {
+         /* Return slots not pushed to the current stack arena. */
+         cx->stackPool.current->avail = (jsuword)sp;
+ 
+         /* Reduce the count of slots the GC will scan in this stack segment. */
+         sh = cx->stackHeaders;
+         JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc);
+         sh->nslots -= argc - (sp - argv);
+     }
+     return argv;
+ 
+ bad:
+     js_FreeStack(cx, *markp);
+     return NULL;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_PopArguments(JSContext *cx, void *mark)
+ {
+     CHECK_REQUEST(cx);
+     js_FreeStack(cx, mark);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_AddArgumentFormatter(JSContext *cx, const char *format,
+                         JSArgumentFormatter formatter)
+ {
+     size_t length;
+     JSArgumentFormatMap **mpp, *map;
+ 
+     length = strlen(format);
+     mpp = &cx->argumentFormatMap;
+     while ((map = *mpp) != NULL) {
+         /* Insert before any shorter string to match before prefixes. */
+         if (map->length < length)
+             break;
+         if (map->length == length && !strcmp(map->format, format))
+             goto out;
+         mpp = &map->next;
+     }
+     map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map);
+     if (!map)
+         return JS_FALSE;
+     map->format = format;
+     map->length = length;
+     map->next = *mpp;
+     *mpp = map;
+ out:
+     map->formatter = formatter;
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
+ {
+     size_t length;
+     JSArgumentFormatMap **mpp, *map;
+ 
+     length = strlen(format);
+     mpp = &cx->argumentFormatMap;
+     while ((map = *mpp) != NULL) {
+         if (map->length == length && !strcmp(map->format, format)) {
+             *mpp = map->next;
+             JS_free(cx, map);
+             return;
+         }
+         mpp = &map->next;
+     }
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
+ {
+     JSBool ok, b;
+     JSObject *obj;
+     JSString *str;
+     jsdouble d, *dp;
+ 
+     CHECK_REQUEST(cx);
+     switch (type) {
+       case JSTYPE_VOID:
+         *vp = JSVAL_VOID;
+         ok = JS_TRUE;
+         break;
+       case JSTYPE_OBJECT:
+         ok = js_ValueToObject(cx, v, &obj);
+         if (ok)
+             *vp = OBJECT_TO_JSVAL(obj);
+         break;
+       case JSTYPE_FUNCTION:
+         *vp = v;
+         obj = js_ValueToFunctionObject(cx, vp, JSV2F_SEARCH_STACK);
+         ok = (obj != NULL);
+         break;
+       case JSTYPE_STRING:
+         str = js_ValueToString(cx, v);
+         ok = (str != NULL);
+         if (ok)
+             *vp = STRING_TO_JSVAL(str);
+         break;
+       case JSTYPE_NUMBER:
+         ok = js_ValueToNumber(cx, v, &d);
+         if (ok) {
+             dp = js_NewDouble(cx, d, 0);
+             ok = (dp != NULL);
+             if (ok)
+                 *vp = DOUBLE_TO_JSVAL(dp);
+         }
+         break;
+       case JSTYPE_BOOLEAN:
+         ok = js_ValueToBoolean(cx, v, &b);
+         if (ok)
+             *vp = BOOLEAN_TO_JSVAL(b);
+         break;
+       default: {
+         char numBuf[12];
+         JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
+         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE,
+                              numBuf);
+         ok = JS_FALSE;
+         break;
+       }
+     }
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToObject(cx, v, objp);
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_ValueToFunction(JSContext *cx, jsval v)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_ValueToConstructor(JSContext *cx, jsval v)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_ValueToString(JSContext *cx, jsval v)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToString(cx, v);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToNumber(cx, v, dp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToECMAInt32(cx, v, ip);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToECMAUint32(cx, v, ip);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToInt32(cx, v, ip);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToUint16(cx, v, ip);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
+ {
+     CHECK_REQUEST(cx);
+     return js_ValueToBoolean(cx, v, bp);
+ }
+ 
+ JS_PUBLIC_API(JSType)
+ JS_TypeOfValue(JSContext *cx, jsval v)
+ {
+     JSType type;
+     JSObject *obj;
+     JSObjectOps *ops;
+     JSClass *clasp;
+ 
+     CHECK_REQUEST(cx);
+     if (JSVAL_IS_OBJECT(v)) {
+         type = JSTYPE_OBJECT;           /* XXXbe JSTYPE_NULL for JS2 */
+         obj = JSVAL_TO_OBJECT(v);
+         if (obj) {
+             ops = obj->map->ops;
+ #if JS_HAS_XML_SUPPORT
+             if (ops == &js_XMLObjectOps.base) {
+                 type = JSTYPE_XML;
+             } else
+ #endif
+             {
+                 /*
+                  * ECMA 262, 11.4.3 says that any native object that implements
+                  * [[Call]] should be of type "function". Note that RegExp and
+                  * Script are both of type "function" for compatibility with
+                  * older SpiderMonkeys.
+                  */
+                 clasp = OBJ_GET_CLASS(cx, obj);
+                 if ((ops == &js_ObjectOps)
+                     ? (clasp->call
+                        ? (clasp == &js_RegExpClass || clasp == &js_ScriptClass)
+                        : clasp == &js_FunctionClass)
+                     : ops->call != NULL) {
+                     type = JSTYPE_FUNCTION;
+                 } else {
+ #ifdef NARCISSUS
+                     if (!OBJ_GET_PROPERTY(cx, obj,
+                                           ATOM_TO_JSID(cx->runtime->atomState
+                                                        .callAtom),
+                                           &v)) {
+                         JS_ClearPendingException(cx);
+                     } else if (JSVAL_IS_FUNCTION(cx, v)) {
+                         type = JSTYPE_FUNCTION;
+                     }
+ #endif
+                 }
+             }
+         }
+     } else if (JSVAL_IS_NUMBER(v)) {
+         type = JSTYPE_NUMBER;
+     } else if (JSVAL_IS_STRING(v)) {
+         type = JSTYPE_STRING;
+     } else if (JSVAL_IS_BOOLEAN(v)) {
+         type = JSTYPE_BOOLEAN;
+     } else {
+         type = JSTYPE_VOID;
+     }
+     return type;
+ }
+ 
+ JS_PUBLIC_API(const char *)
+ JS_GetTypeName(JSContext *cx, JSType type)
+ {
+     if ((uintN)type >= (uintN)JSTYPE_LIMIT)
+         return NULL;
+     return js_type_str[type];
+ }
+ 
+ /************************************************************************/
+ 
+ JS_PUBLIC_API(JSRuntime *)
+ JS_NewRuntime(uint32 maxbytes)
+ {
+     JSRuntime *rt;
+ 
+ #ifdef DEBUG
+     JS_BEGIN_MACRO
+     /*
+      * This code asserts that the numbers associated with the error names in
+      * jsmsg.def are monotonically increasing.  It uses values for the error
+      * names enumerated in jscntxt.c.  It's not a compiletime check, but it's
+      * better than nothing.
+      */
+     int errorNumber = 0;
+ #define MSG_DEF(name, number, count, exception, format) \
+     JS_ASSERT(name == errorNumber++);
+ #include "js.msg"
+ #undef MSG_DEF
+     JS_END_MACRO;
+ #endif /* DEBUG */
+ 
+     if (!js_InitStringGlobals())
+         return NULL;
+     rt = (JSRuntime *) malloc(sizeof(JSRuntime));
+     if (!rt)
+         return NULL;
+ 
+     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
+     memset(rt, 0, sizeof(JSRuntime));
+     JS_INIT_CLIST(&rt->contextList);
+     JS_INIT_CLIST(&rt->trapList);
+     JS_INIT_CLIST(&rt->watchPointList);
+ 
+     if (!js_InitGC(rt, maxbytes))
+         goto bad;
+ #ifdef JS_THREADSAFE
+     rt->gcLock = JS_NEW_LOCK();
+     if (!rt->gcLock)
+         goto bad;
+     rt->gcDone = JS_NEW_CONDVAR(rt->gcLock);
+     if (!rt->gcDone)
+         goto bad;
+     rt->requestDone = JS_NEW_CONDVAR(rt->gcLock);
+     if (!rt->requestDone)
+         goto bad;
+     /* this is asymmetric with JS_ShutDown: */
+     if (!js_SetupLocks(8, 16))
+         goto bad;
+     rt->rtLock = JS_NEW_LOCK();
+     if (!rt->rtLock)
+         goto bad;
+     rt->stateChange = JS_NEW_CONDVAR(rt->gcLock);
+     if (!rt->stateChange)
+         goto bad;
+     rt->setSlotLock = JS_NEW_LOCK();
+     if (!rt->setSlotLock)
+         goto bad;
+     rt->setSlotDone = JS_NEW_CONDVAR(rt->setSlotLock);
+     if (!rt->setSlotDone)
+         goto bad;
+     rt->scopeSharingDone = JS_NEW_CONDVAR(rt->gcLock);
+     if (!rt->scopeSharingDone)
+         goto bad;
+     rt->scopeSharingTodo = NO_SCOPE_SHARING_TODO;
+ #endif
+     rt->propertyCache.empty = JS_TRUE;
+     if (!js_InitPropertyTree(rt))
+         goto bad;
+     return rt;
+ 
+ bad:
+     JS_DestroyRuntime(rt);
+     return NULL;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_DestroyRuntime(JSRuntime *rt)
+ {
+ #ifdef DEBUG
+     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
+     if (!JS_CLIST_IS_EMPTY(&rt->contextList)) {
+         JSContext *cx, *iter = NULL;
+         uintN cxcount = 0;
+         while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL)
+             cxcount++;
+         fprintf(stderr,
+ "JS API usage error: %u contexts left in runtime upon JS_DestroyRuntime.\n",
+                 cxcount);
+     }
+ #endif
+ 
+     js_FreeRuntimeScriptState(rt);
+     js_FinishAtomState(&rt->atomState);
+     js_FinishGC(rt);
+ #ifdef JS_THREADSAFE
+     if (rt->gcLock)
+         JS_DESTROY_LOCK(rt->gcLock);
+     if (rt->gcDone)
+         JS_DESTROY_CONDVAR(rt->gcDone);
+     if (rt->requestDone)
+         JS_DESTROY_CONDVAR(rt->requestDone);
+     if (rt->rtLock)
+         JS_DESTROY_LOCK(rt->rtLock);
+     if (rt->stateChange)
+         JS_DESTROY_CONDVAR(rt->stateChange);
+     if (rt->setSlotLock)
+         JS_DESTROY_LOCK(rt->setSlotLock);
+     if (rt->setSlotDone)
+         JS_DESTROY_CONDVAR(rt->setSlotDone);
+     if (rt->scopeSharingDone)
+         JS_DESTROY_CONDVAR(rt->scopeSharingDone);
+ #endif
+     js_FinishPropertyTree(rt);
+     free(rt);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ShutDown(void)
+ {
+     JS_ArenaShutDown();
+     js_FinishDtoa();
+     js_FreeStringGlobals();
+ #ifdef JS_THREADSAFE
+     js_CleanupLocks();
+ #endif
+ }
+ 
+ JS_PUBLIC_API(void *)
+ JS_GetRuntimePrivate(JSRuntime *rt)
+ {
+     return rt->data;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_SetRuntimePrivate(JSRuntime *rt, void *data)
+ {
+     rt->data = data;
+ }
+ 
+ #ifdef JS_THREADSAFE
+ 
+ JS_PUBLIC_API(void)
+ JS_BeginRequest(JSContext *cx)
+ {
+     JSRuntime *rt;
+ 
+     JS_ASSERT(cx->thread);
+     if (!cx->requestDepth) {
+         /* Wait until the GC is finished. */
+         rt = cx->runtime;
+         JS_LOCK_GC(rt);
+ 
+         /* NB: we use cx->thread here, not js_CurrentThreadId(). */
+         if (rt->gcThread != cx->thread) {
+             while (rt->gcLevel > 0)
+                 JS_AWAIT_GC_DONE(rt);
+         }
+ 
+         /* Indicate that a request is running. */
+         rt->requestCount++;
+         cx->requestDepth = 1;
+         JS_UNLOCK_GC(rt);
+         return;
+     }
+     cx->requestDepth++;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_EndRequest(JSContext *cx)
+ {
+     JSRuntime *rt;
+     JSScope *scope, **todop;
+     uintN nshares;
+ 
+     CHECK_REQUEST(cx);
+     JS_ASSERT(cx->requestDepth > 0);
+     if (cx->requestDepth == 1) {
+         /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
+         rt = cx->runtime;
+         JS_LOCK_GC(rt);
+         cx->requestDepth = 0;
+ 
+         /* See whether cx has any single-threaded scopes to start sharing. */
+         todop = &rt->scopeSharingTodo;
+         nshares = 0;
+         while ((scope = *todop) != NO_SCOPE_SHARING_TODO) {
+             if (scope->ownercx != cx) {
+                 todop = &scope->u.link;
+                 continue;
+             }
+             *todop = scope->u.link;
+             scope->u.link = NULL;       /* null u.link for sanity ASAP */
+ 
+             /*
+              * If js_DropObjectMap returns null, we held the last ref to scope.
+              * The waiting thread(s) must have been killed, after which the GC
+              * collected the object that held this scope.  Unlikely, because it
+              * requires that the GC ran (e.g., from a branch callback) during
+              * this request, but possible.
+              */
+             if (js_DropObjectMap(cx, &scope->map, NULL)) {
+                 js_InitLock(&scope->lock);
+                 scope->u.count = 0;                 /* NULL may not pun as 0 */
+                 js_FinishSharingScope(rt, scope);   /* set ownercx = NULL */
+                 nshares++;
+             }
+         }
+         if (nshares)
+             JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone);
+ 
+         /* Give the GC a chance to run if this was the last request running. */
+         JS_ASSERT(rt->requestCount > 0);
+         rt->requestCount--;
+         if (rt->requestCount == 0)
+             JS_NOTIFY_REQUEST_DONE(rt);
+ 
+         JS_UNLOCK_GC(rt);
+         return;
+     }
+ 
+     cx->requestDepth--;
+ }
+ 
+ /* Yield to pending GC operations, regardless of request depth */
+ JS_PUBLIC_API(void)
+ JS_YieldRequest(JSContext *cx)
+ {
+     JSRuntime *rt;
+ 
+     JS_ASSERT(cx->thread);
+     CHECK_REQUEST(cx);
+ 
+     rt = cx->runtime;
+     JS_LOCK_GC(rt);
+     JS_ASSERT(rt->requestCount > 0);
+     rt->requestCount--;
+     if (rt->requestCount == 0)
+         JS_NOTIFY_REQUEST_DONE(rt);
+     JS_UNLOCK_GC(rt);
+     /* XXXbe give the GC or another request calling it a chance to run here?
+              Assumes FIFO scheduling */
+     JS_LOCK_GC(rt);
+     rt->requestCount++;
+     JS_UNLOCK_GC(rt);
+ }
+ 
+ JS_PUBLIC_API(jsrefcount)
+ JS_SuspendRequest(JSContext *cx)
+ {
+     jsrefcount saveDepth = cx->requestDepth;
+ 
+     while (cx->requestDepth)
+         JS_EndRequest(cx);
+     return saveDepth;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
+ {
+     JS_ASSERT(!cx->requestDepth);
+     while (--saveDepth >= 0)
+         JS_BeginRequest(cx);
+ }
+ 
+ #endif /* JS_THREADSAFE */
+ 
+ JS_PUBLIC_API(void)
+ JS_Lock(JSRuntime *rt)
+ {
+     JS_LOCK_RUNTIME(rt);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_Unlock(JSRuntime *rt)
+ {
+     JS_UNLOCK_RUNTIME(rt);
+ }
+ 
+ JS_PUBLIC_API(JSContext *)
+ JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
+ {
+     return js_NewContext(rt, stackChunkSize);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_DestroyContext(JSContext *cx)
+ {
+     js_DestroyContext(cx, JS_FORCE_GC);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_DestroyContextNoGC(JSContext *cx)
+ {
+     js_DestroyContext(cx, JS_NO_GC);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_DestroyContextMaybeGC(JSContext *cx)
+ {
+     js_DestroyContext(cx, JS_MAYBE_GC);
+ }
+ 
+ JS_PUBLIC_API(void *)
+ JS_GetContextPrivate(JSContext *cx)
+ {
+     return cx->data;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_SetContextPrivate(JSContext *cx, void *data)
+ {
+     cx->data = data;
+ }
+ 
+ JS_PUBLIC_API(JSRuntime *)
+ JS_GetRuntime(JSContext *cx)
+ {
+     return cx->runtime;
+ }
+ 
+ JS_PUBLIC_API(JSContext *)
+ JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
+ {
+     return js_ContextIterator(rt, JS_TRUE, iterp);
+ }
+ 
+ JS_PUBLIC_API(JSVersion)
+ JS_GetVersion(JSContext *cx)
+ {
+     return cx->version & JSVERSION_MASK;
+ }
+ 
+ JS_PUBLIC_API(JSVersion)
+ JS_SetVersion(JSContext *cx, JSVersion version)
+ {
+     JSVersion oldVersion;
+ 
+     JS_ASSERT(version != JSVERSION_UNKNOWN);
+     JS_ASSERT((version & ~JSVERSION_MASK) == 0);
+ 
+     oldVersion = cx->version & JSVERSION_MASK;
+     if (version == oldVersion)
+         return oldVersion;
+ 
+     cx->version = (cx->version & ~JSVERSION_MASK) | version;
+     js_OnVersionChange(cx);
+     return oldVersion;
+ }
+ 
+ static struct v2smap {
+     JSVersion   version;
+     const char  *string;
+ } v2smap[] = {
+     {JSVERSION_1_0,     "1.0"},
+     {JSVERSION_1_1,     "1.1"},
+     {JSVERSION_1_2,     "1.2"},
+     {JSVERSION_1_3,     "1.3"},
+     {JSVERSION_1_4,     "1.4"},
+     {JSVERSION_ECMA_3,  "ECMAv3"},
+     {JSVERSION_1_5,     "1.5"},
+     {JSVERSION_1_6,     "1.6"},
+     {JSVERSION_DEFAULT, js_default_str},
+     {JSVERSION_UNKNOWN, NULL},          /* must be last, NULL is sentinel */
+ };
+ 
+ JS_PUBLIC_API(const char *)
+ JS_VersionToString(JSVersion version)
+ {
+     int i;
+ 
+     for (i = 0; v2smap[i].string; i++)
+         if (v2smap[i].version == version)
+             return v2smap[i].string;
+     return "unknown";
+ }
+ 
+ JS_PUBLIC_API(JSVersion)
+ JS_StringToVersion(const char *string)
+ {
+     int i;
+ 
+     for (i = 0; v2smap[i].string; i++)
+         if (strcmp(v2smap[i].string, string) == 0)
+             return v2smap[i].version;
+     return JSVERSION_UNKNOWN;
+ }
+ 
+ JS_PUBLIC_API(uint32)
+ JS_GetOptions(JSContext *cx)
+ {
+     return cx->options;
+ }
+ 
+ #define SYNC_OPTIONS_TO_VERSION(cx)                                           \
+     JS_BEGIN_MACRO                                                            \
+         if ((cx)->options & JSOPTION_XML)                                     \
+             (cx)->version |= JSVERSION_HAS_XML;                               \
+         else                                                                  \
+             (cx)->version &= ~JSVERSION_HAS_XML;                              \
+     JS_END_MACRO
+ 
+ JS_PUBLIC_API(uint32)
+ JS_SetOptions(JSContext *cx, uint32 options)
+ {
+     uint32 oldopts = cx->options;
+     cx->options = options;
+     SYNC_OPTIONS_TO_VERSION(cx);
+     return oldopts;
+ }
+ 
+ JS_PUBLIC_API(uint32)
+ JS_ToggleOptions(JSContext *cx, uint32 options)
+ {
+     uint32 oldopts = cx->options;
+     cx->options ^= options;
+     SYNC_OPTIONS_TO_VERSION(cx);
+     return oldopts;
+ }
+ 
+ JS_PUBLIC_API(const char *)
+ JS_GetImplementationVersion(void)
+ {
+     return "JavaScript-C 1.6 pre-release 1 2006-04-04";
+ }
+ 
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_GetGlobalObject(JSContext *cx)
+ {
+     return cx->globalObject;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_SetGlobalObject(JSContext *cx, JSObject *obj)
+ {
+     cx->globalObject = obj;
+ #if JS_HAS_XML_SUPPORT
+     cx->xmlSettingFlags = 0;
+ #endif
+ }
+ 
+ static JSObject *
+ InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
+ {
+     JSDHashTable *table;
+     JSBool resolving;
+     JSRuntime *rt;
+     JSResolvingKey key;
+     JSResolvingEntry *entry;
+     JSObject *fun_proto, *obj_proto;
+ 
+     /* If cx has no global object, use obj so prototypes can be found. */
+     if (!cx->globalObject)
+         JS_SetGlobalObject(cx, obj);
+ 
+     /* Record Function and Object in cx->resolvingTable, if we are resolving. */
+     table = cx->resolvingTable;
+     resolving = (table && table->entryCount);
+     if (resolving) {
+         rt = cx->runtime;
+         key.obj = obj;
+         key.id = ATOM_TO_JSID(rt->atomState.FunctionAtom);
+         entry = (JSResolvingEntry *)
+                 JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
+         if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) {
+             /* Already resolving Function, record Object too. */
+             JS_ASSERT(entry->key.obj == obj);
+             key.id = ATOM_TO_JSID(rt->atomState.ObjectAtom);
+             entry = (JSResolvingEntry *)
+                     JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
+         }
+         if (!entry) {
+             JS_ReportOutOfMemory(cx);
+             return NULL;
+         }
+         JS_ASSERT(!entry->key.obj && entry->flags == 0);
+         entry->key = key;
+         entry->flags = JSRESFLAG_LOOKUP;
+     }
+ 
+     /* Initialize the function class first so constructors can be made. */
+     fun_proto = js_InitFunctionClass(cx, obj);
+     if (!fun_proto)
+         goto out;
+ 
+     /* Initialize the object class next so Object.prototype works. */
+     obj_proto = js_InitObjectClass(cx, obj);
+     if (!obj_proto) {
+         fun_proto = NULL;
+         goto out;
+     }
+ 
+     /* Function.prototype and the global object delegate to Object.prototype. */
+     OBJ_SET_PROTO(cx, fun_proto, obj_proto);
+     if (!OBJ_GET_PROTO(cx, obj))
+         OBJ_SET_PROTO(cx, obj, obj_proto);
+ 
+ out:
+     /* If resolving, remove the other entry (Object or Function) from table. */
+     if (resolving)
+         JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
+     return fun_proto;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
+ {
+     CHECK_REQUEST(cx);
+ 
+ #if JS_HAS_UNDEFINED
+ {
+     /* Define a top-level property 'undefined' with the undefined value. */
+     JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
+     if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+                              NULL, NULL, JSPROP_PERMANENT, NULL)) {
+         return JS_FALSE;
+     }
+ }
+ #endif
+ 
+     /* Function and Object require cooperative bootstrapping magic. */
+     if (!InitFunctionAndObjectClasses(cx, obj))
+         return JS_FALSE;
+ 
+     /* Initialize the rest of the standard objects and functions. */
+     return js_InitArrayClass(cx, obj) &&
+            js_InitBooleanClass(cx, obj) &&
+            js_InitMathClass(cx, obj) &&
+            js_InitNumberClass(cx, obj) &&
+            js_InitStringClass(cx, obj) &&
+ #if JS_HAS_CALL_OBJECT
+            js_InitCallClass(cx, obj) &&
+ #endif
+ #if JS_HAS_REGEXPS
+            js_InitRegExpClass(cx, obj) &&
+ #endif
+ #if JS_HAS_SCRIPT_OBJECT
+            js_InitScriptClass(cx, obj) &&
+ #endif
+ #if JS_HAS_ERROR_EXCEPTIONS
+            js_InitExceptionClasses(cx, obj) &&
+ #endif
+ #if JS_HAS_XML_SUPPORT
+            js_InitXMLClasses(cx, obj) &&
+ #endif
+ #if JS_HAS_FILE_OBJECT
+            js_InitFileClass(cx, obj) &&
+ #endif
+            js_InitDateClass(cx, obj);
+ }
+ 
+ #define ATOM_OFFSET(name)       offsetof(JSAtomState, name##Atom)
+ #define OFFSET_TO_ATOM(rt,off)  (*(JSAtom **)((char*)&(rt)->atomState + (off)))
+ 
+ /*
+  * Table of class initializers and their atom offsets in rt->atomState.
+  * If you add a "standard" class, remember to update this table.
+  */
+ static struct {
+     JSObjectOp  init;
+     size_t      atomOffset;
+ } standard_class_atoms[] = {
+     {InitFunctionAndObjectClasses,  ATOM_OFFSET(Function)},
+     {InitFunctionAndObjectClasses,  ATOM_OFFSET(Object)},
+     {js_InitArrayClass,             ATOM_OFFSET(Array)},
+     {js_InitBooleanClass,           ATOM_OFFSET(Boolean)},
+     {js_InitDateClass,              ATOM_OFFSET(Date)},
+     {js_InitMathClass,              ATOM_OFFSET(Math)},
+     {js_InitNumberClass,            ATOM_OFFSET(Number)},
+     {js_InitStringClass,            ATOM_OFFSET(String)},
+ #if JS_HAS_CALL_OBJECT
+     {js_InitCallClass,              ATOM_OFFSET(Call)},
+ #endif
+ #if JS_HAS_ERROR_EXCEPTIONS
+     {js_InitExceptionClasses,       ATOM_OFFSET(Error)},
+ #endif
+ #if JS_HAS_REGEXPS
+     {js_InitRegExpClass,            ATOM_OFFSET(RegExp)},
+ #endif
+ #if JS_HAS_SCRIPT_OBJECT
+     {js_InitScriptClass,            ATOM_OFFSET(Script)},
+ #endif
+ #if JS_HAS_XML_SUPPORT
+     {js_InitXMLClass,               ATOM_OFFSET(XML)},
+     {js_InitNamespaceClass,         ATOM_OFFSET(Namespace)},
+     {js_InitQNameClass,             ATOM_OFFSET(QName)},
+ #endif
+ #if JS_HAS_FILE_OBJECT
+     {js_InitFileClass,              ATOM_OFFSET(File)},
+ #endif
+     {NULL,                          0}
+ };
+ 
+ /*
+  * Table of top-level function and constant names and their init functions.
+  * If you add a "standard" global function or property, remember to update
+  * this table.
+  */
+ typedef struct JSStdName {
+     JSObjectOp  init;
+     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
+     const char  *name;          /* null if atom is pre-pinned, else name */
+ } JSStdName;
+ 
+ static JSAtom *
+ StdNameToAtom(JSContext *cx, JSStdName *stdn)
+ {
+     size_t offset;
+     JSAtom *atom;
+     const char *name;
+ 
+     offset = stdn->atomOffset;
+     atom = OFFSET_TO_ATOM(cx->runtime, offset);
+     if (!atom) {
+         name = stdn->name;
+         if (name) {
+             atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED);
+             OFFSET_TO_ATOM(cx->runtime, offset) = atom;
+         }
+     }
+     return atom;
+ }
+ 
+ #define EAGERLY_PINNED_ATOM(name)   ATOM_OFFSET(name), NULL
+ #define LAZILY_PINNED_ATOM(name)    ATOM_OFFSET(lazy.name), js_##name##_str
+ 
+ static JSStdName standard_class_names[] = {
+     /* ECMA requires that eval be a direct property of the global object. */
+     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(eval)},
+ 
+     /* Global properties and functions defined by the Number class. */
+     {js_InitNumberClass,        LAZILY_PINNED_ATOM(NaN)},
+     {js_InitNumberClass,        LAZILY_PINNED_ATOM(Infinity)},
+     {js_InitNumberClass,        LAZILY_PINNED_ATOM(isNaN)},
+     {js_InitNumberClass,        LAZILY_PINNED_ATOM(isFinite)},
+     {js_InitNumberClass,        LAZILY_PINNED_ATOM(parseFloat)},
+     {js_InitNumberClass,        LAZILY_PINNED_ATOM(parseInt)},
+ 
+     /* String global functions. */
+     {js_InitStringClass,        LAZILY_PINNED_ATOM(escape)},
+     {js_InitStringClass,        LAZILY_PINNED_ATOM(unescape)},
+     {js_InitStringClass,        LAZILY_PINNED_ATOM(decodeURI)},
+     {js_InitStringClass,        LAZILY_PINNED_ATOM(encodeURI)},
+     {js_InitStringClass,        LAZILY_PINNED_ATOM(decodeURIComponent)},
+     {js_InitStringClass,        LAZILY_PINNED_ATOM(encodeURIComponent)},
+ #if JS_HAS_UNEVAL
+     {js_InitStringClass,        LAZILY_PINNED_ATOM(uneval)},
+ #endif
+ 
+     /* Exception constructors. */
+ #if JS_HAS_ERROR_EXCEPTIONS
+     {js_InitExceptionClasses,   EAGERLY_PINNED_ATOM(Error)},
+     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(InternalError)},
+     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(EvalError)},
+     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(RangeError)},
+     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(ReferenceError)},
+     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(SyntaxError)},
+     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(TypeError)},
+     {js_InitExceptionClasses,   LAZILY_PINNED_ATOM(URIError)},
+ #endif
+ 
+ #if JS_HAS_XML_SUPPORT
+     {js_InitAnyNameClass,       LAZILY_PINNED_ATOM(AnyName)},
+     {js_InitAttributeNameClass, LAZILY_PINNED_ATOM(AttributeName)},
+     {js_InitXMLClass,           LAZILY_PINNED_ATOM(XMLList)},
+     {js_InitXMLClass,           LAZILY_PINNED_ATOM(isXMLName)},
+ #endif
+ 
+     {NULL,                      0, NULL}
+ };
+ 
+ static JSStdName object_prototype_names[] = {
+     /* Object.prototype properties (global delegates to Object.prototype). */
+     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(proto)},
+     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(parent)},
+     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(count)},
+ #if JS_HAS_TOSOURCE
+     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toSource)},
+ #endif
+     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toString)},
+     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(toLocaleString)},
+     {js_InitObjectClass,        EAGERLY_PINNED_ATOM(valueOf)},
+ #if JS_HAS_OBJ_WATCHPOINT
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(watch)},
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(unwatch)},
+ #endif
+ #if JS_HAS_NEW_OBJ_METHODS
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(hasOwnProperty)},
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(isPrototypeOf)},
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(propertyIsEnumerable)},
+ #endif
+ #if JS_HAS_GETTER_SETTER
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(defineGetter)},
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(defineSetter)},
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(lookupGetter)},
+     {js_InitObjectClass,        LAZILY_PINNED_ATOM(lookupSetter)},
+ #endif
+ 
+     {NULL,                      0, NULL}
+ };
+ 
+ #undef EAGERLY_PINNED_ATOM
+ #undef LAZILY_PINNED_ATOM
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
+                         JSBool *resolved)
+ {
+     JSString *idstr;
+     JSRuntime *rt;
+     JSAtom *atom;
+     JSObjectOp init;
+     uintN i;
+ 
+     CHECK_REQUEST(cx);
+     *resolved = JS_FALSE;
+ 
+     if (!JSVAL_IS_STRING(id))
+         return JS_TRUE;
+     idstr = JSVAL_TO_STRING(id);
+     rt = cx->runtime;
+ 
+ #if JS_HAS_UNDEFINED
+     /* Check whether we're resolving 'undefined', and define it if so. */
+     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+     if (idstr == ATOM_TO_STRING(atom)) {
+         *resolved = JS_TRUE;
+         return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+                                    NULL, NULL, JSPROP_PERMANENT, NULL);
+     }
+ #endif
+ 
+     /* Try for class constructors/prototypes named by well-known atoms. */
+     init = NULL;
+     for (i = 0; standard_class_atoms[i].init; i++) {
+         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
+         if (idstr == ATOM_TO_STRING(atom)) {
+             init = standard_class_atoms[i].init;
+             break;
+         }
+     }
+ 
+     if (!init) {
+         /* Try less frequently used top-level functions and constants. */
+         for (i = 0; standard_class_names[i].init; i++) {
+             atom = StdNameToAtom(cx, &standard_class_names[i]);
+             if (!atom)
+                 return JS_FALSE;
+             if (idstr == ATOM_TO_STRING(atom)) {
+                 init = standard_class_names[i].init;
+                 break;
+             }
+         }
+ 
+         if (!init && !OBJ_GET_PROTO(cx, obj)) {
+             /*
+              * Try even less frequently used names delegated from the global
+              * object to Object.prototype, but only if the Object class hasn't
+              * yet been initialized.
+              */
+             for (i = 0; object_prototype_names[i].init; i++) {
+                 atom = StdNameToAtom(cx, &object_prototype_names[i]);
+                 if (!atom)
+                     return JS_FALSE;
+                 if (idstr == ATOM_TO_STRING(atom)) {
+                     init = standard_class_names[i].init;
+                     break;
+                 }
+             }
+         }
+     }
+ 
+     if (init) {
+         if (!init(cx, obj))
+             return JS_FALSE;
+         *resolved = JS_TRUE;
+     }
+     return JS_TRUE;
+ }
+ 
+ static JSBool
+ AlreadyHasOwnProperty(JSObject *obj, JSAtom *atom)
+ {
+     JS_ASSERT(OBJ_IS_NATIVE(obj));
+     return SCOPE_GET_PROPERTY(OBJ_SCOPE(obj), ATOM_TO_JSID(atom)) != NULL;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
+ {
+     JSRuntime *rt;
+     JSAtom *atom;
+     uintN i;
+ 
+     CHECK_REQUEST(cx);
+     rt = cx->runtime;
+ 
+ #if JS_HAS_UNDEFINED
+     /* Check whether we need to bind 'undefined' and define it if so. */
+     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+     if (!AlreadyHasOwnProperty(obj, atom) &&
+         !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+                              NULL, NULL, JSPROP_PERMANENT, NULL)) {
+         return JS_FALSE;
+     }
+ #endif
+ 
+     /* Initialize any classes that have not been resolved yet. */
+     for (i = 0; standard_class_atoms[i].init; i++) {
+         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
+         if (!AlreadyHasOwnProperty(obj, atom) &&
+             !standard_class_atoms[i].init(cx, obj)) {
+             return JS_FALSE;
+         }
+     }
+ 
+     return JS_TRUE;
+ }
+ 
+ static JSIdArray *
+ AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip)
+ {
+     jsint i, length;
+     
+     i = *ip;
+     length = ida->length;
+     if (i >= length) {
+         ida = js_SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8));
+         if (!ida)
+             return NULL;
+         JS_ASSERT(i < ida->length);
+     }
+     ida->vector[i] = ATOM_TO_JSID(atom);
+     *ip = i + 1;
+     return ida;
+ }
+ 
+ static JSIdArray *
+ EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
+                     jsint *ip, JSBool *foundp)
+ {
+     *foundp = AlreadyHasOwnProperty(obj, atom);
+     if (*foundp)
+         ida = AddAtomToArray(cx, atom, ida, ip);
+     return ida;
+ }
+ 
+ JS_PUBLIC_API(JSIdArray *)
+ JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
+                                     JSIdArray *ida)
+ {
+     JSRuntime *rt;
+     jsint i, j, k;
+     JSAtom *atom;
+     JSBool found;
+     JSObjectOp init;
+ 
+     CHECK_REQUEST(cx);
+     rt = cx->runtime;
+     if (ida) {
+         i = ida->length;
+     } else {
+         ida = js_NewIdArray(cx, 8);
+         if (!ida)
+             return NULL;
+         i = 0;
+     }
+ 
+ #if JS_HAS_UNDEFINED
+     /* Check whether 'undefined' has been resolved and enumerate it if so. */
+     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+     ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
+     if (!ida)
+         return NULL;
+ #endif
+ 
+     /* Enumerate only classes that *have* been resolved. */
+     for (j = 0; standard_class_atoms[j].init; j++) {
+         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
+         ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
+         if (!ida)
+             return NULL;
+ 
+         if (found) {
+             init = standard_class_atoms[j].init;
+ 
+             for (k = 0; standard_class_names[k].init; k++) {
+                 if (standard_class_names[k].init == init) {
+                     atom = StdNameToAtom(cx, &standard_class_names[k]);
+                     ida = AddAtomToArray(cx, atom, ida, &i);
+                     if (!ida)
+                         return NULL;
+                 }
+             }
+ 
+             if (init == js_InitObjectClass) {
+                 for (k = 0; object_prototype_names[k].init; k++) {
+                     atom = StdNameToAtom(cx, &object_prototype_names[k]);
+                     ida = AddAtomToArray(cx, atom, ida, &i);
+                     if (!ida)
+                         return NULL;
+                 }
+             }
+         }
+     }
+ 
+     /* Trim to exact length via js_SetIdArrayLength. */
+     return js_SetIdArrayLength(cx, ida, i);
+ }
+ 
+ #undef ATOM_OFFSET
+ #undef OFFSET_TO_ATOM
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_GetScopeChain(JSContext *cx)
+ {
+     return cx->fp ? cx->fp->scopeChain : NULL;
+ }
+ 
+ JS_PUBLIC_API(void *)
+ JS_malloc(JSContext *cx, size_t nbytes)
+ {
+     void *p;
+ 
+     JS_ASSERT(nbytes != 0);
+     if (nbytes == 0)
+         nbytes = 1;
+     cx->runtime->gcMallocBytes += nbytes;
+     p = malloc(nbytes);
+     if (!p)
+         JS_ReportOutOfMemory(cx);
+     return p;
+ }
+ 
+ JS_PUBLIC_API(void *)
+ JS_realloc(JSContext *cx, void *p, size_t nbytes)
+ {
+     p = realloc(p, nbytes);
+     if (!p)
+         JS_ReportOutOfMemory(cx);
+     return p;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_free(JSContext *cx, void *p)
+ {
+     if (p)
+         free(p);
+ }
+ 
+ JS_PUBLIC_API(char *)
+ JS_strdup(JSContext *cx, const char *s)
+ {
+     size_t n;
+     void *p;
+ 
+     n = strlen(s) + 1;
+     p = JS_malloc(cx, n);
+     if (!p)
+         return NULL;
+     return (char *)memcpy(p, s, n);
+ }
+ 
+ JS_PUBLIC_API(jsdouble *)
+ JS_NewDouble(JSContext *cx, jsdouble d)
+ {
+     CHECK_REQUEST(cx);
+     return js_NewDouble(cx, d, 0);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
+ {
+     CHECK_REQUEST(cx);
+     return js_NewDoubleValue(cx, d, rval);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
+ {
+     CHECK_REQUEST(cx);
+     return js_NewNumberValue(cx, d, rval);
+ }
+ 
+ #undef JS_AddRoot
+ JS_PUBLIC_API(JSBool)
+ JS_AddRoot(JSContext *cx, void *rp)
+ {
+     CHECK_REQUEST(cx);
+     return js_AddRoot(cx, rp, NULL);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name)
+ {
+     return js_AddRootRT(rt, rp, name);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_RemoveRoot(JSContext *cx, void *rp)
+ {
+     CHECK_REQUEST(cx);
+     return js_RemoveRoot(cx->runtime, rp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_RemoveRootRT(JSRuntime *rt, void *rp)
+ {
+     return js_RemoveRoot(rt, rp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
+ {
+     CHECK_REQUEST(cx);
+     return js_AddRoot(cx, rp, name);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ClearNewbornRoots(JSContext *cx)
+ {
+     uintN i;
+ 
+     for (i = 0; i < GCX_NTYPES; i++)
+         cx->newborn[i] = NULL;
+     cx->lastAtom = NULL;
+     cx->lastInternalResult = JSVAL_NULL;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_EnterLocalRootScope(JSContext *cx)
+ {
+     CHECK_REQUEST(cx);
+     return js_EnterLocalRootScope(cx);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_LeaveLocalRootScope(JSContext *cx)
+ {
+     CHECK_REQUEST(cx);
+     js_LeaveLocalRootScope(cx);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ForgetLocalRoot(JSContext *cx, void *thing)
+ {
+     CHECK_REQUEST(cx);
+     js_ForgetLocalRoot(cx, (jsval) thing);
+ }
+ 
+ #include "jshash.h" /* Added by JSIFY */
+ 
+ #ifdef DEBUG
+ 
+ typedef struct NamedRootDumpArgs {
+     void (*dump)(const char *name, void *rp, void *data);
+     void *data;
+ } NamedRootDumpArgs;
+ 
+ JS_STATIC_DLL_CALLBACK(JSDHashOperator)
+ js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+                      void *arg)
+ {
+     NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;
+     JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+ 
+     if (rhe->name)
+         args->dump(rhe->name, rhe->root, args->data);
+     return JS_DHASH_NEXT;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_DumpNamedRoots(JSRuntime *rt,
+                   void (*dump)(const char *name, void *rp, void *data),
+                   void *data)
+ {
+     NamedRootDumpArgs args;
+ 
+     args.dump = dump;
+     args.data = data;
+     JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);
+ }
+ 
+ #endif /* DEBUG */
+ 
+ typedef struct GCRootMapArgs {
+     JSGCRootMapFun map;
+     void *data;
+ } GCRootMapArgs;
+ 
+ JS_STATIC_DLL_CALLBACK(JSDHashOperator)
+ js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+                  void *arg)
+ {
+     GCRootMapArgs *args = (GCRootMapArgs *) arg;
+     JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+     intN mapflags;
+     JSDHashOperator op;
+ 
+     mapflags = args->map(rhe->root, rhe->name, args->data);
+ 
+ #if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT &&                                     \
+     JS_MAP_GCROOT_STOP == JS_DHASH_STOP &&                                     \
+     JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE
+     op = (JSDHashOperator)mapflags;
+ #else
+     op = JS_DHASH_NEXT;
+     if (mapflags & JS_MAP_GCROOT_STOP)
+         op |= JS_DHASH_STOP;
+     if (mapflags & JS_MAP_GCROOT_REMOVE)
+         op |= JS_DHASH_REMOVE;
+ #endif
+ 
+     return op;
+ }
+ 
+ JS_PUBLIC_API(uint32)
+ JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
+ {
+     GCRootMapArgs args;
+     uint32 rv;
+ 
+     args.map = map;
+     args.data = data;
+     JS_LOCK_GC(rt);
+     rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args);
+     JS_UNLOCK_GC(rt);
+     return rv;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_LockGCThing(JSContext *cx, void *thing)
+ {
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     ok = js_LockGCThing(cx, thing);
+     if (!ok)
+         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_LOCK);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_LockGCThingRT(JSRuntime *rt, void *thing)
+ {
+     return js_LockGCThingRT(rt, thing);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_UnlockGCThing(JSContext *cx, void *thing)
+ {
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     ok = js_UnlockGCThingRT(cx->runtime, thing);
+     if (!ok)
+         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
+ {
+     return js_UnlockGCThingRT(rt, thing);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
+ {
+     JS_ASSERT(cx->runtime->gcLevel > 0);
+ #ifdef JS_THREADSAFE
+     JS_ASSERT(cx->runtime->gcThread == js_CurrentThreadId());
+ #endif
+ 
+     GC_MARK(cx, thing, name, arg);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_GC(JSContext *cx)
+ {
+     /* Don't nuke active arenas if executing or compiling. */
+     if (cx->stackPool.current == &cx->stackPool.first)
+         JS_FinishArenaPool(&cx->stackPool);
+     if (cx->tempPool.current == &cx->tempPool.first)
+         JS_FinishArenaPool(&cx->tempPool);
+     js_ForceGC(cx, 0);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_MaybeGC(JSContext *cx)
+ {
+ #ifdef WAY_TOO_MUCH_GC
+     JS_GC(cx);
+ #else
+     JSRuntime *rt;
+     uint32 bytes, lastBytes;
+ 
+     rt = cx->runtime;
+     bytes = rt->gcBytes;
+     lastBytes = rt->gcLastBytes;
+     if ((bytes > 8192 && bytes > lastBytes + lastBytes / 2) ||
+         rt->gcMallocBytes > rt->gcMaxMallocBytes) {
+         /*
+          * Run the GC if we have half again as many bytes of GC-things as
+          * the last time we GC'd, or if we have malloc'd more bytes through
+          * JS_malloc than we were told to allocate by JS_NewRuntime.
+          */
+         JS_GC(cx);
+     }
+ #endif
+ }
+ 
+ JS_PUBLIC_API(JSGCCallback)
+ JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
+ {
+     return JS_SetGCCallbackRT(cx->runtime, cb);
+ }
+ 
+ JS_PUBLIC_API(JSGCCallback)
+ JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
+ {
+     JSGCCallback oldcb;
+ 
+     oldcb = rt->gcCallback;
+     rt->gcCallback = cb;
+     return oldcb;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_IsAboutToBeFinalized(JSContext *cx, void *thing)
+ {
+     JS_ASSERT(thing);
+     return js_IsAboutToBeFinalized(cx, thing);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value)
+ {
+     switch (key) {
+       case JSGC_MAX_BYTES:
+         rt->gcMaxBytes = value;
+         break;
+       case JSGC_MAX_MALLOC_BYTES:
+         rt->gcMaxMallocBytes = value;
+         break;
+     }
+ }
+ 
+ JS_PUBLIC_API(intN)
+ JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
+ {
+     return js_ChangeExternalStringFinalizer(NULL, finalizer);
+ }
+ 
+ JS_PUBLIC_API(intN)
+ JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
+ {
+     return js_ChangeExternalStringFinalizer(finalizer, NULL);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
+ {
+     JSString *str;
+ 
+     CHECK_REQUEST(cx);
+     JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES);
+ 
+     str = (JSString *) js_NewGCThing(cx, (uintN) type, sizeof(JSString));
+     if (!str)
+         return NULL;
+     str->length = length;
+     str->chars = chars;
+     return str;
+ }
+ 
+ JS_PUBLIC_API(intN)
+ JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
+ {
+     uint8 type = (uint8) (*js_GetGCThingFlags(str) & GCF_TYPEMASK);
+ 
+     if (type >= GCX_EXTERNAL_STRING)
+         return (intN)type;
+     JS_ASSERT(type == GCX_STRING || type == GCX_MUTABLE_STRING);
+     return -1;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
+ {
+ #if JS_STACK_GROWTH_DIRECTION > 0
+     if (limitAddr == 0)
+         limitAddr = (jsuword)-1;
+ #endif
+     cx->stackLimit = limitAddr;
+ }
+ 
+ /************************************************************************/
+ 
+ JS_PUBLIC_API(void)
+ JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
+ {
+     JS_free(cx, ida);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     if (JSVAL_IS_INT(v)) {
+         *idp = v;
+     } else {
+         atom = js_ValueToStringAtom(cx, v);
+         if (!atom)
+             return JS_FALSE;
+         *idp = ATOM_TO_JSID(atom);
+     }
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
+ {
+     CHECK_REQUEST(cx);
+     *vp = ID_TO_VALUE(id);
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+ {
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_EnumerateStub(JSContext *cx, JSObject *obj)
+ {
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id)
+ {
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+ {
+ #if JS_BUG_EAGER_TOSTRING
+     if (type == JSTYPE_STRING)
+         return JS_TRUE;
+ #endif
+     js_TryValueOf(cx, obj, type, vp);
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_FinalizeStub(JSContext *cx, JSObject *obj)
+ {
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+              JSClass *clasp, JSNative constructor, uintN nargs,
+              JSPropertySpec *ps, JSFunctionSpec *fs,
+              JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
+ {
+     JSAtom *atom;
+     JSObject *proto, *ctor;
+     JSTempValueRooter tvr;
+     jsval cval, rval;
+     JSBool named;
+     JSFunction *fun;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
+     if (!atom)
+         return NULL;
+ 
+     /* Create a prototype object for this class. */
+     proto = js_NewObject(cx, clasp, parent_proto, obj);
+     if (!proto)
+         return NULL;
+ 
+     /* After this point, control must exit via label bad or out. */
+     JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(proto), &tvr);
+ 
+     if (!constructor) {
+         /* Lacking a constructor, name the prototype (e.g., Math). */
+         named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
+                                     OBJECT_TO_JSVAL(proto),
+                                     NULL, NULL, 0, NULL);
+         if (!named)
+             goto bad;
+         ctor = proto;
+     } else {
+         /* Define the constructor function in obj's scope. */
+         fun = js_DefineFunction(cx, obj, atom, constructor, nargs, 0);
+         named = (fun != NULL);
+         if (!fun)
+             goto bad;
+ 
+         /*
+          * Remember the class this function is a constructor for so that
+          * we know to create an object of this class when we call the
+          * constructor.
+          */
+         fun->clasp = clasp;
+ 
+         /*
+          * Optionally construct the prototype object, before the class has
+          * been fully initialized.  Allow the ctor to replace proto with a
+          * different object, as is done for operator new -- and as at least
+          * XML support requires.
+          */
+         ctor = fun->object;
+         if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
+             cval = OBJECT_TO_JSVAL(ctor);
+             if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))
+                 goto bad;
+             if (!JSVAL_IS_PRIMITIVE(rval) && JSVAL_TO_OBJECT(rval) != proto)
+                 proto = JSVAL_TO_OBJECT(rval);
+         }
+ 
+         /* Connect constructor and prototype by named properties. */
+         if (!js_SetClassPrototype(cx, ctor, proto,
+                                   JSPROP_READONLY | JSPROP_PERMANENT)) {
+             goto bad;
+         }
+ 
+         /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
+         if (OBJ_GET_CLASS(cx, ctor) == clasp) {
+             /* XXXMLM - this fails in framesets that are writing over
+              *           themselves!
+              * JS_ASSERT(!OBJ_GET_PROTO(cx, ctor));
+              */
+             OBJ_SET_PROTO(cx, ctor, proto);
+         }
+     }
+ 
+     /* Add properties and methods to the prototype and the constructor. */
+     if ((ps && !JS_DefineProperties(cx, proto, ps)) ||
+         (fs && !JS_DefineFunctions(cx, proto, fs)) ||
+         (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||
+         (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {
+         goto bad;
+     }
+ 
+ out:
+     JS_POP_TEMP_ROOT(cx, &tvr);
+     return proto;
+ 
+ bad:
+     if (named)
+         (void) OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &rval);
+     proto = NULL;
+     goto out;
+ }
+ 
+ #ifdef JS_THREADSAFE
+ JS_PUBLIC_API(JSClass *)
+ JS_GetClass(JSContext *cx, JSObject *obj)
+ {
+     return (JSClass *)
+         JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS));
+ }
+ #else
+ JS_PUBLIC_API(JSClass *)
+ JS_GetClass(JSObject *obj)
+ {
+     return LOCKED_OBJ_GET_CLASS(obj);
+ }
+ #endif
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
+ {
+     JSFunction *fun;
+ 
+     CHECK_REQUEST(cx);
+     if (OBJ_GET_CLASS(cx, obj) == clasp)
+         return JS_TRUE;
+     if (argv) {
+         fun = js_ValueToFunction(cx, &argv[-2], 0);
+         if (fun) {
+             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+                                  JSMSG_INCOMPATIBLE_PROTO,
+                                  clasp->name, JS_GetFunctionName(fun),
+                                  OBJ_GET_CLASS(cx, obj)->name);
+         }
+     }
+     return JS_FALSE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+ {
+     return js_HasInstance(cx, obj, v, bp);
+ }
+ 
+ JS_PUBLIC_API(void *)
+ JS_GetPrivate(JSContext *cx, JSObject *obj)
+ {
+     jsval v;
+ 
+     JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
+     v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+     if (!JSVAL_IS_INT(v))
+         return NULL;
+     return JSVAL_TO_PRIVATE(v);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
+ {
+     JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
+     OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(data));
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(void *)
+ JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
+                       jsval *argv)
+ {
+     if (!JS_InstanceOf(cx, obj, clasp, argv))
+         return NULL;
+     return JS_GetPrivate(cx, obj);
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_GetPrototype(JSContext *cx, JSObject *obj)
+ {
+     JSObject *proto;
+ 
+     CHECK_REQUEST(cx);
+     proto = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PROTO));
+ 
+     /* Beware ref to dead object (we may be called from obj's finalizer). */
+     return proto && proto->map ? proto : NULL;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
+ {
+     CHECK_REQUEST(cx);
+     if (obj->map->ops->setProto)
+         return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto);
+     OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto));
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_GetParent(JSContext *cx, JSObject *obj)
+ {
+     JSObject *parent;
+ 
+     parent = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PARENT));
+ 
+     /* Beware ref to dead object (we may be called from obj's finalizer). */
+     return parent && parent->map ? parent : NULL;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
+ {
+     CHECK_REQUEST(cx);
+     if (obj->map->ops->setParent)
+         return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent);
+     OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent));
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_GetConstructor(JSContext *cx, JSObject *proto)
+ {
+     jsval cval;
+ 
+     CHECK_REQUEST(cx);
+     if (!OBJ_GET_PROPERTY(cx, proto,
+                           ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
+                           &cval)) {
+         return NULL;
+     }
+     if (!JSVAL_IS_FUNCTION(cx, cval)) {
+         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
+                              OBJ_GET_CLASS(cx, proto)->name);
+         return NULL;
+     }
+     return JSVAL_TO_OBJECT(cval);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
+ {
+     JS_ASSERT(((jsid)obj & JSID_TAGMASK) == 0);
+     *idp = OBJECT_TO_JSID(obj);
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
+ {
+     CHECK_REQUEST(cx);
+     if (!clasp)
+         clasp = &js_ObjectClass;    /* default class is Object */
+     return js_NewObject(cx, clasp, proto, parent);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
+ {
+     JSScope *scope;
+     JSIdArray *ida;
+     uint32 nslots;
+     jsval v, *vp, *end;
+ 
+     if (!OBJ_IS_NATIVE(obj)) {
+         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+                              JSMSG_CANT_SEAL_OBJECT,
+                              OBJ_GET_CLASS(cx, obj)->name);
+         return JS_FALSE;
+     }
+ 
+     scope = OBJ_SCOPE(obj);
+ 
+ #if defined JS_THREADSAFE && defined DEBUG
+     /* Insist on scope being used exclusively by cx's thread. */
+     if (scope->ownercx != cx) {
+         JS_LOCK_OBJ(cx, obj);
+         JS_ASSERT(OBJ_SCOPE(obj) == scope);
+         JS_ASSERT(scope->ownercx == cx);
+         JS_UNLOCK_SCOPE(cx, scope);
+     }
+ #endif
+ 
+     /* Nothing to do if obj's scope is already sealed. */
+     if (SCOPE_IS_SEALED(scope))
+         return JS_TRUE;
+ 
+     /* XXX Enumerate lazy properties now, as they can't be added later. */
+     ida = JS_Enumerate(cx, obj);
+     if (!ida)
+         return JS_FALSE;
+     JS_DestroyIdArray(cx, ida);
+ 
+     /* Ensure that obj has its own, mutable scope, and seal that scope. */
+     JS_LOCK_OBJ(cx, obj);
+     scope = js_GetMutableScope(cx, obj);
+     if (scope)
+         SCOPE_SET_SEALED(scope);
+     JS_UNLOCK_SCOPE(cx, scope);
+     if (!scope)
+         return JS_FALSE;
+ 
+     /* If we are not sealing an entire object graph, we're done. */
+     if (!deep)
+         return JS_TRUE;
+ 
+     /* Walk obj->slots and if any value is a non-null object, seal it. */
+     nslots = JS_MIN(scope->map.freeslot, scope->map.nslots);
+     for (vp = obj->slots, end = vp + nslots; vp < end; vp++) {
+         v = *vp;
+         if (JSVAL_IS_PRIMITIVE(v))
+             continue;
+         if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep))
+             return JS_FALSE;
+     }
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+                    JSObject *parent)
+ {
+     CHECK_REQUEST(cx);
+     if (!clasp)
+         clasp = &js_ObjectClass;    /* default class is Object */
+     return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
+                                 JSObject *parent, uintN argc, jsval *argv)
+ {
+     CHECK_REQUEST(cx);
+     if (!clasp)
+         clasp = &js_ObjectClass;    /* default class is Object */
+     return js_ConstructObject(cx, clasp, proto, parent, argc, argv);
+ }
+ 
+ static JSBool
+ DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+                JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+                uintN flags, intN tinyid)
+ {
+     jsid id;
+     JSAtom *atom;
+ 
+     if (attrs & JSPROP_INDEX) {
+         id = INT_TO_JSID(JS_PTR_TO_INT32(name));
+         atom = NULL;
+         attrs &= ~JSPROP_INDEX;
+     } else {
+         atom = js_Atomize(cx, name, strlen(name), 0);
+         if (!atom)
+             return JS_FALSE;
+         id = ATOM_TO_JSID(atom);
+     }
+     if (flags != 0 && OBJ_IS_NATIVE(obj)) {
+         return js_DefineNativeProperty(cx, obj, id, value, getter, setter,
+                                        attrs, flags, tinyid, NULL);
+     }
+     return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
+                                NULL);
+ }
+ 
+ #define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
+ 
+ static JSBool
+ DefineUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen, jsval value,
+                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+                  uintN flags, intN tinyid)
+ {
+     JSAtom *atom;
+ 
+     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+     if (!atom)
+         return JS_FALSE;
+     if (flags != 0 && OBJ_IS_NATIVE(obj)) {
+         return js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
+                                        getter, setter, attrs, flags, tinyid,
+                                        NULL);
+     }
+     return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), value,
+                                getter, setter, attrs, NULL);
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
+                 JSObject *proto, uintN attrs)
+ {
+     JSObject *nobj;
+ 
+     CHECK_REQUEST(cx);
+     if (!clasp)
+         clasp = &js_ObjectClass;    /* default class is Object */
+     nobj = js_NewObject(cx, clasp, proto, obj);
+     if (!nobj)
+         return NULL;
+     if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
+                         0, 0)) {
+         cx->newborn[GCX_OBJECT] = NULL;
+         return NULL;
+     }
+     return nobj;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
+ {
+     JSBool ok;
+     jsval value;
+     uintN flags;
+ 
+     CHECK_REQUEST(cx);
+     for (ok = JS_TRUE; cds->name; cds++) {
+         ok = js_NewNumberValue(cx, cds->dval, &value);
+         if (!ok)
+             break;
+         flags = cds->flags;
+         if (!flags)
+             flags = JSPROP_READONLY | JSPROP_PERMANENT;
+         ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0);
+         if (!ok)
+             break;
+     }
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
+ {
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     for (ok = JS_TRUE; ps->name; ps++) {
+         ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID,
+                             ps->getter, ps->setter, ps->flags,
+                             SPROP_HAS_SHORTID, ps->tinyid);
+         if (!ok)
+             break;
+     }
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+                   JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
+ {
+     CHECK_REQUEST(cx);
+     return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
+                             int8 tinyid, jsval value,
+                             JSPropertyOp getter, JSPropertyOp setter,
+                             uintN attrs)
+ {
+     CHECK_REQUEST(cx);
+     return DefineProperty(cx, obj, name, value, getter, setter, attrs,
+                           SPROP_HAS_SHORTID, tinyid);
+ }
+ 
+ static JSBool
+ LookupProperty(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
+                JSProperty **propp)
+ {
+     JSAtom *atom;
+ 
+     atom = js_Atomize(cx, name, strlen(name), 0);
+     if (!atom)
+         return JS_FALSE;
+     return OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), objp, propp);
+ }
+ 
+ static JSBool
+ LookupUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  JSObject **objp, JSProperty **propp)
+ {
+     JSAtom *atom;
+ 
+     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+     if (!atom)
+         return JS_FALSE;
+     return OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), objp, propp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
+                  const char *alias)
+ {
+     JSObject *obj2;
+     JSProperty *prop;
+     JSAtom *atom;
+     JSBool ok;
+     JSScopeProperty *sprop;
+ 
+     CHECK_REQUEST(cx);
+     if (!LookupProperty(cx, obj, name, &obj2, &prop))
+         return JS_FALSE;
+     if (!prop) {
+         js_ReportIsNotDefined(cx, name);
+         return JS_FALSE;
+     }
+     if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
+         OBJ_DROP_PROPERTY(cx, obj2, prop);
+         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
+                              alias, name, OBJ_GET_CLASS(cx, obj2)->name);
+         return JS_FALSE;
+     }
+     atom = js_Atomize(cx, alias, strlen(alias), 0);
+     if (!atom) {
+         ok = JS_FALSE;
+     } else {
+         sprop = (JSScopeProperty *)prop;
+         ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom),
+                                    sprop->getter, sprop->setter, sprop->slot,
+                                    sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
+                                    sprop->shortid)
+               != NULL);
+     }
+     OBJ_DROP_PROPERTY(cx, obj, prop);
+     return ok;
+ }
+ 
+ static jsval
+ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
+ {
+     JSScopeProperty *sprop;
+     jsval rval;
+ 
+     if (!prop) {
+         /* XXX bad API: no way to tell "not defined" from "void value" */
+         return JSVAL_VOID;
+     }
+     if (OBJ_IS_NATIVE(obj2)) {
+         /* Peek at the native property's slot value, without doing a Get. */
+         sprop = (JSScopeProperty *)prop;
+         rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
+                ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
+                : JSVAL_TRUE;
+     } else {
+         /* XXX bad API: no way to return "defined but value unknown" */
+         rval = JSVAL_TRUE;
+     }
+     OBJ_DROP_PROPERTY(cx, obj2, prop);
+     return rval;
+ }
+ 
+ static JSBool
+ GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
+                       uintN *attrsp, JSBool *foundp,
+                       JSPropertyOp *getterp, JSPropertyOp *setterp)
+ {
+     JSObject *obj2;
+     JSProperty *prop;
+     JSBool ok;
+ 
+     if (!atom)
+         return JS_FALSE;
+     if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop))
+         return JS_FALSE;
+ 
+     if (!prop || obj != obj2) {
+         *attrsp = 0;
+         *foundp = JS_FALSE;
+         if (getterp)
+             *getterp = NULL;
+         if (setterp)
+             *setterp = NULL;
+         if (prop)
+             OBJ_DROP_PROPERTY(cx, obj2, prop);
+         return JS_TRUE;
+     }
+ 
+     *foundp = JS_TRUE;
+     ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, attrsp);
+     if (ok && OBJ_IS_NATIVE(obj)) {
+         JSScopeProperty *sprop = (JSScopeProperty *) prop;
+ 
+         if (getterp)
+             *getterp = sprop->getter;
+         if (setterp)
+             *setterp = sprop->setter;
+     }
+     OBJ_DROP_PROPERTY(cx, obj, prop);
+     return ok;
+ }
+ 
+ static JSBool
+ SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
+                       uintN attrs, JSBool *foundp)
+ {
+     JSObject *obj2;
+     JSProperty *prop;
+     JSBool ok;
+ 
+     if (!atom)
+         return JS_FALSE;
+     if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop))
+         return JS_FALSE;
+     if (!prop || obj != obj2) {
+         *foundp = JS_FALSE;
+         if (prop)
+             OBJ_DROP_PROPERTY(cx, obj2, prop);
+         return JS_TRUE;
+     }
+ 
+     *foundp = JS_TRUE;
+     ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs);
+     OBJ_DROP_PROPERTY(cx, obj, prop);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+                          uintN *attrsp, JSBool *foundp)
+ {
+     CHECK_REQUEST(cx);
+     return GetPropertyAttributes(cx, obj,
+                                  js_Atomize(cx, name, strlen(name), 0),
+                                  attrsp, foundp, NULL, NULL);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+                                    const char *name,
+                                    uintN *attrsp, JSBool *foundp,
+                                    JSPropertyOp *getterp,
+                                    JSPropertyOp *setterp)
+ {
+     CHECK_REQUEST(cx);
+     return GetPropertyAttributes(cx, obj,
+                                  js_Atomize(cx, name, strlen(name), 0),
+                                  attrsp, foundp, getterp, setterp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+                          uintN attrs, JSBool *foundp)
+ {
+     CHECK_REQUEST(cx);
+     return SetPropertyAttributes(cx, obj,
+                                  js_Atomize(cx, name, strlen(name), 0),
+                                  attrs, foundp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
+ {
+     JSBool ok;
+     JSObject *obj2;
+     JSProperty *prop;
+ 
+     CHECK_REQUEST(cx);
+     ok = LookupProperty(cx, obj, name, &obj2, &prop);
+     if (ok) {
+         *foundp = (prop != NULL);
+         if (prop)
+             OBJ_DROP_PROPERTY(cx, obj2, prop);
+     }
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+ {
+     JSBool ok;
+     JSObject *obj2;
+     JSProperty *prop;
+ 
+     CHECK_REQUEST(cx);
+     ok = LookupProperty(cx, obj, name, &obj2, &prop);
+     if (ok)
+         *vp = LookupResult(cx, obj, obj2, prop);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
+                            uintN flags, jsval *vp)
+ {
+     JSAtom *atom;
+     JSBool ok;
+     JSObject *obj2;
+     JSProperty *prop;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_Atomize(cx, name, strlen(name), 0);
+     if (!atom)
+         return JS_FALSE;
+     ok = OBJ_IS_NATIVE(obj)
+          ? js_LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(atom), flags,
+                                       &obj2, &prop)
+          : OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop);
+     if (ok)
+         *vp = LookupResult(cx, obj, obj2, prop);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_Atomize(cx, name, strlen(name), 0);
+     if (!atom)
+         return JS_FALSE;
+     return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
+              jsval *vp)
+ {
+     JSAtom *atom;
+     jsid id;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_Atomize(cx, name, strlen(name), 0);
+     if (!atom)
+         return JS_FALSE;
+     id = ATOM_TO_JSID(atom);
+ 
+ #if JS_HAS_XML_SUPPORT
+     if (OBJECT_IS_XML(cx, obj)) {
+         JSXMLObjectOps *ops;
+ 
+         ops = (JSXMLObjectOps *) obj->map->ops;
+         obj = ops->getMethod(cx, obj, id, vp);
+         if (!obj)
+             return JS_FALSE;
+     } else
+ #endif
+     {
+         if (!OBJ_GET_PROPERTY(cx, obj, id, vp))
+             return JS_FALSE;
+     }
+ 
+     *objp = obj;
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_Atomize(cx, name, strlen(name), 0);
+     if (!atom)
+         return JS_FALSE;
+     return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
+ {
+     jsval junk;
+ 
+     CHECK_REQUEST(cx);
+     return JS_DeleteProperty2(cx, obj, name, &junk);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
+                    jsval *rval)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_Atomize(cx, name, strlen(name), 0);
+     if (!atom)
+         return JS_FALSE;
+     return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DefineUCProperty(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen, jsval value,
+                     JSPropertyOp getter, JSPropertyOp setter,
+                     uintN attrs)
+ {
+     CHECK_REQUEST(cx);
+     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
+                             attrs, 0, 0);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+                            const jschar *name, size_t namelen,
+                            uintN *attrsp, JSBool *foundp)
+ {
+     CHECK_REQUEST(cx);
+     return GetPropertyAttributes(cx, obj,
+                     js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+                     attrsp, foundp, NULL, NULL);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+                                      const jschar *name, size_t namelen,
+                                      uintN *attrsp, JSBool *foundp,
+                                      JSPropertyOp *getterp,
+                                      JSPropertyOp *setterp)
+ {
+     CHECK_REQUEST(cx);
+     return GetPropertyAttributes(cx, obj,
+                     js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+                     attrsp, foundp, getterp, setterp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+                            const jschar *name, size_t namelen,
+                            uintN attrs, JSBool *foundp)
+ {
+     CHECK_REQUEST(cx);
+     return SetPropertyAttributes(cx, obj,
+                     js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+                     attrs, foundp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
+                               const jschar *name, size_t namelen,
+                               int8 tinyid, jsval value,
+                               JSPropertyOp getter, JSPropertyOp setter,
+                               uintN attrs)
+ {
+     CHECK_REQUEST(cx);
+     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
+                             attrs, SPROP_HAS_SHORTID, tinyid);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_HasUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  JSBool *vp)
+ {
+     JSBool ok;
+     JSObject *obj2;
+     JSProperty *prop;
+ 
+     CHECK_REQUEST(cx);
+     ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
+     if (ok) {
+         *vp = (prop != NULL);
+         if (prop)
+             OBJ_DROP_PROPERTY(cx, obj2, prop);
+     }
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_LookupUCProperty(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen,
+                     jsval *vp)
+ {
+     JSBool ok;
+     JSObject *obj2;
+     JSProperty *prop;
+ 
+     CHECK_REQUEST(cx);
+     ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
+     if (ok)
+         *vp = LookupResult(cx, obj, obj2, prop);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  jsval *vp)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+     if (!atom)
+         return JS_FALSE;
+     return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  jsval *vp)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+     if (!atom)
+         return JS_FALSE;
+     return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
+                      const jschar *name, size_t namelen,
+                      jsval *rval)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+     if (!atom)
+         return JS_FALSE;
+     return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
+ {
+     CHECK_REQUEST(cx);
+     /* NB: jsuint cast does ToUint32. */
+     return js_NewArrayObject(cx, (jsuint)length, vector);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_IsArrayObject(JSContext *cx, JSObject *obj)
+ {
+     return OBJ_GET_CLASS(cx, obj) == &js_ArrayClass;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
+ {
+     CHECK_REQUEST(cx);
+     return js_GetLengthProperty(cx, obj, lengthp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
+ {
+     CHECK_REQUEST(cx);
+     return js_SetLengthProperty(cx, obj, length);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
+ {
+     CHECK_REQUEST(cx);
+     return js_HasLengthProperty(cx, obj, lengthp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
+                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
+ {
+     CHECK_REQUEST(cx);
+     return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(index), value,
+                                getter, setter, attrs, NULL);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
+ {
+     JSObject *obj2;
+     JSProperty *prop;
+     JSScopeProperty *sprop;
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     if (!LookupProperty(cx, obj, name, &obj2, &prop))
+         return JS_FALSE;
+     if (!prop) {
+         js_ReportIsNotDefined(cx, name);
+         return JS_FALSE;
+     }
+     if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
+         char numBuf[12];
+         OBJ_DROP_PROPERTY(cx, obj2, prop);
+         JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
+         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
+                              numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
+         return JS_FALSE;
+     }
+     sprop = (JSScopeProperty *)prop;
+     ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias),
+                                sprop->getter, sprop->setter, sprop->slot,
+                                sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
+                                sprop->shortid)
+           != NULL);
+     OBJ_DROP_PROPERTY(cx, obj, prop);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
+ {
+     JSBool ok;
+     JSObject *obj2;
+     JSProperty *prop;
+ 
+     CHECK_REQUEST(cx);
+     ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSID(index), &obj2, &prop);
+     if (ok) {
+         *foundp = (prop != NULL);
+         if (prop)
+             OBJ_DROP_PROPERTY(cx, obj2, prop);
+     }
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+ {
+     JSBool ok;
+     JSObject *obj2;
+     JSProperty *prop;
+ 
+     CHECK_REQUEST(cx);
+     ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSID(index), &obj2, &prop);
+     if (ok)
+         *vp = LookupResult(cx, obj, obj2, prop);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+ {
+     CHECK_REQUEST(cx);
+     return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+ {
+     CHECK_REQUEST(cx);
+     return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index)
+ {
+     jsval junk;
+ 
+     CHECK_REQUEST(cx);
+     return JS_DeleteElement2(cx, obj, index, &junk);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
+ {
+     CHECK_REQUEST(cx);
+     return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSID(index), rval);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ClearScope(JSContext *cx, JSObject *obj)
+ {
+     CHECK_REQUEST(cx);
+ 
+     if (obj->map->ops->clear)
+         obj->map->ops->clear(cx, obj);
+ }
+ 
+ JS_PUBLIC_API(JSIdArray *)
+ JS_Enumerate(JSContext *cx, JSObject *obj)
+ {
+     jsint i, n;
+     jsval iter_state, num_properties;
+     jsid id;
+     JSIdArray *ida;
+     jsval *vector;
+ 
+     CHECK_REQUEST(cx);
+ 
+     ida = NULL;
+     iter_state = JSVAL_NULL;
+ 
+     /* Get the number of properties to enumerate. */
+     if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties))
+         goto error;
+     if (!JSVAL_IS_INT(num_properties)) {
+         JS_ASSERT(0);
+         goto error;
+     }
+ 
+     /* Grow as needed if we don't know the exact amount ahead of time. */
+     n = JSVAL_TO_INT(num_properties);
+     if (n <= 0)
+         n = 8;
+ 
+     /* Create an array of jsids large enough to hold all the properties */
+     ida = js_NewIdArray(cx, n);
+     if (!ida)
+         goto error;
+ 
+     i = 0;
+     vector = &ida->vector[0];
+     for (;;) {
+         if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id))
+             goto error;
+ 
+         /* No more jsid's to enumerate ? */
+         if (iter_state == JSVAL_NULL)
+             break;
+ 
+         if (i == ida->length) {
+             ida = js_SetIdArrayLength(cx, ida, ida->length * 2);
+             if (!ida)
+                 goto error;
+             vector = &ida->vector[0];
+         }
+         vector[i++] = id;
+     }
+     return js_SetIdArrayLength(cx, ida, i);
+ 
+ error:
+     if (iter_state != JSVAL_NULL)
+         OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
+     if (ida)
+         JS_DestroyIdArray(cx, ida);
+     return NULL;
+ }
+ 
+ /*
+  * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
+  *     prop_iterator_class somehow...
+  * + preserve the OBJ_ENUMERATE API while optimizing the native object case
+  * + native case here uses a JSScopeProperty *, but that iterates in reverse!
+  * + so we make non-native match, by reverse-iterating after JS_Enumerating
+  */
+ #define JSSLOT_ITER_INDEX       (JSSLOT_PRIVATE + 1)
+ 
+ #if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS
+ # error "JSSLOT_ITER_INDEX botch!"
+ #endif
+ 
+ static void
+ prop_iter_finalize(JSContext *cx, JSObject *obj)
+ {
+     jsval v;
+     jsint i;
+     JSIdArray *ida;
+ 
+     v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX);
+     if (JSVAL_IS_VOID(v))
+         return;
+ 
+     i = JSVAL_TO_INT(v);
+     if (i >= 0) {
+         /* Non-native case: destroy the ida enumerated when obj was created. */
+         ida = (JSIdArray *) JS_GetPrivate(cx, obj);
+         if (ida)
+             JS_DestroyIdArray(cx, ida);
+     }
+ }
+ 
+ static uint32
+ prop_iter_mark(JSContext *cx, JSObject *obj, void *arg)
+ {
+     jsval v;
+     jsint i, n;
+     JSScopeProperty *sprop;
+     JSIdArray *ida;
+     jsid id;
+ 
+     v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+     JS_ASSERT(!JSVAL_IS_VOID(v));
+ 
+     i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX));
+     if (i < 0) {
+         /* Native case: just mark the next property to visit. */
+         sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v);
+         if (sprop)
+             MARK_SCOPE_PROPERTY(sprop);
+     } else {
+         /* Non-native case: mark each id in the JSIdArray private. */
+         ida = (JSIdArray *) JSVAL_TO_PRIVATE(v);
+         for (i = 0, n = ida->length; i < n; i++) {
+             id = ida->vector[i];
+             if (JSID_IS_ATOM(id))
+                 GC_MARK_ATOM(cx, JSID_TO_ATOM(id), arg);
+             else if (JSID_IS_OBJECT(id))
+                 GC_MARK(cx, JSID_TO_OBJECT(id), "id", arg);
+         }
+     }
+     return 0;
+ }
+ 
+ static JSClass prop_iter_class = {
+     "PropertyIterator",
+     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
+     JS_PropertyStub,  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+     JS_EnumerateStub, JS_ResolveStub,  JS_ConvertStub,  prop_iter_finalize,
+     NULL,             NULL,            NULL,            NULL,
+     NULL,             NULL,            prop_iter_mark,  NULL
+ };
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
+ {
+     JSObject *iterobj;
+     JSScope *scope;
+     void *pdata;
+     jsint index;
+     JSIdArray *ida;
+     
+     CHECK_REQUEST(cx);
+     iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj);
+     if (!iterobj)
+         return NULL;
+ 
+     if (OBJ_IS_NATIVE(obj)) {
+         /* Native case: start with the last property in obj's own scope. */
+         scope = OBJ_SCOPE(obj);
+         pdata = (scope->object == obj) ? scope->lastProp : NULL;
+         index = -1;
+     } else {
+         /* Non-native case: enumerate a JSIdArray and keep it via private. */
+         ida = JS_Enumerate(cx, obj);
+         if (!ida)
+             goto bad;
+         pdata = ida;
+         index = ida->length;
+     }
+ 
+     if (!JS_SetPrivate(cx, iterobj, pdata))
+         goto bad;
+     OBJ_SET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(index));
+     return iterobj;
+ 
+ bad:
+     cx->newborn[GCX_OBJECT] = NULL;
+     return NULL;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
+ {
+     jsint i;
+     JSObject *obj;
+     JSScope *scope;
+     JSScopeProperty *sprop;
+     JSIdArray *ida;
+ 
+     CHECK_REQUEST(cx);
+     i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX));
+     if (i < 0) {
+         /* Native case: private data is a property tree node pointer. */
+         obj = OBJ_GET_PARENT(cx, iterobj);
+         JS_ASSERT(OBJ_IS_NATIVE(obj));
+         scope = OBJ_SCOPE(obj);
+         JS_ASSERT(scope->object == obj);
+         sprop = (JSScopeProperty *) JS_GetPrivate(cx, iterobj);
+ 
+         /*
+          * If the next property mapped by scope in the property tree ancestor
+          * line is not enumerable, or it's an alias, or one or more properties
+          * were deleted from the "middle" of the scope-mapped ancestor line
+          * and the next property was among those deleted, skip it and keep on
+          * trying to find an enumerable property that is still in scope.
+          */
+         while (sprop &&
+                (!(sprop->attrs & JSPROP_ENUMERATE) ||
+                 (sprop->flags & SPROP_IS_ALIAS) ||
+                 (SCOPE_HAD_MIDDLE_DELETE(scope) &&
+                  !SCOPE_HAS_PROPERTY(scope, sprop)))) {
+             sprop = sprop->parent;
+         }
+ 
+         if (!sprop) {
+             *idp = JSVAL_VOID;
+         } else {
+             if (!JS_SetPrivate(cx, iterobj, sprop->parent))
+                 return JS_FALSE;
+             *idp = sprop->id;
+         }
+     } else {
+         /* Non-native case: use the ida enumerated when iterobj was created. */
+         ida = (JSIdArray *) JS_GetPrivate(cx, iterobj);
+         JS_ASSERT(i <= ida->length);
+         if (i == 0) {
+             *idp = JSVAL_VOID; 
+         } else {
+             *idp = ida->vector[--i];
+             OBJ_SET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(i));
+         }
+     }
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+                jsval *vp, uintN *attrsp)
+ {
+     CHECK_REQUEST(cx);
+     return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp);
+ }
+ 
+ JS_PUBLIC_API(JSCheckAccessOp)
+ JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb)
+ {
+     JSCheckAccessOp oldacb;
+ 
+     oldacb = rt->checkObjectAccess;
+     rt->checkObjectAccess = acb;
+     return oldacb;
+ }
+ 
+ static JSBool
+ ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
+                     uint32 index, uint32 limit)
+ {
+     /* Check the computed, possibly per-instance, upper bound. */
+     if (clasp->reserveSlots)
+         JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj));
+     if (index >= limit) {
+         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+                              JSMSG_RESERVED_SLOT_RANGE);
+         return JS_FALSE;
+     }
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
+ {
+     JSClass *clasp;
+     uint32 limit, slot;
+ 
+     CHECK_REQUEST(cx);
+     clasp = OBJ_GET_CLASS(cx, obj);
+     limit = JSCLASS_RESERVED_SLOTS(clasp);
+     if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
+         return JS_FALSE;
+     slot = JSSLOT_START(clasp) + index;
+     *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
+ {
+     JSClass *clasp;
+     uint32 limit, slot;
+ 
+     CHECK_REQUEST(cx);
+     clasp = OBJ_GET_CLASS(cx, obj);
+     limit = JSCLASS_RESERVED_SLOTS(clasp);
+     if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
+         return JS_FALSE;
+     slot = JSSLOT_START(clasp) + index;
+     return OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
+ }
+ 
+ #ifdef JS_THREADSAFE
+ JS_PUBLIC_API(jsrefcount)
+ JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
+ {
+     return JS_ATOMIC_INCREMENT(&principals->refcount);
+ }
+ 
+ JS_PUBLIC_API(jsrefcount)
+ JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
+ {
+     jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount);
+     if (rc == 0)
+         principals->destroy(cx, principals);
+     return rc;
+ }
+ #endif
+ 
+ JS_PUBLIC_API(JSPrincipalsTranscoder)
+ JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px)
+ {
+     JSPrincipalsTranscoder oldpx;
+ 
+     oldpx = rt->principalsTranscoder;
+     rt->principalsTranscoder = px;
+     return oldpx;
+ }
+ 
+ JS_PUBLIC_API(JSObjectPrincipalsFinder)
+ JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop)
+ {
+     JSObjectPrincipalsFinder oldfop;
+ 
+     oldfop = rt->findObjectPrincipals;
+     rt->findObjectPrincipals = fop;
+     return oldfop;
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
+                JSObject *parent, const char *name)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+ 
+     if (!name) {
+         atom = NULL;
+     } else {
+         atom = js_Atomize(cx, name, strlen(name), 0);
+         if (!atom)
+             return NULL;
+     }
+     return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
+ {
+     CHECK_REQUEST(cx);
+     if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {
+         /* Indicate we cannot clone this object. */
+         return funobj;
+     }
+     return js_CloneFunctionObject(cx, funobj, parent);
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_GetFunctionObject(JSFunction *fun)
+ {
+     return fun->object;
+ }
+ 
+ JS_PUBLIC_API(const char *)
+ JS_GetFunctionName(JSFunction *fun)
+ {
+     return fun->atom
+            ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
+            : js_anonymous_str;
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_GetFunctionId(JSFunction *fun)
+ {
+     return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
+ }
+ 
+ JS_PUBLIC_API(uintN)
+ JS_GetFunctionFlags(JSFunction *fun)
+ {
+     return fun->flags;
+ }
+ 
+ JS_PUBLIC_API(uint16)
+ JS_GetFunctionArity(JSFunction *fun)
+ {
+     return fun->nargs;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
+ {
+     return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
+ }
+ 
+ JS_STATIC_DLL_CALLBACK(JSBool)
+ js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
+                                     uintN argc, jsval *argv, jsval *rval)
+ {
+     jsval fsv;
+     JSFunctionSpec *fs;
+     JSObject *tmp;
+ 
+     if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), 0, &fsv))
+         return JS_FALSE;
+     fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
+ 
+     /*
+      * We know that argv[0] is valid because JS_DefineFunctions, which is our
+      * only (indirect) referrer, defined us as requiring at least one argument
+      * (notice how it passes fs->nargs + 1 as the next-to-last argument to
+      * JS_DefineFunction).
+      */
+     if (JSVAL_IS_PRIMITIVE(argv[0])) {
+         /*
+          * Make sure that this is an object or null, as required by the generic
+          * functions.
+          */
+         if (!js_ValueToObject(cx, argv[0], &tmp))
+             return JS_FALSE;
+         argv[0] = OBJECT_TO_JSVAL(tmp);
+     }
+ 
+     /*
+      * Copy all actual (argc) and required but missing (fs->nargs + 1 - argc)
+      * args down over our |this| parameter, argv[-1], which is almost always
+      * the class constructor object, e.g. Array.  Then call the corresponding
+      * prototype native method with our first argument passed as |this|.
+      */
+     memmove(argv - 1, argv, JS_MAX(fs->nargs + 1U, argc) * sizeof(jsval));
+ 
+     /*
+      * Follow Function.prototype.apply and .call by using the global object as
+      * the 'this' param if no args.
+      */
+     JS_ASSERT(cx->fp->argv == argv);
+     if (!js_ComputeThis(cx, JSVAL_TO_OBJECT(argv[-1]), cx->fp))
+         return JS_FALSE;
+ 
+     /*
+      * Protect against argc - 1 underflowing below. By calling js_ComputeThis,
+      * we made it as if the static was called with one parameter.
+      */
+     if (argc == 0)
+         argc = 1;
+ 
+     return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc - 1, argv, rval);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
+ {
+     uintN flags;
+     JSObject *ctor;
+     JSFunction *fun;
+ 
+     CHECK_REQUEST(cx);
+     ctor = NULL;
+     for (; fs->name; fs++) {
+         flags = fs->flags;
+ 
+         /*
+          * Define a generic arity N+1 static method for the arity N prototype
+          * method if flags contains JSFUN_GENERIC_NATIVE.
+          */
+         if (flags & JSFUN_GENERIC_NATIVE) {
+             if (!ctor) {
+                 ctor = JS_GetConstructor(cx, obj);
+                 if (!ctor)
+                     return JS_FALSE;
+             }
+ 
+             flags &= ~JSFUN_GENERIC_NATIVE;
+             fun = JS_DefineFunction(cx, ctor, fs->name,
+                                     js_generic_native_method_dispatcher,
+                                     fs->nargs + 1, flags);
+             if (!fun)
+                 return JS_FALSE;
+             fun->extra = fs->extra;
+ 
+             /*
+              * As jsapi.h notes, fs must point to storage that lives as long
+              * as fun->object lives.
+              */
+             if (!JS_SetReservedSlot(cx, fun->object, 0, PRIVATE_TO_JSVAL(fs)))
+                 return JS_FALSE;
+         }
+ 
+         fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
+         if (!fun)
+             return JS_FALSE;
+         fun->extra = fs->extra;
+     }
+     return JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+                   uintN nargs, uintN attrs)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_Atomize(cx, name, strlen(name), 0);
+     if (!atom)
+         return NULL;
+     return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_DefineUCFunction(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen, JSNative call,
+                     uintN nargs, uintN attrs)
+ {
+     JSAtom *atom;
+ 
+     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+     if (!atom)
+         return NULL;
+     return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
+ }
+ 
+ static JSScript *
+ CompileTokenStream(JSContext *cx, JSObject *obj, JSTokenStream *ts,
+                    void *tempMark, JSBool *eofp)
+ {
+     JSBool eof;
+     JSArenaPool codePool, notePool;
+     JSCodeGenerator cg;
+     JSScript *script;
+ 
+     CHECK_REQUEST(cx);
+     eof = JS_FALSE;
+     JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
+     JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));
+     if (!js_InitCodeGenerator(cx, &cg, &codePool, &notePool,
+                               ts->filename, ts->lineno,
+                               ts->principals)) {
+         script = NULL;
+     } else if (!js_CompileTokenStream(cx, obj, ts, &cg)) {
+         script = NULL;
+         eof = (ts->flags & TSF_EOF) != 0;
+     } else {
+         script = js_NewScriptFromCG(cx, &cg, NULL);
+     }
+     if (eofp)
+         *eofp = eof;
+     if (!js_CloseTokenStream(cx, ts)) {
+         if (script)
+             js_DestroyScript(cx, script);
+         script = NULL;
+     }
+     cg.tempMark = tempMark;
+     js_FinishCodeGenerator(cx, &cg);
+     JS_FinishArenaPool(&codePool);
+     JS_FinishArenaPool(&notePool);
+     return script;
+ }
+ 
+ JS_PUBLIC_API(JSScript *)
+ JS_CompileScript(JSContext *cx, JSObject *obj,
+                  const char *bytes, size_t length,
+                  const char *filename, uintN lineno)
+ {
+     jschar *chars;
+     JSScript *script;
+ 
+     CHECK_REQUEST(cx);
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return NULL;
+     script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno);
+     JS_free(cx, chars);
+     return script;
+ }
+ 
+ JS_PUBLIC_API(JSScript *)
+ JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
+                               JSPrincipals *principals,
+                               const char *bytes, size_t length,
+                               const char *filename, uintN lineno)
+ {
+     jschar *chars;
+     JSScript *script;
+ 
+     CHECK_REQUEST(cx);
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return NULL;
+     script = JS_CompileUCScriptForPrincipals(cx, obj, principals,
+                                              chars, length, filename, lineno);
+     JS_free(cx, chars);
+     return script;
+ }
+ 
+ JS_PUBLIC_API(JSScript *)
+ JS_CompileUCScript(JSContext *cx, JSObject *obj,
+                    const jschar *chars, size_t length,
+                    const char *filename, uintN lineno)
+ {
+     CHECK_REQUEST(cx);
+     return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length,
+                                            filename, lineno);
+ }
+ 
+ #if JS_HAS_EXCEPTIONS
+ # define LAST_FRAME_EXCEPTION_CHECK(cx,result)                                \
+     JS_BEGIN_MACRO                                                            \
+         if (!(result))                                                        \
+             js_ReportUncaughtException(cx);                                   \
+     JS_END_MACRO
+ #else
+ # define LAST_FRAME_EXCEPTION_CHECK(cx,result)  /* nothing */
+ #endif
+ 
+ #define LAST_FRAME_CHECKS(cx,result)                                          \
+     JS_BEGIN_MACRO                                                            \
+         if (!(cx)->fp) {                                                      \
+             (cx)->lastInternalResult = JSVAL_NULL;                            \
+             LAST_FRAME_EXCEPTION_CHECK(cx, result);                           \
+         }                                                                     \
+     JS_END_MACRO
+ 
+ JS_PUBLIC_API(JSScript *)
+ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                 JSPrincipals *principals,
+                                 const jschar *chars, size_t length,
+                                 const char *filename, uintN lineno)
+ {
+     void *mark;
+     JSTokenStream *ts;
+     JSScript *script;
+ 
+     CHECK_REQUEST(cx);
+     mark = JS_ARENA_MARK(&cx->tempPool);
+     ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
+     if (!ts)
+         return NULL;
+     script = CompileTokenStream(cx, obj, ts, mark, NULL);
+     LAST_FRAME_CHECKS(cx, script);
+     return script;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
+                           const char *bytes, size_t length)
+ {
+     jschar *chars;
+     JSBool result;
+     JSExceptionState *exnState;
+     void *tempMark;
+     JSTokenStream *ts;
+     JSErrorReporter older;
+ 
+     CHECK_REQUEST(cx);
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return JS_TRUE;
+ 
+     /*
+      * Return true on any out-of-memory error, so our caller doesn't try to
+      * collect more buffered source.
+      */
+     result = JS_TRUE;
+     exnState = JS_SaveExceptionState(cx);
+     tempMark = JS_ARENA_MARK(&cx->tempPool);
+     ts = js_NewTokenStream(cx, chars, length, NULL, 0, NULL);
+     if (ts) {
+         older = JS_SetErrorReporter(cx, NULL);
+         if (!js_ParseTokenStream(cx, obj, ts) &&
+             (ts->flags & TSF_UNEXPECTED_EOF)) {
+             /*
+              * We ran into an error.  If it was because we ran out of source,
+              * we return false, so our caller will know to try to collect more
+              * buffered source.
+              */
+             result = JS_FALSE;
+         }
+ 
+         JS_SetErrorReporter(cx, older);
+         js_CloseTokenStream(cx, ts);
+         JS_ARENA_RELEASE(&cx->tempPool, tempMark);
+     }
+ 
+     JS_free(cx, chars);
+     JS_RestoreExceptionState(cx, exnState);
+     return result;
+ }
+ 
+ JS_PUBLIC_API(JSScript *)
+ JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
+ {
+     void *mark;
+     JSTokenStream *ts;
+     JSScript *script;
+ 
+     CHECK_REQUEST(cx);
+     mark = JS_ARENA_MARK(&cx->tempPool);
+     ts = js_NewFileTokenStream(cx, filename, stdin);
+     if (!ts)
+         return NULL;
+     script = CompileTokenStream(cx, obj, ts, mark, NULL);
+     LAST_FRAME_CHECKS(cx, script);
+     return script;
+ }
+ 
+ JS_PUBLIC_API(JSScript *)
+ JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
+                      FILE *file)
+ {
+     return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
+ }
+ 
+ JS_PUBLIC_API(JSScript *)
+ JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
+                                   const char *filename, FILE *file,
+                                   JSPrincipals *principals)
+ {
+     void *mark;
+     JSTokenStream *ts;
+     JSScript *script;
+ 
+     CHECK_REQUEST(cx);
+     mark = JS_ARENA_MARK(&cx->tempPool);
+     ts = js_NewFileTokenStream(cx, NULL, file);
+     if (!ts)
+         return NULL;
+     ts->filename = filename;
+     /* XXXshaver js_NewFileTokenStream should do this, because it drops */
+     if (principals) {
+         ts->principals = principals;
+         JSPRINCIPALS_HOLD(cx, ts->principals);
+     }
+     script = CompileTokenStream(cx, obj, ts, mark, NULL);
+     LAST_FRAME_CHECKS(cx, script);
+     return script;
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_NewScriptObject(JSContext *cx, JSScript *script)
+ {
+     JSObject *obj;
+ 
+     obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
+     if (!obj)
+         return NULL;
+ 
+     if (script) {
+         if (!JS_SetPrivate(cx, obj, script))
+             return NULL;
+         script->object = obj;
+     }
+     return obj;
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_GetScriptObject(JSScript *script)
+ {
+     return script->object;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_DestroyScript(JSContext *cx, JSScript *script)
+ {
+     CHECK_REQUEST(cx);
+     js_DestroyScript(cx, script);
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
+                    uintN nargs, const char **argnames,
+                    const char *bytes, size_t length,
+                    const char *filename, uintN lineno)
+ {
+     jschar *chars;
+     JSFunction *fun;
+ 
+     CHECK_REQUEST(cx);
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return NULL;
+     fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length,
+                                filename, lineno);
+     JS_free(cx, chars);
+     return fun;
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
+                                 JSPrincipals *principals, const char *name,
+                                 uintN nargs, const char **argnames,
+                                 const char *bytes, size_t length,
+                                 const char *filename, uintN lineno)
+ {
+     jschar *chars;
+     JSFunction *fun;
+ 
+     CHECK_REQUEST(cx);
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return NULL;
+     fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
+                                             nargs, argnames, chars, length,
+                                             filename, lineno);
+     JS_free(cx, chars);
+     return fun;
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
+                      uintN nargs, const char **argnames,
+                      const jschar *chars, size_t length,
+                      const char *filename, uintN lineno)
+ {
+     CHECK_REQUEST(cx);
+     return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name,
+                                              nargs, argnames,
+                                              chars, length,
+                                              filename, lineno);
+ }
+ 
+ JS_PUBLIC_API(JSFunction *)
+ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
+                                   JSPrincipals *principals, const char *name,
+                                   uintN nargs, const char **argnames,
+                                   const jschar *chars, size_t length,
+                                   const char *filename, uintN lineno)
+ {
+     void *mark;
+     JSTokenStream *ts;
+     JSFunction *fun;
+     JSAtom *funAtom, *argAtom;
+     uintN i;
+ 
+     CHECK_REQUEST(cx);
+     mark = JS_ARENA_MARK(&cx->tempPool);
+     ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
+     if (!ts) {
+         fun = NULL;
+         goto out;
+     }
+     if (!name) {
+         funAtom = NULL;
+     } else {
+         funAtom = js_Atomize(cx, name, strlen(name), 0);
+         if (!funAtom) {
+             fun = NULL;
+             goto out;
+         }
+     }
+     fun = js_NewFunction(cx, NULL, NULL, nargs, 0, obj, funAtom);
+     if (!fun)
+         goto out;
+     if (nargs) {
+         for (i = 0; i < nargs; i++) {
+             argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
+             if (!argAtom)
+                 break;
+             if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(argAtom),
+                                       js_GetArgument, js_SetArgument,
+                                       SPROP_INVALID_SLOT,
+                                       JSPROP_PERMANENT | JSPROP_SHARED,
+                                       SPROP_HAS_SHORTID, i)) {
+                 break;
+             }
+         }
+         if (i < nargs) {
+             fun = NULL;
+             goto out;
+         }
+     }
+     if (!js_CompileFunctionBody(cx, ts, fun)) {
+         fun = NULL;
+         goto out;
+     }
+     if (obj && funAtom) {
+         if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom),
+                                  OBJECT_TO_JSVAL(fun->object),
+                                  NULL, NULL, JSPROP_ENUMERATE, NULL)) {
+             return NULL;
+         }
+     }
+ out:
+     if (ts)
+         js_CloseTokenStream(cx, ts);
+     JS_ARENA_RELEASE(&cx->tempPool, mark);
+     LAST_FRAME_CHECKS(cx, fun);
+     return fun;
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
+                    uintN indent)
+ {
+     JSPrinter *jp;
+     JSString *str;
+ 
+     CHECK_REQUEST(cx);
+     jp = js_NewPrinter(cx, name,
+                        indent & ~JS_DONT_PRETTY_PRINT,
+                        !(indent & JS_DONT_PRETTY_PRINT));
+     if (!jp)
+         return NULL;
+     if (js_DecompileScript(jp, script))
+         str = js_GetPrinterOutput(jp);
+     else
+         str = NULL;
+     js_DestroyPrinter(jp);
+     return str;
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
+ {
+     JSPrinter *jp;
+     JSString *str;
+ 
+     CHECK_REQUEST(cx);
+     jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
+                        indent & ~JS_DONT_PRETTY_PRINT,
+                        !(indent & JS_DONT_PRETTY_PRINT));
+     if (!jp)
+         return NULL;
+     if (js_DecompileFunction(jp, fun))
+         str = js_GetPrinterOutput(jp);
+     else
+         str = NULL;
+     js_DestroyPrinter(jp);
+     return str;
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
+ {
+     JSPrinter *jp;
+     JSString *str;
+ 
+     CHECK_REQUEST(cx);
+     jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
+                        indent & ~JS_DONT_PRETTY_PRINT,
+                        !(indent & JS_DONT_PRETTY_PRINT));
+     if (!jp)
+         return NULL;
+     if (js_DecompileFunctionBody(jp, fun))
+         str = js_GetPrinterOutput(jp);
+     else
+         str = NULL;
+     js_DestroyPrinter(jp);
+     return str;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
+ {
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     ok = js_Execute(cx, obj, script, NULL, 0, rval);
+     LAST_FRAME_CHECKS(cx, ok);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
+                      JSExecPart part, jsval *rval)
+ {
+     JSScript tmp;
+     JSRuntime *rt;
+     JSBool ok;
+ 
+     /* Make a temporary copy of the JSScript structure and farble it a bit. */
+     tmp = *script;
+     if (part == JSEXEC_PROLOG) {
+         tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode);
+     } else {
+         tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode);
+         tmp.code = tmp.main;
+     }
+ 
+     /* Tell the debugger about our temporary copy of the script structure. */
+     rt = cx->runtime;
+     if (rt->newScriptHook) {
+         rt->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL,
+                           rt->newScriptHookData);
+     }
+ 
+     /* Execute the farbled struct and tell the debugger to forget about it. */
+     ok = JS_ExecuteScript(cx, obj, &tmp, rval);
+     if (rt->destroyScriptHook)
+         rt->destroyScriptHook(cx, &tmp, rt->destroyScriptHookData);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_EvaluateScript(JSContext *cx, JSObject *obj,
+                   const char *bytes, uintN length,
+                   const char *filename, uintN lineno,
+                   jsval *rval)
+ {
+     jschar *chars;
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return JS_FALSE;
+     ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval);
+     JS_free(cx, chars);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                JSPrincipals *principals,
+                                const char *bytes, uintN length,
+                                const char *filename, uintN lineno,
+                                jsval *rval)
+ {
+     jschar *chars;
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return JS_FALSE;
+     ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
+                                           filename, lineno, rval);
+     JS_free(cx, chars);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
+                     const jschar *chars, uintN length,
+                     const char *filename, uintN lineno,
+                     jsval *rval)
+ {
+     CHECK_REQUEST(cx);
+     return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length,
+                                             filename, lineno, rval);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                  JSPrincipals *principals,
+                                  const jschar *chars, uintN length,
+                                  const char *filename, uintN lineno,
+                                  jsval *rval)
+ {
+     uint32 options;
+     JSScript *script;
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     options = cx->options;
+     cx->options = options | JSOPTION_COMPILE_N_GO;
+     script = JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length,
+                                              filename, lineno);
+     cx->options = options;
+     if (!script)
+         return JS_FALSE;
+     ok = js_Execute(cx, obj, script, NULL, 0, rval);
+     LAST_FRAME_CHECKS(cx, ok);
+     JS_DestroyScript(cx, script);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
+                 jsval *argv, jsval *rval)
+ {
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv,
+                          rval);
+     LAST_FRAME_CHECKS(cx, ok);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
+                     jsval *argv, jsval *rval)
+ {
+     JSBool ok;
+     jsval fval;
+ 
+     CHECK_REQUEST(cx);
+ #if JS_HAS_XML_SUPPORT
+     if (OBJECT_IS_XML(cx, obj)) {
+         JSXMLObjectOps *ops;
+         JSAtom *atom;
+ 
+         ops = (JSXMLObjectOps *) obj->map->ops;
+         atom = js_Atomize(cx, name, strlen(name), 0);
+         if (!atom)
+             return JS_FALSE;
+         obj = ops->getMethod(cx, obj, ATOM_TO_JSID(atom), &fval);
+         if (!obj)
+             return JS_FALSE;
+     } else
+ #endif
+     if (!JS_GetProperty(cx, obj, name, &fval))
+         return JS_FALSE;
+     ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
+     LAST_FRAME_CHECKS(cx, ok);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
+                      jsval *argv, jsval *rval)
+ {
+     JSBool ok;
+ 
+     CHECK_REQUEST(cx);
+     ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
+     LAST_FRAME_CHECKS(cx, ok);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBranchCallback)
+ JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb)
+ {
+     JSBranchCallback oldcb;
+ 
+     oldcb = cx->branchCallback;
+     cx->branchCallback = cb;
+     return oldcb;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_IsRunning(JSContext *cx)
+ {
+     return cx->fp != NULL;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_IsConstructing(JSContext *cx)
+ {
+     return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
+ }
+ 
+ JS_FRIEND_API(JSBool)
+ JS_IsAssigning(JSContext *cx)
+ {
+     JSStackFrame *fp;
+     jsbytecode *pc;
+ 
+     for (fp = cx->fp; fp && !fp->script; fp = fp->down)
+         continue;
+     if (!fp || !(pc = fp->pc))
+         return JS_FALSE;
+     return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_SetCallReturnValue2(JSContext *cx, jsval v)
+ {
+ #if JS_HAS_LVALUE_RETURN
+     cx->rval2 = v;
+     cx->rval2set = JS_TRUE;
+ #endif
+ }
+ 
+ /************************************************************************/
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewString(JSContext *cx, char *bytes, size_t length)
+ {
+     jschar *chars;
+     JSString *str;
+ 
+     CHECK_REQUEST(cx);
+     /* Make a Unicode vector from the 8-bit char codes in bytes. */
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return NULL;
+ 
+     /* Free chars (but not bytes, which caller frees on error) if we fail. */
+     str = js_NewString(cx, chars, length, 0);
+     if (!str) {
+         JS_free(cx, chars);
+         return NULL;
+     }
+ 
+     /* Hand off bytes to the deflated string cache, if possible. */
+     if (!js_SetStringBytes(str, bytes, length))
+         JS_free(cx, bytes);
+     return str;
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
+ {
+     jschar *js;
+     JSString *str;
+ 
+     CHECK_REQUEST(cx);
+     js = js_InflateString(cx, s, n);
+     if (!js)
+         return NULL;
+     str = js_NewString(cx, js, n, 0);
+     if (!str)
+         JS_free(cx, js);
+     return str;
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewStringCopyZ(JSContext *cx, const char *s)
+ {
+     size_t n;
+     jschar *js;
+     JSString *str;
+ 
+     CHECK_REQUEST(cx);
+     if (!s)
+         return cx->runtime->emptyString;
+     n = strlen(s);
+     js = js_InflateString(cx, s, n);
+     if (!js)
+         return NULL;
+     str = js_NewString(cx, js, n, 0);
+     if (!str)
+         JS_free(cx, js);
+     return str;
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_InternString(JSContext *cx, const char *s)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
+     if (!atom)
+         return NULL;
+     return ATOM_TO_STRING(atom);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
+ {
+     CHECK_REQUEST(cx);
+     return js_NewString(cx, chars, length, 0);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
+ {
+     CHECK_REQUEST(cx);
+     return js_NewStringCopyN(cx, s, n, 0);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
+ {
+     CHECK_REQUEST(cx);
+     if (!s)
+         return cx->runtime->emptyString;
+     return js_NewStringCopyZ(cx, s, 0);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
+ {
+     JSAtom *atom;
+ 
+     CHECK_REQUEST(cx);
+     atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
+     if (!atom)
+         return NULL;
+     return ATOM_TO_STRING(atom);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_InternUCString(JSContext *cx, const jschar *s)
+ {
+     return JS_InternUCStringN(cx, s, js_strlen(s));
+ }
+ 
+ JS_PUBLIC_API(char *)
+ JS_GetStringBytes(JSString *str)
+ {
+     char *bytes;
+ 
+     bytes = js_GetStringBytes(str);
+     return bytes ? bytes : "";
+ }
+ 
+ JS_PUBLIC_API(jschar *)
+ JS_GetStringChars(JSString *str)
+ {
+     /*
+      * API botch (again, shades of JS_GetStringBytes): we have no cx to pass
+      * to js_UndependString (called by js_GetStringChars) for out-of-memory
+      * error reports, so js_UndependString passes NULL and suppresses errors.
+      * If it fails to convert a dependent string into an independent one, our
+      * caller will not be guaranteed a \u0000 terminator as a backstop.  This
+      * may break some clients who already misbehave on embedded NULs.
+      *
+      * The gain of dependent strings, which cure quadratic and cubic growth
+      * rate bugs in string concatenation, is worth this slight loss in API
+      * compatibility.
+      */
+     jschar *chars;
+ 
+     chars = js_GetStringChars(str);
+     return chars ? chars : JSSTRING_CHARS(str);
+ }
+ 
+ JS_PUBLIC_API(size_t)
+ JS_GetStringLength(JSString *str)
+ {
+     return JSSTRING_LENGTH(str);
+ }
+ 
+ JS_PUBLIC_API(intN)
+ JS_CompareStrings(JSString *str1, JSString *str2)
+ {
+     return js_CompareStrings(str1, str2);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
+ {
+     CHECK_REQUEST(cx);
+     return js_NewString(cx, chars, length, GCF_MUTABLE);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
+                       size_t length)
+ {
+     CHECK_REQUEST(cx);
+     return js_NewDependentString(cx, str, start, length, 0);
+ }
+ 
+ JS_PUBLIC_API(JSString *)
+ JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
+ {
+     CHECK_REQUEST(cx);
+     return js_ConcatStrings(cx, left, right);
+ }
+ 
+ JS_PUBLIC_API(const jschar *)
+ JS_UndependString(JSContext *cx, JSString *str)
+ {
+     CHECK_REQUEST(cx);
+     return js_UndependString(cx, str);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_MakeStringImmutable(JSContext *cx, JSString *str)
+ {
+     CHECK_REQUEST(cx);
+     if (!js_UndependString(cx, str))
+         return JS_FALSE;
+ 
+     *js_GetGCThingFlags(str) &= ~GCF_MUTABLE;
+     return JS_TRUE;
+ }
+ 
+ /************************************************************************/
+ 
+ JS_PUBLIC_API(void)
+ JS_ReportError(JSContext *cx, const char *format, ...)
+ {
+     va_list ap;
+ 
+     va_start(ap, format);
+     js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
+     va_end(ap);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
+                      void *userRef, const uintN errorNumber, ...)
+ {
+     va_list ap;
+ 
+     va_start(ap, errorNumber);
+     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
+                            errorNumber, JS_TRUE, ap);
+     va_end(ap);
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
+                      void *userRef, const uintN errorNumber, ...)
+ {
+     va_list ap;
+ 
+     va_start(ap, errorNumber);
+     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
+                            errorNumber, JS_FALSE, ap);
+     va_end(ap);
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ReportWarning(JSContext *cx, const char *format, ...)
+ {
+     va_list ap;
+     JSBool ok;
+ 
+     va_start(ap, format);
+     ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
+     va_end(ap);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
+                              JSErrorCallback errorCallback, void *userRef,
+                              const uintN errorNumber, ...)
+ {
+     va_list ap;
+     JSBool ok;
+ 
+     va_start(ap, errorNumber);
+     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
+                                 errorNumber, JS_TRUE, ap);
+     va_end(ap);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
+                                JSErrorCallback errorCallback, void *userRef,
+                                const uintN errorNumber, ...)
+ {
+     va_list ap;
+     JSBool ok;
+ 
+     va_start(ap, errorNumber);
+     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
+                                 errorNumber, JS_FALSE, ap);
+     va_end(ap);
+     return ok;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ReportOutOfMemory(JSContext *cx)
+ {
+     js_ReportOutOfMemory(cx, js_GetErrorMessage);
+ }
+ 
+ JS_PUBLIC_API(JSErrorReporter)
+ JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
+ {
+     JSErrorReporter older;
+ 
+     older = cx->errorReporter;
+     cx->errorReporter = er;
+     return older;
+ }
+ 
+ /************************************************************************/
+ 
+ /*
+  * Regular Expressions.
+  */
+ JS_PUBLIC_API(JSObject *)
+ JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
+ {
+ #if JS_HAS_REGEXPS
+     jschar *chars;
+     JSObject *obj;
+ 
+     CHECK_REQUEST(cx);
+     chars = js_InflateString(cx, bytes, length);
+     if (!chars)
+         return NULL;
+     obj = js_NewRegExpObject(cx, NULL, chars, length, flags);
+     JS_free(cx, chars);
+     return obj;
+ #else
+     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS);
+     return NULL;
+ #endif
+ }
+ 
+ JS_PUBLIC_API(JSObject *)
+ JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
+ {
+     CHECK_REQUEST(cx);
+ #if JS_HAS_REGEXPS
+     return js_NewRegExpObject(cx, NULL, chars, length, flags);
+ #else
+     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS);
+     return NULL;
+ #endif
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
+ {
+     JSRegExpStatics *res;
+ 
+     CHECK_REQUEST(cx);
+     /* No locking required, cx is thread-private and input must be live. */
+     res = &cx->regExpStatics;
+     res->input = input;
+     res->multiline = multiline;
+     cx->runtime->gcPoke = JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ClearRegExpStatics(JSContext *cx)
+ {
+     JSRegExpStatics *res;
+ 
+     /* No locking required, cx is thread-private and input must be live. */
+     res = &cx->regExpStatics;
+     res->input = NULL;
+     res->multiline = JS_FALSE;
+     res->parenCount = 0;
+     res->lastMatch = res->lastParen = js_EmptySubString;
+     res->leftContext = res->rightContext = js_EmptySubString;
+     cx->runtime->gcPoke = JS_TRUE;
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ClearRegExpRoots(JSContext *cx)
+ {
+     JSRegExpStatics *res;
+ 
+     /* No locking required, cx is thread-private and input must be live. */
+     res = &cx->regExpStatics;
+     res->input = NULL;
+     cx->runtime->gcPoke = JS_TRUE;
+ }
+ 
+ /* TODO: compile, execute, get/set other statics... */
+ 
+ /************************************************************************/
+ 
+ JS_PUBLIC_API(void)
+ JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
+ {
+     cx->localeCallbacks = callbacks;
+ }
+ 
+ JS_PUBLIC_API(JSLocaleCallbacks *)
+ JS_GetLocaleCallbacks(JSContext *cx)
+ {
+     return cx->localeCallbacks;
+ }
+ 
+ /************************************************************************/
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_IsExceptionPending(JSContext *cx)
+ {
+ #if JS_HAS_EXCEPTIONS
+     return (JSBool) cx->throwing;
+ #else
+     return JS_FALSE;
+ #endif
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_GetPendingException(JSContext *cx, jsval *vp)
+ {
+ #if JS_HAS_EXCEPTIONS
+     CHECK_REQUEST(cx);
+     if (!cx->throwing)
+         return JS_FALSE;
+     *vp = cx->exception;
+     return JS_TRUE;
+ #else
+     return JS_FALSE;
+ #endif
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_SetPendingException(JSContext *cx, jsval v)
+ {
+     CHECK_REQUEST(cx);
+ #if JS_HAS_EXCEPTIONS
+     cx->throwing = JS_TRUE;
+     cx->exception = v;
+ #endif
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_ClearPendingException(JSContext *cx)
+ {
+ #if JS_HAS_EXCEPTIONS
+     cx->throwing = JS_FALSE;
+     cx->exception = JSVAL_VOID;
+ #endif
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ReportPendingException(JSContext *cx)
+ {
+ #if JS_HAS_EXCEPTIONS
+     JSBool save, ok;
+ 
+     CHECK_REQUEST(cx);
+ 
+     /*
+      * Set cx->creatingException to suppress the standard error-to-exception
+      * conversion done by all {js,JS}_Report* functions except for OOM.  The
+      * cx->creatingException flag was added to suppress recursive divergence
+      * under js_ErrorToException, but it serves for our purposes here too.
+      */
+     save = cx->creatingException;
+     cx->creatingException = JS_TRUE;
+     ok = js_ReportUncaughtException(cx);
+     cx->creatingException = save;
+     return ok;
+ #else
+     return JS_TRUE;
+ #endif
+ }
+ 
+ #if JS_HAS_EXCEPTIONS
+ struct JSExceptionState {
+     JSBool throwing;
+     jsval  exception;
+ };
+ #endif
+ 
+ JS_PUBLIC_API(JSExceptionState *)
+ JS_SaveExceptionState(JSContext *cx)
+ {
+ #if JS_HAS_EXCEPTIONS
+     JSExceptionState *state;
+ 
+     CHECK_REQUEST(cx);
+     state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState));
+     if (state) {
+         state->throwing = JS_GetPendingException(cx, &state->exception);
+         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
+             js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
+     }
+     return state;
+ #else
+     return NULL;
+ #endif
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
+ {
+ #if JS_HAS_EXCEPTIONS
+     CHECK_REQUEST(cx);
+     if (state) {
+         if (state->throwing)
+             JS_SetPendingException(cx, state->exception);
+         else
+             JS_ClearPendingException(cx);
+         JS_DropExceptionState(cx, state);
+     }
+ #endif
+ }
+ 
+ JS_PUBLIC_API(void)
+ JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
+ {
+ #if JS_HAS_EXCEPTIONS
+     CHECK_REQUEST(cx);
+     if (state) {
+         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
+             JS_RemoveRoot(cx, &state->exception);
+         JS_free(cx, state);
+     }
+ #endif
+ }
+ 
+ JS_PUBLIC_API(JSErrorReport *)
+ JS_ErrorFromException(JSContext *cx, jsval v)
+ {
+ #if JS_HAS_ERROR_EXCEPTIONS
+     CHECK_REQUEST(cx);
+     return js_ErrorFromException(cx, v);
+ #else
+     return NULL;
+ #endif
+ }
+ 
+ JS_PUBLIC_API(JSBool)
+ JS_ThrowReportedError(JSContext *cx, const char *message,
+                       JSErrorReport *reportp)
+ {
+     return js_ErrorToException(cx, message, reportp);
+ }
+ 
+ #ifdef JS_THREADSAFE
+ JS_PUBLIC_API(jsword)
+ JS_GetContextThread(JSContext *cx)
+ {
+     return cx->thread;
+ }
+ 
+ JS_PUBLIC_API(jsword)
+ JS_SetContextThread(JSContext *cx)
+ {
+     jsword old = cx->thread;
+     cx->thread = js_CurrentThreadId();
+     return old;
+ }
+ 
+ JS_PUBLIC_API(jsword)
+ JS_ClearContextThread(JSContext *cx)
+ {
+     jsword old = cx->thread;
+     cx->thread = 0;
+     return old;
+ }
+ #endif
+ 
+ /************************************************************************/
+ 
+ #if defined(XP_WIN)
+ #include <windows.h>
+ /*
+  * Initialization routine for the JS DLL...
+  */
+ 
+ /*
+  * Global Instance handle...
+  * In Win32 this is the module handle of the DLL.
+  *
+  * In Win16 this is the instance handle of the application
+  * which loaded the DLL.
+  */
+ 
+ #ifdef _WIN32
+ BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
+ {
+     return TRUE;
+ }
+ 
+ #else  /* !_WIN32 */
+ 
+ int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
+                       WORD cbHeapSize, LPSTR lpszCmdLine )
+ {
+     return TRUE;
+ }
+ 
+ BOOL CALLBACK __loadds WEP(BOOL fSystemExit)
+ {
+     return TRUE;
+ }
+ 
+ #endif /* !_WIN32 */
+ #endif /* XP_WIN */


ossp-pkg/js/src/jsapi.c 1.1 -> 1.1.1.1



ossp-pkg/js/src/jsapi.h -> 1.1

*** /dev/null    Sat Nov 23 05:37:38 2024
--- -    Sat Nov 23 05:37:41 2024
***************
*** 0 ****
--- 1,1989 ----
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+  *
+  * ***** BEGIN LICENSE BLOCK *****
+  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+  *
+  * The contents of this file are subject to the Mozilla Public License Version
+  * 1.1 (the "License"); you may not use this file except in compliance with
+  * the License. You may obtain a copy of the License at
+  * http://www.mozilla.org/MPL/
+  *
+  * Software distributed under the License is distributed on an "AS IS" basis,
+  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  * for the specific language governing rights and limitations under the
+  * License.
+  *
+  * The Original Code is Mozilla Communicator client code, released
+  * March 31, 1998.
+  *
+  * The Initial Developer of the Original Code is
+  * Netscape Communications Corporation.
+  * Portions created by the Initial Developer are Copyright (C) 1998
+  * the Initial Developer. All Rights Reserved.
+  *
+  * Contributor(s):
+  *
+  * Alternatively, the contents of this file may be used under the terms of
+  * either of the GNU General Public License Version 2 or later (the "GPL"),
+  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  * in which case the provisions of the GPL or the LGPL are applicable instead
+  * of those above. If you wish to allow use of your version of this file only
+  * under the terms of either the GPL or the LGPL, and not to allow others to
+  * use your version of this file under the terms of the MPL, indicate your
+  * decision by deleting the provisions above and replace them with the notice
+  * and other provisions required by the GPL or the LGPL. If you do not delete
+  * the provisions above, a recipient may use your version of this file under
+  * the terms of any one of the MPL, the GPL or the LGPL.
+  *
+  * ***** END LICENSE BLOCK ***** */
+ 
+ #ifndef jsapi_h___
+ #define jsapi_h___
+ /*
+  * JavaScript API.
+  */
+ #include <stddef.h>
+ #include <stdio.h>
+ #include "jspubtd.h"
+ 
+ JS_BEGIN_EXTERN_C
+ 
+ /*
+  * Type tags stored in the low bits of a jsval.
+  */
+ #define JSVAL_OBJECT            0x0     /* untagged reference to object */
+ #define JSVAL_INT               0x1     /* tagged 31-bit integer value */
+ #define JSVAL_DOUBLE            0x2     /* tagged reference to double */
+ #define JSVAL_STRING            0x4     /* tagged reference to string */
+ #define JSVAL_BOOLEAN           0x6     /* tagged boolean value */
+ 
+ /* Type tag bitfield length and derived macros. */
+ #define JSVAL_TAGBITS           3
+ #define JSVAL_TAGMASK           JS_BITMASK(JSVAL_TAGBITS)
+ #define JSVAL_TAG(v)            ((v) & JSVAL_TAGMASK)
+ #define JSVAL_SETTAG(v,t)       ((v) | (t))
+ #define JSVAL_CLRTAG(v)         ((v) & ~(jsval)JSVAL_TAGMASK)
+ #define JSVAL_ALIGN             JS_BIT(JSVAL_TAGBITS)
+ 
+ /* Predicates for type testing. */
+ #define JSVAL_IS_OBJECT(v)      (JSVAL_TAG(v) == JSVAL_OBJECT)
+ #define JSVAL_IS_NUMBER(v)      (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v))
+ #define JSVAL_IS_INT(v)         (((v) & JSVAL_INT) && (v) != JSVAL_VOID)
+ #define JSVAL_IS_DOUBLE(v)      (JSVAL_TAG(v) == JSVAL_DOUBLE)
+ #define JSVAL_IS_STRING(v)      (JSVAL_TAG(v) == JSVAL_STRING)
+ #define JSVAL_IS_BOOLEAN(v)     (JSVAL_TAG(v) == JSVAL_BOOLEAN)
+ #define JSVAL_IS_NULL(v)        ((v) == JSVAL_NULL)
+ #define JSVAL_IS_VOID(v)        ((v) == JSVAL_VOID)
+ #define JSVAL_IS_PRIMITIVE(v)   (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v))
+ 
+ /* Objects, strings, and doubles are GC'ed. */
+ #define JSVAL_IS_GCTHING(v)     (!((v) & JSVAL_INT) && !JSVAL_IS_BOOLEAN(v))
+ #define JSVAL_TO_GCTHING(v)     ((void *)JSVAL_CLRTAG(v))
+ #define JSVAL_TO_OBJECT(v)      ((JSObject *)JSVAL_TO_GCTHING(v))
+ #define JSVAL_TO_DOUBLE(v)      ((jsdouble *)JSVAL_TO_GCTHING(v))
+ #define JSVAL_TO_STRING(v)      ((JSString *)JSVAL_TO_GCTHING(v))
+ #define OBJECT_TO_JSVAL(obj)    ((jsval)(obj))
+ #define DOUBLE_TO_JSVAL(dp)     JSVAL_SETTAG((jsval)(dp), JSVAL_DOUBLE)
+ #define STRING_TO_JSVAL(str)    JSVAL_SETTAG((jsval)(str), JSVAL_STRING)
+ 
+ /* Lock and unlock the GC thing held by a jsval. */
+ #define JSVAL_LOCK(cx,v)        (JSVAL_IS_GCTHING(v)                          \
+                                  ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v))    \
+                                  : JS_TRUE)
+ #define JSVAL_UNLOCK(cx,v)      (JSVAL_IS_GCTHING(v)                          \
+                                  ? JS_UnlockGCThing(cx, JSVAL_TO_GCTHING(v))  \
+                                  : JS_TRUE)
+ 
+ /* Domain limits for the jsval int type. */
+ #define JSVAL_INT_BITS          31
+ #define JSVAL_INT_POW2(n)       ((jsval)1 << (n))
+ #define JSVAL_INT_MIN           ((jsval)1 - JSVAL_INT_POW2(30))
+ #define JSVAL_INT_MAX           (JSVAL_INT_POW2(30) - 1)
+ #define INT_FITS_IN_JSVAL(i)    ((jsuint)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX)
+ #define JSVAL_TO_INT(v)         ((jsint)(v) >> 1)
+ #define INT_TO_JSVAL(i)         (((jsval)(i) << 1) | JSVAL_INT)
+ 
+ /* Convert between boolean and jsval. */
+ #define JSVAL_TO_BOOLEAN(v)     ((JSBool)((v) >> JSVAL_TAGBITS))
+ #define BOOLEAN_TO_JSVAL(b)     JSVAL_SETTAG((jsval)(b) << JSVAL_TAGBITS,     \
+                                              JSVAL_BOOLEAN)
+ 
+ /* A private data pointer (2-byte-aligned) can be stored as an int jsval. */
+ #define JSVAL_TO_PRIVATE(v)     ((void *)((v) & ~JSVAL_INT))
+ #define PRIVATE_TO_JSVAL(p)     ((jsval)(p) | JSVAL_INT)
+ 
+ /* Property attributes, set in JSPropertySpec and passed to API functions. */
+ #define JSPROP_ENUMERATE        0x01    /* property is visible to for/in loop */
+ #define JSPROP_READONLY         0x02    /* not settable: assignment is no-op */
+ #define JSPROP_PERMANENT        0x04    /* property cannot be deleted */
+ #define JSPROP_EXPORTED         0x08    /* property is exported from object */
+ #define JSPROP_GETTER           0x10    /* property holds getter function */
+ #define JSPROP_SETTER           0x20    /* property holds setter function */
+ #define JSPROP_SHARED           0x40    /* don't allocate a value slot for this
+                                            property; don't copy the property on
+                                            set of the same-named property in an
+                                            object that delegates to a prototype
+                                            containing this property */
+ #define JSPROP_INDEX            0x80    /* name is actually (jsint) index */
+ 
+ /* Function flags, set in JSFunctionSpec and passed to JS_NewFunction etc. */
+ #define JSFUN_LAMBDA            0x08    /* expressed, not declared, function */
+ #define JSFUN_GETTER            JSPROP_GETTER
+ #define JSFUN_SETTER            JSPROP_SETTER
+ #define JSFUN_BOUND_METHOD      0x40    /* bind this to fun->object's parent */
+ #define JSFUN_HEAVYWEIGHT       0x80    /* activation requires a Call object */
+ #define JSFUN_FLAGS_MASK        0xf8    /* overlay JSFUN_* attributes */
+ 
+ /*
+  * Re-use JSFUN_LAMBDA, which applies only to scripted functions, for use in
+  * JSFunctionSpec arrays that specify generic native prototype methods, i.e.,
+  * methods of a class prototype that are exposed as static methods taking an
+  * extra leading argument: the generic |this| parameter.
+  *
+  * If you set this flag in a JSFunctionSpec struct's flags initializer, then
+  * that struct must live at least as long as the native static method object
+  * created due to this flag by JS_DefineFunctions or JS_InitClass.  Typically
+  * JSFunctionSpec structs are allocated in static arrays.
+  */
+ #define JSFUN_GENERIC_NATIVE    JSFUN_LAMBDA
+ 
+ /*
+  * Well-known JS values.  The extern'd variables are initialized when the
+  * first JSContext is created by JS_NewContext (see below).
+  */
+ #define JSVAL_VOID              INT_TO_JSVAL(0 - JSVAL_INT_POW2(30))
+ #define JSVAL_NULL              OBJECT_TO_JSVAL(0)
+ #define JSVAL_ZERO              INT_TO_JSVAL(0)
+ #define JSVAL_ONE               INT_TO_JSVAL(1)
+ #define JSVAL_FALSE             BOOLEAN_TO_JSVAL(JS_FALSE)
+ #define JSVAL_TRUE              BOOLEAN_TO_JSVAL(JS_TRUE)
+ 
+ /*
+  * Microseconds since the epoch, midnight, January 1, 1970 UTC.  See the
+  * comment in jstypes.h regarding safe int64 usage.
+  */
+ extern JS_PUBLIC_API(int64)
+ JS_Now();
+ 
+ /* Don't want to export data, so provide accessors for non-inline jsvals. */
+ extern JS_PUBLIC_API(jsval)
+ JS_GetNaNValue(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsval)
+ JS_GetNegativeInfinityValue(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsval)
+ JS_GetPositiveInfinityValue(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsval)
+ JS_GetEmptyStringValue(JSContext *cx);
+ 
+ /*
+  * Format is a string of the following characters (spaces are insignificant),
+  * specifying the tabulated type conversions:
+  *
+  *   b      JSBool          Boolean
+  *   c      uint16/jschar   ECMA uint16, Unicode char
+  *   i      int32           ECMA int32
+  *   u      uint32          ECMA uint32
+  *   j      int32           Rounded int32 (coordinate)
+  *   d      jsdouble        IEEE double
+  *   I      jsdouble        Integral IEEE double
+  *   s      char *          C string
+  *   S      JSString *      Unicode string, accessed by a JSString pointer
+  *   W      jschar *        Unicode character vector, 0-terminated (W for wide)
+  *   o      JSObject *      Object reference
+  *   f      JSFunction *    Function private
+  *   v      jsval           Argument value (no conversion)
+  *   *      N/A             Skip this argument (no vararg)
+  *   /      N/A             End of required arguments
+  *
+  * The variable argument list after format must consist of &b, &c, &s, e.g.,
+  * where those variables have the types given above.  For the pointer types
+  * char *, JSString *, and JSObject *, the pointed-at memory returned belongs
+  * to the JS runtime, not to the calling native code.  The runtime promises
+  * to keep this memory valid so long as argv refers to allocated stack space
+  * (so long as the native function is active).
+  *
+  * Fewer arguments than format specifies may be passed only if there is a /
+  * in format after the last required argument specifier and argc is at least
+  * the number of required arguments.  More arguments than format specifies
+  * may be passed without error; it is up to the caller to deal with trailing
+  * unconverted arguments.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
+                     ...);
+ 
+ #ifdef va_start
+ extern JS_PUBLIC_API(JSBool)
+ JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
+                       const char *format, va_list ap);
+ #endif
+ 
+ /*
+  * Inverse of JS_ConvertArguments: scan format and convert trailing arguments
+  * into jsvals, GC-rooted if necessary by the JS stack.  Return null on error,
+  * and a pointer to the new argument vector on success.  Also return a stack
+  * mark on success via *markp, in which case the caller must eventually clean
+  * up by calling JS_PopArguments.
+  *
+  * Note that the number of actual arguments supplied is specified exclusively
+  * by format, so there is no argc parameter.
+  */
+ extern JS_PUBLIC_API(jsval *)
+ JS_PushArguments(JSContext *cx, void **markp, const char *format, ...);
+ 
+ #ifdef va_start
+ extern JS_PUBLIC_API(jsval *)
+ JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap);
+ #endif
+ 
+ extern JS_PUBLIC_API(void)
+ JS_PopArguments(JSContext *cx, void *mark);
+ 
+ #ifdef JS_ARGUMENT_FORMATTER_DEFINED
+ 
+ /*
+  * Add and remove a format string handler for JS_{Convert,Push}Arguments{,VA}.
+  * The handler function has this signature (see jspubtd.h):
+  *
+  *   JSBool MyArgumentFormatter(JSContext *cx, const char *format,
+  *                              JSBool fromJS, jsval **vpp, va_list *app);
+  *
+  * It should return true on success, and return false after reporting an error
+  * or detecting an already-reported error.
+  *
+  * For a given format string, for example "AA", the formatter is called from
+  * JS_ConvertArgumentsVA like so:
+  *
+  *   formatter(cx, "AA...", JS_TRUE, &sp, &ap);
+  *
+  * sp points into the arguments array on the JS stack, while ap points into
+  * the stdarg.h va_list on the C stack.  The JS_TRUE passed for fromJS tells
+  * the formatter to convert zero or more jsvals at sp to zero or more C values
+  * accessed via pointers-to-values at ap, updating both sp (via *vpp) and ap
+  * (via *app) to point past the converted arguments and their result pointers
+  * on the C stack.
+  *
+  * When called from JS_PushArgumentsVA, the formatter is invoked thus:
+  *
+  *   formatter(cx, "AA...", JS_FALSE, &sp, &ap);
+  *
+  * where JS_FALSE for fromJS means to wrap the C values at ap according to the
+  * format specifier and store them at sp, updating ap and sp appropriately.
+  *
+  * The "..." after "AA" is the rest of the format string that was passed into
+  * JS_{Convert,Push}Arguments{,VA}.  The actual format trailing substring used
+  * in each Convert or PushArguments call is passed to the formatter, so that
+  * one such function may implement several formats, in order to share code.
+  *
+  * Remove just forgets about any handler associated with format.  Add does not
+  * copy format, it points at the string storage allocated by the caller, which
+  * is typically a string constant.  If format is in dynamic storage, it is up
+  * to the caller to keep the string alive until Remove is called.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_AddArgumentFormatter(JSContext *cx, const char *format,
+                         JSArgumentFormatter formatter);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_RemoveArgumentFormatter(JSContext *cx, const char *format);
+ 
+ #endif /* JS_ARGUMENT_FORMATTER_DEFINED */
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_ValueToFunction(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_ValueToConstructor(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_ValueToString(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp);
+ 
+ /*
+  * Convert a value to a number, then to an int32, according to the ECMA rules
+  * for ToInt32.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip);
+ 
+ /*
+  * Convert a value to a number, then to a uint32, according to the ECMA rules
+  * for ToUint32.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip);
+ 
+ /*
+  * Convert a value to a number, then to an int32 if it fits by rounding to
+  * nearest; but failing with an error report if the double is out of range
+  * or unordered.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip);
+ 
+ /*
+  * ECMA ToUint16, for mapping a jsval to a Unicode point.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp);
+ 
+ extern JS_PUBLIC_API(JSType)
+ JS_TypeOfValue(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(const char *)
+ JS_GetTypeName(JSContext *cx, JSType type);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Initialization, locking, contexts, and memory allocation.
+  */
+ #define JS_NewRuntime       JS_Init
+ #define JS_DestroyRuntime   JS_Finish
+ #define JS_LockRuntime      JS_Lock
+ #define JS_UnlockRuntime    JS_Unlock
+ 
+ extern JS_PUBLIC_API(JSRuntime *)
+ JS_NewRuntime(uint32 maxbytes);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyRuntime(JSRuntime *rt);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ShutDown(void);
+ 
+ JS_PUBLIC_API(void *)
+ JS_GetRuntimePrivate(JSRuntime *rt);
+ 
+ JS_PUBLIC_API(void)
+ JS_SetRuntimePrivate(JSRuntime *rt, void *data);
+ 
+ #ifdef JS_THREADSAFE
+ 
+ extern JS_PUBLIC_API(void)
+ JS_BeginRequest(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_EndRequest(JSContext *cx);
+ 
+ /* Yield to pending GC operations, regardless of request depth */
+ extern JS_PUBLIC_API(void)
+ JS_YieldRequest(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsrefcount)
+ JS_SuspendRequest(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth);
+ 
+ #endif /* JS_THREADSAFE */
+ 
+ extern JS_PUBLIC_API(void)
+ JS_Lock(JSRuntime *rt);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_Unlock(JSRuntime *rt);
+ 
+ extern JS_PUBLIC_API(JSContext *)
+ JS_NewContext(JSRuntime *rt, size_t stackChunkSize);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyContext(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyContextNoGC(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyContextMaybeGC(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_GetContextPrivate(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetContextPrivate(JSContext *cx, void *data);
+ 
+ extern JS_PUBLIC_API(JSRuntime *)
+ JS_GetRuntime(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSContext *)
+ JS_ContextIterator(JSRuntime *rt, JSContext **iterp);
+ 
+ extern JS_PUBLIC_API(JSVersion)
+ JS_GetVersion(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSVersion)
+ JS_SetVersion(JSContext *cx, JSVersion version);
+ 
+ extern JS_PUBLIC_API(const char *)
+ JS_VersionToString(JSVersion version);
+ 
+ extern JS_PUBLIC_API(JSVersion)
+ JS_StringToVersion(const char *string);
+ 
+ /*
+  * JS options are orthogonal to version, and may be freely composed with one
+  * another as well as with version.
+  *
+  * JSOPTION_VAROBJFIX is recommended -- see the comments associated with the
+  * prototypes for JS_ExecuteScript, JS_EvaluateScript, etc.
+  */
+ #define JSOPTION_STRICT         JS_BIT(0)       /* warn on dubious practice */
+ #define JSOPTION_WERROR         JS_BIT(1)       /* convert warning to error */
+ #define JSOPTION_VAROBJFIX      JS_BIT(2)       /* make JS_EvaluateScript use
+                                                    the last object on its 'obj'
+                                                    param's scope chain as the
+                                                    ECMA 'variables object' */
+ #define JSOPTION_PRIVATE_IS_NSISUPPORTS \
+                                 JS_BIT(3)       /* context private data points
+                                                    to an nsISupports subclass */
+ #define JSOPTION_COMPILE_N_GO   JS_BIT(4)       /* caller of JS_Compile*Script
+                                                    promises to execute compiled
+                                                    script once only; enables
+                                                    compile-time scope chain
+                                                    resolution of consts. */
+ #define JSOPTION_ATLINE         JS_BIT(5)       /* //@line number ["filename"]
+                                                    option supported for the
+                                                    XUL preprocessor and kindred
+                                                    beasts. */
+ #define JSOPTION_XML            JS_BIT(6)       /* EMCAScript for XML support:
+                                                    parse <!-- --> as a token,
+                                                    not backward compatible with
+                                                    the comment-hiding hack used
+                                                    in HTML script tags. */
+ #define JSOPTION_NATIVE_BRANCH_CALLBACK \
+                                 JS_BIT(7)       /* the branch callback set by
+                                                    JS_SetBranchCallback may be
+                                                    called with a null script
+                                                    parameter, by native code
+                                                    that loops intensively */
+ 
+ extern JS_PUBLIC_API(uint32)
+ JS_GetOptions(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(uint32)
+ JS_SetOptions(JSContext *cx, uint32 options);
+ 
+ extern JS_PUBLIC_API(uint32)
+ JS_ToggleOptions(JSContext *cx, uint32 options);
+ 
+ extern JS_PUBLIC_API(const char *)
+ JS_GetImplementationVersion(void);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetGlobalObject(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetGlobalObject(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Initialize standard JS class constructors, prototypes, and any top-level
+  * functions and constants associated with the standard classes (e.g. isNaN
+  * for Number).
+  *
+  * NB: This sets cx's global object to obj if it was null.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_InitStandardClasses(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Resolve id, which must contain either a string or an int, to a standard
+  * class name in obj if possible, defining the class's constructor and/or
+  * prototype and storing true in *resolved.  If id does not name a standard
+  * class or a top-level property induced by initializing a standard class,
+  * store false in *resolved and just return true.  Return false on error,
+  * as usual for JSBool result-typed API entry points.
+  *
+  * This API can be called directly from a global object class's resolve op,
+  * to define standard classes lazily.  The class's enumerate op should call
+  * JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
+  * loops any classes not yet resolved lazily.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
+                         JSBool *resolved);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Enumerate any already-resolved standard class ids into ida, or into a new
+  * JSIdArray if ida is null.  Return the augmented array on success, null on
+  * failure with ida (if it was non-null on entry) destroyed.
+  */
+ extern JS_PUBLIC_API(JSIdArray *)
+ JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
+                                     JSIdArray *ida);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetScopeChain(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_malloc(JSContext *cx, size_t nbytes);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_realloc(JSContext *cx, void *p, size_t nbytes);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_free(JSContext *cx, void *p);
+ 
+ extern JS_PUBLIC_API(char *)
+ JS_strdup(JSContext *cx, const char *s);
+ 
+ extern JS_PUBLIC_API(jsdouble *)
+ JS_NewDouble(JSContext *cx, jsdouble d);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
+ 
+ /*
+  * A JS GC root is a pointer to a JSObject *, JSString *, or jsdouble * that
+  * itself points into the GC heap (more recently, we support this extension:
+  * a root may be a pointer to a jsval v for which JSVAL_IS_GCTHING(v) is true).
+  *
+  * Therefore, you never pass JSObject *obj to JS_AddRoot(cx, obj).  You always
+  * call JS_AddRoot(cx, &obj), passing obj by reference.  And later, before obj
+  * or the structure it is embedded within goes out of scope or is freed, you
+  * must call JS_RemoveRoot(cx, &obj).
+  *
+  * Also, use JS_AddNamedRoot(cx, &structPtr->memberObj, "structPtr->memberObj")
+  * in preference to JS_AddRoot(cx, &structPtr->memberObj), in order to identify
+  * roots by their source callsites.  This way, you can find the callsite while
+  * debugging if you should fail to do JS_RemoveRoot(cx, &structPtr->memberObj)
+  * before freeing structPtr's memory.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_AddRoot(JSContext *cx, void *rp);
+ 
+ #ifdef NAME_ALL_GC_ROOTS
+ #define JS_DEFINE_TO_TOKEN(def) #def
+ #define JS_DEFINE_TO_STRING(def) JS_DEFINE_TO_TOKEN(def)
+ #define JS_AddRoot(cx,rp) JS_AddNamedRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+ #endif
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_AddNamedRoot(JSContext *cx, void *rp, const char *name);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_RemoveRoot(JSContext *cx, void *rp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_RemoveRootRT(JSRuntime *rt, void *rp);
+ 
+ /*
+  * The last GC thing of each type (object, string, double, external string
+  * types) created on a given context is kept alive until another thing of the
+  * same type is created, using a newborn root in the context.  These newborn
+  * roots help native code protect newly-created GC-things from GC invocations
+  * activated before those things can be rooted using local or global roots.
+  *
+  * However, the newborn roots can also entrain great gobs of garbage, so the
+  * JS_GC entry point clears them for the context on which GC is being forced.
+  * Embeddings may need to do likewise for all contexts.
+  *
+  * See the scoped local root API immediately below for a better way to manage
+  * newborns in cases where native hooks (functions, getters, setters, etc.)
+  * create many GC-things, potentially without connecting them to predefined
+  * local roots such as *rval or argv[i] in an active native function.  Using
+  * JS_EnterLocalRootScope disables updating of the context's per-gc-thing-type
+  * newborn roots, until control flow unwinds and leaves the outermost nesting
+  * local root scope.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ClearNewbornRoots(JSContext *cx);
+ 
+ /*
+  * Scoped local root management allows native functions, getter/setters, etc.
+  * to avoid worrying about the newborn root pigeon-holes, overloading local
+  * roots allocated in argv and *rval, or ending up having to call JS_Add*Root
+  * and JS_RemoveRoot to manage global roots temporarily.
+  *
+  * Instead, calling JS_EnterLocalRootScope and JS_LeaveLocalRootScope around
+  * the body of the native hook causes the engine to allocate a local root for
+  * each newborn created in between the two API calls, using a local root stack
+  * associated with cx.  For example:
+  *
+  *    JSBool
+  *    my_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+  *    {
+  *        JSBool ok;
+  *
+  *        if (!JS_EnterLocalRootScope(cx))
+  *            return JS_FALSE;
+  *        ok = my_GetPropertyBody(cx, obj, id, vp);
+  *        JS_LeaveLocalRootScope(cx);
+  *        return ok;
+  *    }
+  *
+  * NB: JS_LeaveLocalRootScope must be called once for every prior successful
+  * call to JS_EnterLocalRootScope.  If JS_EnterLocalRootScope fails, you must
+  * not make the matching JS_LeaveLocalRootScope call.
+  *
+  * In case a native hook allocates many objects or other GC-things, but the
+  * native protects some of those GC-things by storing them as property values
+  * in an object that is itself protected, the hook can call JS_ForgetLocalRoot
+  * to free the local root automatically pushed for the now-protected GC-thing.
+  *
+  * JS_ForgetLocalRoot works on any GC-thing allocated in the current local
+  * root scope, but it's more time-efficient when called on references to more
+  * recently created GC-things.  Calling it successively on other than the most
+  * recently allocated GC-thing will tend to average the time inefficiency, and
+  * may risk O(n^2) growth rate, but in any event, you shouldn't allocate too
+  * many local roots if you can root as you go (build a tree of objects from
+  * the top down, forgetting each latest-allocated GC-thing immediately upon
+  * linking it to its parent).
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_EnterLocalRootScope(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_LeaveLocalRootScope(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ForgetLocalRoot(JSContext *cx, void *thing);
+ 
+ #ifdef DEBUG
+ extern JS_PUBLIC_API(void)
+ JS_DumpNamedRoots(JSRuntime *rt,
+                   void (*dump)(const char *name, void *rp, void *data),
+                   void *data);
+ #endif
+ 
+ /*
+  * Call JS_MapGCRoots to map the GC's roots table using map(rp, name, data).
+  * The root is pointed at by rp; if the root is unnamed, name is null; data is
+  * supplied from the third parameter to JS_MapGCRoots.
+  *
+  * The map function should return JS_MAP_GCROOT_REMOVE to cause the currently
+  * enumerated root to be removed.  To stop enumeration, set JS_MAP_GCROOT_STOP
+  * in the return value.  To keep on mapping, return JS_MAP_GCROOT_NEXT.  These
+  * constants are flags; you can OR them together.
+  *
+  * This function acquires and releases rt's GC lock around the mapping of the
+  * roots table, so the map function should run to completion in as few cycles
+  * as possible.  Of course, map cannot call JS_GC, JS_MaybeGC, JS_BeginRequest,
+  * or any JS API entry point that acquires locks, without double-tripping or
+  * deadlocking on the GC lock.
+  *
+  * JS_MapGCRoots returns the count of roots that were successfully mapped.
+  */
+ #define JS_MAP_GCROOT_NEXT      0       /* continue mapping entries */
+ #define JS_MAP_GCROOT_STOP      1       /* stop mapping entries */
+ #define JS_MAP_GCROOT_REMOVE    2       /* remove and free the current entry */
+ 
+ typedef intN
+ (* JS_DLL_CALLBACK JSGCRootMapFun)(void *rp, const char *name, void *data);
+ 
+ extern JS_PUBLIC_API(uint32)
+ JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LockGCThing(JSContext *cx, void *thing);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LockGCThingRT(JSRuntime *rt, void *thing);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_UnlockGCThing(JSContext *cx, void *thing);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_UnlockGCThingRT(JSRuntime *rt, void *thing);
+ 
+ /*
+  * For implementors of JSObjectOps.mark, to mark a GC-thing reachable via a
+  * property or other strong ref identified for debugging purposes by name.
+  * The name argument's storage needs to live only as long as the call to
+  * this routine.
+  *
+  * The final arg is used by GC_MARK_DEBUG code to build a ref path through
+  * the GC's live thing graph.  Implementors of JSObjectOps.mark should pass
+  * its final arg through to this function when marking all GC-things that are
+  * directly reachable from the object being marked.
+  *
+  * See the JSMarkOp typedef in jspubtd.h, and the JSObjectOps struct below.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_GC(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_MaybeGC(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSGCCallback)
+ JS_SetGCCallback(JSContext *cx, JSGCCallback cb);
+ 
+ extern JS_PUBLIC_API(JSGCCallback)
+ JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsAboutToBeFinalized(JSContext *cx, void *thing);
+ 
+ typedef enum JSGCParamKey {
+     JSGC_MAX_BYTES        = 0,  /* maximum nominal heap before last ditch GC */
+     JSGC_MAX_MALLOC_BYTES = 1   /* # of JS_malloc bytes before last ditch GC */
+ } JSGCParamKey;
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value);
+ 
+ /*
+  * Add a finalizer for external strings created by JS_NewExternalString (see
+  * below) using a type-code returned from this function, and that understands
+  * how to free or release the memory pointed at by JS_GetStringChars(str).
+  *
+  * Return a nonnegative type index if there is room for finalizer in the
+  * global GC finalizers table, else return -1.  If the engine is compiled
+  * JS_THREADSAFE and used in a multi-threaded environment, this function must
+  * be invoked on the primordial thread only, at startup -- or else the entire
+  * program must single-thread itself while loading a module that calls this
+  * function.
+  */
+ extern JS_PUBLIC_API(intN)
+ JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer);
+ 
+ /*
+  * Remove finalizer from the global GC finalizers table, returning its type
+  * code if found, -1 if not found.
+  *
+  * As with JS_AddExternalStringFinalizer, there is a threading restriction
+  * if you compile the engine JS_THREADSAFE: this function may be called for a
+  * given finalizer pointer on only one thread; different threads may call to
+  * remove distinct finalizers safely.
+  *
+  * You must ensure that all strings with finalizer's type have been collected
+  * before calling this function.  Otherwise, string data will be leaked by the
+  * GC, for want of a finalizer to call.
+  */
+ extern JS_PUBLIC_API(intN)
+ JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer);
+ 
+ /*
+  * Create a new JSString whose chars member refers to external memory, i.e.,
+  * memory requiring special, type-specific finalization.  The type code must
+  * be a nonnegative return value from JS_AddExternalStringFinalizer.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type);
+ 
+ /*
+  * Returns the external-string finalizer index for this string, or -1 if it is
+  * an "internal" (native to JS engine) string.
+  */
+ extern JS_PUBLIC_API(intN)
+ JS_GetExternalStringGCType(JSRuntime *rt, JSString *str);
+ 
+ /*
+  * Sets maximum (if stack grows upward) or minimum (downward) legal stack byte
+  * address in limitAddr for the thread or process stack used by cx.  To disable
+  * stack size checking, pass 0 for limitAddr.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Classes, objects, and properties.
+  */
+ 
+ /* For detailed comments on the function pointer types, see jspubtd.h. */
+ struct JSClass {
+     const char          *name;
+     uint32              flags;
+ 
+     /* Mandatory non-null function pointer members. */
+     JSPropertyOp        addProperty;
+     JSPropertyOp        delProperty;
+     JSPropertyOp        getProperty;
+     JSPropertyOp        setProperty;
+     JSEnumerateOp       enumerate;
+     JSResolveOp         resolve;
+     JSConvertOp         convert;
+     JSFinalizeOp        finalize;
+ 
+     /* Optionally non-null members start here. */
+     JSGetObjectOps      getObjectOps;
+     JSCheckAccessOp     checkAccess;
+     JSNative            call;
+     JSNative            construct;
+     JSXDRObjectOp       xdrObject;
+     JSHasInstanceOp     hasInstance;
+     JSMarkOp            mark;
+     JSReserveSlotsOp    reserveSlots;
+ };
+ 
+ struct JSExtendedClass {
+     JSClass             base;
+     JSEqualityOp        equality;
+     JSObjectOp          outerObject;
+     JSObjectOp          innerObject;
+     jsword              reserved0;
+     jsword              reserved1;
+     jsword              reserved2;
+     jsword              reserved3;
+     jsword              reserved4;
+ };
+ 
+ #define JSCLASS_HAS_PRIVATE             (1<<0)  /* objects have private slot */
+ #define JSCLASS_NEW_ENUMERATE           (1<<1)  /* has JSNewEnumerateOp hook */
+ #define JSCLASS_NEW_RESOLVE             (1<<2)  /* has JSNewResolveOp hook */
+ #define JSCLASS_PRIVATE_IS_NSISUPPORTS  (1<<3)  /* private is (nsISupports *) */
+ #define JSCLASS_SHARE_ALL_PROPERTIES    (1<<4)  /* all properties are SHARED */
+ #define JSCLASS_NEW_RESOLVE_GETS_START  (1<<5)  /* JSNewResolveOp gets starting
+                                                    object in prototype chain
+                                                    passed in via *objp in/out
+                                                    parameter */
+ #define JSCLASS_CONSTRUCT_PROTOTYPE     (1<<6)  /* call constructor on class
+                                                    prototype */
+ #define JSCLASS_DOCUMENT_OBSERVER       (1<<7)  /* DOM document observer */
+ 
+ /*
+  * To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or
+  * JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where
+  * n is a constant in [1, 255].  Reserved slots are indexed from 0 to n-1.
+  */
+ #define JSCLASS_RESERVED_SLOTS_SHIFT    8       /* room for 8 flags below */
+ #define JSCLASS_RESERVED_SLOTS_WIDTH    8       /* and 16 above this field */
+ #define JSCLASS_RESERVED_SLOTS_MASK     JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH)
+ #define JSCLASS_HAS_RESERVED_SLOTS(n)   (((n) & JSCLASS_RESERVED_SLOTS_MASK)  \
+                                          << JSCLASS_RESERVED_SLOTS_SHIFT)
+ #define JSCLASS_RESERVED_SLOTS(clasp)   (((clasp)->flags                      \
+                                           >> JSCLASS_RESERVED_SLOTS_SHIFT)    \
+                                          & JSCLASS_RESERVED_SLOTS_MASK)
+ 
+ #define JSCLASS_HIGH_FLAGS_SHIFT        (JSCLASS_RESERVED_SLOTS_SHIFT +       \
+                                          JSCLASS_RESERVED_SLOTS_WIDTH)
+ 
+ /* True if JSClass is really a JSExtendedClass. */
+ #define JSCLASS_IS_EXTENDED             (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
+ 
+ /* Initializer for unused members of statically initialized JSClass structs. */
+ #define JSCLASS_NO_OPTIONAL_MEMBERS     0,0,0,0,0,0,0,0
+ #define JSCLASS_NO_RESERVED_MEMBERS     0,0,0,0,0
+ 
+ /* For detailed comments on these function pointer types, see jspubtd.h. */
+ struct JSObjectOps {
+     /* Mandatory non-null function pointer members. */
+     JSNewObjectMapOp    newObjectMap;
+     JSObjectMapOp       destroyObjectMap;
+     JSLookupPropOp      lookupProperty;
+     JSDefinePropOp      defineProperty;
+     JSPropertyIdOp      getProperty;
+     JSPropertyIdOp      setProperty;
+     JSAttributesOp      getAttributes;
+     JSAttributesOp      setAttributes;
+     JSPropertyIdOp      deleteProperty;
+     JSConvertOp         defaultValue;
+     JSNewEnumerateOp    enumerate;
+     JSCheckAccessIdOp   checkAccess;
+ 
+     /* Optionally non-null members start here. */
+     JSObjectOp          thisObject;
+     JSPropertyRefOp     dropProperty;
+     JSNative            call;
+     JSNative            construct;
+     JSXDRObjectOp       xdrObject;
+     JSHasInstanceOp     hasInstance;
+     JSSetObjectSlotOp   setProto;
+     JSSetObjectSlotOp   setParent;
+     JSMarkOp            mark;
+     JSFinalizeOp        clear;
+     JSGetRequiredSlotOp getRequiredSlot;
+     JSSetRequiredSlotOp setRequiredSlot;
+ };
+ 
+ struct JSXMLObjectOps {
+     JSObjectOps         base;
+     JSGetMethodOp       getMethod;
+     JSSetMethodOp       setMethod;
+     JSEnumerateValuesOp enumerateValues;
+     JSEqualityOp        equality;
+     JSConcatenateOp     concatenate;
+ };
+ 
+ /*
+  * Classes that expose JSObjectOps via a non-null getObjectOps class hook may
+  * derive a property structure from this struct, return a pointer to it from
+  * lookupProperty and defineProperty, and use the pointer to avoid rehashing
+  * in getAttributes and setAttributes.
+  *
+  * The jsid type contains either an int jsval (see JSVAL_IS_INT above), or an
+  * internal pointer that is opaque to users of this API, but which users may
+  * convert from and to a jsval using JS_ValueToId and JS_IdToValue.
+  */
+ struct JSProperty {
+     jsid id;
+ };
+ 
+ struct JSIdArray {
+     jsint length;
+     jsid  vector[1];    /* actually, length jsid words */
+ };
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyIdArray(JSContext *cx, JSIdArray *ida);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToId(JSContext *cx, jsval v, jsid *idp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IdToValue(JSContext *cx, jsid id, jsval *vp);
+ 
+ /*
+  * The magic XML namespace id is int-tagged, but not a valid integer jsval.
+  * Global object classes in embeddings that enable JS_HAS_XML_SUPPORT (E4X)
+  * should handle this id specially before converting id via JSVAL_TO_INT.
+  */
+ #define JS_DEFAULT_XML_NAMESPACE_ID ((jsid) JSVAL_VOID)
+ 
+ /*
+  * JSNewResolveOp flag bits.
+  */
+ #define JSRESOLVE_QUALIFIED     0x01    /* resolve a qualified property id */
+ #define JSRESOLVE_ASSIGNING     0x02    /* resolve on the left of assignment */
+ #define JSRESOLVE_DETECTING     0x04    /* 'if (o.p)...' or '(o.p) ?...:...' */
+ #define JSRESOLVE_DECLARING     0x08    /* var, const, or function prolog op */
+ #define JSRESOLVE_CLASSNAME     0x10    /* class name used when constructing */
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EnumerateStub(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_FinalizeStub(JSContext *cx, JSObject *obj);
+ 
+ struct JSConstDoubleSpec {
+     jsdouble        dval;
+     const char      *name;
+     uint8           flags;
+     uint8           spare[3];
+ };
+ 
+ /*
+  * To define an array element rather than a named property member, cast the
+  * element's index to (const char *) and initialize name with it, and set the
+  * JSPROP_INDEX bit in flags.
+  */
+ struct JSPropertySpec {
+     const char      *name;
+     int8            tinyid;
+     uint8           flags;
+     JSPropertyOp    getter;
+     JSPropertyOp    setter;
+ };
+ 
+ struct JSFunctionSpec {
+     const char      *name;
+     JSNative        call;
+     uint8           nargs;
+     uint8           flags;
+     uint16          extra;      /* number of arg slots for local GC roots */
+ };
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+              JSClass *clasp, JSNative constructor, uintN nargs,
+              JSPropertySpec *ps, JSFunctionSpec *fs,
+              JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
+ 
+ #ifdef JS_THREADSAFE
+ extern JS_PUBLIC_API(JSClass *)
+ JS_GetClass(JSContext *cx, JSObject *obj);
+ 
+ #define JS_GET_CLASS(cx,obj) JS_GetClass(cx, obj)
+ #else
+ extern JS_PUBLIC_API(JSClass *)
+ JS_GetClass(JSObject *obj);
+ 
+ #define JS_GET_CLASS(cx,obj) JS_GetClass(obj)
+ #endif
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_GetPrivate(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetPrivate(JSContext *cx, JSObject *obj, void *data);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
+                       jsval *argv);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetPrototype(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetParent(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetConstructor(JSContext *cx, JSObject *proto);
+ 
+ /*
+  * Get a unique identifier for obj, good for the lifetime of obj (even if it
+  * is moved by a copying GC).  Return false on failure (likely out of memory),
+  * and true with *idp containing the unique id on success.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+                    JSObject *parent);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
+                                 JSObject *parent, uintN argc, jsval *argv);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
+                 JSObject *proto, uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+                   JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+ 
+ /*
+  * Determine the attributes (JSPROP_* flags) of a property on a given object.
+  *
+  * If the object does not have a property by that name, *foundp will be
+  * JS_FALSE and the value of *attrsp is undefined.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+                          uintN *attrsp, JSBool *foundp);
+ 
+ /*
+  * The same, but if the property is native, return its getter and setter via
+  * *getterp and *setterp, respectively (and only if the out parameter pointer
+  * is not null).
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+                                    const char *name,
+                                    uintN *attrsp, JSBool *foundp,
+                                    JSPropertyOp *getterp,
+                                    JSPropertyOp *setterp);
+ 
+ /*
+  * Set the attributes of a property on a given object.
+  *
+  * If the object does not have a property by that name, *foundp will be
+  * JS_FALSE and nothing will be altered.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+                          uintN attrs, JSBool *foundp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
+                             int8 tinyid, jsval value,
+                             JSPropertyOp getter, JSPropertyOp setter,
+                             uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
+                  const char *alias);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
+                            uintN flags, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
+              jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
+                    jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineUCProperty(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen, jsval value,
+                     JSPropertyOp getter, JSPropertyOp setter,
+                     uintN attrs);
+ 
+ /*
+  * Determine the attributes (JSPROP_* flags) of a property on a given object.
+  *
+  * If the object does not have a property by that name, *foundp will be
+  * JS_FALSE and the value of *attrsp is undefined.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+                            const jschar *name, size_t namelen,
+                            uintN *attrsp, JSBool *foundp);
+ 
+ /*
+  * The same, but if the property is native, return its getter and setter via
+  * *getterp and *setterp, respectively (and only if the out parameter pointer
+  * is not null).
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+                                      const jschar *name, size_t namelen,
+                                      uintN *attrsp, JSBool *foundp,
+                                      JSPropertyOp *getterp,
+                                      JSPropertyOp *setterp);
+ 
+ /*
+  * Set the attributes of a property on a given object.
+  *
+  * If the object does not have a property by that name, *foundp will be
+  * JS_FALSE and nothing will be altered.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+                            const jschar *name, size_t namelen,
+                            uintN attrs, JSBool *foundp);
+ 
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
+                               const jschar *name, size_t namelen,
+                               int8 tinyid, jsval value,
+                               JSPropertyOp getter, JSPropertyOp setter,
+                               uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  JSBool *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LookupUCProperty(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen,
+                     jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
+                      const jschar *name, size_t namelen,
+                      jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsArrayObject(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
+                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ClearScope(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSIdArray *)
+ JS_Enumerate(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Create an object to iterate over enumerable properties of obj, in arbitrary
+  * property definition order.  NB: This differs from longstanding for..in loop
+  * order, which uses order of property definition in obj.
+  */
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewPropertyIterator(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Return true on success with *idp containing the id of the next enumerable
+  * property to visit using iterobj, or JSVAL_VOID if there is no such property
+  * left to visit.  Return false on error.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+                jsval *vp, uintN *attrsp);
+ 
+ extern JS_PUBLIC_API(JSCheckAccessOp)
+ JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Security protocol.
+  */
+ struct JSPrincipals {
+     char *codebase;
+ 
+     /* XXX unspecified and unused by Mozilla code -- can we remove these? */
+     void * (* JS_DLL_CALLBACK getPrincipalArray)(JSContext *cx, JSPrincipals *);
+     JSBool (* JS_DLL_CALLBACK globalPrivilegesEnabled)(JSContext *cx, JSPrincipals *);
+ 
+     /* Don't call "destroy"; use reference counting macros below. */
+     jsrefcount refcount;
+ 
+     void   (* JS_DLL_CALLBACK destroy)(JSContext *cx, JSPrincipals *);
+     JSBool (* JS_DLL_CALLBACK subsume)(JSPrincipals *, JSPrincipals *);
+ };
+ 
+ #ifdef JS_THREADSAFE
+ #define JSPRINCIPALS_HOLD(cx, principals)   JS_HoldPrincipals(cx,principals)
+ #define JSPRINCIPALS_DROP(cx, principals)   JS_DropPrincipals(cx,principals)
+ 
+ extern JS_PUBLIC_API(jsrefcount)
+ JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals);
+ 
+ extern JS_PUBLIC_API(jsrefcount)
+ JS_DropPrincipals(JSContext *cx, JSPrincipals *principals);
+ 
+ #else
+ #define JSPRINCIPALS_HOLD(cx, principals)   (++(principals)->refcount)
+ #define JSPRINCIPALS_DROP(cx, principals)                                     \
+     ((--(principals)->refcount == 0)                                          \
+      ? ((*(principals)->destroy)((cx), (principals)), 0)                      \
+      : (principals)->refcount)
+ #endif
+ 
+ extern JS_PUBLIC_API(JSPrincipalsTranscoder)
+ JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px);
+ 
+ extern JS_PUBLIC_API(JSObjectPrincipalsFinder)
+ JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Functions and scripts.
+  */
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_NewFunction(JSContext *cx, JSNative call, uintN nargs, uintN flags,
+                JSObject *parent, const char *name);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetFunctionObject(JSFunction *fun);
+ 
+ /*
+  * Deprecated, useful only for diagnostics.  Use JS_GetFunctionId instead for
+  * anonymous vs. "anonymous" disambiguation and Unicode fidelity.
+  */
+ extern JS_PUBLIC_API(const char *)
+ JS_GetFunctionName(JSFunction *fun);
+ 
+ /*
+  * Return the function's identifier as a JSString, or null if fun is unnamed.
+  * The returned string lives as long as fun, so you don't need to root a saved
+  * reference to it if fun is well-connected or rooted, and provided you bound
+  * the use of the saved reference by fun's lifetime.
+  *
+  * Prefer JS_GetFunctionId over JS_GetFunctionName because it returns null for
+  * truly anonymous functions, and because it doesn't chop to ISO-Latin-1 chars
+  * from UTF-16-ish jschars.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_GetFunctionId(JSFunction *fun);
+ 
+ /*
+  * Return JSFUN_* flags for fun.
+  */
+ extern JS_PUBLIC_API(uintN)
+ JS_GetFunctionFlags(JSFunction *fun);
+ 
+ /*
+  * Return the arity (length) of fun.
+  */
+ extern JS_PUBLIC_API(uint16)
+ JS_GetFunctionArity(JSFunction *fun);
+ 
+ /*
+  * Infallible predicate to test whether obj is a function object (faster than
+  * comparing obj's class name to "Function", but equivalent unless someone has
+  * overwritten the "Function" identifier with a different constructor and then
+  * created instances using that constructor that might be passed in as obj).
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ObjectIsFunction(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+                   uintN nargs, uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_DefineUCFunction(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen, JSNative call,
+                     uintN nargs, uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
+ 
+ /*
+  * Given a buffer, return JS_FALSE if the buffer might become a valid
+  * javascript statement with the addition of more lines.  Otherwise return
+  * JS_TRUE.  The intent is to support interactive compilation - accumulate
+  * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
+  * the compiler.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
+                           const char *bytes, size_t length);
+ 
+ /*
+  * The JSScript objects returned by the following functions refer to string and
+  * other kinds of literals, including doubles and RegExp objects.  These
+  * literals are vulnerable to garbage collection; to root script objects and
+  * prevent literals from being collected, create a rootable object using
+  * JS_NewScriptObject, and root the resulting object using JS_Add[Named]Root.
+  */
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileScript(JSContext *cx, JSObject *obj,
+                  const char *bytes, size_t length,
+                  const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
+                               JSPrincipals *principals,
+                               const char *bytes, size_t length,
+                               const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileUCScript(JSContext *cx, JSObject *obj,
+                    const jschar *chars, size_t length,
+                    const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                 JSPrincipals *principals,
+                                 const jschar *chars, size_t length,
+                                 const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
+                      FILE *fh);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
+                                   const char *filename, FILE *fh,
+                                   JSPrincipals *principals);
+ 
+ /*
+  * NB: you must use JS_NewScriptObject and root a pointer to its return value
+  * in order to keep a JSScript and its atoms safe from garbage collection after
+  * creating the script via JS_Compile* and before a JS_ExecuteScript* call.
+  * E.g., and without error checks:
+  *
+  *    JSScript *script = JS_CompileFile(cx, global, filename);
+  *    JSObject *scrobj = JS_NewScriptObject(cx, script);
+  *    JS_AddNamedRoot(cx, &scrobj, "scrobj");
+  *    do {
+  *        jsval result;
+  *        JS_ExecuteScript(cx, global, script, &result);
+  *        JS_GC();
+  *    } while (!JSVAL_IS_BOOLEAN(result) || JSVAL_TO_BOOLEAN(result));
+  *    JS_RemoveRoot(cx, &scrobj);
+  */
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewScriptObject(JSContext *cx, JSScript *script);
+ 
+ /*
+  * Infallible getter for a script's object.  If JS_NewScriptObject has not been
+  * called on script yet, the return value will be null.
+  */
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetScriptObject(JSScript *script);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyScript(JSContext *cx, JSScript *script);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
+                    uintN nargs, const char **argnames,
+                    const char *bytes, size_t length,
+                    const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
+                                 JSPrincipals *principals, const char *name,
+                                 uintN nargs, const char **argnames,
+                                 const char *bytes, size_t length,
+                                 const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
+                      uintN nargs, const char **argnames,
+                      const jschar *chars, size_t length,
+                      const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
+                                   JSPrincipals *principals, const char *name,
+                                   uintN nargs, const char **argnames,
+                                   const jschar *chars, size_t length,
+                                   const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
+                    uintN indent);
+ 
+ /*
+  * API extension: OR this into indent to avoid pretty-printing the decompiled
+  * source resulting from JS_DecompileFunction{,Body}.
+  */
+ #define JS_DONT_PRETTY_PRINT    ((uintN)0x8000)
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent);
+ 
+ /*
+  * NB: JS_ExecuteScript, JS_ExecuteScriptPart, and the JS_Evaluate*Script*
+  * quadruplets all use the obj parameter as the initial scope chain header,
+  * the 'this' keyword value, and the variables object (ECMA parlance for where
+  * 'var' and 'function' bind names) of the execution context for script.
+  *
+  * Using obj as the variables object is problematic if obj's parent (which is
+  * the scope chain link; see JS_SetParent and JS_NewObject) is not null: in
+  * this case, variables created by 'var x = 0', e.g., go in obj, but variables
+  * created by assignment to an unbound id, 'x = 0', go in the last object on
+  * the scope chain linked by parent.
+  *
+  * ECMA calls that last scoping object the "global object", but note that many
+  * embeddings have several such objects.  ECMA requires that "global code" be
+  * executed with the variables object equal to this global object.  But these
+  * JS API entry points provide freedom to execute code against a "sub-global",
+  * i.e., a parented or scoped object, in which case the variables object will
+  * differ from the last object on the scope chain, resulting in confusing and
+  * non-ECMA explicit vs. implicit variable creation.
+  *
+  * Caveat embedders: unless you already depend on this buggy variables object
+  * binding behavior, you should call JS_SetOptions(cx, JSOPTION_VAROBJFIX) or
+  * JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_VAROBJFIX) -- the latter if
+  * someone may have set other options on cx already -- for each context in the
+  * application, if you pass parented objects as the obj parameter, or may ever
+  * pass such objects in the future.
+  *
+  * Why a runtime option?  The alternative is to add six or so new API entry
+  * points with signatures matching the following six, and that doesn't seem
+  * worth the code bloat cost.  Such new entry points would probably have less
+  * obvious names, too, so would not tend to be used.  The JS_SetOption call,
+  * OTOH, can be more easily hacked into existing code that does not depend on
+  * the bug; such code can continue to use the familiar JS_EvaluateScript,
+  * etc., entry points.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval);
+ 
+ /*
+  * Execute either the function-defining prolog of a script, or the script's
+  * main body, but not both.
+  */
+ typedef enum JSExecPart { JSEXEC_PROLOG, JSEXEC_MAIN } JSExecPart;
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
+                      JSExecPart part, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EvaluateScript(JSContext *cx, JSObject *obj,
+                   const char *bytes, uintN length,
+                   const char *filename, uintN lineno,
+                   jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                JSPrincipals *principals,
+                                const char *bytes, uintN length,
+                                const char *filename, uintN lineno,
+                                jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
+                     const jschar *chars, uintN length,
+                     const char *filename, uintN lineno,
+                     jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                  JSPrincipals *principals,
+                                  const jschar *chars, uintN length,
+                                  const char *filename, uintN lineno,
+                                  jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
+                 jsval *argv, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
+                     jsval *argv, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
+                      jsval *argv, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBranchCallback)
+ JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsRunning(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsConstructing(JSContext *cx);
+ 
+ /*
+  * Returns true if a script is executing and its current bytecode is a set
+  * (assignment) operation, even if there are native (no script) stack frames
+  * between the script and the caller to JS_IsAssigning.
+  */
+ extern JS_FRIEND_API(JSBool)
+ JS_IsAssigning(JSContext *cx);
+ 
+ /*
+  * Set the second return value, which should be a string or int jsval that
+  * identifies a property in the returned object, to form an ECMA reference
+  * type value (obj, id).  Only native methods can return reference types,
+  * and if the returned value is used on the left-hand side of an assignment
+  * op, the identified property will be set.  If the return value is in an
+  * r-value, the interpreter just gets obj[id]'s value.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_SetCallReturnValue2(JSContext *cx, jsval v);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Strings.
+  *
+  * NB: JS_NewString takes ownership of bytes on success, avoiding a copy; but
+  * on error (signified by null return), it leaves bytes owned by the caller.
+  * So the caller must free bytes in the error case, if it has no use for them.
+  * In contrast, all the JS_New*StringCopy* functions do not take ownership of
+  * the character memory passed to them -- they copy it.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewString(JSContext *cx, char *bytes, size_t length);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewStringCopyN(JSContext *cx, const char *s, size_t n);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewStringCopyZ(JSContext *cx, const char *s);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_InternString(JSContext *cx, const char *s);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewUCString(JSContext *cx, jschar *chars, size_t length);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewUCStringCopyZ(JSContext *cx, const jschar *s);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_InternUCString(JSContext *cx, const jschar *s);
+ 
+ extern JS_PUBLIC_API(char *)
+ JS_GetStringBytes(JSString *str);
+ 
+ extern JS_PUBLIC_API(jschar *)
+ JS_GetStringChars(JSString *str);
+ 
+ extern JS_PUBLIC_API(size_t)
+ JS_GetStringLength(JSString *str);
+ 
+ extern JS_PUBLIC_API(intN)
+ JS_CompareStrings(JSString *str1, JSString *str2);
+ 
+ /*
+  * Mutable string support.  A string's characters are never mutable in this JS
+  * implementation, but a growable string has a buffer that can be reallocated,
+  * and a dependent string is a substring of another (growable, dependent, or
+  * immutable) string.  The direct data members of the (opaque to API clients)
+  * JSString struct may be changed in a single-threaded way for growable and
+  * dependent strings.
+  *
+  * Therefore mutable strings cannot be used by more than one thread at a time.
+  * You may call JS_MakeStringImmutable to convert the string from a mutable
+  * (growable or dependent) string to an immutable (and therefore thread-safe)
+  * string.  The engine takes care of converting growable and dependent strings
+  * to immutable for you if you store strings in multi-threaded objects using
+  * JS_SetProperty or kindred API entry points.
+  *
+  * If you store a JSString pointer in a native data structure that is (safely)
+  * accessible to multiple threads, you must call JS_MakeStringImmutable before
+  * retiring the store.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length);
+ 
+ /*
+  * Create a dependent string, i.e., a string that owns no character storage,
+  * but that refers to a slice of another string's chars.  Dependent strings
+  * are mutable by definition, so the thread safety comments above apply.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
+                       size_t length);
+ 
+ /*
+  * Concatenate two strings, resulting in a new growable string.  If you create
+  * the left string and pass it to JS_ConcatStrings on a single thread, try to
+  * use JS_NewGrowableString to create the left string -- doing so helps Concat
+  * avoid allocating a new buffer for the result and copying left's chars into
+  * the new buffer.  See above for thread safety comments.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right);
+ 
+ /*
+  * Convert a dependent string into an independent one.  This function does not
+  * change the string's mutability, so the thread safety comments above apply.
+  */
+ extern JS_PUBLIC_API(const jschar *)
+ JS_UndependString(JSContext *cx, JSString *str);
+ 
+ /*
+  * Convert a mutable string (either growable or dependent) into an immutable,
+  * thread-safe one.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_MakeStringImmutable(JSContext *cx, JSString *str);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Locale specific string conversion callback.
+  */
+ struct JSLocaleCallbacks {
+     JSLocaleToUpperCase     localeToUpperCase;
+     JSLocaleToLowerCase     localeToLowerCase;
+     JSLocaleCompare         localeCompare;
+     JSLocaleToUnicode       localeToUnicode;
+ };
+ 
+ /*
+  * Establish locale callbacks. The pointer must persist as long as the
+  * JSContext.  Passing NULL restores the default behaviour.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks);
+ 
+ /*
+  * Return the address of the current locale callbacks struct, which may
+  * be NULL.
+  */
+ extern JS_PUBLIC_API(JSLocaleCallbacks *)
+ JS_GetLocaleCallbacks(JSContext *cx);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Error reporting.
+  */
+ 
+ /*
+  * Report an exception represented by the sprintf-like conversion of format
+  * and its arguments.  This exception message string is passed to a pre-set
+  * JSErrorReporter function (set by JS_SetErrorReporter; see jspubtd.h for
+  * the JSErrorReporter typedef).
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ReportError(JSContext *cx, const char *format, ...);
+ 
+ /*
+  * Use an errorNumber to retrieve the format string, args are char *
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
+                      void *userRef, const uintN errorNumber, ...);
+ 
+ /*
+  * Use an errorNumber to retrieve the format string, args are jschar *
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
+                      void *userRef, const uintN errorNumber, ...);
+ 
+ /*
+  * As above, but report a warning instead (JSREPORT_IS_WARNING(report.flags)).
+  * Return true if there was no error trying to issue the warning, and if the
+  * warning was not converted into an error due to the JSOPTION_WERROR option
+  * being set, false otherwise.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ReportWarning(JSContext *cx, const char *format, ...);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
+                              JSErrorCallback errorCallback, void *userRef,
+                              const uintN errorNumber, ...);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
+                                JSErrorCallback errorCallback, void *userRef,
+                                const uintN errorNumber, ...);
+ 
+ /*
+  * Complain when out of memory.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ReportOutOfMemory(JSContext *cx);
+ 
+ struct JSErrorReport {
+     const char      *filename;      /* source file name, URL, etc., or null */
+     uintN           lineno;         /* source line number */
+     const char      *linebuf;       /* offending source line without final \n */
+     const char      *tokenptr;      /* pointer to error token in linebuf */
+     const jschar    *uclinebuf;     /* unicode (original) line buffer */
+     const jschar    *uctokenptr;    /* unicode (original) token pointer */
+     uintN           flags;          /* error/warning, etc. */
+     uintN           errorNumber;    /* the error number, e.g. see js.msg */
+     const jschar    *ucmessage;     /* the (default) error message */
+     const jschar    **messageArgs;  /* arguments for the error message */
+ };
+ 
+ /*
+  * JSErrorReport flag values.  These may be freely composed.
+  */
+ #define JSREPORT_ERROR      0x0     /* pseudo-flag for default case */
+ #define JSREPORT_WARNING    0x1     /* reported via JS_ReportWarning */
+ #define JSREPORT_EXCEPTION  0x2     /* exception was thrown */
+ #define JSREPORT_STRICT     0x4     /* error or warning due to strict option */
+ 
+ /*
+  * If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
+  * has been thrown for this runtime error, and the host should ignore it.
+  * Exception-aware hosts should also check for JS_IsExceptionPending if
+  * JS_ExecuteScript returns failure, and signal or propagate the exception, as
+  * appropriate.
+  */
+ #define JSREPORT_IS_WARNING(flags)      (((flags) & JSREPORT_WARNING) != 0)
+ #define JSREPORT_IS_EXCEPTION(flags)    (((flags) & JSREPORT_EXCEPTION) != 0)
+ #define JSREPORT_IS_STRICT(flags)       (((flags) & JSREPORT_STRICT) != 0)
+ 
+ extern JS_PUBLIC_API(JSErrorReporter)
+ JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Regular Expressions.
+  */
+ #define JSREG_FOLD      0x01    /* fold uppercase to lowercase */
+ #define JSREG_GLOB      0x02    /* global exec, creates array of matches */
+ #define JSREG_MULTILINE 0x04    /* treat ^ and $ as begin and end of line */
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ClearRegExpStatics(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ClearRegExpRoots(JSContext *cx);
+ 
+ /* TODO: compile, exec, get/set other statics... */
+ 
+ /************************************************************************/
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsExceptionPending(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetPendingException(JSContext *cx, jsval *vp);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetPendingException(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ClearPendingException(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ReportPendingException(JSContext *cx);
+ 
+ /*
+  * Save the current exception state.  This takes a snapshot of cx's current
+  * exception state without making any change to that state.
+  *
+  * The returned state pointer MUST be passed later to JS_RestoreExceptionState
+  * (to restore that saved state, overriding any more recent state) or else to
+  * JS_DropExceptionState (to free the state struct in case it is not correct
+  * or desirable to restore it).  Both Restore and Drop free the state struct,
+  * so callers must stop using the pointer returned from Save after calling the
+  * Release or Drop API.
+  */
+ extern JS_PUBLIC_API(JSExceptionState *)
+ JS_SaveExceptionState(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DropExceptionState(JSContext *cx, JSExceptionState *state);
+ 
+ /*
+  * If the given value is an exception object that originated from an error,
+  * the exception will contain an error report struct, and this API will return
+  * the address of that struct.  Otherwise, it returns NULL.  The lifetime of
+  * the error report struct that might be returned is the same as the lifetime
+  * of the exception object.
+  */
+ extern JS_PUBLIC_API(JSErrorReport *)
+ JS_ErrorFromException(JSContext *cx, jsval v);
+ 
+ /*
+  * Given a reported error's message and JSErrorReport struct pointer, throw
+  * the corresponding exception on cx.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ThrowReportedError(JSContext *cx, const char *message,
+                       JSErrorReport *reportp);
+ 
+ #ifdef JS_THREADSAFE
+ 
+ /*
+  * Associate the current thread with the given context.  This is done
+  * implicitly by JS_NewContext.
+  *
+  * Returns the old thread id for this context, which should be treated as
+  * an opaque value.  This value is provided for comparison to 0, which
+  * indicates that ClearContextThread has been called on this context
+  * since the last SetContextThread, or non-0, which indicates the opposite.
+  */
+ extern JS_PUBLIC_API(jsword)
+ JS_GetContextThread(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsword)
+ JS_SetContextThread(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsword)
+ JS_ClearContextThread(JSContext *cx);
+ 
+ #endif /* JS_THREADSAFE */
+ 
+ /************************************************************************/
+ 
+ JS_END_EXTERN_C
+ 
+ #endif /* jsapi_h___ */


ossp-pkg/js/src/jsapi.h -> 1.1.1.1

*** /dev/null    Sat Nov 23 05:37:38 2024
--- -    Sat Nov 23 05:37:41 2024
***************
*** 0 ****
--- 1,1989 ----
+ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+  *
+  * ***** BEGIN LICENSE BLOCK *****
+  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+  *
+  * The contents of this file are subject to the Mozilla Public License Version
+  * 1.1 (the "License"); you may not use this file except in compliance with
+  * the License. You may obtain a copy of the License at
+  * http://www.mozilla.org/MPL/
+  *
+  * Software distributed under the License is distributed on an "AS IS" basis,
+  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  * for the specific language governing rights and limitations under the
+  * License.
+  *
+  * The Original Code is Mozilla Communicator client code, released
+  * March 31, 1998.
+  *
+  * The Initial Developer of the Original Code is
+  * Netscape Communications Corporation.
+  * Portions created by the Initial Developer are Copyright (C) 1998
+  * the Initial Developer. All Rights Reserved.
+  *
+  * Contributor(s):
+  *
+  * Alternatively, the contents of this file may be used under the terms of
+  * either of the GNU General Public License Version 2 or later (the "GPL"),
+  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  * in which case the provisions of the GPL or the LGPL are applicable instead
+  * of those above. If you wish to allow use of your version of this file only
+  * under the terms of either the GPL or the LGPL, and not to allow others to
+  * use your version of this file under the terms of the MPL, indicate your
+  * decision by deleting the provisions above and replace them with the notice
+  * and other provisions required by the GPL or the LGPL. If you do not delete
+  * the provisions above, a recipient may use your version of this file under
+  * the terms of any one of the MPL, the GPL or the LGPL.
+  *
+  * ***** END LICENSE BLOCK ***** */
+ 
+ #ifndef jsapi_h___
+ #define jsapi_h___
+ /*
+  * JavaScript API.
+  */
+ #include <stddef.h>
+ #include <stdio.h>
+ #include "jspubtd.h"
+ 
+ JS_BEGIN_EXTERN_C
+ 
+ /*
+  * Type tags stored in the low bits of a jsval.
+  */
+ #define JSVAL_OBJECT            0x0     /* untagged reference to object */
+ #define JSVAL_INT               0x1     /* tagged 31-bit integer value */
+ #define JSVAL_DOUBLE            0x2     /* tagged reference to double */
+ #define JSVAL_STRING            0x4     /* tagged reference to string */
+ #define JSVAL_BOOLEAN           0x6     /* tagged boolean value */
+ 
+ /* Type tag bitfield length and derived macros. */
+ #define JSVAL_TAGBITS           3
+ #define JSVAL_TAGMASK           JS_BITMASK(JSVAL_TAGBITS)
+ #define JSVAL_TAG(v)            ((v) & JSVAL_TAGMASK)
+ #define JSVAL_SETTAG(v,t)       ((v) | (t))
+ #define JSVAL_CLRTAG(v)         ((v) & ~(jsval)JSVAL_TAGMASK)
+ #define JSVAL_ALIGN             JS_BIT(JSVAL_TAGBITS)
+ 
+ /* Predicates for type testing. */
+ #define JSVAL_IS_OBJECT(v)      (JSVAL_TAG(v) == JSVAL_OBJECT)
+ #define JSVAL_IS_NUMBER(v)      (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v))
+ #define JSVAL_IS_INT(v)         (((v) & JSVAL_INT) && (v) != JSVAL_VOID)
+ #define JSVAL_IS_DOUBLE(v)      (JSVAL_TAG(v) == JSVAL_DOUBLE)
+ #define JSVAL_IS_STRING(v)      (JSVAL_TAG(v) == JSVAL_STRING)
+ #define JSVAL_IS_BOOLEAN(v)     (JSVAL_TAG(v) == JSVAL_BOOLEAN)
+ #define JSVAL_IS_NULL(v)        ((v) == JSVAL_NULL)
+ #define JSVAL_IS_VOID(v)        ((v) == JSVAL_VOID)
+ #define JSVAL_IS_PRIMITIVE(v)   (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v))
+ 
+ /* Objects, strings, and doubles are GC'ed. */
+ #define JSVAL_IS_GCTHING(v)     (!((v) & JSVAL_INT) && !JSVAL_IS_BOOLEAN(v))
+ #define JSVAL_TO_GCTHING(v)     ((void *)JSVAL_CLRTAG(v))
+ #define JSVAL_TO_OBJECT(v)      ((JSObject *)JSVAL_TO_GCTHING(v))
+ #define JSVAL_TO_DOUBLE(v)      ((jsdouble *)JSVAL_TO_GCTHING(v))
+ #define JSVAL_TO_STRING(v)      ((JSString *)JSVAL_TO_GCTHING(v))
+ #define OBJECT_TO_JSVAL(obj)    ((jsval)(obj))
+ #define DOUBLE_TO_JSVAL(dp)     JSVAL_SETTAG((jsval)(dp), JSVAL_DOUBLE)
+ #define STRING_TO_JSVAL(str)    JSVAL_SETTAG((jsval)(str), JSVAL_STRING)
+ 
+ /* Lock and unlock the GC thing held by a jsval. */
+ #define JSVAL_LOCK(cx,v)        (JSVAL_IS_GCTHING(v)                          \
+                                  ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v))    \
+                                  : JS_TRUE)
+ #define JSVAL_UNLOCK(cx,v)      (JSVAL_IS_GCTHING(v)                          \
+                                  ? JS_UnlockGCThing(cx, JSVAL_TO_GCTHING(v))  \
+                                  : JS_TRUE)
+ 
+ /* Domain limits for the jsval int type. */
+ #define JSVAL_INT_BITS          31
+ #define JSVAL_INT_POW2(n)       ((jsval)1 << (n))
+ #define JSVAL_INT_MIN           ((jsval)1 - JSVAL_INT_POW2(30))
+ #define JSVAL_INT_MAX           (JSVAL_INT_POW2(30) - 1)
+ #define INT_FITS_IN_JSVAL(i)    ((jsuint)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX)
+ #define JSVAL_TO_INT(v)         ((jsint)(v) >> 1)
+ #define INT_TO_JSVAL(i)         (((jsval)(i) << 1) | JSVAL_INT)
+ 
+ /* Convert between boolean and jsval. */
+ #define JSVAL_TO_BOOLEAN(v)     ((JSBool)((v) >> JSVAL_TAGBITS))
+ #define BOOLEAN_TO_JSVAL(b)     JSVAL_SETTAG((jsval)(b) << JSVAL_TAGBITS,     \
+                                              JSVAL_BOOLEAN)
+ 
+ /* A private data pointer (2-byte-aligned) can be stored as an int jsval. */
+ #define JSVAL_TO_PRIVATE(v)     ((void *)((v) & ~JSVAL_INT))
+ #define PRIVATE_TO_JSVAL(p)     ((jsval)(p) | JSVAL_INT)
+ 
+ /* Property attributes, set in JSPropertySpec and passed to API functions. */
+ #define JSPROP_ENUMERATE        0x01    /* property is visible to for/in loop */
+ #define JSPROP_READONLY         0x02    /* not settable: assignment is no-op */
+ #define JSPROP_PERMANENT        0x04    /* property cannot be deleted */
+ #define JSPROP_EXPORTED         0x08    /* property is exported from object */
+ #define JSPROP_GETTER           0x10    /* property holds getter function */
+ #define JSPROP_SETTER           0x20    /* property holds setter function */
+ #define JSPROP_SHARED           0x40    /* don't allocate a value slot for this
+                                            property; don't copy the property on
+                                            set of the same-named property in an
+                                            object that delegates to a prototype
+                                            containing this property */
+ #define JSPROP_INDEX            0x80    /* name is actually (jsint) index */
+ 
+ /* Function flags, set in JSFunctionSpec and passed to JS_NewFunction etc. */
+ #define JSFUN_LAMBDA            0x08    /* expressed, not declared, function */
+ #define JSFUN_GETTER            JSPROP_GETTER
+ #define JSFUN_SETTER            JSPROP_SETTER
+ #define JSFUN_BOUND_METHOD      0x40    /* bind this to fun->object's parent */
+ #define JSFUN_HEAVYWEIGHT       0x80    /* activation requires a Call object */
+ #define JSFUN_FLAGS_MASK        0xf8    /* overlay JSFUN_* attributes */
+ 
+ /*
+  * Re-use JSFUN_LAMBDA, which applies only to scripted functions, for use in
+  * JSFunctionSpec arrays that specify generic native prototype methods, i.e.,
+  * methods of a class prototype that are exposed as static methods taking an
+  * extra leading argument: the generic |this| parameter.
+  *
+  * If you set this flag in a JSFunctionSpec struct's flags initializer, then
+  * that struct must live at least as long as the native static method object
+  * created due to this flag by JS_DefineFunctions or JS_InitClass.  Typically
+  * JSFunctionSpec structs are allocated in static arrays.
+  */
+ #define JSFUN_GENERIC_NATIVE    JSFUN_LAMBDA
+ 
+ /*
+  * Well-known JS values.  The extern'd variables are initialized when the
+  * first JSContext is created by JS_NewContext (see below).
+  */
+ #define JSVAL_VOID              INT_TO_JSVAL(0 - JSVAL_INT_POW2(30))
+ #define JSVAL_NULL              OBJECT_TO_JSVAL(0)
+ #define JSVAL_ZERO              INT_TO_JSVAL(0)
+ #define JSVAL_ONE               INT_TO_JSVAL(1)
+ #define JSVAL_FALSE             BOOLEAN_TO_JSVAL(JS_FALSE)
+ #define JSVAL_TRUE              BOOLEAN_TO_JSVAL(JS_TRUE)
+ 
+ /*
+  * Microseconds since the epoch, midnight, January 1, 1970 UTC.  See the
+  * comment in jstypes.h regarding safe int64 usage.
+  */
+ extern JS_PUBLIC_API(int64)
+ JS_Now();
+ 
+ /* Don't want to export data, so provide accessors for non-inline jsvals. */
+ extern JS_PUBLIC_API(jsval)
+ JS_GetNaNValue(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsval)
+ JS_GetNegativeInfinityValue(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsval)
+ JS_GetPositiveInfinityValue(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsval)
+ JS_GetEmptyStringValue(JSContext *cx);
+ 
+ /*
+  * Format is a string of the following characters (spaces are insignificant),
+  * specifying the tabulated type conversions:
+  *
+  *   b      JSBool          Boolean
+  *   c      uint16/jschar   ECMA uint16, Unicode char
+  *   i      int32           ECMA int32
+  *   u      uint32          ECMA uint32
+  *   j      int32           Rounded int32 (coordinate)
+  *   d      jsdouble        IEEE double
+  *   I      jsdouble        Integral IEEE double
+  *   s      char *          C string
+  *   S      JSString *      Unicode string, accessed by a JSString pointer
+  *   W      jschar *        Unicode character vector, 0-terminated (W for wide)
+  *   o      JSObject *      Object reference
+  *   f      JSFunction *    Function private
+  *   v      jsval           Argument value (no conversion)
+  *   *      N/A             Skip this argument (no vararg)
+  *   /      N/A             End of required arguments
+  *
+  * The variable argument list after format must consist of &b, &c, &s, e.g.,
+  * where those variables have the types given above.  For the pointer types
+  * char *, JSString *, and JSObject *, the pointed-at memory returned belongs
+  * to the JS runtime, not to the calling native code.  The runtime promises
+  * to keep this memory valid so long as argv refers to allocated stack space
+  * (so long as the native function is active).
+  *
+  * Fewer arguments than format specifies may be passed only if there is a /
+  * in format after the last required argument specifier and argc is at least
+  * the number of required arguments.  More arguments than format specifies
+  * may be passed without error; it is up to the caller to deal with trailing
+  * unconverted arguments.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
+                     ...);
+ 
+ #ifdef va_start
+ extern JS_PUBLIC_API(JSBool)
+ JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
+                       const char *format, va_list ap);
+ #endif
+ 
+ /*
+  * Inverse of JS_ConvertArguments: scan format and convert trailing arguments
+  * into jsvals, GC-rooted if necessary by the JS stack.  Return null on error,
+  * and a pointer to the new argument vector on success.  Also return a stack
+  * mark on success via *markp, in which case the caller must eventually clean
+  * up by calling JS_PopArguments.
+  *
+  * Note that the number of actual arguments supplied is specified exclusively
+  * by format, so there is no argc parameter.
+  */
+ extern JS_PUBLIC_API(jsval *)
+ JS_PushArguments(JSContext *cx, void **markp, const char *format, ...);
+ 
+ #ifdef va_start
+ extern JS_PUBLIC_API(jsval *)
+ JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap);
+ #endif
+ 
+ extern JS_PUBLIC_API(void)
+ JS_PopArguments(JSContext *cx, void *mark);
+ 
+ #ifdef JS_ARGUMENT_FORMATTER_DEFINED
+ 
+ /*
+  * Add and remove a format string handler for JS_{Convert,Push}Arguments{,VA}.
+  * The handler function has this signature (see jspubtd.h):
+  *
+  *   JSBool MyArgumentFormatter(JSContext *cx, const char *format,
+  *                              JSBool fromJS, jsval **vpp, va_list *app);
+  *
+  * It should return true on success, and return false after reporting an error
+  * or detecting an already-reported error.
+  *
+  * For a given format string, for example "AA", the formatter is called from
+  * JS_ConvertArgumentsVA like so:
+  *
+  *   formatter(cx, "AA...", JS_TRUE, &sp, &ap);
+  *
+  * sp points into the arguments array on the JS stack, while ap points into
+  * the stdarg.h va_list on the C stack.  The JS_TRUE passed for fromJS tells
+  * the formatter to convert zero or more jsvals at sp to zero or more C values
+  * accessed via pointers-to-values at ap, updating both sp (via *vpp) and ap
+  * (via *app) to point past the converted arguments and their result pointers
+  * on the C stack.
+  *
+  * When called from JS_PushArgumentsVA, the formatter is invoked thus:
+  *
+  *   formatter(cx, "AA...", JS_FALSE, &sp, &ap);
+  *
+  * where JS_FALSE for fromJS means to wrap the C values at ap according to the
+  * format specifier and store them at sp, updating ap and sp appropriately.
+  *
+  * The "..." after "AA" is the rest of the format string that was passed into
+  * JS_{Convert,Push}Arguments{,VA}.  The actual format trailing substring used
+  * in each Convert or PushArguments call is passed to the formatter, so that
+  * one such function may implement several formats, in order to share code.
+  *
+  * Remove just forgets about any handler associated with format.  Add does not
+  * copy format, it points at the string storage allocated by the caller, which
+  * is typically a string constant.  If format is in dynamic storage, it is up
+  * to the caller to keep the string alive until Remove is called.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_AddArgumentFormatter(JSContext *cx, const char *format,
+                         JSArgumentFormatter formatter);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_RemoveArgumentFormatter(JSContext *cx, const char *format);
+ 
+ #endif /* JS_ARGUMENT_FORMATTER_DEFINED */
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_ValueToFunction(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_ValueToConstructor(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_ValueToString(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp);
+ 
+ /*
+  * Convert a value to a number, then to an int32, according to the ECMA rules
+  * for ToInt32.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip);
+ 
+ /*
+  * Convert a value to a number, then to a uint32, according to the ECMA rules
+  * for ToUint32.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip);
+ 
+ /*
+  * Convert a value to a number, then to an int32 if it fits by rounding to
+  * nearest; but failing with an error report if the double is out of range
+  * or unordered.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip);
+ 
+ /*
+  * ECMA ToUint16, for mapping a jsval to a Unicode point.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp);
+ 
+ extern JS_PUBLIC_API(JSType)
+ JS_TypeOfValue(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(const char *)
+ JS_GetTypeName(JSContext *cx, JSType type);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Initialization, locking, contexts, and memory allocation.
+  */
+ #define JS_NewRuntime       JS_Init
+ #define JS_DestroyRuntime   JS_Finish
+ #define JS_LockRuntime      JS_Lock
+ #define JS_UnlockRuntime    JS_Unlock
+ 
+ extern JS_PUBLIC_API(JSRuntime *)
+ JS_NewRuntime(uint32 maxbytes);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyRuntime(JSRuntime *rt);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ShutDown(void);
+ 
+ JS_PUBLIC_API(void *)
+ JS_GetRuntimePrivate(JSRuntime *rt);
+ 
+ JS_PUBLIC_API(void)
+ JS_SetRuntimePrivate(JSRuntime *rt, void *data);
+ 
+ #ifdef JS_THREADSAFE
+ 
+ extern JS_PUBLIC_API(void)
+ JS_BeginRequest(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_EndRequest(JSContext *cx);
+ 
+ /* Yield to pending GC operations, regardless of request depth */
+ extern JS_PUBLIC_API(void)
+ JS_YieldRequest(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsrefcount)
+ JS_SuspendRequest(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth);
+ 
+ #endif /* JS_THREADSAFE */
+ 
+ extern JS_PUBLIC_API(void)
+ JS_Lock(JSRuntime *rt);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_Unlock(JSRuntime *rt);
+ 
+ extern JS_PUBLIC_API(JSContext *)
+ JS_NewContext(JSRuntime *rt, size_t stackChunkSize);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyContext(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyContextNoGC(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyContextMaybeGC(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_GetContextPrivate(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetContextPrivate(JSContext *cx, void *data);
+ 
+ extern JS_PUBLIC_API(JSRuntime *)
+ JS_GetRuntime(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSContext *)
+ JS_ContextIterator(JSRuntime *rt, JSContext **iterp);
+ 
+ extern JS_PUBLIC_API(JSVersion)
+ JS_GetVersion(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSVersion)
+ JS_SetVersion(JSContext *cx, JSVersion version);
+ 
+ extern JS_PUBLIC_API(const char *)
+ JS_VersionToString(JSVersion version);
+ 
+ extern JS_PUBLIC_API(JSVersion)
+ JS_StringToVersion(const char *string);
+ 
+ /*
+  * JS options are orthogonal to version, and may be freely composed with one
+  * another as well as with version.
+  *
+  * JSOPTION_VAROBJFIX is recommended -- see the comments associated with the
+  * prototypes for JS_ExecuteScript, JS_EvaluateScript, etc.
+  */
+ #define JSOPTION_STRICT         JS_BIT(0)       /* warn on dubious practice */
+ #define JSOPTION_WERROR         JS_BIT(1)       /* convert warning to error */
+ #define JSOPTION_VAROBJFIX      JS_BIT(2)       /* make JS_EvaluateScript use
+                                                    the last object on its 'obj'
+                                                    param's scope chain as the
+                                                    ECMA 'variables object' */
+ #define JSOPTION_PRIVATE_IS_NSISUPPORTS \
+                                 JS_BIT(3)       /* context private data points
+                                                    to an nsISupports subclass */
+ #define JSOPTION_COMPILE_N_GO   JS_BIT(4)       /* caller of JS_Compile*Script
+                                                    promises to execute compiled
+                                                    script once only; enables
+                                                    compile-time scope chain
+                                                    resolution of consts. */
+ #define JSOPTION_ATLINE         JS_BIT(5)       /* //@line number ["filename"]
+                                                    option supported for the
+                                                    XUL preprocessor and kindred
+                                                    beasts. */
+ #define JSOPTION_XML            JS_BIT(6)       /* EMCAScript for XML support:
+                                                    parse <!-- --> as a token,
+                                                    not backward compatible with
+                                                    the comment-hiding hack used
+                                                    in HTML script tags. */
+ #define JSOPTION_NATIVE_BRANCH_CALLBACK \
+                                 JS_BIT(7)       /* the branch callback set by
+                                                    JS_SetBranchCallback may be
+                                                    called with a null script
+                                                    parameter, by native code
+                                                    that loops intensively */
+ 
+ extern JS_PUBLIC_API(uint32)
+ JS_GetOptions(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(uint32)
+ JS_SetOptions(JSContext *cx, uint32 options);
+ 
+ extern JS_PUBLIC_API(uint32)
+ JS_ToggleOptions(JSContext *cx, uint32 options);
+ 
+ extern JS_PUBLIC_API(const char *)
+ JS_GetImplementationVersion(void);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetGlobalObject(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetGlobalObject(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Initialize standard JS class constructors, prototypes, and any top-level
+  * functions and constants associated with the standard classes (e.g. isNaN
+  * for Number).
+  *
+  * NB: This sets cx's global object to obj if it was null.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_InitStandardClasses(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Resolve id, which must contain either a string or an int, to a standard
+  * class name in obj if possible, defining the class's constructor and/or
+  * prototype and storing true in *resolved.  If id does not name a standard
+  * class or a top-level property induced by initializing a standard class,
+  * store false in *resolved and just return true.  Return false on error,
+  * as usual for JSBool result-typed API entry points.
+  *
+  * This API can be called directly from a global object class's resolve op,
+  * to define standard classes lazily.  The class's enumerate op should call
+  * JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
+  * loops any classes not yet resolved lazily.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
+                         JSBool *resolved);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Enumerate any already-resolved standard class ids into ida, or into a new
+  * JSIdArray if ida is null.  Return the augmented array on success, null on
+  * failure with ida (if it was non-null on entry) destroyed.
+  */
+ extern JS_PUBLIC_API(JSIdArray *)
+ JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
+                                     JSIdArray *ida);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetScopeChain(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_malloc(JSContext *cx, size_t nbytes);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_realloc(JSContext *cx, void *p, size_t nbytes);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_free(JSContext *cx, void *p);
+ 
+ extern JS_PUBLIC_API(char *)
+ JS_strdup(JSContext *cx, const char *s);
+ 
+ extern JS_PUBLIC_API(jsdouble *)
+ JS_NewDouble(JSContext *cx, jsdouble d);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
+ 
+ /*
+  * A JS GC root is a pointer to a JSObject *, JSString *, or jsdouble * that
+  * itself points into the GC heap (more recently, we support this extension:
+  * a root may be a pointer to a jsval v for which JSVAL_IS_GCTHING(v) is true).
+  *
+  * Therefore, you never pass JSObject *obj to JS_AddRoot(cx, obj).  You always
+  * call JS_AddRoot(cx, &obj), passing obj by reference.  And later, before obj
+  * or the structure it is embedded within goes out of scope or is freed, you
+  * must call JS_RemoveRoot(cx, &obj).
+  *
+  * Also, use JS_AddNamedRoot(cx, &structPtr->memberObj, "structPtr->memberObj")
+  * in preference to JS_AddRoot(cx, &structPtr->memberObj), in order to identify
+  * roots by their source callsites.  This way, you can find the callsite while
+  * debugging if you should fail to do JS_RemoveRoot(cx, &structPtr->memberObj)
+  * before freeing structPtr's memory.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_AddRoot(JSContext *cx, void *rp);
+ 
+ #ifdef NAME_ALL_GC_ROOTS
+ #define JS_DEFINE_TO_TOKEN(def) #def
+ #define JS_DEFINE_TO_STRING(def) JS_DEFINE_TO_TOKEN(def)
+ #define JS_AddRoot(cx,rp) JS_AddNamedRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+ #endif
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_AddNamedRoot(JSContext *cx, void *rp, const char *name);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_RemoveRoot(JSContext *cx, void *rp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_RemoveRootRT(JSRuntime *rt, void *rp);
+ 
+ /*
+  * The last GC thing of each type (object, string, double, external string
+  * types) created on a given context is kept alive until another thing of the
+  * same type is created, using a newborn root in the context.  These newborn
+  * roots help native code protect newly-created GC-things from GC invocations
+  * activated before those things can be rooted using local or global roots.
+  *
+  * However, the newborn roots can also entrain great gobs of garbage, so the
+  * JS_GC entry point clears them for the context on which GC is being forced.
+  * Embeddings may need to do likewise for all contexts.
+  *
+  * See the scoped local root API immediately below for a better way to manage
+  * newborns in cases where native hooks (functions, getters, setters, etc.)
+  * create many GC-things, potentially without connecting them to predefined
+  * local roots such as *rval or argv[i] in an active native function.  Using
+  * JS_EnterLocalRootScope disables updating of the context's per-gc-thing-type
+  * newborn roots, until control flow unwinds and leaves the outermost nesting
+  * local root scope.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ClearNewbornRoots(JSContext *cx);
+ 
+ /*
+  * Scoped local root management allows native functions, getter/setters, etc.
+  * to avoid worrying about the newborn root pigeon-holes, overloading local
+  * roots allocated in argv and *rval, or ending up having to call JS_Add*Root
+  * and JS_RemoveRoot to manage global roots temporarily.
+  *
+  * Instead, calling JS_EnterLocalRootScope and JS_LeaveLocalRootScope around
+  * the body of the native hook causes the engine to allocate a local root for
+  * each newborn created in between the two API calls, using a local root stack
+  * associated with cx.  For example:
+  *
+  *    JSBool
+  *    my_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+  *    {
+  *        JSBool ok;
+  *
+  *        if (!JS_EnterLocalRootScope(cx))
+  *            return JS_FALSE;
+  *        ok = my_GetPropertyBody(cx, obj, id, vp);
+  *        JS_LeaveLocalRootScope(cx);
+  *        return ok;
+  *    }
+  *
+  * NB: JS_LeaveLocalRootScope must be called once for every prior successful
+  * call to JS_EnterLocalRootScope.  If JS_EnterLocalRootScope fails, you must
+  * not make the matching JS_LeaveLocalRootScope call.
+  *
+  * In case a native hook allocates many objects or other GC-things, but the
+  * native protects some of those GC-things by storing them as property values
+  * in an object that is itself protected, the hook can call JS_ForgetLocalRoot
+  * to free the local root automatically pushed for the now-protected GC-thing.
+  *
+  * JS_ForgetLocalRoot works on any GC-thing allocated in the current local
+  * root scope, but it's more time-efficient when called on references to more
+  * recently created GC-things.  Calling it successively on other than the most
+  * recently allocated GC-thing will tend to average the time inefficiency, and
+  * may risk O(n^2) growth rate, but in any event, you shouldn't allocate too
+  * many local roots if you can root as you go (build a tree of objects from
+  * the top down, forgetting each latest-allocated GC-thing immediately upon
+  * linking it to its parent).
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_EnterLocalRootScope(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_LeaveLocalRootScope(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ForgetLocalRoot(JSContext *cx, void *thing);
+ 
+ #ifdef DEBUG
+ extern JS_PUBLIC_API(void)
+ JS_DumpNamedRoots(JSRuntime *rt,
+                   void (*dump)(const char *name, void *rp, void *data),
+                   void *data);
+ #endif
+ 
+ /*
+  * Call JS_MapGCRoots to map the GC's roots table using map(rp, name, data).
+  * The root is pointed at by rp; if the root is unnamed, name is null; data is
+  * supplied from the third parameter to JS_MapGCRoots.
+  *
+  * The map function should return JS_MAP_GCROOT_REMOVE to cause the currently
+  * enumerated root to be removed.  To stop enumeration, set JS_MAP_GCROOT_STOP
+  * in the return value.  To keep on mapping, return JS_MAP_GCROOT_NEXT.  These
+  * constants are flags; you can OR them together.
+  *
+  * This function acquires and releases rt's GC lock around the mapping of the
+  * roots table, so the map function should run to completion in as few cycles
+  * as possible.  Of course, map cannot call JS_GC, JS_MaybeGC, JS_BeginRequest,
+  * or any JS API entry point that acquires locks, without double-tripping or
+  * deadlocking on the GC lock.
+  *
+  * JS_MapGCRoots returns the count of roots that were successfully mapped.
+  */
+ #define JS_MAP_GCROOT_NEXT      0       /* continue mapping entries */
+ #define JS_MAP_GCROOT_STOP      1       /* stop mapping entries */
+ #define JS_MAP_GCROOT_REMOVE    2       /* remove and free the current entry */
+ 
+ typedef intN
+ (* JS_DLL_CALLBACK JSGCRootMapFun)(void *rp, const char *name, void *data);
+ 
+ extern JS_PUBLIC_API(uint32)
+ JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LockGCThing(JSContext *cx, void *thing);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LockGCThingRT(JSRuntime *rt, void *thing);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_UnlockGCThing(JSContext *cx, void *thing);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_UnlockGCThingRT(JSRuntime *rt, void *thing);
+ 
+ /*
+  * For implementors of JSObjectOps.mark, to mark a GC-thing reachable via a
+  * property or other strong ref identified for debugging purposes by name.
+  * The name argument's storage needs to live only as long as the call to
+  * this routine.
+  *
+  * The final arg is used by GC_MARK_DEBUG code to build a ref path through
+  * the GC's live thing graph.  Implementors of JSObjectOps.mark should pass
+  * its final arg through to this function when marking all GC-things that are
+  * directly reachable from the object being marked.
+  *
+  * See the JSMarkOp typedef in jspubtd.h, and the JSObjectOps struct below.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_GC(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_MaybeGC(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSGCCallback)
+ JS_SetGCCallback(JSContext *cx, JSGCCallback cb);
+ 
+ extern JS_PUBLIC_API(JSGCCallback)
+ JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsAboutToBeFinalized(JSContext *cx, void *thing);
+ 
+ typedef enum JSGCParamKey {
+     JSGC_MAX_BYTES        = 0,  /* maximum nominal heap before last ditch GC */
+     JSGC_MAX_MALLOC_BYTES = 1   /* # of JS_malloc bytes before last ditch GC */
+ } JSGCParamKey;
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value);
+ 
+ /*
+  * Add a finalizer for external strings created by JS_NewExternalString (see
+  * below) using a type-code returned from this function, and that understands
+  * how to free or release the memory pointed at by JS_GetStringChars(str).
+  *
+  * Return a nonnegative type index if there is room for finalizer in the
+  * global GC finalizers table, else return -1.  If the engine is compiled
+  * JS_THREADSAFE and used in a multi-threaded environment, this function must
+  * be invoked on the primordial thread only, at startup -- or else the entire
+  * program must single-thread itself while loading a module that calls this
+  * function.
+  */
+ extern JS_PUBLIC_API(intN)
+ JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer);
+ 
+ /*
+  * Remove finalizer from the global GC finalizers table, returning its type
+  * code if found, -1 if not found.
+  *
+  * As with JS_AddExternalStringFinalizer, there is a threading restriction
+  * if you compile the engine JS_THREADSAFE: this function may be called for a
+  * given finalizer pointer on only one thread; different threads may call to
+  * remove distinct finalizers safely.
+  *
+  * You must ensure that all strings with finalizer's type have been collected
+  * before calling this function.  Otherwise, string data will be leaked by the
+  * GC, for want of a finalizer to call.
+  */
+ extern JS_PUBLIC_API(intN)
+ JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer);
+ 
+ /*
+  * Create a new JSString whose chars member refers to external memory, i.e.,
+  * memory requiring special, type-specific finalization.  The type code must
+  * be a nonnegative return value from JS_AddExternalStringFinalizer.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type);
+ 
+ /*
+  * Returns the external-string finalizer index for this string, or -1 if it is
+  * an "internal" (native to JS engine) string.
+  */
+ extern JS_PUBLIC_API(intN)
+ JS_GetExternalStringGCType(JSRuntime *rt, JSString *str);
+ 
+ /*
+  * Sets maximum (if stack grows upward) or minimum (downward) legal stack byte
+  * address in limitAddr for the thread or process stack used by cx.  To disable
+  * stack size checking, pass 0 for limitAddr.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Classes, objects, and properties.
+  */
+ 
+ /* For detailed comments on the function pointer types, see jspubtd.h. */
+ struct JSClass {
+     const char          *name;
+     uint32              flags;
+ 
+     /* Mandatory non-null function pointer members. */
+     JSPropertyOp        addProperty;
+     JSPropertyOp        delProperty;
+     JSPropertyOp        getProperty;
+     JSPropertyOp        setProperty;
+     JSEnumerateOp       enumerate;
+     JSResolveOp         resolve;
+     JSConvertOp         convert;
+     JSFinalizeOp        finalize;
+ 
+     /* Optionally non-null members start here. */
+     JSGetObjectOps      getObjectOps;
+     JSCheckAccessOp     checkAccess;
+     JSNative            call;
+     JSNative            construct;
+     JSXDRObjectOp       xdrObject;
+     JSHasInstanceOp     hasInstance;
+     JSMarkOp            mark;
+     JSReserveSlotsOp    reserveSlots;
+ };
+ 
+ struct JSExtendedClass {
+     JSClass             base;
+     JSEqualityOp        equality;
+     JSObjectOp          outerObject;
+     JSObjectOp          innerObject;
+     jsword              reserved0;
+     jsword              reserved1;
+     jsword              reserved2;
+     jsword              reserved3;
+     jsword              reserved4;
+ };
+ 
+ #define JSCLASS_HAS_PRIVATE             (1<<0)  /* objects have private slot */
+ #define JSCLASS_NEW_ENUMERATE           (1<<1)  /* has JSNewEnumerateOp hook */
+ #define JSCLASS_NEW_RESOLVE             (1<<2)  /* has JSNewResolveOp hook */
+ #define JSCLASS_PRIVATE_IS_NSISUPPORTS  (1<<3)  /* private is (nsISupports *) */
+ #define JSCLASS_SHARE_ALL_PROPERTIES    (1<<4)  /* all properties are SHARED */
+ #define JSCLASS_NEW_RESOLVE_GETS_START  (1<<5)  /* JSNewResolveOp gets starting
+                                                    object in prototype chain
+                                                    passed in via *objp in/out
+                                                    parameter */
+ #define JSCLASS_CONSTRUCT_PROTOTYPE     (1<<6)  /* call constructor on class
+                                                    prototype */
+ #define JSCLASS_DOCUMENT_OBSERVER       (1<<7)  /* DOM document observer */
+ 
+ /*
+  * To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or
+  * JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where
+  * n is a constant in [1, 255].  Reserved slots are indexed from 0 to n-1.
+  */
+ #define JSCLASS_RESERVED_SLOTS_SHIFT    8       /* room for 8 flags below */
+ #define JSCLASS_RESERVED_SLOTS_WIDTH    8       /* and 16 above this field */
+ #define JSCLASS_RESERVED_SLOTS_MASK     JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH)
+ #define JSCLASS_HAS_RESERVED_SLOTS(n)   (((n) & JSCLASS_RESERVED_SLOTS_MASK)  \
+                                          << JSCLASS_RESERVED_SLOTS_SHIFT)
+ #define JSCLASS_RESERVED_SLOTS(clasp)   (((clasp)->flags                      \
+                                           >> JSCLASS_RESERVED_SLOTS_SHIFT)    \
+                                          & JSCLASS_RESERVED_SLOTS_MASK)
+ 
+ #define JSCLASS_HIGH_FLAGS_SHIFT        (JSCLASS_RESERVED_SLOTS_SHIFT +       \
+                                          JSCLASS_RESERVED_SLOTS_WIDTH)
+ 
+ /* True if JSClass is really a JSExtendedClass. */
+ #define JSCLASS_IS_EXTENDED             (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
+ 
+ /* Initializer for unused members of statically initialized JSClass structs. */
+ #define JSCLASS_NO_OPTIONAL_MEMBERS     0,0,0,0,0,0,0,0
+ #define JSCLASS_NO_RESERVED_MEMBERS     0,0,0,0,0
+ 
+ /* For detailed comments on these function pointer types, see jspubtd.h. */
+ struct JSObjectOps {
+     /* Mandatory non-null function pointer members. */
+     JSNewObjectMapOp    newObjectMap;
+     JSObjectMapOp       destroyObjectMap;
+     JSLookupPropOp      lookupProperty;
+     JSDefinePropOp      defineProperty;
+     JSPropertyIdOp      getProperty;
+     JSPropertyIdOp      setProperty;
+     JSAttributesOp      getAttributes;
+     JSAttributesOp      setAttributes;
+     JSPropertyIdOp      deleteProperty;
+     JSConvertOp         defaultValue;
+     JSNewEnumerateOp    enumerate;
+     JSCheckAccessIdOp   checkAccess;
+ 
+     /* Optionally non-null members start here. */
+     JSObjectOp          thisObject;
+     JSPropertyRefOp     dropProperty;
+     JSNative            call;
+     JSNative            construct;
+     JSXDRObjectOp       xdrObject;
+     JSHasInstanceOp     hasInstance;
+     JSSetObjectSlotOp   setProto;
+     JSSetObjectSlotOp   setParent;
+     JSMarkOp            mark;
+     JSFinalizeOp        clear;
+     JSGetRequiredSlotOp getRequiredSlot;
+     JSSetRequiredSlotOp setRequiredSlot;
+ };
+ 
+ struct JSXMLObjectOps {
+     JSObjectOps         base;
+     JSGetMethodOp       getMethod;
+     JSSetMethodOp       setMethod;
+     JSEnumerateValuesOp enumerateValues;
+     JSEqualityOp        equality;
+     JSConcatenateOp     concatenate;
+ };
+ 
+ /*
+  * Classes that expose JSObjectOps via a non-null getObjectOps class hook may
+  * derive a property structure from this struct, return a pointer to it from
+  * lookupProperty and defineProperty, and use the pointer to avoid rehashing
+  * in getAttributes and setAttributes.
+  *
+  * The jsid type contains either an int jsval (see JSVAL_IS_INT above), or an
+  * internal pointer that is opaque to users of this API, but which users may
+  * convert from and to a jsval using JS_ValueToId and JS_IdToValue.
+  */
+ struct JSProperty {
+     jsid id;
+ };
+ 
+ struct JSIdArray {
+     jsint length;
+     jsid  vector[1];    /* actually, length jsid words */
+ };
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyIdArray(JSContext *cx, JSIdArray *ida);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ValueToId(JSContext *cx, jsval v, jsid *idp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IdToValue(JSContext *cx, jsid id, jsval *vp);
+ 
+ /*
+  * The magic XML namespace id is int-tagged, but not a valid integer jsval.
+  * Global object classes in embeddings that enable JS_HAS_XML_SUPPORT (E4X)
+  * should handle this id specially before converting id via JSVAL_TO_INT.
+  */
+ #define JS_DEFAULT_XML_NAMESPACE_ID ((jsid) JSVAL_VOID)
+ 
+ /*
+  * JSNewResolveOp flag bits.
+  */
+ #define JSRESOLVE_QUALIFIED     0x01    /* resolve a qualified property id */
+ #define JSRESOLVE_ASSIGNING     0x02    /* resolve on the left of assignment */
+ #define JSRESOLVE_DETECTING     0x04    /* 'if (o.p)...' or '(o.p) ?...:...' */
+ #define JSRESOLVE_DECLARING     0x08    /* var, const, or function prolog op */
+ #define JSRESOLVE_CLASSNAME     0x10    /* class name used when constructing */
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EnumerateStub(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_FinalizeStub(JSContext *cx, JSObject *obj);
+ 
+ struct JSConstDoubleSpec {
+     jsdouble        dval;
+     const char      *name;
+     uint8           flags;
+     uint8           spare[3];
+ };
+ 
+ /*
+  * To define an array element rather than a named property member, cast the
+  * element's index to (const char *) and initialize name with it, and set the
+  * JSPROP_INDEX bit in flags.
+  */
+ struct JSPropertySpec {
+     const char      *name;
+     int8            tinyid;
+     uint8           flags;
+     JSPropertyOp    getter;
+     JSPropertyOp    setter;
+ };
+ 
+ struct JSFunctionSpec {
+     const char      *name;
+     JSNative        call;
+     uint8           nargs;
+     uint8           flags;
+     uint16          extra;      /* number of arg slots for local GC roots */
+ };
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+              JSClass *clasp, JSNative constructor, uintN nargs,
+              JSPropertySpec *ps, JSFunctionSpec *fs,
+              JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
+ 
+ #ifdef JS_THREADSAFE
+ extern JS_PUBLIC_API(JSClass *)
+ JS_GetClass(JSContext *cx, JSObject *obj);
+ 
+ #define JS_GET_CLASS(cx,obj) JS_GetClass(cx, obj)
+ #else
+ extern JS_PUBLIC_API(JSClass *)
+ JS_GetClass(JSObject *obj);
+ 
+ #define JS_GET_CLASS(cx,obj) JS_GetClass(obj)
+ #endif
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_GetPrivate(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetPrivate(JSContext *cx, JSObject *obj, void *data);
+ 
+ extern JS_PUBLIC_API(void *)
+ JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
+                       jsval *argv);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetPrototype(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetParent(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetConstructor(JSContext *cx, JSObject *proto);
+ 
+ /*
+  * Get a unique identifier for obj, good for the lifetime of obj (even if it
+  * is moved by a copying GC).  Return false on failure (likely out of memory),
+  * and true with *idp containing the unique id on success.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+                    JSObject *parent);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
+                                 JSObject *parent, uintN argc, jsval *argv);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
+                 JSObject *proto, uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+                   JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+ 
+ /*
+  * Determine the attributes (JSPROP_* flags) of a property on a given object.
+  *
+  * If the object does not have a property by that name, *foundp will be
+  * JS_FALSE and the value of *attrsp is undefined.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+                          uintN *attrsp, JSBool *foundp);
+ 
+ /*
+  * The same, but if the property is native, return its getter and setter via
+  * *getterp and *setterp, respectively (and only if the out parameter pointer
+  * is not null).
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+                                    const char *name,
+                                    uintN *attrsp, JSBool *foundp,
+                                    JSPropertyOp *getterp,
+                                    JSPropertyOp *setterp);
+ 
+ /*
+  * Set the attributes of a property on a given object.
+  *
+  * If the object does not have a property by that name, *foundp will be
+  * JS_FALSE and nothing will be altered.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+                          uintN attrs, JSBool *foundp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
+                             int8 tinyid, jsval value,
+                             JSPropertyOp getter, JSPropertyOp setter,
+                             uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
+                  const char *alias);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
+                            uintN flags, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
+              jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
+                    jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineUCProperty(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen, jsval value,
+                     JSPropertyOp getter, JSPropertyOp setter,
+                     uintN attrs);
+ 
+ /*
+  * Determine the attributes (JSPROP_* flags) of a property on a given object.
+  *
+  * If the object does not have a property by that name, *foundp will be
+  * JS_FALSE and the value of *attrsp is undefined.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+                            const jschar *name, size_t namelen,
+                            uintN *attrsp, JSBool *foundp);
+ 
+ /*
+  * The same, but if the property is native, return its getter and setter via
+  * *getterp and *setterp, respectively (and only if the out parameter pointer
+  * is not null).
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+                                      const jschar *name, size_t namelen,
+                                      uintN *attrsp, JSBool *foundp,
+                                      JSPropertyOp *getterp,
+                                      JSPropertyOp *setterp);
+ 
+ /*
+  * Set the attributes of a property on a given object.
+  *
+  * If the object does not have a property by that name, *foundp will be
+  * JS_FALSE and nothing will be altered.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+                            const jschar *name, size_t namelen,
+                            uintN attrs, JSBool *foundp);
+ 
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
+                               const jschar *name, size_t namelen,
+                               int8 tinyid, jsval value,
+                               JSPropertyOp getter, JSPropertyOp setter,
+                               uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  JSBool *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LookupUCProperty(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen,
+                     jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetUCProperty(JSContext *cx, JSObject *obj,
+                  const jschar *name, size_t namelen,
+                  jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
+                      const jschar *name, size_t namelen,
+                      jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsArrayObject(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
+                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ClearScope(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSIdArray *)
+ JS_Enumerate(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Create an object to iterate over enumerable properties of obj, in arbitrary
+  * property definition order.  NB: This differs from longstanding for..in loop
+  * order, which uses order of property definition in obj.
+  */
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewPropertyIterator(JSContext *cx, JSObject *obj);
+ 
+ /*
+  * Return true on success with *idp containing the id of the next enumerable
+  * property to visit using iterobj, or JSVAL_VOID if there is no such property
+  * left to visit.  Return false on error.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+                jsval *vp, uintN *attrsp);
+ 
+ extern JS_PUBLIC_API(JSCheckAccessOp)
+ JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Security protocol.
+  */
+ struct JSPrincipals {
+     char *codebase;
+ 
+     /* XXX unspecified and unused by Mozilla code -- can we remove these? */
+     void * (* JS_DLL_CALLBACK getPrincipalArray)(JSContext *cx, JSPrincipals *);
+     JSBool (* JS_DLL_CALLBACK globalPrivilegesEnabled)(JSContext *cx, JSPrincipals *);
+ 
+     /* Don't call "destroy"; use reference counting macros below. */
+     jsrefcount refcount;
+ 
+     void   (* JS_DLL_CALLBACK destroy)(JSContext *cx, JSPrincipals *);
+     JSBool (* JS_DLL_CALLBACK subsume)(JSPrincipals *, JSPrincipals *);
+ };
+ 
+ #ifdef JS_THREADSAFE
+ #define JSPRINCIPALS_HOLD(cx, principals)   JS_HoldPrincipals(cx,principals)
+ #define JSPRINCIPALS_DROP(cx, principals)   JS_DropPrincipals(cx,principals)
+ 
+ extern JS_PUBLIC_API(jsrefcount)
+ JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals);
+ 
+ extern JS_PUBLIC_API(jsrefcount)
+ JS_DropPrincipals(JSContext *cx, JSPrincipals *principals);
+ 
+ #else
+ #define JSPRINCIPALS_HOLD(cx, principals)   (++(principals)->refcount)
+ #define JSPRINCIPALS_DROP(cx, principals)                                     \
+     ((--(principals)->refcount == 0)                                          \
+      ? ((*(principals)->destroy)((cx), (principals)), 0)                      \
+      : (principals)->refcount)
+ #endif
+ 
+ extern JS_PUBLIC_API(JSPrincipalsTranscoder)
+ JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px);
+ 
+ extern JS_PUBLIC_API(JSObjectPrincipalsFinder)
+ JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Functions and scripts.
+  */
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_NewFunction(JSContext *cx, JSNative call, uintN nargs, uintN flags,
+                JSObject *parent, const char *name);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetFunctionObject(JSFunction *fun);
+ 
+ /*
+  * Deprecated, useful only for diagnostics.  Use JS_GetFunctionId instead for
+  * anonymous vs. "anonymous" disambiguation and Unicode fidelity.
+  */
+ extern JS_PUBLIC_API(const char *)
+ JS_GetFunctionName(JSFunction *fun);
+ 
+ /*
+  * Return the function's identifier as a JSString, or null if fun is unnamed.
+  * The returned string lives as long as fun, so you don't need to root a saved
+  * reference to it if fun is well-connected or rooted, and provided you bound
+  * the use of the saved reference by fun's lifetime.
+  *
+  * Prefer JS_GetFunctionId over JS_GetFunctionName because it returns null for
+  * truly anonymous functions, and because it doesn't chop to ISO-Latin-1 chars
+  * from UTF-16-ish jschars.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_GetFunctionId(JSFunction *fun);
+ 
+ /*
+  * Return JSFUN_* flags for fun.
+  */
+ extern JS_PUBLIC_API(uintN)
+ JS_GetFunctionFlags(JSFunction *fun);
+ 
+ /*
+  * Return the arity (length) of fun.
+  */
+ extern JS_PUBLIC_API(uint16)
+ JS_GetFunctionArity(JSFunction *fun);
+ 
+ /*
+  * Infallible predicate to test whether obj is a function object (faster than
+  * comparing obj's class name to "Function", but equivalent unless someone has
+  * overwritten the "Function" identifier with a different constructor and then
+  * created instances using that constructor that might be passed in as obj).
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ObjectIsFunction(JSContext *cx, JSObject *obj);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+                   uintN nargs, uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_DefineUCFunction(JSContext *cx, JSObject *obj,
+                     const jschar *name, size_t namelen, JSNative call,
+                     uintN nargs, uintN attrs);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
+ 
+ /*
+  * Given a buffer, return JS_FALSE if the buffer might become a valid
+  * javascript statement with the addition of more lines.  Otherwise return
+  * JS_TRUE.  The intent is to support interactive compilation - accumulate
+  * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
+  * the compiler.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
+                           const char *bytes, size_t length);
+ 
+ /*
+  * The JSScript objects returned by the following functions refer to string and
+  * other kinds of literals, including doubles and RegExp objects.  These
+  * literals are vulnerable to garbage collection; to root script objects and
+  * prevent literals from being collected, create a rootable object using
+  * JS_NewScriptObject, and root the resulting object using JS_Add[Named]Root.
+  */
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileScript(JSContext *cx, JSObject *obj,
+                  const char *bytes, size_t length,
+                  const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
+                               JSPrincipals *principals,
+                               const char *bytes, size_t length,
+                               const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileUCScript(JSContext *cx, JSObject *obj,
+                    const jschar *chars, size_t length,
+                    const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                 JSPrincipals *principals,
+                                 const jschar *chars, size_t length,
+                                 const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
+                      FILE *fh);
+ 
+ extern JS_PUBLIC_API(JSScript *)
+ JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
+                                   const char *filename, FILE *fh,
+                                   JSPrincipals *principals);
+ 
+ /*
+  * NB: you must use JS_NewScriptObject and root a pointer to its return value
+  * in order to keep a JSScript and its atoms safe from garbage collection after
+  * creating the script via JS_Compile* and before a JS_ExecuteScript* call.
+  * E.g., and without error checks:
+  *
+  *    JSScript *script = JS_CompileFile(cx, global, filename);
+  *    JSObject *scrobj = JS_NewScriptObject(cx, script);
+  *    JS_AddNamedRoot(cx, &scrobj, "scrobj");
+  *    do {
+  *        jsval result;
+  *        JS_ExecuteScript(cx, global, script, &result);
+  *        JS_GC();
+  *    } while (!JSVAL_IS_BOOLEAN(result) || JSVAL_TO_BOOLEAN(result));
+  *    JS_RemoveRoot(cx, &scrobj);
+  */
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewScriptObject(JSContext *cx, JSScript *script);
+ 
+ /*
+  * Infallible getter for a script's object.  If JS_NewScriptObject has not been
+  * called on script yet, the return value will be null.
+  */
+ extern JS_PUBLIC_API(JSObject *)
+ JS_GetScriptObject(JSScript *script);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DestroyScript(JSContext *cx, JSScript *script);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
+                    uintN nargs, const char **argnames,
+                    const char *bytes, size_t length,
+                    const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
+                                 JSPrincipals *principals, const char *name,
+                                 uintN nargs, const char **argnames,
+                                 const char *bytes, size_t length,
+                                 const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
+                      uintN nargs, const char **argnames,
+                      const jschar *chars, size_t length,
+                      const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSFunction *)
+ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
+                                   JSPrincipals *principals, const char *name,
+                                   uintN nargs, const char **argnames,
+                                   const jschar *chars, size_t length,
+                                   const char *filename, uintN lineno);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
+                    uintN indent);
+ 
+ /*
+  * API extension: OR this into indent to avoid pretty-printing the decompiled
+  * source resulting from JS_DecompileFunction{,Body}.
+  */
+ #define JS_DONT_PRETTY_PRINT    ((uintN)0x8000)
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent);
+ 
+ /*
+  * NB: JS_ExecuteScript, JS_ExecuteScriptPart, and the JS_Evaluate*Script*
+  * quadruplets all use the obj parameter as the initial scope chain header,
+  * the 'this' keyword value, and the variables object (ECMA parlance for where
+  * 'var' and 'function' bind names) of the execution context for script.
+  *
+  * Using obj as the variables object is problematic if obj's parent (which is
+  * the scope chain link; see JS_SetParent and JS_NewObject) is not null: in
+  * this case, variables created by 'var x = 0', e.g., go in obj, but variables
+  * created by assignment to an unbound id, 'x = 0', go in the last object on
+  * the scope chain linked by parent.
+  *
+  * ECMA calls that last scoping object the "global object", but note that many
+  * embeddings have several such objects.  ECMA requires that "global code" be
+  * executed with the variables object equal to this global object.  But these
+  * JS API entry points provide freedom to execute code against a "sub-global",
+  * i.e., a parented or scoped object, in which case the variables object will
+  * differ from the last object on the scope chain, resulting in confusing and
+  * non-ECMA explicit vs. implicit variable creation.
+  *
+  * Caveat embedders: unless you already depend on this buggy variables object
+  * binding behavior, you should call JS_SetOptions(cx, JSOPTION_VAROBJFIX) or
+  * JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_VAROBJFIX) -- the latter if
+  * someone may have set other options on cx already -- for each context in the
+  * application, if you pass parented objects as the obj parameter, or may ever
+  * pass such objects in the future.
+  *
+  * Why a runtime option?  The alternative is to add six or so new API entry
+  * points with signatures matching the following six, and that doesn't seem
+  * worth the code bloat cost.  Such new entry points would probably have less
+  * obvious names, too, so would not tend to be used.  The JS_SetOption call,
+  * OTOH, can be more easily hacked into existing code that does not depend on
+  * the bug; such code can continue to use the familiar JS_EvaluateScript,
+  * etc., entry points.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval);
+ 
+ /*
+  * Execute either the function-defining prolog of a script, or the script's
+  * main body, but not both.
+  */
+ typedef enum JSExecPart { JSEXEC_PROLOG, JSEXEC_MAIN } JSExecPart;
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
+                      JSExecPart part, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EvaluateScript(JSContext *cx, JSObject *obj,
+                   const char *bytes, uintN length,
+                   const char *filename, uintN lineno,
+                   jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                JSPrincipals *principals,
+                                const char *bytes, uintN length,
+                                const char *filename, uintN lineno,
+                                jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
+                     const jschar *chars, uintN length,
+                     const char *filename, uintN lineno,
+                     jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+                                  JSPrincipals *principals,
+                                  const jschar *chars, uintN length,
+                                  const char *filename, uintN lineno,
+                                  jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
+                 jsval *argv, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
+                     jsval *argv, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
+                      jsval *argv, jsval *rval);
+ 
+ extern JS_PUBLIC_API(JSBranchCallback)
+ JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsRunning(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsConstructing(JSContext *cx);
+ 
+ /*
+  * Returns true if a script is executing and its current bytecode is a set
+  * (assignment) operation, even if there are native (no script) stack frames
+  * between the script and the caller to JS_IsAssigning.
+  */
+ extern JS_FRIEND_API(JSBool)
+ JS_IsAssigning(JSContext *cx);
+ 
+ /*
+  * Set the second return value, which should be a string or int jsval that
+  * identifies a property in the returned object, to form an ECMA reference
+  * type value (obj, id).  Only native methods can return reference types,
+  * and if the returned value is used on the left-hand side of an assignment
+  * op, the identified property will be set.  If the return value is in an
+  * r-value, the interpreter just gets obj[id]'s value.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_SetCallReturnValue2(JSContext *cx, jsval v);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Strings.
+  *
+  * NB: JS_NewString takes ownership of bytes on success, avoiding a copy; but
+  * on error (signified by null return), it leaves bytes owned by the caller.
+  * So the caller must free bytes in the error case, if it has no use for them.
+  * In contrast, all the JS_New*StringCopy* functions do not take ownership of
+  * the character memory passed to them -- they copy it.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewString(JSContext *cx, char *bytes, size_t length);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewStringCopyN(JSContext *cx, const char *s, size_t n);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewStringCopyZ(JSContext *cx, const char *s);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_InternString(JSContext *cx, const char *s);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewUCString(JSContext *cx, jschar *chars, size_t length);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewUCStringCopyZ(JSContext *cx, const jschar *s);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length);
+ 
+ extern JS_PUBLIC_API(JSString *)
+ JS_InternUCString(JSContext *cx, const jschar *s);
+ 
+ extern JS_PUBLIC_API(char *)
+ JS_GetStringBytes(JSString *str);
+ 
+ extern JS_PUBLIC_API(jschar *)
+ JS_GetStringChars(JSString *str);
+ 
+ extern JS_PUBLIC_API(size_t)
+ JS_GetStringLength(JSString *str);
+ 
+ extern JS_PUBLIC_API(intN)
+ JS_CompareStrings(JSString *str1, JSString *str2);
+ 
+ /*
+  * Mutable string support.  A string's characters are never mutable in this JS
+  * implementation, but a growable string has a buffer that can be reallocated,
+  * and a dependent string is a substring of another (growable, dependent, or
+  * immutable) string.  The direct data members of the (opaque to API clients)
+  * JSString struct may be changed in a single-threaded way for growable and
+  * dependent strings.
+  *
+  * Therefore mutable strings cannot be used by more than one thread at a time.
+  * You may call JS_MakeStringImmutable to convert the string from a mutable
+  * (growable or dependent) string to an immutable (and therefore thread-safe)
+  * string.  The engine takes care of converting growable and dependent strings
+  * to immutable for you if you store strings in multi-threaded objects using
+  * JS_SetProperty or kindred API entry points.
+  *
+  * If you store a JSString pointer in a native data structure that is (safely)
+  * accessible to multiple threads, you must call JS_MakeStringImmutable before
+  * retiring the store.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length);
+ 
+ /*
+  * Create a dependent string, i.e., a string that owns no character storage,
+  * but that refers to a slice of another string's chars.  Dependent strings
+  * are mutable by definition, so the thread safety comments above apply.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
+                       size_t length);
+ 
+ /*
+  * Concatenate two strings, resulting in a new growable string.  If you create
+  * the left string and pass it to JS_ConcatStrings on a single thread, try to
+  * use JS_NewGrowableString to create the left string -- doing so helps Concat
+  * avoid allocating a new buffer for the result and copying left's chars into
+  * the new buffer.  See above for thread safety comments.
+  */
+ extern JS_PUBLIC_API(JSString *)
+ JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right);
+ 
+ /*
+  * Convert a dependent string into an independent one.  This function does not
+  * change the string's mutability, so the thread safety comments above apply.
+  */
+ extern JS_PUBLIC_API(const jschar *)
+ JS_UndependString(JSContext *cx, JSString *str);
+ 
+ /*
+  * Convert a mutable string (either growable or dependent) into an immutable,
+  * thread-safe one.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_MakeStringImmutable(JSContext *cx, JSString *str);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Locale specific string conversion callback.
+  */
+ struct JSLocaleCallbacks {
+     JSLocaleToUpperCase     localeToUpperCase;
+     JSLocaleToLowerCase     localeToLowerCase;
+     JSLocaleCompare         localeCompare;
+     JSLocaleToUnicode       localeToUnicode;
+ };
+ 
+ /*
+  * Establish locale callbacks. The pointer must persist as long as the
+  * JSContext.  Passing NULL restores the default behaviour.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks);
+ 
+ /*
+  * Return the address of the current locale callbacks struct, which may
+  * be NULL.
+  */
+ extern JS_PUBLIC_API(JSLocaleCallbacks *)
+ JS_GetLocaleCallbacks(JSContext *cx);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Error reporting.
+  */
+ 
+ /*
+  * Report an exception represented by the sprintf-like conversion of format
+  * and its arguments.  This exception message string is passed to a pre-set
+  * JSErrorReporter function (set by JS_SetErrorReporter; see jspubtd.h for
+  * the JSErrorReporter typedef).
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ReportError(JSContext *cx, const char *format, ...);
+ 
+ /*
+  * Use an errorNumber to retrieve the format string, args are char *
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
+                      void *userRef, const uintN errorNumber, ...);
+ 
+ /*
+  * Use an errorNumber to retrieve the format string, args are jschar *
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
+                      void *userRef, const uintN errorNumber, ...);
+ 
+ /*
+  * As above, but report a warning instead (JSREPORT_IS_WARNING(report.flags)).
+  * Return true if there was no error trying to issue the warning, and if the
+  * warning was not converted into an error due to the JSOPTION_WERROR option
+  * being set, false otherwise.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ReportWarning(JSContext *cx, const char *format, ...);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
+                              JSErrorCallback errorCallback, void *userRef,
+                              const uintN errorNumber, ...);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
+                                JSErrorCallback errorCallback, void *userRef,
+                                const uintN errorNumber, ...);
+ 
+ /*
+  * Complain when out of memory.
+  */
+ extern JS_PUBLIC_API(void)
+ JS_ReportOutOfMemory(JSContext *cx);
+ 
+ struct JSErrorReport {
+     const char      *filename;      /* source file name, URL, etc., or null */
+     uintN           lineno;         /* source line number */
+     const char      *linebuf;       /* offending source line without final \n */
+     const char      *tokenptr;      /* pointer to error token in linebuf */
+     const jschar    *uclinebuf;     /* unicode (original) line buffer */
+     const jschar    *uctokenptr;    /* unicode (original) token pointer */
+     uintN           flags;          /* error/warning, etc. */
+     uintN           errorNumber;    /* the error number, e.g. see js.msg */
+     const jschar    *ucmessage;     /* the (default) error message */
+     const jschar    **messageArgs;  /* arguments for the error message */
+ };
+ 
+ /*
+  * JSErrorReport flag values.  These may be freely composed.
+  */
+ #define JSREPORT_ERROR      0x0     /* pseudo-flag for default case */
+ #define JSREPORT_WARNING    0x1     /* reported via JS_ReportWarning */
+ #define JSREPORT_EXCEPTION  0x2     /* exception was thrown */
+ #define JSREPORT_STRICT     0x4     /* error or warning due to strict option */
+ 
+ /*
+  * If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
+  * has been thrown for this runtime error, and the host should ignore it.
+  * Exception-aware hosts should also check for JS_IsExceptionPending if
+  * JS_ExecuteScript returns failure, and signal or propagate the exception, as
+  * appropriate.
+  */
+ #define JSREPORT_IS_WARNING(flags)      (((flags) & JSREPORT_WARNING) != 0)
+ #define JSREPORT_IS_EXCEPTION(flags)    (((flags) & JSREPORT_EXCEPTION) != 0)
+ #define JSREPORT_IS_STRICT(flags)       (((flags) & JSREPORT_STRICT) != 0)
+ 
+ extern JS_PUBLIC_API(JSErrorReporter)
+ JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);
+ 
+ /************************************************************************/
+ 
+ /*
+  * Regular Expressions.
+  */
+ #define JSREG_FOLD      0x01    /* fold uppercase to lowercase */
+ #define JSREG_GLOB      0x02    /* global exec, creates array of matches */
+ #define JSREG_MULTILINE 0x04    /* treat ^ and $ as begin and end of line */
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags);
+ 
+ extern JS_PUBLIC_API(JSObject *)
+ JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ClearRegExpStatics(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ClearRegExpRoots(JSContext *cx);
+ 
+ /* TODO: compile, exec, get/set other statics... */
+ 
+ /************************************************************************/
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_IsExceptionPending(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_GetPendingException(JSContext *cx, jsval *vp);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_SetPendingException(JSContext *cx, jsval v);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_ClearPendingException(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(JSBool)
+ JS_ReportPendingException(JSContext *cx);
+ 
+ /*
+  * Save the current exception state.  This takes a snapshot of cx's current
+  * exception state without making any change to that state.
+  *
+  * The returned state pointer MUST be passed later to JS_RestoreExceptionState
+  * (to restore that saved state, overriding any more recent state) or else to
+  * JS_DropExceptionState (to free the state struct in case it is not correct
+  * or desirable to restore it).  Both Restore and Drop free the state struct,
+  * so callers must stop using the pointer returned from Save after calling the
+  * Release or Drop API.
+  */
+ extern JS_PUBLIC_API(JSExceptionState *)
+ JS_SaveExceptionState(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state);
+ 
+ extern JS_PUBLIC_API(void)
+ JS_DropExceptionState(JSContext *cx, JSExceptionState *state);
+ 
+ /*
+  * If the given value is an exception object that originated from an error,
+  * the exception will contain an error report struct, and this API will return
+  * the address of that struct.  Otherwise, it returns NULL.  The lifetime of
+  * the error report struct that might be returned is the same as the lifetime
+  * of the exception object.
+  */
+ extern JS_PUBLIC_API(JSErrorReport *)
+ JS_ErrorFromException(JSContext *cx, jsval v);
+ 
+ /*
+  * Given a reported error's message and JSErrorReport struct pointer, throw
+  * the corresponding exception on cx.
+  */
+ extern JS_PUBLIC_API(JSBool)
+ JS_ThrowReportedError(JSContext *cx, const char *message,
+                       JSErrorReport *reportp);
+ 
+ #ifdef JS_THREADSAFE
+ 
+ /*
+  * Associate the current thread with the given context.  This is done
+  * implicitly by JS_NewContext.
+  *
+  * Returns the old thread id for this context, which should be treated as
+  * an opaque value.  This value is provided for comparison to 0, which
+  * indicates that ClearContextThread has been called on this context
+  * since the last SetContextThread, or non-0, which indicates the opposite.
+  */
+ extern JS_PUBLIC_API(jsword)
+ JS_GetContextThread(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsword)
+ JS_SetContextThread(JSContext *cx);
+ 
+ extern JS_PUBLIC_API(jsword)
+ JS_ClearContextThread(JSContext *cx);
+ 
+ #endif /* JS_THREADSAFE */
+ 
+ /************************************************************************/
+ 
+ JS_END_EXTERN_C
+ 
+ #endif /* jsapi_h___ */

CVSTrac 2.0.1