Back to index

lightning-sunbird  0.9+nobinonly
jsapi.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  * vim: set ts=8 sw=4 et tw=78:
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is Mozilla Communicator client code, released
00018  * March 31, 1998.
00019  *
00020  * The Initial Developer of the Original Code is
00021  * Netscape Communications Corporation.
00022  * Portions created by the Initial Developer are Copyright (C) 1998
00023  * the Initial Developer. All Rights Reserved.
00024  *
00025  * Contributor(s):
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 /*
00042  * JavaScript API.
00043  */
00044 #include "jsstddef.h"
00045 #include <ctype.h>
00046 #include <stdarg.h>
00047 #include <stdlib.h>
00048 #include <string.h>
00049 #include "jstypes.h"
00050 #include "jsarena.h" /* Added by JSIFY */
00051 #include "jsutil.h" /* Added by JSIFY */
00052 #include "jsclist.h"
00053 #include "jsdhash.h"
00054 #include "jsprf.h"
00055 #include "jsapi.h"
00056 #include "jsarray.h"
00057 #include "jsatom.h"
00058 #include "jsbool.h"
00059 #include "jscntxt.h"
00060 #include "jsconfig.h"
00061 #include "jsdate.h"
00062 #include "jsdtoa.h"
00063 #include "jsemit.h"
00064 #include "jsexn.h"
00065 #include "jsfun.h"
00066 #include "jsgc.h"
00067 #include "jsinterp.h"
00068 #include "jslock.h"
00069 #include "jsmath.h"
00070 #include "jsnum.h"
00071 #include "jsobj.h"
00072 #include "jsopcode.h"
00073 #include "jsparse.h"
00074 #include "jsregexp.h"
00075 #include "jsscan.h"
00076 #include "jsscope.h"
00077 #include "jsscript.h"
00078 #include "jsstr.h"
00079 #include "prmjtime.h"
00080 
00081 #if JS_HAS_FILE_OBJECT
00082 #include "jsfile.h"
00083 #endif
00084 
00085 #if JS_HAS_XML_SUPPORT
00086 #include "jsxml.h"
00087 #endif
00088 
00089 #if JS_HAS_GENERATORS
00090 #include "jsiter.h"
00091 #endif
00092 
00093 #ifdef HAVE_VA_LIST_AS_ARRAY
00094 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
00095 #else
00096 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
00097 #endif
00098 
00099 #if defined(JS_PARANOID_REQUEST) && defined(JS_THREADSAFE)
00100 #define CHECK_REQUEST(cx)       JS_ASSERT(cx->requestDepth)
00101 #else
00102 #define CHECK_REQUEST(cx)       ((void)0)
00103 #endif
00104 
00105 JS_PUBLIC_API(int64)
00106 JS_Now()
00107 {
00108     return PRMJ_Now();
00109 }
00110 
00111 JS_PUBLIC_API(jsval)
00112 JS_GetNaNValue(JSContext *cx)
00113 {
00114     return DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
00115 }
00116 
00117 JS_PUBLIC_API(jsval)
00118 JS_GetNegativeInfinityValue(JSContext *cx)
00119 {
00120     return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
00121 }
00122 
00123 JS_PUBLIC_API(jsval)
00124 JS_GetPositiveInfinityValue(JSContext *cx)
00125 {
00126     return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
00127 }
00128 
00129 JS_PUBLIC_API(jsval)
00130 JS_GetEmptyStringValue(JSContext *cx)
00131 {
00132     return STRING_TO_JSVAL(cx->runtime->emptyString);
00133 }
00134 
00135 static JSBool
00136 TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS,
00137                      jsval **vpp, va_list *app)
00138 {
00139     const char *format;
00140     JSArgumentFormatMap *map;
00141 
00142     format = *formatp;
00143     for (map = cx->argumentFormatMap; map; map = map->next) {
00144         if (!strncmp(format, map->format, map->length)) {
00145             *formatp = format + map->length;
00146             return map->formatter(cx, format, fromJS, vpp, app);
00147         }
00148     }
00149     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
00150     return JS_FALSE;
00151 }
00152 
00153 JS_PUBLIC_API(JSBool)
00154 JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
00155                     ...)
00156 {
00157     va_list ap;
00158     JSBool ok;
00159 
00160     va_start(ap, format);
00161     ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
00162     va_end(ap);
00163     return ok;
00164 }
00165 
00166 JS_PUBLIC_API(JSBool)
00167 JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
00168                       const char *format, va_list ap)
00169 {
00170     jsval *sp;
00171     JSBool required;
00172     char c;
00173     JSFunction *fun;
00174     jsdouble d;
00175     JSString *str;
00176     JSObject *obj;
00177 
00178     CHECK_REQUEST(cx);
00179     sp = argv;
00180     required = JS_TRUE;
00181     while ((c = *format++) != '\0') {
00182         if (isspace(c))
00183             continue;
00184         if (c == '/') {
00185             required = JS_FALSE;
00186             continue;
00187         }
00188         if (sp == argv + argc) {
00189             if (required) {
00190                 fun = js_ValueToFunction(cx, &argv[-2], 0);
00191                 if (fun) {
00192                     char numBuf[12];
00193                     JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
00194                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
00195                                          JSMSG_MORE_ARGS_NEEDED,
00196                                          JS_GetFunctionName(fun), numBuf,
00197                                          (argc == 1) ? "" : "s");
00198                 }
00199                 return JS_FALSE;
00200             }
00201             break;
00202         }
00203         switch (c) {
00204           case 'b':
00205             if (!js_ValueToBoolean(cx, *sp, va_arg(ap, JSBool *)))
00206                 return JS_FALSE;
00207             break;
00208           case 'c':
00209             if (!js_ValueToUint16(cx, *sp, va_arg(ap, uint16 *)))
00210                 return JS_FALSE;
00211             break;
00212           case 'i':
00213             if (!js_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
00214                 return JS_FALSE;
00215             break;
00216           case 'u':
00217             if (!js_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
00218                 return JS_FALSE;
00219             break;
00220           case 'j':
00221             if (!js_ValueToInt32(cx, *sp, va_arg(ap, int32 *)))
00222                 return JS_FALSE;
00223             break;
00224           case 'd':
00225             if (!js_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
00226                 return JS_FALSE;
00227             break;
00228           case 'I':
00229             if (!js_ValueToNumber(cx, *sp, &d))
00230                 return JS_FALSE;
00231             *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
00232             break;
00233           case 's':
00234           case 'S':
00235           case 'W':
00236             str = js_ValueToString(cx, *sp);
00237             if (!str)
00238                 return JS_FALSE;
00239             *sp = STRING_TO_JSVAL(str);
00240             if (c == 's')
00241                 *va_arg(ap, char **) = JS_GetStringBytes(str);
00242             else if (c == 'W')
00243                 *va_arg(ap, jschar **) = JS_GetStringChars(str);
00244             else
00245                 *va_arg(ap, JSString **) = str;
00246             break;
00247           case 'o':
00248             if (!js_ValueToObject(cx, *sp, &obj))
00249                 return JS_FALSE;
00250             *sp = OBJECT_TO_JSVAL(obj);
00251             *va_arg(ap, JSObject **) = obj;
00252             break;
00253           case 'f':
00254             obj = js_ValueToFunctionObject(cx, sp, 0);
00255             if (!obj)
00256                 return JS_FALSE;
00257             *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj);
00258             break;
00259           case 'v':
00260             *va_arg(ap, jsval *) = *sp;
00261             break;
00262           case '*':
00263             break;
00264           default:
00265             format--;
00266             if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
00267                                       JS_ADDRESSOF_VA_LIST(ap))) {
00268                 return JS_FALSE;
00269             }
00270             /* NB: the formatter already updated sp, so we continue here. */
00271             continue;
00272         }
00273         sp++;
00274     }
00275     return JS_TRUE;
00276 }
00277 
00278 JS_PUBLIC_API(jsval *)
00279 JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
00280 {
00281     va_list ap;
00282     jsval *argv;
00283 
00284     va_start(ap, format);
00285     argv = JS_PushArgumentsVA(cx, markp, format, ap);
00286     va_end(ap);
00287     return argv;
00288 }
00289 
00290 JS_PUBLIC_API(jsval *)
00291 JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
00292 {
00293     uintN argc;
00294     jsval *argv, *sp;
00295     char c;
00296     const char *cp;
00297     JSString *str;
00298     JSFunction *fun;
00299     JSStackHeader *sh;
00300 
00301     CHECK_REQUEST(cx);
00302     *markp = NULL;
00303     argc = 0;
00304     for (cp = format; (c = *cp) != '\0'; cp++) {
00305         /*
00306          * Count non-space non-star characters as individual jsval arguments.
00307          * This may over-allocate stack, but we'll fix below.
00308          */
00309         if (isspace(c) || c == '*')
00310             continue;
00311         argc++;
00312     }
00313     sp = js_AllocStack(cx, argc, markp);
00314     if (!sp)
00315         return NULL;
00316     argv = sp;
00317     while ((c = *format++) != '\0') {
00318         if (isspace(c) || c == '*')
00319             continue;
00320         switch (c) {
00321           case 'b':
00322             *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int));
00323             break;
00324           case 'c':
00325             *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int));
00326             break;
00327           case 'i':
00328           case 'j':
00329             if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
00330                 goto bad;
00331             break;
00332           case 'u':
00333             if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
00334                 goto bad;
00335             break;
00336           case 'd':
00337           case 'I':
00338             if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
00339                 goto bad;
00340             break;
00341           case 's':
00342             str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
00343             if (!str)
00344                 goto bad;
00345             *sp = STRING_TO_JSVAL(str);
00346             break;
00347           case 'W':
00348             str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
00349             if (!str)
00350                 goto bad;
00351             *sp = STRING_TO_JSVAL(str);
00352             break;
00353           case 'S':
00354             str = va_arg(ap, JSString *);
00355             *sp = STRING_TO_JSVAL(str);
00356             break;
00357           case 'o':
00358             *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
00359             break;
00360           case 'f':
00361             fun = va_arg(ap, JSFunction *);
00362             *sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
00363             break;
00364           case 'v':
00365             *sp = va_arg(ap, jsval);
00366             break;
00367           default:
00368             format--;
00369             if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp,
00370                                       JS_ADDRESSOF_VA_LIST(ap))) {
00371                 goto bad;
00372             }
00373             /* NB: the formatter already updated sp, so we continue here. */
00374             continue;
00375         }
00376         sp++;
00377     }
00378 
00379     /*
00380      * We may have overallocated stack due to a multi-character format code
00381      * handled by a JSArgumentFormatter.  Give back that stack space!
00382      */
00383     JS_ASSERT(sp <= argv + argc);
00384     if (sp < argv + argc) {
00385         /* Return slots not pushed to the current stack arena. */
00386         cx->stackPool.current->avail = (jsuword)sp;
00387 
00388         /* Reduce the count of slots the GC will scan in this stack segment. */
00389         sh = cx->stackHeaders;
00390         JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc);
00391         sh->nslots -= argc - (sp - argv);
00392     }
00393     return argv;
00394 
00395 bad:
00396     js_FreeStack(cx, *markp);
00397     return NULL;
00398 }
00399 
00400 JS_PUBLIC_API(void)
00401 JS_PopArguments(JSContext *cx, void *mark)
00402 {
00403     CHECK_REQUEST(cx);
00404     js_FreeStack(cx, mark);
00405 }
00406 
00407 JS_PUBLIC_API(JSBool)
00408 JS_AddArgumentFormatter(JSContext *cx, const char *format,
00409                         JSArgumentFormatter formatter)
00410 {
00411     size_t length;
00412     JSArgumentFormatMap **mpp, *map;
00413 
00414     length = strlen(format);
00415     mpp = &cx->argumentFormatMap;
00416     while ((map = *mpp) != NULL) {
00417         /* Insert before any shorter string to match before prefixes. */
00418         if (map->length < length)
00419             break;
00420         if (map->length == length && !strcmp(map->format, format))
00421             goto out;
00422         mpp = &map->next;
00423     }
00424     map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map);
00425     if (!map)
00426         return JS_FALSE;
00427     map->format = format;
00428     map->length = length;
00429     map->next = *mpp;
00430     *mpp = map;
00431 out:
00432     map->formatter = formatter;
00433     return JS_TRUE;
00434 }
00435 
00436 JS_PUBLIC_API(void)
00437 JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
00438 {
00439     size_t length;
00440     JSArgumentFormatMap **mpp, *map;
00441 
00442     length = strlen(format);
00443     mpp = &cx->argumentFormatMap;
00444     while ((map = *mpp) != NULL) {
00445         if (map->length == length && !strcmp(map->format, format)) {
00446             *mpp = map->next;
00447             JS_free(cx, map);
00448             return;
00449         }
00450         mpp = &map->next;
00451     }
00452 }
00453 
00454 JS_PUBLIC_API(JSBool)
00455 JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
00456 {
00457     JSBool ok, b;
00458     JSObject *obj;
00459     JSString *str;
00460     jsdouble d, *dp;
00461 
00462     CHECK_REQUEST(cx);
00463     switch (type) {
00464       case JSTYPE_VOID:
00465         *vp = JSVAL_VOID;
00466         ok = JS_TRUE;
00467         break;
00468       case JSTYPE_OBJECT:
00469         ok = js_ValueToObject(cx, v, &obj);
00470         if (ok)
00471             *vp = OBJECT_TO_JSVAL(obj);
00472         break;
00473       case JSTYPE_FUNCTION:
00474         *vp = v;
00475         obj = js_ValueToFunctionObject(cx, vp, JSV2F_SEARCH_STACK);
00476         ok = (obj != NULL);
00477         break;
00478       case JSTYPE_STRING:
00479         str = js_ValueToString(cx, v);
00480         ok = (str != NULL);
00481         if (ok)
00482             *vp = STRING_TO_JSVAL(str);
00483         break;
00484       case JSTYPE_NUMBER:
00485         ok = js_ValueToNumber(cx, v, &d);
00486         if (ok) {
00487             dp = js_NewDouble(cx, d, 0);
00488             ok = (dp != NULL);
00489             if (ok)
00490                 *vp = DOUBLE_TO_JSVAL(dp);
00491         }
00492         break;
00493       case JSTYPE_BOOLEAN:
00494         ok = js_ValueToBoolean(cx, v, &b);
00495         if (ok)
00496             *vp = BOOLEAN_TO_JSVAL(b);
00497         break;
00498       default: {
00499         char numBuf[12];
00500         JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
00501         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE,
00502                              numBuf);
00503         ok = JS_FALSE;
00504         break;
00505       }
00506     }
00507     return ok;
00508 }
00509 
00510 JS_PUBLIC_API(JSBool)
00511 JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
00512 {
00513     CHECK_REQUEST(cx);
00514     return js_ValueToObject(cx, v, objp);
00515 }
00516 
00517 JS_PUBLIC_API(JSFunction *)
00518 JS_ValueToFunction(JSContext *cx, jsval v)
00519 {
00520     CHECK_REQUEST(cx);
00521     return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
00522 }
00523 
00524 JS_PUBLIC_API(JSFunction *)
00525 JS_ValueToConstructor(JSContext *cx, jsval v)
00526 {
00527     CHECK_REQUEST(cx);
00528     return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
00529 }
00530 
00531 JS_PUBLIC_API(JSString *)
00532 JS_ValueToString(JSContext *cx, jsval v)
00533 {
00534     CHECK_REQUEST(cx);
00535     return js_ValueToString(cx, v);
00536 }
00537 
00538 JS_PUBLIC_API(JSBool)
00539 JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
00540 {
00541     CHECK_REQUEST(cx);
00542     return js_ValueToNumber(cx, v, dp);
00543 }
00544 
00545 JS_PUBLIC_API(JSBool)
00546 JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
00547 {
00548     CHECK_REQUEST(cx);
00549     return js_ValueToECMAInt32(cx, v, ip);
00550 }
00551 
00552 JS_PUBLIC_API(JSBool)
00553 JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
00554 {
00555     CHECK_REQUEST(cx);
00556     return js_ValueToECMAUint32(cx, v, ip);
00557 }
00558 
00559 JS_PUBLIC_API(JSBool)
00560 JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
00561 {
00562     CHECK_REQUEST(cx);
00563     return js_ValueToInt32(cx, v, ip);
00564 }
00565 
00566 JS_PUBLIC_API(JSBool)
00567 JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
00568 {
00569     CHECK_REQUEST(cx);
00570     return js_ValueToUint16(cx, v, ip);
00571 }
00572 
00573 JS_PUBLIC_API(JSBool)
00574 JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
00575 {
00576     CHECK_REQUEST(cx);
00577     return js_ValueToBoolean(cx, v, bp);
00578 }
00579 
00580 JS_PUBLIC_API(JSType)
00581 JS_TypeOfValue(JSContext *cx, jsval v)
00582 {
00583     JSType type;
00584     JSObject *obj;
00585     JSObjectOps *ops;
00586     JSClass *clasp;
00587 
00588     CHECK_REQUEST(cx);
00589     if (JSVAL_IS_OBJECT(v)) {
00590         type = JSTYPE_OBJECT;           /* XXXbe JSTYPE_NULL for JS2 */
00591         obj = JSVAL_TO_OBJECT(v);
00592         if (obj) {
00593             ops = obj->map->ops;
00594 #if JS_HAS_XML_SUPPORT
00595             if (ops == &js_XMLObjectOps.base) {
00596                 type = JSTYPE_XML;
00597             } else
00598 #endif
00599             {
00600                 /*
00601                  * ECMA 262, 11.4.3 says that any native object that implements
00602                  * [[Call]] should be of type "function". Note that RegExp and
00603                  * Script are both of type "function" for compatibility with
00604                  * older SpiderMonkeys.
00605                  */
00606                 clasp = OBJ_GET_CLASS(cx, obj);
00607                 if ((ops == &js_ObjectOps)
00608                     ? (clasp->call
00609                        ? (clasp == &js_RegExpClass || clasp == &js_ScriptClass)
00610                        : clasp == &js_FunctionClass)
00611                     : ops->call != NULL) {
00612                     type = JSTYPE_FUNCTION;
00613                 } else {
00614 #ifdef NARCISSUS
00615                     if (!OBJ_GET_PROPERTY(cx, obj,
00616                                           ATOM_TO_JSID(cx->runtime->atomState
00617                                                        .callAtom),
00618                                           &v)) {
00619                         JS_ClearPendingException(cx);
00620                     } else if (VALUE_IS_FUNCTION(cx, v)) {
00621                         type = JSTYPE_FUNCTION;
00622                     }
00623 #endif
00624                 }
00625             }
00626         }
00627     } else if (JSVAL_IS_NUMBER(v)) {
00628         type = JSTYPE_NUMBER;
00629     } else if (JSVAL_IS_STRING(v)) {
00630         type = JSTYPE_STRING;
00631     } else if (JSVAL_IS_BOOLEAN(v)) {
00632         type = JSTYPE_BOOLEAN;
00633     } else {
00634         type = JSTYPE_VOID;
00635     }
00636     return type;
00637 }
00638 
00639 JS_PUBLIC_API(const char *)
00640 JS_GetTypeName(JSContext *cx, JSType type)
00641 {
00642     if ((uintN)type >= (uintN)JSTYPE_LIMIT)
00643         return NULL;
00644     return js_type_strs[type];
00645 }
00646 
00647 /************************************************************************/
00648 
00649 JS_PUBLIC_API(JSRuntime *)
00650 JS_NewRuntime(uint32 maxbytes)
00651 {
00652     JSRuntime *rt;
00653 
00654 #ifdef DEBUG
00655     static JSBool didFirstChecks;
00656 
00657     if (!didFirstChecks) {
00658         /*
00659          * This code asserts that the numbers associated with the error names
00660          * in jsmsg.def are monotonically increasing.  It uses values for the
00661          * error names enumerated in jscntxt.c.  It's not a compile-time check
00662          * but it's better than nothing.
00663          */
00664         int errorNumber = 0;
00665 #define MSG_DEF(name, number, count, exception, format)                       \
00666     JS_ASSERT(name == errorNumber++);
00667 #include "js.msg"
00668 #undef MSG_DEF
00669 
00670 #define MSG_DEF(name, number, count, exception, format)                       \
00671     JS_BEGIN_MACRO                                                            \
00672         uintN numfmtspecs = 0;                                                \
00673         const char *fmt;                                                      \
00674         for (fmt = format; *fmt != '\0'; fmt++) {                             \
00675             if (*fmt == '{' && isdigit(fmt[1]))                               \
00676                 ++numfmtspecs;                                                \
00677         }                                                                     \
00678         JS_ASSERT(count == numfmtspecs);                                      \
00679     JS_END_MACRO;
00680 #include "js.msg"
00681 #undef MSG_DEF
00682 
00683         didFirstChecks = JS_TRUE;
00684     }
00685 #endif /* DEBUG */
00686 
00687     rt = (JSRuntime *) malloc(sizeof(JSRuntime));
00688     if (!rt)
00689         return NULL;
00690 
00691     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
00692     memset(rt, 0, sizeof(JSRuntime));
00693     JS_INIT_CLIST(&rt->contextList);
00694     JS_INIT_CLIST(&rt->trapList);
00695     JS_INIT_CLIST(&rt->watchPointList);
00696 
00697     if (!js_InitGC(rt, maxbytes))
00698         goto bad;
00699 #ifdef JS_THREADSAFE
00700     if (PR_FAILURE == PR_NewThreadPrivateIndex(&rt->threadTPIndex,
00701                                                js_ThreadDestructorCB)) {
00702         goto bad;
00703     }
00704     rt->gcLock = JS_NEW_LOCK();
00705     if (!rt->gcLock)
00706         goto bad;
00707     rt->gcDone = JS_NEW_CONDVAR(rt->gcLock);
00708     if (!rt->gcDone)
00709         goto bad;
00710     rt->requestDone = JS_NEW_CONDVAR(rt->gcLock);
00711     if (!rt->requestDone)
00712         goto bad;
00713     /* this is asymmetric with JS_ShutDown: */
00714     if (!js_SetupLocks(8, 16))
00715         goto bad;
00716     rt->rtLock = JS_NEW_LOCK();
00717     if (!rt->rtLock)
00718         goto bad;
00719     rt->stateChange = JS_NEW_CONDVAR(rt->gcLock);
00720     if (!rt->stateChange)
00721         goto bad;
00722     rt->setSlotLock = JS_NEW_LOCK();
00723     if (!rt->setSlotLock)
00724         goto bad;
00725     rt->setSlotDone = JS_NEW_CONDVAR(rt->setSlotLock);
00726     if (!rt->setSlotDone)
00727         goto bad;
00728     rt->scopeSharingDone = JS_NEW_CONDVAR(rt->gcLock);
00729     if (!rt->scopeSharingDone)
00730         goto bad;
00731     rt->scopeSharingTodo = NO_SCOPE_SHARING_TODO;
00732 #endif
00733     rt->propertyCache.empty = JS_TRUE;
00734     if (!js_InitPropertyTree(rt))
00735         goto bad;
00736     return rt;
00737 
00738 bad:
00739     JS_DestroyRuntime(rt);
00740     return NULL;
00741 }
00742 
00743 JS_PUBLIC_API(void)
00744 JS_DestroyRuntime(JSRuntime *rt)
00745 {
00746 #ifdef DEBUG
00747     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
00748     if (!JS_CLIST_IS_EMPTY(&rt->contextList)) {
00749         JSContext *cx, *iter = NULL;
00750         uintN cxcount = 0;
00751         while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL)
00752             cxcount++;
00753         fprintf(stderr,
00754 "JS API usage error: %u contexts left in runtime upon JS_DestroyRuntime.\n",
00755                 cxcount);
00756     }
00757 #endif
00758 
00759     js_FreeRuntimeScriptState(rt);
00760     js_FinishAtomState(&rt->atomState);
00761     js_FinishGC(rt);
00762 #ifdef JS_THREADSAFE
00763     if (rt->gcLock)
00764         JS_DESTROY_LOCK(rt->gcLock);
00765     if (rt->gcDone)
00766         JS_DESTROY_CONDVAR(rt->gcDone);
00767     if (rt->requestDone)
00768         JS_DESTROY_CONDVAR(rt->requestDone);
00769     if (rt->rtLock)
00770         JS_DESTROY_LOCK(rt->rtLock);
00771     if (rt->stateChange)
00772         JS_DESTROY_CONDVAR(rt->stateChange);
00773     if (rt->setSlotLock)
00774         JS_DESTROY_LOCK(rt->setSlotLock);
00775     if (rt->setSlotDone)
00776         JS_DESTROY_CONDVAR(rt->setSlotDone);
00777     if (rt->scopeSharingDone)
00778         JS_DESTROY_CONDVAR(rt->scopeSharingDone);
00779 #else
00780     GSN_CACHE_CLEAR(&rt->gsnCache);
00781 #endif
00782     js_FinishPropertyTree(rt);
00783     free(rt);
00784 }
00785 
00786 JS_PUBLIC_API(void)
00787 JS_ShutDown(void)
00788 {
00789     js_FinishDtoa();
00790 #ifdef JS_THREADSAFE
00791     js_CleanupLocks();
00792 #endif
00793 }
00794 
00795 JS_PUBLIC_API(void *)
00796 JS_GetRuntimePrivate(JSRuntime *rt)
00797 {
00798     return rt->data;
00799 }
00800 
00801 JS_PUBLIC_API(void)
00802 JS_SetRuntimePrivate(JSRuntime *rt, void *data)
00803 {
00804     rt->data = data;
00805 }
00806 
00807 #ifdef JS_THREADSAFE
00808 
00809 JS_PUBLIC_API(void)
00810 JS_BeginRequest(JSContext *cx)
00811 {
00812     JSRuntime *rt;
00813 
00814     JS_ASSERT(cx->thread->id == js_CurrentThreadId());
00815     if (!cx->requestDepth) {
00816         /* Wait until the GC is finished. */
00817         rt = cx->runtime;
00818         JS_LOCK_GC(rt);
00819 
00820         /* NB: we use cx->thread here, not js_GetCurrentThread(). */
00821         if (rt->gcThread != cx->thread) {
00822             while (rt->gcLevel > 0)
00823                 JS_AWAIT_GC_DONE(rt);
00824         }
00825 
00826         /* Indicate that a request is running. */
00827         rt->requestCount++;
00828         cx->requestDepth = 1;
00829         JS_UNLOCK_GC(rt);
00830         return;
00831     }
00832     cx->requestDepth++;
00833 }
00834 
00835 JS_PUBLIC_API(void)
00836 JS_EndRequest(JSContext *cx)
00837 {
00838     JSRuntime *rt;
00839     JSScope *scope, **todop;
00840     uintN nshares;
00841 
00842     CHECK_REQUEST(cx);
00843     JS_ASSERT(cx->requestDepth > 0);
00844     if (cx->requestDepth == 1) {
00845         /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
00846         rt = cx->runtime;
00847         JS_LOCK_GC(rt);
00848         cx->requestDepth = 0;
00849 
00850         /* See whether cx has any single-threaded scopes to start sharing. */
00851         todop = &rt->scopeSharingTodo;
00852         nshares = 0;
00853         while ((scope = *todop) != NO_SCOPE_SHARING_TODO) {
00854             if (scope->ownercx != cx) {
00855                 todop = &scope->u.link;
00856                 continue;
00857             }
00858             *todop = scope->u.link;
00859             scope->u.link = NULL;       /* null u.link for sanity ASAP */
00860 
00861             /*
00862              * If js_DropObjectMap returns null, we held the last ref to scope.
00863              * The waiting thread(s) must have been killed, after which the GC
00864              * collected the object that held this scope.  Unlikely, because it
00865              * requires that the GC ran (e.g., from a branch callback) during
00866              * this request, but possible.
00867              */
00868             if (js_DropObjectMap(cx, &scope->map, NULL)) {
00869                 js_InitLock(&scope->lock);
00870                 scope->u.count = 0;                 /* NULL may not pun as 0 */
00871                 js_FinishSharingScope(rt, scope);   /* set ownercx = NULL */
00872                 nshares++;
00873             }
00874         }
00875         if (nshares)
00876             JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone);
00877 
00878         /* Give the GC a chance to run if this was the last request running. */
00879         JS_ASSERT(rt->requestCount > 0);
00880         rt->requestCount--;
00881         if (rt->requestCount == 0)
00882             JS_NOTIFY_REQUEST_DONE(rt);
00883 
00884         JS_UNLOCK_GC(rt);
00885         return;
00886     }
00887 
00888     cx->requestDepth--;
00889 }
00890 
00891 /* Yield to pending GC operations, regardless of request depth */
00892 JS_PUBLIC_API(void)
00893 JS_YieldRequest(JSContext *cx)
00894 {
00895     JSRuntime *rt;
00896 
00897     JS_ASSERT(cx->thread);
00898     CHECK_REQUEST(cx);
00899 
00900     rt = cx->runtime;
00901     JS_LOCK_GC(rt);
00902     JS_ASSERT(rt->requestCount > 0);
00903     rt->requestCount--;
00904     if (rt->requestCount == 0)
00905         JS_NOTIFY_REQUEST_DONE(rt);
00906     JS_UNLOCK_GC(rt);
00907     /* XXXbe give the GC or another request calling it a chance to run here?
00908              Assumes FIFO scheduling */
00909     JS_LOCK_GC(rt);
00910     if (rt->gcThread != cx->thread) {
00911         while (rt->gcLevel > 0)
00912             JS_AWAIT_GC_DONE(rt);
00913     }
00914     rt->requestCount++;
00915     JS_UNLOCK_GC(rt);
00916 }
00917 
00918 JS_PUBLIC_API(jsrefcount)
00919 JS_SuspendRequest(JSContext *cx)
00920 {
00921     jsrefcount saveDepth = cx->requestDepth;
00922 
00923     while (cx->requestDepth)
00924         JS_EndRequest(cx);
00925     return saveDepth;
00926 }
00927 
00928 JS_PUBLIC_API(void)
00929 JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
00930 {
00931     JS_ASSERT(!cx->requestDepth);
00932     while (--saveDepth >= 0)
00933         JS_BeginRequest(cx);
00934 }
00935 
00936 #endif /* JS_THREADSAFE */
00937 
00938 JS_PUBLIC_API(void)
00939 JS_Lock(JSRuntime *rt)
00940 {
00941     JS_LOCK_RUNTIME(rt);
00942 }
00943 
00944 JS_PUBLIC_API(void)
00945 JS_Unlock(JSRuntime *rt)
00946 {
00947     JS_UNLOCK_RUNTIME(rt);
00948 }
00949 
00950 JS_PUBLIC_API(JSContextCallback)
00951 JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
00952 {
00953     JSContextCallback old;
00954 
00955     old = rt->cxCallback;
00956     rt->cxCallback = cxCallback;
00957     return old;
00958 }
00959 
00960 JS_PUBLIC_API(JSContext *)
00961 JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
00962 {
00963     return js_NewContext(rt, stackChunkSize);
00964 }
00965 
00966 JS_PUBLIC_API(void)
00967 JS_DestroyContext(JSContext *cx)
00968 {
00969     js_DestroyContext(cx, JSDCM_FORCE_GC);
00970 }
00971 
00972 JS_PUBLIC_API(void)
00973 JS_DestroyContextNoGC(JSContext *cx)
00974 {
00975     js_DestroyContext(cx, JSDCM_NO_GC);
00976 }
00977 
00978 JS_PUBLIC_API(void)
00979 JS_DestroyContextMaybeGC(JSContext *cx)
00980 {
00981     js_DestroyContext(cx, JSDCM_MAYBE_GC);
00982 }
00983 
00984 JS_PUBLIC_API(void *)
00985 JS_GetContextPrivate(JSContext *cx)
00986 {
00987     return cx->data;
00988 }
00989 
00990 JS_PUBLIC_API(void)
00991 JS_SetContextPrivate(JSContext *cx, void *data)
00992 {
00993     cx->data = data;
00994 }
00995 
00996 JS_PUBLIC_API(JSRuntime *)
00997 JS_GetRuntime(JSContext *cx)
00998 {
00999     return cx->runtime;
01000 }
01001 
01002 JS_PUBLIC_API(JSContext *)
01003 JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
01004 {
01005     return js_ContextIterator(rt, JS_TRUE, iterp);
01006 }
01007 
01008 JS_PUBLIC_API(JSVersion)
01009 JS_GetVersion(JSContext *cx)
01010 {
01011     return cx->version & JSVERSION_MASK;
01012 }
01013 
01014 JS_PUBLIC_API(JSVersion)
01015 JS_SetVersion(JSContext *cx, JSVersion version)
01016 {
01017     JSVersion oldVersion;
01018 
01019     JS_ASSERT(version != JSVERSION_UNKNOWN);
01020     JS_ASSERT((version & ~JSVERSION_MASK) == 0);
01021 
01022     oldVersion = cx->version & JSVERSION_MASK;
01023     if (version == oldVersion)
01024         return oldVersion;
01025 
01026     /* We no longer support 1.4 or below. */
01027     if (version != JSVERSION_DEFAULT && version <= JSVERSION_1_4)
01028         return oldVersion;
01029 
01030     cx->version = (cx->version & ~JSVERSION_MASK) | version;
01031     js_OnVersionChange(cx);
01032     return oldVersion;
01033 }
01034 
01035 static struct v2smap {
01036     JSVersion   version;
01037     const char  *string;
01038 } v2smap[] = {
01039     {JSVERSION_1_0,     "1.0"},
01040     {JSVERSION_1_1,     "1.1"},
01041     {JSVERSION_1_2,     "1.2"},
01042     {JSVERSION_1_3,     "1.3"},
01043     {JSVERSION_1_4,     "1.4"},
01044     {JSVERSION_ECMA_3,  "ECMAv3"},
01045     {JSVERSION_1_5,     "1.5"},
01046     {JSVERSION_1_6,     "1.6"},
01047     {JSVERSION_1_7,     "1.7"},
01048     {JSVERSION_DEFAULT, js_default_str},
01049     {JSVERSION_UNKNOWN, NULL},          /* must be last, NULL is sentinel */
01050 };
01051 
01052 JS_PUBLIC_API(const char *)
01053 JS_VersionToString(JSVersion version)
01054 {
01055     int i;
01056 
01057     for (i = 0; v2smap[i].string; i++)
01058         if (v2smap[i].version == version)
01059             return v2smap[i].string;
01060     return "unknown";
01061 }
01062 
01063 JS_PUBLIC_API(JSVersion)
01064 JS_StringToVersion(const char *string)
01065 {
01066     int i;
01067 
01068     for (i = 0; v2smap[i].string; i++)
01069         if (strcmp(v2smap[i].string, string) == 0)
01070             return v2smap[i].version;
01071     return JSVERSION_UNKNOWN;
01072 }
01073 
01074 JS_PUBLIC_API(uint32)
01075 JS_GetOptions(JSContext *cx)
01076 {
01077     return cx->options;
01078 }
01079 
01080 #define SYNC_OPTIONS_TO_VERSION(cx)                                           \
01081     JS_BEGIN_MACRO                                                            \
01082         if ((cx)->options & JSOPTION_XML)                                     \
01083             (cx)->version |= JSVERSION_HAS_XML;                               \
01084         else                                                                  \
01085             (cx)->version &= ~JSVERSION_HAS_XML;                              \
01086     JS_END_MACRO
01087 
01088 JS_PUBLIC_API(uint32)
01089 JS_SetOptions(JSContext *cx, uint32 options)
01090 {
01091     uint32 oldopts = cx->options;
01092     cx->options = options;
01093     SYNC_OPTIONS_TO_VERSION(cx);
01094     return oldopts;
01095 }
01096 
01097 JS_PUBLIC_API(uint32)
01098 JS_ToggleOptions(JSContext *cx, uint32 options)
01099 {
01100     uint32 oldopts = cx->options;
01101     cx->options ^= options;
01102     SYNC_OPTIONS_TO_VERSION(cx);
01103     return oldopts;
01104 }
01105 
01106 JS_PUBLIC_API(const char *)
01107 JS_GetImplementationVersion(void)
01108 {
01109     return "JavaScript-C 1.7.0 2007-10-03";
01110 }
01111 
01112 
01113 JS_PUBLIC_API(JSObject *)
01114 JS_GetGlobalObject(JSContext *cx)
01115 {
01116     return cx->globalObject;
01117 }
01118 
01119 JS_PUBLIC_API(void)
01120 JS_SetGlobalObject(JSContext *cx, JSObject *obj)
01121 {
01122     cx->globalObject = obj;
01123 
01124 #if JS_HAS_XML_SUPPORT
01125     cx->xmlSettingFlags = 0;
01126 #endif
01127 }
01128 
01129 JSObject *
01130 js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
01131 {
01132     JSDHashTable *table;
01133     JSBool resolving;
01134     JSRuntime *rt;
01135     JSResolvingKey key;
01136     JSResolvingEntry *entry;
01137     JSObject *fun_proto, *obj_proto;
01138 
01139     /* If cx has no global object, use obj so prototypes can be found. */
01140     if (!cx->globalObject)
01141         JS_SetGlobalObject(cx, obj);
01142 
01143     /* Record Function and Object in cx->resolvingTable, if we are resolving. */
01144     table = cx->resolvingTable;
01145     resolving = (table && table->entryCount);
01146     rt = cx->runtime;
01147     key.obj = obj;
01148     if (resolving) {
01149         key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]);
01150         entry = (JSResolvingEntry *)
01151                 JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
01152         if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) {
01153             /* Already resolving Function, record Object too. */
01154             JS_ASSERT(entry->key.obj == obj);
01155             key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
01156             entry = (JSResolvingEntry *)
01157                     JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
01158         }
01159         if (!entry) {
01160             JS_ReportOutOfMemory(cx);
01161             return NULL;
01162         }
01163         JS_ASSERT(!entry->key.obj && entry->flags == 0);
01164         entry->key = key;
01165         entry->flags = JSRESFLAG_LOOKUP;
01166     } else {
01167         key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
01168         if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry))
01169             return NULL;
01170 
01171         key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]);
01172         if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) {
01173             key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
01174             JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
01175             return NULL;
01176         }
01177 
01178         table = cx->resolvingTable;
01179     }
01180 
01181     /* Initialize the function class first so constructors can be made. */
01182     fun_proto = js_InitFunctionClass(cx, obj);
01183     if (!fun_proto)
01184         goto out;
01185 
01186     /* Initialize the object class next so Object.prototype works. */
01187     obj_proto = js_InitObjectClass(cx, obj);
01188     if (!obj_proto) {
01189         fun_proto = NULL;
01190         goto out;
01191     }
01192 
01193     /* Function.prototype and the global object delegate to Object.prototype. */
01194     OBJ_SET_PROTO(cx, fun_proto, obj_proto);
01195     if (!OBJ_GET_PROTO(cx, obj))
01196         OBJ_SET_PROTO(cx, obj, obj_proto);
01197 
01198 out:
01199     /* If resolving, remove the other entry (Object or Function) from table. */
01200     JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
01201     if (!resolving) {
01202         /* If not resolving, remove the first entry added above, for Object. */
01203         JS_ASSERT(key.id ==                                                   \
01204                   ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]));
01205         key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
01206         JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
01207     }
01208     return fun_proto;
01209 }
01210 
01211 JS_PUBLIC_API(JSBool)
01212 JS_InitStandardClasses(JSContext *cx, JSObject *obj)
01213 {
01214     JSAtom *atom;
01215 
01216     CHECK_REQUEST(cx);
01217 
01218     /* Define a top-level property 'undefined' with the undefined value. */
01219     atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
01220     if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
01221                              NULL, NULL, JSPROP_PERMANENT, NULL)) {
01222         return JS_FALSE;
01223     }
01224 
01225     /* Function and Object require cooperative bootstrapping magic. */
01226     if (!js_InitFunctionAndObjectClasses(cx, obj))
01227         return JS_FALSE;
01228 
01229     /* Initialize the rest of the standard objects and functions. */
01230     return js_InitArrayClass(cx, obj) &&
01231            js_InitBlockClass(cx, obj) &&
01232            js_InitBooleanClass(cx, obj) &&
01233            js_InitCallClass(cx, obj) &&
01234            js_InitExceptionClasses(cx, obj) &&
01235            js_InitMathClass(cx, obj) &&
01236            js_InitNumberClass(cx, obj) &&
01237            js_InitRegExpClass(cx, obj) &&
01238            js_InitStringClass(cx, obj) &&
01239 #if JS_HAS_SCRIPT_OBJECT
01240            js_InitScriptClass(cx, obj) &&
01241 #endif
01242 #if JS_HAS_XML_SUPPORT
01243            js_InitXMLClasses(cx, obj) &&
01244 #endif
01245 #if JS_HAS_FILE_OBJECT
01246            js_InitFileClass(cx, obj) &&
01247 #endif
01248 #if JS_HAS_GENERATORS
01249            js_InitIteratorClasses(cx, obj) &&
01250 #endif
01251            js_InitDateClass(cx, obj);
01252 }
01253 
01254 #define ATOM_OFFSET(name)       offsetof(JSAtomState,name##Atom)
01255 #define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState,classAtoms[JSProto_##name])
01256 #define OFFSET_TO_ATOM(rt,off)  (*(JSAtom **)((char*)&(rt)->atomState + (off)))
01257 #define CLASP(name)             (JSClass *)&js_##name##Class
01258 
01259 #define EAGER_ATOM(name)            ATOM_OFFSET(name), NULL
01260 #define EAGER_CLASS_ATOM(name)      CLASS_ATOM_OFFSET(name), NULL
01261 #define EAGER_ATOM_AND_CLASP(name)  EAGER_CLASS_ATOM(name), CLASP(name)
01262 #define LAZY_ATOM(name)             ATOM_OFFSET(lazy.name), js_##name##_str
01263 
01264 typedef struct JSStdName {
01265     JSObjectOp  init;
01266     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
01267     const char  *name;          /* null if atom is pre-pinned, else name */
01268     JSClass     *clasp;
01269 } JSStdName;
01270 
01271 static JSAtom *
01272 StdNameToAtom(JSContext *cx, JSStdName *stdn)
01273 {
01274     size_t offset;
01275     JSAtom *atom;
01276     const char *name;
01277 
01278     offset = stdn->atomOffset;
01279     atom = OFFSET_TO_ATOM(cx->runtime, offset);
01280     if (!atom) {
01281         name = stdn->name;
01282         if (name) {
01283             atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED);
01284             OFFSET_TO_ATOM(cx->runtime, offset) = atom;
01285         }
01286     }
01287     return atom;
01288 }
01289 
01290 /*
01291  * Table of class initializers and their atom offsets in rt->atomState.
01292  * If you add a "standard" class, remember to update this table.
01293  */
01294 static JSStdName standard_class_atoms[] = {
01295     {js_InitFunctionAndObjectClasses,   EAGER_ATOM_AND_CLASP(Function)},
01296     {js_InitFunctionAndObjectClasses,   EAGER_ATOM_AND_CLASP(Object)},
01297     {js_InitArrayClass,                 EAGER_ATOM_AND_CLASP(Array)},
01298     {js_InitBlockClass,                 EAGER_ATOM_AND_CLASP(Block)},
01299     {js_InitBooleanClass,               EAGER_ATOM_AND_CLASP(Boolean)},
01300     {js_InitDateClass,                  EAGER_ATOM_AND_CLASP(Date)},
01301     {js_InitMathClass,                  EAGER_ATOM_AND_CLASP(Math)},
01302     {js_InitNumberClass,                EAGER_ATOM_AND_CLASP(Number)},
01303     {js_InitStringClass,                EAGER_ATOM_AND_CLASP(String)},
01304     {js_InitCallClass,                  EAGER_ATOM_AND_CLASP(Call)},
01305     {js_InitExceptionClasses,           EAGER_ATOM_AND_CLASP(Error)},
01306     {js_InitRegExpClass,                EAGER_ATOM_AND_CLASP(RegExp)},
01307 #if JS_HAS_SCRIPT_OBJECT
01308     {js_InitScriptClass,                EAGER_ATOM_AND_CLASP(Script)},
01309 #endif
01310 #if JS_HAS_XML_SUPPORT
01311     {js_InitXMLClass,                   EAGER_ATOM_AND_CLASP(XML)},
01312     {js_InitNamespaceClass,             EAGER_ATOM_AND_CLASP(Namespace)},
01313     {js_InitQNameClass,                 EAGER_ATOM_AND_CLASP(QName)},
01314 #endif
01315 #if JS_HAS_FILE_OBJECT
01316     {js_InitFileClass,                  EAGER_ATOM_AND_CLASP(File)},
01317 #endif
01318 #if JS_HAS_GENERATORS
01319     {js_InitIteratorClasses,            EAGER_ATOM_AND_CLASP(StopIteration)},
01320 #endif
01321     {NULL,                              0, NULL, NULL}
01322 };
01323 
01324 /*
01325  * Table of top-level function and constant names and their init functions.
01326  * If you add a "standard" global function or property, remember to update
01327  * this table.
01328  */
01329 static JSStdName standard_class_names[] = {
01330     /* ECMA requires that eval be a direct property of the global object. */
01331     {js_InitObjectClass,        EAGER_ATOM(eval), NULL},
01332 
01333     /* Global properties and functions defined by the Number class. */
01334     {js_InitNumberClass,        LAZY_ATOM(NaN), NULL},
01335     {js_InitNumberClass,        LAZY_ATOM(Infinity), NULL},
01336     {js_InitNumberClass,        LAZY_ATOM(isNaN), NULL},
01337     {js_InitNumberClass,        LAZY_ATOM(isFinite), NULL},
01338     {js_InitNumberClass,        LAZY_ATOM(parseFloat), NULL},
01339     {js_InitNumberClass,        LAZY_ATOM(parseInt), NULL},
01340 
01341     /* String global functions. */
01342     {js_InitStringClass,        LAZY_ATOM(escape), NULL},
01343     {js_InitStringClass,        LAZY_ATOM(unescape), NULL},
01344     {js_InitStringClass,        LAZY_ATOM(decodeURI), NULL},
01345     {js_InitStringClass,        LAZY_ATOM(encodeURI), NULL},
01346     {js_InitStringClass,        LAZY_ATOM(decodeURIComponent), NULL},
01347     {js_InitStringClass,        LAZY_ATOM(encodeURIComponent), NULL},
01348 #if JS_HAS_UNEVAL
01349     {js_InitStringClass,        LAZY_ATOM(uneval), NULL},
01350 #endif
01351 
01352     /* Exception constructors. */
01353     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(Error), CLASP(Error)},
01354     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(InternalError), CLASP(Error)},
01355     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(EvalError), CLASP(Error)},
01356     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(RangeError), CLASP(Error)},
01357     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)},
01358     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)},
01359     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(TypeError), CLASP(Error)},
01360     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(URIError), CLASP(Error)},
01361 
01362 #if JS_HAS_XML_SUPPORT
01363     {js_InitAnyNameClass,       EAGER_ATOM_AND_CLASP(AnyName)},
01364     {js_InitAttributeNameClass, EAGER_ATOM_AND_CLASP(AttributeName)},
01365     {js_InitXMLClass,           LAZY_ATOM(XMLList), &js_XMLClass},
01366     {js_InitXMLClass,           LAZY_ATOM(isXMLName), NULL},
01367 #endif
01368 
01369 #if JS_HAS_GENERATORS
01370     {js_InitIteratorClasses,    EAGER_ATOM_AND_CLASP(Iterator)},
01371     {js_InitIteratorClasses,    EAGER_ATOM_AND_CLASP(Generator)},
01372 #endif
01373 
01374     {NULL,                      0, NULL, NULL}
01375 };
01376 
01377 static JSStdName object_prototype_names[] = {
01378     /* Object.prototype properties (global delegates to Object.prototype). */
01379     {js_InitObjectClass,        EAGER_ATOM(proto), NULL},
01380     {js_InitObjectClass,        EAGER_ATOM(parent), NULL},
01381     {js_InitObjectClass,        EAGER_ATOM(count), NULL},
01382 #if JS_HAS_TOSOURCE
01383     {js_InitObjectClass,        EAGER_ATOM(toSource), NULL},
01384 #endif
01385     {js_InitObjectClass,        EAGER_ATOM(toString), NULL},
01386     {js_InitObjectClass,        EAGER_ATOM(toLocaleString), NULL},
01387     {js_InitObjectClass,        EAGER_ATOM(valueOf), NULL},
01388 #if JS_HAS_OBJ_WATCHPOINT
01389     {js_InitObjectClass,        LAZY_ATOM(watch), NULL},
01390     {js_InitObjectClass,        LAZY_ATOM(unwatch), NULL},
01391 #endif
01392     {js_InitObjectClass,        LAZY_ATOM(hasOwnProperty), NULL},
01393     {js_InitObjectClass,        LAZY_ATOM(isPrototypeOf), NULL},
01394     {js_InitObjectClass,        LAZY_ATOM(propertyIsEnumerable), NULL},
01395 #if JS_HAS_GETTER_SETTER
01396     {js_InitObjectClass,        LAZY_ATOM(defineGetter), NULL},
01397     {js_InitObjectClass,        LAZY_ATOM(defineSetter), NULL},
01398     {js_InitObjectClass,        LAZY_ATOM(lookupGetter), NULL},
01399     {js_InitObjectClass,        LAZY_ATOM(lookupSetter), NULL},
01400 #endif
01401 
01402     {NULL,                      0, NULL, NULL}
01403 };
01404 
01405 JS_PUBLIC_API(JSBool)
01406 JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
01407                         JSBool *resolved)
01408 {
01409     JSString *idstr;
01410     JSRuntime *rt;
01411     JSAtom *atom;
01412     JSStdName *stdnm;
01413     uintN i;
01414 
01415     CHECK_REQUEST(cx);
01416     *resolved = JS_FALSE;
01417 
01418     if (!JSVAL_IS_STRING(id))
01419         return JS_TRUE;
01420     idstr = JSVAL_TO_STRING(id);
01421     rt = cx->runtime;
01422 
01423     /* Check whether we're resolving 'undefined', and define it if so. */
01424     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
01425     if (idstr == ATOM_TO_STRING(atom)) {
01426         *resolved = JS_TRUE;
01427         return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
01428                                    NULL, NULL, JSPROP_PERMANENT, NULL);
01429     }
01430 
01431     /* Try for class constructors/prototypes named by well-known atoms. */
01432     stdnm = NULL;
01433     for (i = 0; standard_class_atoms[i].init; i++) {
01434         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
01435         if (idstr == ATOM_TO_STRING(atom)) {
01436             stdnm = &standard_class_atoms[i];
01437             break;
01438         }
01439     }
01440 
01441     if (!stdnm) {
01442         /* Try less frequently used top-level functions and constants. */
01443         for (i = 0; standard_class_names[i].init; i++) {
01444             atom = StdNameToAtom(cx, &standard_class_names[i]);
01445             if (!atom)
01446                 return JS_FALSE;
01447             if (idstr == ATOM_TO_STRING(atom)) {
01448                 stdnm = &standard_class_names[i];
01449                 break;
01450             }
01451         }
01452 
01453         if (!stdnm && !OBJ_GET_PROTO(cx, obj)) {
01454             /*
01455              * Try even less frequently used names delegated from the global
01456              * object to Object.prototype, but only if the Object class hasn't
01457              * yet been initialized.
01458              */
01459             for (i = 0; object_prototype_names[i].init; i++) {
01460                 atom = StdNameToAtom(cx, &object_prototype_names[i]);
01461                 if (!atom)
01462                     return JS_FALSE;
01463                 if (idstr == ATOM_TO_STRING(atom)) {
01464                     stdnm = &standard_class_names[i];
01465                     break;
01466                 }
01467             }
01468         }
01469     }
01470 
01471     if (stdnm) {
01472         /*
01473          * If this standard class is anonymous and obj advertises itself as a
01474          * global object (in order to reserve slots for standard class object
01475          * pointers), then we don't want to resolve by name.
01476          *
01477          * If inversely, either id does not name a class, or id does not name
01478          * an anonymous class, or the global does not reserve slots for class
01479          * objects, then we must call the init hook here.
01480          */
01481         if (stdnm->clasp &&
01482             (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS) &&
01483             (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL)) {
01484             return JS_TRUE;
01485         }
01486 
01487         if (!stdnm->init(cx, obj))
01488             return JS_FALSE;
01489         *resolved = JS_TRUE;
01490     }
01491     return JS_TRUE;
01492 }
01493 
01494 static JSBool
01495 AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom)
01496 {
01497     JSScopeProperty *sprop;
01498     JSScope *scope;
01499 
01500     JS_ASSERT(OBJ_IS_NATIVE(obj));
01501     JS_LOCK_OBJ(cx, obj);
01502     scope = OBJ_SCOPE(obj);
01503     sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
01504     JS_UNLOCK_SCOPE(cx, scope);
01505     return sprop != NULL;
01506 }
01507 
01508 JS_PUBLIC_API(JSBool)
01509 JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
01510 {
01511     JSRuntime *rt;
01512     JSAtom *atom;
01513     uintN i;
01514 
01515     CHECK_REQUEST(cx);
01516     rt = cx->runtime;
01517 
01518     /* Check whether we need to bind 'undefined' and define it if so. */
01519     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
01520     if (!AlreadyHasOwnProperty(cx, obj, atom) &&
01521         !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
01522                              NULL, NULL, JSPROP_PERMANENT, NULL)) {
01523         return JS_FALSE;
01524     }
01525 
01526     /* Initialize any classes that have not been resolved yet. */
01527     for (i = 0; standard_class_atoms[i].init; i++) {
01528         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
01529         if (!AlreadyHasOwnProperty(cx, obj, atom) &&
01530             !standard_class_atoms[i].init(cx, obj)) {
01531             return JS_FALSE;
01532         }
01533     }
01534 
01535     return JS_TRUE;
01536 }
01537 
01538 static JSIdArray *
01539 AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip)
01540 {
01541     jsint i, length;
01542 
01543     i = *ip;
01544     length = ida->length;
01545     if (i >= length) {
01546         ida = js_SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8));
01547         if (!ida)
01548             return NULL;
01549         JS_ASSERT(i < ida->length);
01550     }
01551     ida->vector[i] = ATOM_TO_JSID(atom);
01552     *ip = i + 1;
01553     return ida;
01554 }
01555 
01556 static JSIdArray *
01557 EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
01558                     jsint *ip, JSBool *foundp)
01559 {
01560     *foundp = AlreadyHasOwnProperty(cx, obj, atom);
01561     if (*foundp)
01562         ida = AddAtomToArray(cx, atom, ida, ip);
01563     return ida;
01564 }
01565 
01566 JS_PUBLIC_API(JSIdArray *)
01567 JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
01568                                     JSIdArray *ida)
01569 {
01570     JSRuntime *rt;
01571     jsint i, j, k;
01572     JSAtom *atom;
01573     JSBool found;
01574     JSObjectOp init;
01575 
01576     CHECK_REQUEST(cx);
01577     rt = cx->runtime;
01578     if (ida) {
01579         i = ida->length;
01580     } else {
01581         ida = js_NewIdArray(cx, 8);
01582         if (!ida)
01583             return NULL;
01584         i = 0;
01585     }
01586 
01587     /* Check whether 'undefined' has been resolved and enumerate it if so. */
01588     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
01589     ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
01590     if (!ida)
01591         return NULL;
01592 
01593     /* Enumerate only classes that *have* been resolved. */
01594     for (j = 0; standard_class_atoms[j].init; j++) {
01595         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
01596         ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
01597         if (!ida)
01598             return NULL;
01599 
01600         if (found) {
01601             init = standard_class_atoms[j].init;
01602 
01603             for (k = 0; standard_class_names[k].init; k++) {
01604                 if (standard_class_names[k].init == init) {
01605                     atom = StdNameToAtom(cx, &standard_class_names[k]);
01606                     ida = AddAtomToArray(cx, atom, ida, &i);
01607                     if (!ida)
01608                         return NULL;
01609                 }
01610             }
01611 
01612             if (init == js_InitObjectClass) {
01613                 for (k = 0; object_prototype_names[k].init; k++) {
01614                     atom = StdNameToAtom(cx, &object_prototype_names[k]);
01615                     ida = AddAtomToArray(cx, atom, ida, &i);
01616                     if (!ida)
01617                         return NULL;
01618                 }
01619             }
01620         }
01621     }
01622 
01623     /* Trim to exact length via js_SetIdArrayLength. */
01624     return js_SetIdArrayLength(cx, ida, i);
01625 }
01626 
01627 #undef ATOM_OFFSET
01628 #undef CLASS_ATOM_OFFSET
01629 #undef OFFSET_TO_ATOM
01630 #undef CLASP
01631 
01632 #undef EAGER_ATOM
01633 #undef EAGER_CLASS_ATOM
01634 #undef EAGER_ATOM_CLASP
01635 #undef LAZY_ATOM
01636 
01637 JS_PUBLIC_API(JSBool)
01638 JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
01639                   JSObject **objp)
01640 {
01641     CHECK_REQUEST(cx);
01642     return js_GetClassObject(cx, obj, key, objp);
01643 }
01644 
01645 JS_PUBLIC_API(JSObject *)
01646 JS_GetScopeChain(JSContext *cx)
01647 {
01648     JSStackFrame *fp;
01649 
01650     fp = cx->fp;
01651     if (!fp) {
01652         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
01653         return NULL;
01654     }
01655     return js_GetScopeChain(cx, fp);
01656 }
01657 
01658 JS_PUBLIC_API(void *)
01659 JS_malloc(JSContext *cx, size_t nbytes)
01660 {
01661     void *p;
01662 
01663     JS_ASSERT(nbytes != 0);
01664     if (nbytes == 0)
01665         nbytes = 1;
01666 
01667     p = malloc(nbytes);
01668     if (!p) {
01669         JS_ReportOutOfMemory(cx);
01670         return NULL;
01671     }
01672     js_UpdateMallocCounter(cx, nbytes);
01673 
01674     return p;
01675 }
01676 
01677 JS_PUBLIC_API(void *)
01678 JS_realloc(JSContext *cx, void *p, size_t nbytes)
01679 {
01680     p = realloc(p, nbytes);
01681     if (!p)
01682         JS_ReportOutOfMemory(cx);
01683     return p;
01684 }
01685 
01686 JS_PUBLIC_API(void)
01687 JS_free(JSContext *cx, void *p)
01688 {
01689     if (p)
01690         free(p);
01691 }
01692 
01693 JS_PUBLIC_API(char *)
01694 JS_strdup(JSContext *cx, const char *s)
01695 {
01696     size_t n;
01697     void *p;
01698 
01699     n = strlen(s) + 1;
01700     p = JS_malloc(cx, n);
01701     if (!p)
01702         return NULL;
01703     return (char *)memcpy(p, s, n);
01704 }
01705 
01706 JS_PUBLIC_API(jsdouble *)
01707 JS_NewDouble(JSContext *cx, jsdouble d)
01708 {
01709     CHECK_REQUEST(cx);
01710     return js_NewDouble(cx, d, 0);
01711 }
01712 
01713 JS_PUBLIC_API(JSBool)
01714 JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
01715 {
01716     CHECK_REQUEST(cx);
01717     return js_NewDoubleValue(cx, d, rval);
01718 }
01719 
01720 JS_PUBLIC_API(JSBool)
01721 JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
01722 {
01723     CHECK_REQUEST(cx);
01724     return js_NewNumberValue(cx, d, rval);
01725 }
01726 
01727 #undef JS_AddRoot
01728 JS_PUBLIC_API(JSBool)
01729 JS_AddRoot(JSContext *cx, void *rp)
01730 {
01731     CHECK_REQUEST(cx);
01732     return js_AddRoot(cx, rp, NULL);
01733 }
01734 
01735 JS_PUBLIC_API(JSBool)
01736 JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name)
01737 {
01738     return js_AddRootRT(rt, rp, name);
01739 }
01740 
01741 JS_PUBLIC_API(JSBool)
01742 JS_RemoveRoot(JSContext *cx, void *rp)
01743 {
01744     CHECK_REQUEST(cx);
01745     return js_RemoveRoot(cx->runtime, rp);
01746 }
01747 
01748 JS_PUBLIC_API(JSBool)
01749 JS_RemoveRootRT(JSRuntime *rt, void *rp)
01750 {
01751     return js_RemoveRoot(rt, rp);
01752 }
01753 
01754 JS_PUBLIC_API(JSBool)
01755 JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
01756 {
01757     CHECK_REQUEST(cx);
01758     return js_AddRoot(cx, rp, name);
01759 }
01760 
01761 JS_PUBLIC_API(void)
01762 JS_ClearNewbornRoots(JSContext *cx)
01763 {
01764     JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
01765 }
01766 
01767 JS_PUBLIC_API(JSBool)
01768 JS_EnterLocalRootScope(JSContext *cx)
01769 {
01770     CHECK_REQUEST(cx);
01771     return js_EnterLocalRootScope(cx);
01772 }
01773 
01774 JS_PUBLIC_API(void)
01775 JS_LeaveLocalRootScope(JSContext *cx)
01776 {
01777     CHECK_REQUEST(cx);
01778     js_LeaveLocalRootScope(cx);
01779 }
01780 
01781 JS_PUBLIC_API(void)
01782 JS_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
01783 {
01784     CHECK_REQUEST(cx);
01785     js_LeaveLocalRootScopeWithResult(cx, rval);
01786 }
01787 
01788 JS_PUBLIC_API(void)
01789 JS_ForgetLocalRoot(JSContext *cx, void *thing)
01790 {
01791     CHECK_REQUEST(cx);
01792     js_ForgetLocalRoot(cx, (jsval) thing);
01793 }
01794 
01795 #ifdef DEBUG
01796 
01797 JS_PUBLIC_API(void)
01798 JS_DumpNamedRoots(JSRuntime *rt,
01799                   void (*dump)(const char *name, void *rp, void *data),
01800                   void *data)
01801 {
01802     js_DumpNamedRoots(rt, dump, data);
01803 }
01804 
01805 #endif /* DEBUG */
01806 
01807 JS_PUBLIC_API(uint32)
01808 JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
01809 {
01810     return js_MapGCRoots(rt, map, data);
01811 }
01812 
01813 JS_PUBLIC_API(JSBool)
01814 JS_LockGCThing(JSContext *cx, void *thing)
01815 {
01816     JSBool ok;
01817 
01818     CHECK_REQUEST(cx);
01819     ok = js_LockGCThing(cx, thing);
01820     if (!ok)
01821         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_LOCK);
01822     return ok;
01823 }
01824 
01825 JS_PUBLIC_API(JSBool)
01826 JS_LockGCThingRT(JSRuntime *rt, void *thing)
01827 {
01828     return js_LockGCThingRT(rt, thing);
01829 }
01830 
01831 JS_PUBLIC_API(JSBool)
01832 JS_UnlockGCThing(JSContext *cx, void *thing)
01833 {
01834     JSBool ok;
01835 
01836     CHECK_REQUEST(cx);
01837     ok = js_UnlockGCThingRT(cx->runtime, thing);
01838     if (!ok)
01839         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK);
01840     return ok;
01841 }
01842 
01843 JS_PUBLIC_API(JSBool)
01844 JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
01845 {
01846     return js_UnlockGCThingRT(rt, thing);
01847 }
01848 
01849 JS_PUBLIC_API(void)
01850 JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
01851 {
01852     JS_ASSERT(cx->runtime->gcLevel > 0);
01853 #ifdef JS_THREADSAFE
01854     JS_ASSERT(cx->runtime->gcThread->id == js_CurrentThreadId());
01855 #endif
01856 
01857     GC_MARK(cx, thing, name);
01858 }
01859 
01860 JS_PUBLIC_API(void)
01861 JS_GC(JSContext *cx)
01862 {
01863 #if JS_HAS_GENERATORS
01864     /* Run previously scheduled but delayed close hooks. */
01865     js_RunCloseHooks(cx);
01866 #endif
01867 
01868     /* Don't nuke active arenas if executing or compiling. */
01869     if (cx->stackPool.current == &cx->stackPool.first)
01870         JS_FinishArenaPool(&cx->stackPool);
01871     if (cx->tempPool.current == &cx->tempPool.first)
01872         JS_FinishArenaPool(&cx->tempPool);
01873     js_GC(cx, GC_NORMAL);
01874 
01875 #if JS_HAS_GENERATORS
01876     /*
01877      * Run close hooks for objects that became unreachable after the last GC.
01878      */
01879     js_RunCloseHooks(cx);
01880 #endif
01881 }
01882 
01883 JS_PUBLIC_API(void)
01884 JS_MaybeGC(JSContext *cx)
01885 {
01886     JSRuntime *rt;
01887     uint32 bytes, lastBytes;
01888 
01889     rt = cx->runtime;
01890 
01891 #ifdef JS_GC_ZEAL
01892     if (rt->gcZeal > 0) {
01893         JS_GC(cx);
01894         return;
01895     }
01896 #endif
01897 
01898     bytes = rt->gcBytes;
01899     lastBytes = rt->gcLastBytes;
01900 
01901     /*
01902      * We run the GC if we used all available free GC cells and had to
01903      * allocate extra 1/5 of GC arenas since the last run of GC, or if
01904      * we have malloc'd more bytes through JS_malloc than we were told
01905      * to allocate by JS_NewRuntime.
01906      *
01907      * The reason for
01908      *   bytes > 6/5 lastBytes
01909      * condition is the following. Bug 312238 changed bytes and lastBytes
01910      * to mean the total amount of memory that the GC uses now and right
01911      * after the last GC.
01912      *
01913      * Before the bug the variables meant the size of allocated GC things
01914      * now and right after the last GC. That size did not include the
01915      * memory taken by free GC cells and the condition was
01916      *   bytes > 3/2 lastBytes.
01917      * That is, we run the GC if we have half again as many bytes of
01918      * GC-things as the last time we GC'd. To be compatible we need to
01919      * express that condition through the new meaning of bytes and
01920      * lastBytes.
01921      *
01922      * We write the original condition as
01923      *   B*(1-F) > 3/2 Bl*(1-Fl)
01924      * where B is the total memory size allocated by GC and F is the free
01925      * cell density currently and Sl and Fl are the size and the density
01926      * right after GC. The density by definition is memory taken by free
01927      * cells divided by total amount of memory. In other words, B and Bl
01928      * are bytes and lastBytes with the new meaning and B*(1-F) and
01929      * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
01930      *
01931      * Our task is to exclude F and Fl from the last statement. According
01932      * the stats from bug 331770 Fl is about 20-30% for GC allocations
01933      * that contribute to S and Sl for a typical run of the browser. It
01934      * means that the original condition implied that we did not run GC
01935      * unless we exhausted the pool of free cells. Indeed if we still
01936      * have free cells, then B == Bl since we did not yet allocated any
01937      * new arenas and the condition means
01938      *   1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
01939      * That implies 3/2 Fl > 1/2 or Fl > 1/3. That can not be fulfilled
01940      * for the state described by the stats. So we can write the original
01941      * condition as:
01942      *   F == 0 && B > 3/2 Bl(1-Fl)
01943      * Again using the stats we see that Fl is about 20% when the browser
01944      * starts up and when we are far from hitting rt->gcMaxBytes. With
01945      * this F we have
01946      * F == 0 && B > 3/2 Bl(1-0.8) or just B > 6/5 Bl.
01947      */
01948     if ((bytes > 8192 && bytes > lastBytes + lastBytes / 5) ||
01949         rt->gcMallocBytes >= rt->gcMaxMallocBytes) {
01950         JS_GC(cx);
01951     }
01952 #if JS_HAS_GENERATORS
01953     else {
01954         /* Run scheduled but not yet executed close hooks. */
01955         js_RunCloseHooks(cx);
01956     }
01957 #endif
01958 }
01959 
01960 JS_PUBLIC_API(JSGCCallback)
01961 JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
01962 {
01963     return JS_SetGCCallbackRT(cx->runtime, cb);
01964 }
01965 
01966 JS_PUBLIC_API(JSGCCallback)
01967 JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
01968 {
01969     JSGCCallback oldcb;
01970 
01971     oldcb = rt->gcCallback;
01972     rt->gcCallback = cb;
01973     return oldcb;
01974 }
01975 
01976 JS_PUBLIC_API(JSBool)
01977 JS_IsAboutToBeFinalized(JSContext *cx, void *thing)
01978 {
01979     JS_ASSERT(thing);
01980     return js_IsAboutToBeFinalized(cx, thing);
01981 }
01982 
01983 JS_PUBLIC_API(void)
01984 JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value)
01985 {
01986     switch (key) {
01987       case JSGC_MAX_BYTES:
01988         rt->gcMaxBytes = value;
01989         break;
01990       case JSGC_MAX_MALLOC_BYTES:
01991         rt->gcMaxMallocBytes = value;
01992         break;
01993     }
01994 }
01995 
01996 JS_PUBLIC_API(intN)
01997 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
01998 {
01999     return js_ChangeExternalStringFinalizer(NULL, finalizer);
02000 }
02001 
02002 JS_PUBLIC_API(intN)
02003 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
02004 {
02005     return js_ChangeExternalStringFinalizer(finalizer, NULL);
02006 }
02007 
02008 JS_PUBLIC_API(JSString *)
02009 JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
02010 {
02011     JSString *str;
02012 
02013     CHECK_REQUEST(cx);
02014     JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES);
02015 
02016     str = (JSString *) js_NewGCThing(cx, (uintN) type, sizeof(JSString));
02017     if (!str)
02018         return NULL;
02019     str->length = length;
02020     str->chars = chars;
02021     return str;
02022 }
02023 
02024 JS_PUBLIC_API(intN)
02025 JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
02026 {
02027     uint8 type = (uint8) (*js_GetGCThingFlags(str) & GCF_TYPEMASK);
02028 
02029     if (type >= GCX_EXTERNAL_STRING)
02030         return (intN)type;
02031     JS_ASSERT(type == GCX_STRING || type == GCX_MUTABLE_STRING);
02032     return -1;
02033 }
02034 
02035 JS_PUBLIC_API(void)
02036 JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
02037 {
02038 #if JS_STACK_GROWTH_DIRECTION > 0
02039     if (limitAddr == 0)
02040         limitAddr = (jsuword)-1;
02041 #endif
02042     cx->stackLimit = limitAddr;
02043 }
02044 
02045 /************************************************************************/
02046 
02047 JS_PUBLIC_API(void)
02048 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
02049 {
02050     JS_free(cx, ida);
02051 }
02052 
02053 JS_PUBLIC_API(JSBool)
02054 JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
02055 {
02056     JSAtom *atom;
02057 
02058     CHECK_REQUEST(cx);
02059     if (JSVAL_IS_INT(v)) {
02060         *idp = INT_JSVAL_TO_JSID(v);
02061     } else {
02062 #if JS_HAS_XML_SUPPORT
02063         if (!JSVAL_IS_PRIMITIVE(v)) {
02064             *idp = OBJECT_JSVAL_TO_JSID(v);
02065             return JS_TRUE;
02066         }
02067 #endif
02068         atom = js_ValueToStringAtom(cx, v);
02069         if (!atom)
02070             return JS_FALSE;
02071         *idp = ATOM_TO_JSID(atom);
02072     }
02073     return JS_TRUE;
02074 }
02075 
02076 JS_PUBLIC_API(JSBool)
02077 JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
02078 {
02079     CHECK_REQUEST(cx);
02080     *vp = ID_TO_VALUE(id);
02081     return JS_TRUE;
02082 }
02083 
02084 JS_PUBLIC_API(JSBool)
02085 JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
02086 {
02087     return JS_TRUE;
02088 }
02089 
02090 JS_PUBLIC_API(JSBool)
02091 JS_EnumerateStub(JSContext *cx, JSObject *obj)
02092 {
02093     return JS_TRUE;
02094 }
02095 
02096 JS_PUBLIC_API(JSBool)
02097 JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id)
02098 {
02099     return JS_TRUE;
02100 }
02101 
02102 JS_PUBLIC_API(JSBool)
02103 JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
02104 {
02105     return js_TryValueOf(cx, obj, type, vp);
02106 }
02107 
02108 JS_PUBLIC_API(void)
02109 JS_FinalizeStub(JSContext *cx, JSObject *obj)
02110 {
02111 }
02112 
02113 JS_PUBLIC_API(JSObject *)
02114 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
02115              JSClass *clasp, JSNative constructor, uintN nargs,
02116              JSPropertySpec *ps, JSFunctionSpec *fs,
02117              JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
02118 {
02119     JSAtom *atom;
02120     JSProtoKey key;
02121     JSObject *proto, *ctor;
02122     JSTempValueRooter tvr;
02123     jsval cval, rval;
02124     JSBool named;
02125     JSFunction *fun;
02126 
02127     CHECK_REQUEST(cx);
02128     atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
02129     if (!atom)
02130         return NULL;
02131 
02132     /*
02133      * When initializing a standard class, if no parent_proto (grand-proto of
02134      * instances of the class, parent-proto of the class's prototype object)
02135      * is given, we must use Object.prototype if it is available.  Otherwise,
02136      * we could look up the wrong binding for a class name in obj.  Example:
02137      *
02138      *   String = Array;
02139      *   print("hi there".join);
02140      *
02141      * should print undefined, not Array.prototype.join.  This is required by
02142      * ECMA-262, alas.  It might have been better to make String readonly and
02143      * permanent in the global object, instead -- but that's too big a change
02144      * to swallow at this point.
02145      */
02146     key = JSCLASS_CACHED_PROTO_KEY(clasp);
02147     if (key != JSProto_Null &&
02148         !parent_proto &&
02149         !js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),
02150                               &parent_proto)) {
02151         return NULL;
02152     }
02153 
02154     /* Create a prototype object for this class. */
02155     proto = js_NewObject(cx, clasp, parent_proto, obj);
02156     if (!proto)
02157         return NULL;
02158 
02159     /* After this point, control must exit via label bad or out. */
02160     JS_PUSH_TEMP_ROOT_OBJECT(cx, proto, &tvr);
02161 
02162     if (!constructor) {
02163         /*
02164          * Lacking a constructor, name the prototype (e.g., Math) unless this
02165          * class (a) is anonymous, i.e. for internal use only; (b) the class
02166          * of obj (the global object) is has a reserved slot indexed by key;
02167          * and (c) key is not the null key.
02168          */
02169         if ((clasp->flags & JSCLASS_IS_ANONYMOUS) &&
02170             (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) &&
02171             key != JSProto_Null) {
02172             named = JS_FALSE;
02173         } else {
02174             named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
02175                                         OBJECT_TO_JSVAL(proto),
02176                                         NULL, NULL,
02177                                         (clasp->flags & JSCLASS_IS_ANONYMOUS)
02178                                         ? JSPROP_READONLY | JSPROP_PERMANENT
02179                                         : 0,
02180                                         NULL);
02181             if (!named)
02182                 goto bad;
02183         }
02184 
02185         ctor = proto;
02186     } else {
02187         /* Define the constructor function in obj's scope. */
02188         fun = js_DefineFunction(cx, obj, atom, constructor, nargs, 0);
02189         named = (fun != NULL);
02190         if (!fun)
02191             goto bad;
02192 
02193         /*
02194          * Remember the class this function is a constructor for so that
02195          * we know to create an object of this class when we call the
02196          * constructor.
02197          */
02198         fun->clasp = clasp;
02199 
02200         /*
02201          * Optionally construct the prototype object, before the class has
02202          * been fully initialized.  Allow the ctor to replace proto with a
02203          * different object, as is done for operator new -- and as at least
02204          * XML support requires.
02205          */
02206         ctor = fun->object;
02207         if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
02208             cval = OBJECT_TO_JSVAL(ctor);
02209             if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))
02210                 goto bad;
02211             if (!JSVAL_IS_PRIMITIVE(rval) && JSVAL_TO_OBJECT(rval) != proto)
02212                 proto = JSVAL_TO_OBJECT(rval);
02213         }
02214 
02215         /* Connect constructor and prototype by named properties. */
02216         if (!js_SetClassPrototype(cx, ctor, proto,
02217                                   JSPROP_READONLY | JSPROP_PERMANENT)) {
02218             goto bad;
02219         }
02220 
02221         /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
02222         if (OBJ_GET_CLASS(cx, ctor) == clasp) {
02223             JS_ASSERT(!OBJ_GET_PROTO(cx, ctor));
02224             OBJ_SET_PROTO(cx, ctor, proto);
02225         }
02226     }
02227 
02228     /* Add properties and methods to the prototype and the constructor. */
02229     if ((ps && !JS_DefineProperties(cx, proto, ps)) ||
02230         (fs && !JS_DefineFunctions(cx, proto, fs)) ||
02231         (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||
02232         (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {
02233         goto bad;
02234     }
02235 
02236     /* If this is a standard class, cache its prototype. */
02237     if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor))
02238         goto bad;
02239 
02240 out:
02241     JS_POP_TEMP_ROOT(cx, &tvr);
02242     return proto;
02243 
02244 bad:
02245     if (named)
02246         (void) OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &rval);
02247     proto = NULL;
02248     goto out;
02249 }
02250 
02251 #ifdef JS_THREADSAFE
02252 JS_PUBLIC_API(JSClass *)
02253 JS_GetClass(JSContext *cx, JSObject *obj)
02254 {
02255     return (JSClass *)
02256         JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS));
02257 }
02258 #else
02259 JS_PUBLIC_API(JSClass *)
02260 JS_GetClass(JSObject *obj)
02261 {
02262     return LOCKED_OBJ_GET_CLASS(obj);
02263 }
02264 #endif
02265 
02266 JS_PUBLIC_API(JSBool)
02267 JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
02268 {
02269     JSFunction *fun;
02270 
02271     CHECK_REQUEST(cx);
02272     if (OBJ_GET_CLASS(cx, obj) == clasp)
02273         return JS_TRUE;
02274     if (argv) {
02275         fun = js_ValueToFunction(cx, &argv[-2], 0);
02276         if (fun) {
02277             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
02278                                  JSMSG_INCOMPATIBLE_PROTO,
02279                                  clasp->name, JS_GetFunctionName(fun),
02280                                  OBJ_GET_CLASS(cx, obj)->name);
02281         }
02282     }
02283     return JS_FALSE;
02284 }
02285 
02286 JS_PUBLIC_API(JSBool)
02287 JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
02288 {
02289     return js_HasInstance(cx, obj, v, bp);
02290 }
02291 
02292 JS_PUBLIC_API(void *)
02293 JS_GetPrivate(JSContext *cx, JSObject *obj)
02294 {
02295     jsval v;
02296 
02297     JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
02298     v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
02299     if (!JSVAL_IS_INT(v))
02300         return NULL;
02301     return JSVAL_TO_PRIVATE(v);
02302 }
02303 
02304 JS_PUBLIC_API(JSBool)
02305 JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
02306 {
02307     JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
02308     OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(data));
02309     return JS_TRUE;
02310 }
02311 
02312 JS_PUBLIC_API(void *)
02313 JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
02314                       jsval *argv)
02315 {
02316     if (!JS_InstanceOf(cx, obj, clasp, argv))
02317         return NULL;
02318     return JS_GetPrivate(cx, obj);
02319 }
02320 
02321 JS_PUBLIC_API(JSObject *)
02322 JS_GetPrototype(JSContext *cx, JSObject *obj)
02323 {
02324     JSObject *proto;
02325 
02326     CHECK_REQUEST(cx);
02327     proto = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PROTO));
02328 
02329     /* Beware ref to dead object (we may be called from obj's finalizer). */
02330     return proto && proto->map ? proto : NULL;
02331 }
02332 
02333 JS_PUBLIC_API(JSBool)
02334 JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
02335 {
02336     CHECK_REQUEST(cx);
02337     if (obj->map->ops->setProto)
02338         return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto);
02339     OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto));
02340     return JS_TRUE;
02341 }
02342 
02343 JS_PUBLIC_API(JSObject *)
02344 JS_GetParent(JSContext *cx, JSObject *obj)
02345 {
02346     JSObject *parent;
02347 
02348     parent = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PARENT));
02349 
02350     /* Beware ref to dead object (we may be called from obj's finalizer). */
02351     return parent && parent->map ? parent : NULL;
02352 }
02353 
02354 JS_PUBLIC_API(JSBool)
02355 JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
02356 {
02357     CHECK_REQUEST(cx);
02358     if (obj->map->ops->setParent)
02359         return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent);
02360     OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent));
02361     return JS_TRUE;
02362 }
02363 
02364 JS_PUBLIC_API(JSObject *)
02365 JS_GetConstructor(JSContext *cx, JSObject *proto)
02366 {
02367     jsval cval;
02368 
02369     CHECK_REQUEST(cx);
02370     if (!OBJ_GET_PROPERTY(cx, proto,
02371                           ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
02372                           &cval)) {
02373         return NULL;
02374     }
02375     if (!VALUE_IS_FUNCTION(cx, cval)) {
02376         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
02377                              OBJ_GET_CLASS(cx, proto)->name);
02378         return NULL;
02379     }
02380     return JSVAL_TO_OBJECT(cval);
02381 }
02382 
02383 JS_PUBLIC_API(JSBool)
02384 JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
02385 {
02386     JS_ASSERT(((jsid)obj & JSID_TAGMASK) == 0);
02387     *idp = OBJECT_TO_JSID(obj);
02388     return JS_TRUE;
02389 }
02390 
02391 JS_PUBLIC_API(JSObject *)
02392 JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
02393 {
02394     CHECK_REQUEST(cx);
02395     if (!clasp)
02396         clasp = &js_ObjectClass;    /* default class is Object */
02397     return js_NewObject(cx, clasp, proto, parent);
02398 }
02399 
02400 JS_PUBLIC_API(JSBool)
02401 JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
02402 {
02403     JSScope *scope;
02404     JSIdArray *ida;
02405     uint32 nslots;
02406     jsval v, *vp, *end;
02407 
02408     if (!OBJ_IS_NATIVE(obj)) {
02409         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
02410                              JSMSG_CANT_SEAL_OBJECT,
02411                              OBJ_GET_CLASS(cx, obj)->name);
02412         return JS_FALSE;
02413     }
02414 
02415     scope = OBJ_SCOPE(obj);
02416 
02417 #if defined JS_THREADSAFE && defined DEBUG
02418     /* Insist on scope being used exclusively by cx's thread. */
02419     if (scope->ownercx != cx) {
02420         JS_LOCK_OBJ(cx, obj);
02421         JS_ASSERT(OBJ_SCOPE(obj) == scope);
02422         JS_ASSERT(scope->ownercx == cx);
02423         JS_UNLOCK_SCOPE(cx, scope);
02424     }
02425 #endif
02426 
02427     /* Nothing to do if obj's scope is already sealed. */
02428     if (SCOPE_IS_SEALED(scope))
02429         return JS_TRUE;
02430 
02431     /* XXX Enumerate lazy properties now, as they can't be added later. */
02432     ida = JS_Enumerate(cx, obj);
02433     if (!ida)
02434         return JS_FALSE;
02435     JS_DestroyIdArray(cx, ida);
02436 
02437     /* Ensure that obj has its own, mutable scope, and seal that scope. */
02438     JS_LOCK_OBJ(cx, obj);
02439     scope = js_GetMutableScope(cx, obj);
02440     if (scope)
02441         SCOPE_SET_SEALED(scope);
02442     JS_UNLOCK_OBJ(cx, obj);
02443     if (!scope)
02444         return JS_FALSE;
02445 
02446     /* If we are not sealing an entire object graph, we're done. */
02447     if (!deep)
02448         return JS_TRUE;
02449 
02450     /* Walk obj->slots and if any value is a non-null object, seal it. */
02451     nslots = JS_MIN(scope->map.freeslot, scope->map.nslots);
02452     for (vp = obj->slots, end = vp + nslots; vp < end; vp++) {
02453         v = *vp;
02454         if (JSVAL_IS_PRIMITIVE(v))
02455             continue;
02456         if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep))
02457             return JS_FALSE;
02458     }
02459     return JS_TRUE;
02460 }
02461 
02462 JS_PUBLIC_API(JSObject *)
02463 JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
02464                    JSObject *parent)
02465 {
02466     CHECK_REQUEST(cx);
02467     if (!clasp)
02468         clasp = &js_ObjectClass;    /* default class is Object */
02469     return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
02470 }
02471 
02472 JS_PUBLIC_API(JSObject *)
02473 JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
02474                                 JSObject *parent, uintN argc, jsval *argv)
02475 {
02476     CHECK_REQUEST(cx);
02477     if (!clasp)
02478         clasp = &js_ObjectClass;    /* default class is Object */
02479     return js_ConstructObject(cx, clasp, proto, parent, argc, argv);
02480 }
02481 
02482 static JSBool
02483 DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
02484                JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
02485                uintN flags, intN tinyid)
02486 {
02487     jsid id;
02488     JSAtom *atom;
02489 
02490     if (attrs & JSPROP_INDEX) {
02491         id = INT_TO_JSID(JS_PTR_TO_INT32(name));
02492         atom = NULL;
02493         attrs &= ~JSPROP_INDEX;
02494     } else {
02495         atom = js_Atomize(cx, name, strlen(name), 0);
02496         if (!atom)
02497             return JS_FALSE;
02498         id = ATOM_TO_JSID(atom);
02499     }
02500     if (flags != 0 && OBJ_IS_NATIVE(obj)) {
02501         return js_DefineNativeProperty(cx, obj, id, value, getter, setter,
02502                                        attrs, flags, tinyid, NULL);
02503     }
02504     return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
02505                                NULL);
02506 }
02507 
02508 #define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
02509 
02510 static JSBool
02511 DefineUCProperty(JSContext *cx, JSObject *obj,
02512                  const jschar *name, size_t namelen, jsval value,
02513                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
02514                  uintN flags, intN tinyid)
02515 {
02516     JSAtom *atom;
02517 
02518     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
02519     if (!atom)
02520         return JS_FALSE;
02521     if (flags != 0 && OBJ_IS_NATIVE(obj)) {
02522         return js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
02523                                        getter, setter, attrs, flags, tinyid,
02524                                        NULL);
02525     }
02526     return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), value,
02527                                getter, setter, attrs, NULL);
02528 }
02529 
02530 JS_PUBLIC_API(JSObject *)
02531 JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
02532                 JSObject *proto, uintN attrs)
02533 {
02534     JSObject *nobj;
02535 
02536     CHECK_REQUEST(cx);
02537     if (!clasp)
02538         clasp = &js_ObjectClass;    /* default class is Object */
02539     nobj = js_NewObject(cx, clasp, proto, obj);
02540     if (!nobj)
02541         return NULL;
02542     if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
02543                         0, 0)) {
02544         cx->weakRoots.newborn[GCX_OBJECT] = NULL;
02545         return NULL;
02546     }
02547     return nobj;
02548 }
02549 
02550 JS_PUBLIC_API(JSBool)
02551 JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
02552 {
02553     JSBool ok;
02554     jsval value;
02555     uintN flags;
02556 
02557     CHECK_REQUEST(cx);
02558     for (ok = JS_TRUE; cds->name; cds++) {
02559         ok = js_NewNumberValue(cx, cds->dval, &value);
02560         if (!ok)
02561             break;
02562         flags = cds->flags;
02563         if (!flags)
02564             flags = JSPROP_READONLY | JSPROP_PERMANENT;
02565         ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0);
02566         if (!ok)
02567             break;
02568     }
02569     return ok;
02570 }
02571 
02572 JS_PUBLIC_API(JSBool)
02573 JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
02574 {
02575     JSBool ok;
02576 
02577     CHECK_REQUEST(cx);
02578     for (ok = JS_TRUE; ps->name; ps++) {
02579         ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID,
02580                             ps->getter, ps->setter, ps->flags,
02581                             SPROP_HAS_SHORTID, ps->tinyid);
02582         if (!ok)
02583             break;
02584     }
02585     return ok;
02586 }
02587 
02588 JS_PUBLIC_API(JSBool)
02589 JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
02590                   JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
02591 {
02592     CHECK_REQUEST(cx);
02593     return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
02594 }
02595 
02596 JS_PUBLIC_API(JSBool)
02597 JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
02598                             int8 tinyid, jsval value,
02599                             JSPropertyOp getter, JSPropertyOp setter,
02600                             uintN attrs)
02601 {
02602     CHECK_REQUEST(cx);
02603     return DefineProperty(cx, obj, name, value, getter, setter, attrs,
02604                           SPROP_HAS_SHORTID, tinyid);
02605 }
02606 
02607 static JSBool
02608 LookupProperty(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
02609                JSProperty **propp)
02610 {
02611     JSAtom *atom;
02612 
02613     atom = js_Atomize(cx, name, strlen(name), 0);
02614     if (!atom)
02615         return JS_FALSE;
02616     return OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), objp, propp);
02617 }
02618 
02619 static JSBool
02620 LookupUCProperty(JSContext *cx, JSObject *obj,
02621                  const jschar *name, size_t namelen,
02622                  JSObject **objp, JSProperty **propp)
02623 {
02624     JSAtom *atom;
02625 
02626     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
02627     if (!atom)
02628         return JS_FALSE;
02629     return OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), objp, propp);
02630 }
02631 
02632 JS_PUBLIC_API(JSBool)
02633 JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
02634                  const char *alias)
02635 {
02636     JSObject *obj2;
02637     JSProperty *prop;
02638     JSAtom *atom;
02639     JSBool ok;
02640     JSScopeProperty *sprop;
02641 
02642     CHECK_REQUEST(cx);
02643     if (!LookupProperty(cx, obj, name, &obj2, &prop))
02644         return JS_FALSE;
02645     if (!prop) {
02646         js_ReportIsNotDefined(cx, name);
02647         return JS_FALSE;
02648     }
02649     if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
02650         OBJ_DROP_PROPERTY(cx, obj2, prop);
02651         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
02652                              alias, name, OBJ_GET_CLASS(cx, obj2)->name);
02653         return JS_FALSE;
02654     }
02655     atom = js_Atomize(cx, alias, strlen(alias), 0);
02656     if (!atom) {
02657         ok = JS_FALSE;
02658     } else {
02659         sprop = (JSScopeProperty *)prop;
02660         ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom),
02661                                    sprop->getter, sprop->setter, sprop->slot,
02662                                    sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
02663                                    sprop->shortid)
02664               != NULL);
02665     }
02666     OBJ_DROP_PROPERTY(cx, obj, prop);
02667     return ok;
02668 }
02669 
02670 static jsval
02671 LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
02672 {
02673     JSScopeProperty *sprop;
02674     jsval rval;
02675 
02676     if (!prop) {
02677         /* XXX bad API: no way to tell "not defined" from "void value" */
02678         return JSVAL_VOID;
02679     }
02680     if (OBJ_IS_NATIVE(obj2)) {
02681         /* Peek at the native property's slot value, without doing a Get. */
02682         sprop = (JSScopeProperty *)prop;
02683         rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
02684                ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
02685                : JSVAL_TRUE;
02686     } else {
02687         /* XXX bad API: no way to return "defined but value unknown" */
02688         rval = JSVAL_TRUE;
02689     }
02690     OBJ_DROP_PROPERTY(cx, obj2, prop);
02691     return rval;
02692 }
02693 
02694 static JSBool
02695 GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
02696                       uintN *attrsp, JSBool *foundp,
02697                       JSPropertyOp *getterp, JSPropertyOp *setterp)
02698 {
02699     JSObject *obj2;
02700     JSProperty *prop;
02701     JSBool ok;
02702 
02703     if (!atom)
02704         return JS_FALSE;
02705     if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop))
02706         return JS_FALSE;
02707 
02708     if (!prop || obj != obj2) {
02709         *attrsp = 0;
02710         *foundp = JS_FALSE;
02711         if (getterp)
02712             *getterp = NULL;
02713         if (setterp)
02714             *setterp = NULL;
02715         if (prop)
02716             OBJ_DROP_PROPERTY(cx, obj2, prop);
02717         return JS_TRUE;
02718     }
02719 
02720     *foundp = JS_TRUE;
02721     ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, attrsp);
02722     if (ok && OBJ_IS_NATIVE(obj)) {
02723         JSScopeProperty *sprop = (JSScopeProperty *) prop;
02724 
02725         if (getterp)
02726             *getterp = sprop->getter;
02727         if (setterp)
02728             *setterp = sprop->setter;
02729     }
02730     OBJ_DROP_PROPERTY(cx, obj, prop);
02731     return ok;
02732 }
02733 
02734 static JSBool
02735 SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
02736                       uintN attrs, JSBool *foundp)
02737 {
02738     JSObject *obj2;
02739     JSProperty *prop;
02740     JSBool ok;
02741 
02742     if (!atom)
02743         return JS_FALSE;
02744     if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop))
02745         return JS_FALSE;
02746     if (!prop || obj != obj2) {
02747         *foundp = JS_FALSE;
02748         if (prop)
02749             OBJ_DROP_PROPERTY(cx, obj2, prop);
02750         return JS_TRUE;
02751     }
02752 
02753     *foundp = JS_TRUE;
02754     ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs);
02755     OBJ_DROP_PROPERTY(cx, obj, prop);
02756     return ok;
02757 }
02758 
02759 JS_PUBLIC_API(JSBool)
02760 JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
02761                          uintN *attrsp, JSBool *foundp)
02762 {
02763     CHECK_REQUEST(cx);
02764     return GetPropertyAttributes(cx, obj,
02765                                  js_Atomize(cx, name, strlen(name), 0),
02766                                  attrsp, foundp, NULL, NULL);
02767 }
02768 
02769 JS_PUBLIC_API(JSBool)
02770 JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
02771                                    const char *name,
02772                                    uintN *attrsp, JSBool *foundp,
02773                                    JSPropertyOp *getterp,
02774                                    JSPropertyOp *setterp)
02775 {
02776     CHECK_REQUEST(cx);
02777     return GetPropertyAttributes(cx, obj,
02778                                  js_Atomize(cx, name, strlen(name), 0),
02779                                  attrsp, foundp, getterp, setterp);
02780 }
02781 
02782 JS_PUBLIC_API(JSBool)
02783 JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
02784                          uintN attrs, JSBool *foundp)
02785 {
02786     CHECK_REQUEST(cx);
02787     return SetPropertyAttributes(cx, obj,
02788                                  js_Atomize(cx, name, strlen(name), 0),
02789                                  attrs, foundp);
02790 }
02791 
02792 JS_PUBLIC_API(JSBool)
02793 JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
02794 {
02795     JSBool ok;
02796     JSObject *obj2;
02797     JSProperty *prop;
02798 
02799     CHECK_REQUEST(cx);
02800     ok = LookupProperty(cx, obj, name, &obj2, &prop);
02801     if (ok) {
02802         *foundp = (prop != NULL);
02803         if (prop)
02804             OBJ_DROP_PROPERTY(cx, obj2, prop);
02805     }
02806     return ok;
02807 }
02808 
02809 JS_PUBLIC_API(JSBool)
02810 JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
02811 {
02812     JSBool ok;
02813     JSObject *obj2;
02814     JSProperty *prop;
02815 
02816     CHECK_REQUEST(cx);
02817     ok = LookupProperty(cx, obj, name, &obj2, &prop);
02818     if (ok)
02819         *vp = LookupResult(cx, obj, obj2, prop);
02820     return ok;
02821 }
02822 
02823 JS_PUBLIC_API(JSBool)
02824 JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
02825                            uintN flags, jsval *vp)
02826 {
02827     JSAtom *atom;
02828     JSBool ok;
02829     JSObject *obj2;
02830     JSProperty *prop;
02831 
02832     CHECK_REQUEST(cx);
02833     atom = js_Atomize(cx, name, strlen(name), 0);
02834     if (!atom)
02835         return JS_FALSE;
02836     ok = OBJ_IS_NATIVE(obj)
02837          ? js_LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(atom), flags,
02838                                       &obj2, &prop)
02839          : OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop);
02840     if (ok)
02841         *vp = LookupResult(cx, obj, obj2, prop);
02842     return ok;
02843 }
02844 
02845 JS_PUBLIC_API(JSBool)
02846 JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
02847 {
02848     JSAtom *atom;
02849 
02850     CHECK_REQUEST(cx);
02851     atom = js_Atomize(cx, name, strlen(name), 0);
02852     if (!atom)
02853         return JS_FALSE;
02854     return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
02855 }
02856 
02857 JS_PUBLIC_API(JSBool)
02858 JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
02859                  jsval *vp)
02860 {
02861     CHECK_REQUEST(cx);
02862 
02863 #if JS_HAS_XML_SUPPORT
02864     if (OBJECT_IS_XML(cx, obj)) {
02865         JSXMLObjectOps *ops;
02866 
02867         ops = (JSXMLObjectOps *) obj->map->ops;
02868         obj = ops->getMethod(cx, obj, id, vp);
02869         if (!obj)
02870             return JS_FALSE;
02871     } else
02872 #endif
02873     {
02874         if (!OBJ_GET_PROPERTY(cx, obj, id, vp))
02875             return JS_FALSE;
02876     }
02877 
02878     *objp = obj;
02879     return JS_TRUE;
02880 }
02881 
02882 JS_PUBLIC_API(JSBool)
02883 JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
02884              jsval *vp)
02885 {
02886     JSAtom *atom;
02887 
02888     atom = js_Atomize(cx, name, strlen(name), 0);
02889     if (!atom)
02890         return JS_FALSE;
02891     return JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), objp, vp);
02892 }
02893 
02894 JS_PUBLIC_API(JSBool)
02895 JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
02896 {
02897     JSAtom *atom;
02898 
02899     CHECK_REQUEST(cx);
02900     atom = js_Atomize(cx, name, strlen(name), 0);
02901     if (!atom)
02902         return JS_FALSE;
02903     return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
02904 }
02905 
02906 JS_PUBLIC_API(JSBool)
02907 JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
02908 {
02909     jsval junk;
02910 
02911     CHECK_REQUEST(cx);
02912     return JS_DeleteProperty2(cx, obj, name, &junk);
02913 }
02914 
02915 JS_PUBLIC_API(JSBool)
02916 JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
02917                    jsval *rval)
02918 {
02919     JSAtom *atom;
02920 
02921     CHECK_REQUEST(cx);
02922     atom = js_Atomize(cx, name, strlen(name), 0);
02923     if (!atom)
02924         return JS_FALSE;
02925     return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
02926 }
02927 
02928 JS_PUBLIC_API(JSBool)
02929 JS_DefineUCProperty(JSContext *cx, JSObject *obj,
02930                     const jschar *name, size_t namelen, jsval value,
02931                     JSPropertyOp getter, JSPropertyOp setter,
02932                     uintN attrs)
02933 {
02934     CHECK_REQUEST(cx);
02935     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
02936                             attrs, 0, 0);
02937 }
02938 
02939 JS_PUBLIC_API(JSBool)
02940 JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
02941                            const jschar *name, size_t namelen,
02942                            uintN *attrsp, JSBool *foundp)
02943 {
02944     CHECK_REQUEST(cx);
02945     return GetPropertyAttributes(cx, obj,
02946                     js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
02947                     attrsp, foundp, NULL, NULL);
02948 }
02949 
02950 JS_PUBLIC_API(JSBool)
02951 JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
02952                                      const jschar *name, size_t namelen,
02953                                      uintN *attrsp, JSBool *foundp,
02954                                      JSPropertyOp *getterp,
02955                                      JSPropertyOp *setterp)
02956 {
02957     CHECK_REQUEST(cx);
02958     return GetPropertyAttributes(cx, obj,
02959                     js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
02960                     attrsp, foundp, getterp, setterp);
02961 }
02962 
02963 JS_PUBLIC_API(JSBool)
02964 JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
02965                            const jschar *name, size_t namelen,
02966                            uintN attrs, JSBool *foundp)
02967 {
02968     CHECK_REQUEST(cx);
02969     return SetPropertyAttributes(cx, obj,
02970                     js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
02971                     attrs, foundp);
02972 }
02973 
02974 JS_PUBLIC_API(JSBool)
02975 JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
02976                               const jschar *name, size_t namelen,
02977                               int8 tinyid, jsval value,
02978                               JSPropertyOp getter, JSPropertyOp setter,
02979                               uintN attrs)
02980 {
02981     CHECK_REQUEST(cx);
02982     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
02983                             attrs, SPROP_HAS_SHORTID, tinyid);
02984 }
02985 
02986 JS_PUBLIC_API(JSBool)
02987 JS_HasUCProperty(JSContext *cx, JSObject *obj,
02988                  const jschar *name, size_t namelen,
02989                  JSBool *vp)
02990 {
02991     JSBool ok;
02992     JSObject *obj2;
02993     JSProperty *prop;
02994 
02995     CHECK_REQUEST(cx);
02996     ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
02997     if (ok) {
02998         *vp = (prop != NULL);
02999         if (prop)
03000             OBJ_DROP_PROPERTY(cx, obj2, prop);
03001     }
03002     return ok;
03003 }
03004 
03005 JS_PUBLIC_API(JSBool)
03006 JS_LookupUCProperty(JSContext *cx, JSObject *obj,
03007                     const jschar *name, size_t namelen,
03008                     jsval *vp)
03009 {
03010     JSBool ok;
03011     JSObject *obj2;
03012     JSProperty *prop;
03013 
03014     CHECK_REQUEST(cx);
03015     ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
03016     if (ok)
03017         *vp = LookupResult(cx, obj, obj2, prop);
03018     return ok;
03019 }
03020 
03021 JS_PUBLIC_API(JSBool)
03022 JS_GetUCProperty(JSContext *cx, JSObject *obj,
03023                  const jschar *name, size_t namelen,
03024                  jsval *vp)
03025 {
03026     JSAtom *atom;
03027 
03028     CHECK_REQUEST(cx);
03029     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
03030     if (!atom)
03031         return JS_FALSE;
03032     return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
03033 }
03034 
03035 JS_PUBLIC_API(JSBool)
03036 JS_SetUCProperty(JSContext *cx, JSObject *obj,
03037                  const jschar *name, size_t namelen,
03038                  jsval *vp)
03039 {
03040     JSAtom *atom;
03041 
03042     CHECK_REQUEST(cx);
03043     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
03044     if (!atom)
03045         return JS_FALSE;
03046     return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
03047 }
03048 
03049 JS_PUBLIC_API(JSBool)
03050 JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
03051                      const jschar *name, size_t namelen,
03052                      jsval *rval)
03053 {
03054     JSAtom *atom;
03055 
03056     CHECK_REQUEST(cx);
03057     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
03058     if (!atom)
03059         return JS_FALSE;
03060     return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
03061 }
03062 
03063 JS_PUBLIC_API(JSObject *)
03064 JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
03065 {
03066     CHECK_REQUEST(cx);
03067     /* NB: jsuint cast does ToUint32. */
03068     return js_NewArrayObject(cx, (jsuint)length, vector);
03069 }
03070 
03071 JS_PUBLIC_API(JSBool)
03072 JS_IsArrayObject(JSContext *cx, JSObject *obj)
03073 {
03074     return OBJ_GET_CLASS(cx, obj) == &js_ArrayClass;
03075 }
03076 
03077 JS_PUBLIC_API(JSBool)
03078 JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
03079 {
03080     CHECK_REQUEST(cx);
03081     return js_GetLengthProperty(cx, obj, lengthp);
03082 }
03083 
03084 JS_PUBLIC_API(JSBool)
03085 JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
03086 {
03087     CHECK_REQUEST(cx);
03088     return js_SetLengthProperty(cx, obj, length);
03089 }
03090 
03091 JS_PUBLIC_API(JSBool)
03092 JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
03093 {
03094     CHECK_REQUEST(cx);
03095     return js_HasLengthProperty(cx, obj, lengthp);
03096 }
03097 
03098 JS_PUBLIC_API(JSBool)
03099 JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
03100                  JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
03101 {
03102     CHECK_REQUEST(cx);
03103     return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(index), value,
03104                                getter, setter, attrs, NULL);
03105 }
03106 
03107 JS_PUBLIC_API(JSBool)
03108 JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
03109 {
03110     JSObject *obj2;
03111     JSProperty *prop;
03112     JSScopeProperty *sprop;
03113     JSBool ok;
03114 
03115     CHECK_REQUEST(cx);
03116     if (!LookupProperty(cx, obj, name, &obj2, &prop))
03117         return JS_FALSE;
03118     if (!prop) {
03119         js_ReportIsNotDefined(cx, name);
03120         return JS_FALSE;
03121     }
03122     if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
03123         char numBuf[12];
03124         OBJ_DROP_PROPERTY(cx, obj2, prop);
03125         JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
03126         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
03127                              numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
03128         return JS_FALSE;
03129     }
03130     sprop = (JSScopeProperty *)prop;
03131     ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias),
03132                                sprop->getter, sprop->setter, sprop->slot,
03133                                sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
03134                                sprop->shortid)
03135           != NULL);
03136     OBJ_DROP_PROPERTY(cx, obj, prop);
03137     return ok;
03138 }
03139 
03140 JS_PUBLIC_API(JSBool)
03141 JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
03142 {
03143     JSBool ok;
03144     JSObject *obj2;
03145     JSProperty *prop;
03146 
03147     CHECK_REQUEST(cx);
03148     ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSID(index), &obj2, &prop);
03149     if (ok) {
03150         *foundp = (prop != NULL);
03151         if (prop)
03152             OBJ_DROP_PROPERTY(cx, obj2, prop);
03153     }
03154     return ok;
03155 }
03156 
03157 JS_PUBLIC_API(JSBool)
03158 JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
03159 {
03160     JSBool ok;
03161     JSObject *obj2;
03162     JSProperty *prop;
03163 
03164     CHECK_REQUEST(cx);
03165     ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSID(index), &obj2, &prop);
03166     if (ok)
03167         *vp = LookupResult(cx, obj, obj2, prop);
03168     return ok;
03169 }
03170 
03171 JS_PUBLIC_API(JSBool)
03172 JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
03173 {
03174     CHECK_REQUEST(cx);
03175     return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
03176 }
03177 
03178 JS_PUBLIC_API(JSBool)
03179 JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
03180 {
03181     CHECK_REQUEST(cx);
03182     return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
03183 }
03184 
03185 JS_PUBLIC_API(JSBool)
03186 JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index)
03187 {
03188     jsval junk;
03189 
03190     CHECK_REQUEST(cx);
03191     return JS_DeleteElement2(cx, obj, index, &junk);
03192 }
03193 
03194 JS_PUBLIC_API(JSBool)
03195 JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
03196 {
03197     CHECK_REQUEST(cx);
03198     return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSID(index), rval);
03199 }
03200 
03201 JS_PUBLIC_API(void)
03202 JS_ClearScope(JSContext *cx, JSObject *obj)
03203 {
03204     CHECK_REQUEST(cx);
03205 
03206     if (obj->map->ops->clear)
03207         obj->map->ops->clear(cx, obj);
03208 
03209     /* Clear cached class objects on the global object. */
03210     if (JS_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) {
03211         JSProtoKey key;
03212 
03213         for (key = JSProto_Null; key < JSProto_LIMIT; key++)
03214             JS_SetReservedSlot(cx, obj, key, JSVAL_VOID);
03215     }
03216 }
03217 
03218 JS_PUBLIC_API(JSIdArray *)
03219 JS_Enumerate(JSContext *cx, JSObject *obj)
03220 {
03221     jsint i, n;
03222     jsval iter_state, num_properties;
03223     jsid id;
03224     JSIdArray *ida;
03225     jsval *vector;
03226 
03227     CHECK_REQUEST(cx);
03228 
03229     ida = NULL;
03230     iter_state = JSVAL_NULL;
03231 
03232     /* Get the number of properties to enumerate. */
03233     if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties))
03234         goto error;
03235     if (!JSVAL_IS_INT(num_properties)) {
03236         JS_ASSERT(0);
03237         goto error;
03238     }
03239 
03240     /* Grow as needed if we don't know the exact amount ahead of time. */
03241     n = JSVAL_TO_INT(num_properties);
03242     if (n <= 0)
03243         n = 8;
03244 
03245     /* Create an array of jsids large enough to hold all the properties */
03246     ida = js_NewIdArray(cx, n);
03247     if (!ida)
03248         goto error;
03249 
03250     i = 0;
03251     vector = &ida->vector[0];
03252     for (;;) {
03253         if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id))
03254             goto error;
03255 
03256         /* No more jsid's to enumerate ? */
03257         if (iter_state == JSVAL_NULL)
03258             break;
03259 
03260         if (i == ida->length) {
03261             ida = js_SetIdArrayLength(cx, ida, ida->length * 2);
03262             if (!ida)
03263                 goto error;
03264             vector = &ida->vector[0];
03265         }
03266         vector[i++] = id;
03267     }
03268     return js_SetIdArrayLength(cx, ida, i);
03269 
03270 error:
03271     if (iter_state != JSVAL_NULL)
03272         OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
03273     if (ida)
03274         JS_DestroyIdArray(cx, ida);
03275     return NULL;
03276 }
03277 
03278 /*
03279  * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
03280  *     prop_iterator_class somehow...
03281  * + preserve the OBJ_ENUMERATE API while optimizing the native object case
03282  * + native case here uses a JSScopeProperty *, but that iterates in reverse!
03283  * + so we make non-native match, by reverse-iterating after JS_Enumerating
03284  */
03285 #define JSSLOT_ITER_INDEX       (JSSLOT_PRIVATE + 1)
03286 
03287 #if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS
03288 # error "JSSLOT_ITER_INDEX botch!"
03289 #endif
03290 
03291 static void
03292 prop_iter_finalize(JSContext *cx, JSObject *obj)
03293 {
03294     jsval v;
03295     jsint i;
03296     JSIdArray *ida;
03297 
03298     v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX);
03299     if (JSVAL_IS_VOID(v))
03300         return;
03301 
03302     i = JSVAL_TO_INT(v);
03303     if (i >= 0) {
03304         /* Non-native case: destroy the ida enumerated when obj was created. */
03305         ida = (JSIdArray *) JS_GetPrivate(cx, obj);
03306         if (ida)
03307             JS_DestroyIdArray(cx, ida);
03308     }
03309 }
03310 
03311 static uint32
03312 prop_iter_mark(JSContext *cx, JSObject *obj, void *arg)
03313 {
03314     jsval v;
03315     jsint i, n;
03316     JSScopeProperty *sprop;
03317     JSIdArray *ida;
03318     jsid id;
03319 
03320     v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
03321     JS_ASSERT(!JSVAL_IS_VOID(v));
03322 
03323     i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX));
03324     if (i < 0) {
03325         /* Native case: just mark the next property to visit. */
03326         sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v);
03327         if (sprop)
03328             MARK_SCOPE_PROPERTY(cx, sprop);
03329     } else {
03330         /* Non-native case: mark each id in the JSIdArray private. */
03331         ida = (JSIdArray *) JSVAL_TO_PRIVATE(v);
03332         for (i = 0, n = ida->length; i < n; i++) {
03333             id = ida->vector[i];
03334             MARK_ID(cx, id);
03335         }
03336     }
03337     return 0;
03338 }
03339 
03340 static JSClass prop_iter_class = {
03341     "PropertyIterator",
03342     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
03343     JS_PropertyStub,  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
03344     JS_EnumerateStub, JS_ResolveStub,  JS_ConvertStub,  prop_iter_finalize,
03345     NULL,             NULL,            NULL,            NULL,
03346     NULL,             NULL,            prop_iter_mark,  NULL
03347 };
03348 
03349 JS_PUBLIC_API(JSObject *)
03350 JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
03351 {
03352     JSObject *iterobj;
03353     JSScope *scope;
03354     void *pdata;
03355     jsint index;
03356     JSIdArray *ida;
03357 
03358     CHECK_REQUEST(cx);
03359     iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj);
03360     if (!iterobj)
03361         return NULL;
03362 
03363     if (OBJ_IS_NATIVE(obj)) {
03364         /* Native case: start with the last property in obj's own scope. */
03365         scope = OBJ_SCOPE(obj);
03366         pdata = (scope->object == obj) ? scope->lastProp : NULL;
03367         index = -1;
03368     } else {
03369         JSTempValueRooter tvr;
03370 
03371         /*
03372          * Non-native case: enumerate a JSIdArray and keep it via private.
03373          *
03374          * Note: we have to make sure that we root obj around the call to
03375          * JS_Enumerate to protect against multiple allocations under it.
03376          */
03377         JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(iterobj), &tvr);
03378         ida = JS_Enumerate(cx, obj);
03379         JS_POP_TEMP_ROOT(cx, &tvr);
03380         if (!ida)
03381             goto bad;
03382         pdata = ida;
03383         index = ida->length;
03384     }
03385 
03386     /* iterobj can not escape to other threads here. */
03387     iterobj->slots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(pdata);
03388     iterobj->slots[JSSLOT_ITER_INDEX] = INT_TO_JSVAL(index);
03389     return iterobj;
03390 
03391   bad:
03392     cx->weakRoots.newborn[GCX_OBJECT] = NULL;
03393     return NULL;
03394 }
03395 
03396 JS_PUBLIC_API(JSBool)
03397 JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
03398 {
03399     jsint i;
03400     JSObject *obj;
03401     JSScope *scope;
03402     JSScopeProperty *sprop;
03403     JSIdArray *ida;
03404 
03405     CHECK_REQUEST(cx);
03406     i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX));
03407     if (i < 0) {
03408         /* Native case: private data is a property tree node pointer. */
03409         obj = OBJ_GET_PARENT(cx, iterobj);
03410         JS_ASSERT(OBJ_IS_NATIVE(obj));
03411         scope = OBJ_SCOPE(obj);
03412         JS_ASSERT(scope->object == obj);
03413         sprop = (JSScopeProperty *) JS_GetPrivate(cx, iterobj);
03414 
03415         /*
03416          * If the next property mapped by scope in the property tree ancestor
03417          * line is not enumerable, or it's an alias, or one or more properties
03418          * were deleted from the "middle" of the scope-mapped ancestor line
03419          * and the next property was among those deleted, skip it and keep on
03420          * trying to find an enumerable property that is still in scope.
03421          */
03422         while (sprop &&
03423                (!(sprop->attrs & JSPROP_ENUMERATE) ||
03424                 (sprop->flags & SPROP_IS_ALIAS) ||
03425                 (SCOPE_HAD_MIDDLE_DELETE(scope) &&
03426                  !SCOPE_HAS_PROPERTY(scope, sprop)))) {
03427             sprop = sprop->parent;
03428         }
03429 
03430         if (!sprop) {
03431             *idp = JSVAL_VOID;
03432         } else {
03433             if (!JS_SetPrivate(cx, iterobj, sprop->parent))
03434                 return JS_FALSE;
03435             *idp = sprop->id;
03436         }
03437     } else {
03438         /* Non-native case: use the ida enumerated when iterobj was created. */
03439         ida = (JSIdArray *) JS_GetPrivate(cx, iterobj);
03440         JS_ASSERT(i <= ida->length);
03441         if (i == 0) {
03442             *idp = JSVAL_VOID;
03443         } else {
03444             *idp = ida->vector[--i];
03445             OBJ_SET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(i));
03446         }
03447     }
03448     return JS_TRUE;
03449 }
03450 
03451 JS_PUBLIC_API(JSBool)
03452 JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
03453                jsval *vp, uintN *attrsp)
03454 {
03455     CHECK_REQUEST(cx);
03456     return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp);
03457 }
03458 
03459 JS_PUBLIC_API(JSCheckAccessOp)
03460 JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb)
03461 {
03462     JSCheckAccessOp oldacb;
03463 
03464     oldacb = rt->checkObjectAccess;
03465     rt->checkObjectAccess = acb;
03466     return oldacb;
03467 }
03468 
03469 static JSBool
03470 ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
03471                     uint32 index, uint32 limit)
03472 {
03473     /* Check the computed, possibly per-instance, upper bound. */
03474     if (clasp->reserveSlots)
03475         JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj));
03476     if (index >= limit) {
03477         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
03478                              JSMSG_RESERVED_SLOT_RANGE);
03479         return JS_FALSE;
03480     }
03481     return JS_TRUE;
03482 }
03483 
03484 JS_PUBLIC_API(JSBool)
03485 JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
03486 {
03487     JSClass *clasp;
03488     uint32 limit, slot;
03489 
03490     CHECK_REQUEST(cx);
03491     clasp = OBJ_GET_CLASS(cx, obj);
03492     limit = JSCLASS_RESERVED_SLOTS(clasp);
03493     if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
03494         return JS_FALSE;
03495     slot = JSSLOT_START(clasp) + index;
03496     *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
03497     return JS_TRUE;
03498 }
03499 
03500 JS_PUBLIC_API(JSBool)
03501 JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
03502 {
03503     JSClass *clasp;
03504     uint32 limit, slot;
03505 
03506     CHECK_REQUEST(cx);
03507     clasp = OBJ_GET_CLASS(cx, obj);
03508     limit = JSCLASS_RESERVED_SLOTS(clasp);
03509     if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
03510         return JS_FALSE;
03511     slot = JSSLOT_START(clasp) + index;
03512     return OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
03513 }
03514 
03515 #ifdef JS_THREADSAFE
03516 JS_PUBLIC_API(jsrefcount)
03517 JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
03518 {
03519     return JS_ATOMIC_INCREMENT(&principals->refcount);
03520 }
03521 
03522 JS_PUBLIC_API(jsrefcount)
03523 JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
03524 {
03525     jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount);
03526     if (rc == 0)
03527         principals->destroy(cx, principals);
03528     return rc;
03529 }
03530 #endif
03531 
03532 JS_PUBLIC_API(JSPrincipalsTranscoder)
03533 JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px)
03534 {
03535     JSPrincipalsTranscoder oldpx;
03536 
03537     oldpx = rt->principalsTranscoder;
03538     rt->principalsTranscoder = px;
03539     return oldpx;
03540 }
03541 
03542 JS_PUBLIC_API(JSObjectPrincipalsFinder)
03543 JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop)
03544 {
03545     JSObjectPrincipalsFinder oldfop;
03546 
03547     oldfop = rt->findObjectPrincipals;
03548     rt->findObjectPrincipals = fop;
03549     return oldfop;
03550 }
03551 
03552 JS_PUBLIC_API(JSFunction *)
03553 JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
03554                JSObject *parent, const char *name)
03555 {
03556     JSAtom *atom;
03557 
03558     CHECK_REQUEST(cx);
03559 
03560     if (!name) {
03561         atom = NULL;
03562     } else {
03563         atom = js_Atomize(cx, name, strlen(name), 0);
03564         if (!atom)
03565             return NULL;
03566     }
03567     return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
03568 }
03569 
03570 JS_PUBLIC_API(JSObject *)
03571 JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
03572 {
03573     CHECK_REQUEST(cx);
03574     if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {
03575         /* Indicate we cannot clone this object. */
03576         return funobj;
03577     }
03578     return js_CloneFunctionObject(cx, funobj, parent);
03579 }
03580 
03581 JS_PUBLIC_API(JSObject *)
03582 JS_GetFunctionObject(JSFunction *fun)
03583 {
03584     return fun->object;
03585 }
03586 
03587 JS_PUBLIC_API(const char *)
03588 JS_GetFunctionName(JSFunction *fun)
03589 {
03590     return fun->atom
03591            ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
03592            : js_anonymous_str;
03593 }
03594 
03595 JS_PUBLIC_API(JSString *)
03596 JS_GetFunctionId(JSFunction *fun)
03597 {
03598     return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
03599 }
03600 
03601 JS_PUBLIC_API(uintN)
03602 JS_GetFunctionFlags(JSFunction *fun)
03603 {
03604 #ifdef MOZILLA_1_8_BRANCH
03605     uintN flags = fun->flags;
03606 
03607     return JSFUN_DISJOINT_FLAGS(flags) |
03608            (JSFUN_GETTER_TEST(flags) ? JSFUN_GETTER : 0) |
03609            (JSFUN_SETTER_TEST(flags) ? JSFUN_SETTER : 0) |
03610            (JSFUN_BOUND_METHOD_TEST(flags) ? JSFUN_BOUND_METHOD : 0) |
03611            (JSFUN_HEAVYWEIGHT_TEST(flags) ? JSFUN_HEAVYWEIGHT : 0);
03612 #else
03613     return fun->flags;
03614 #endif
03615 }
03616 
03617 JS_PUBLIC_API(uint16)
03618 JS_GetFunctionArity(JSFunction *fun)
03619 {
03620     return fun->nargs;
03621 }
03622 
03623 JS_PUBLIC_API(JSBool)
03624 JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
03625 {
03626     return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
03627 }
03628 
03629 JS_STATIC_DLL_CALLBACK(JSBool)
03630 js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
03631                                     uintN argc, jsval *argv, jsval *rval)
03632 {
03633     jsval fsv;
03634     JSFunctionSpec *fs;
03635     JSObject *tmp;
03636 
03637     if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), 0, &fsv))
03638         return JS_FALSE;
03639     fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
03640 
03641     /*
03642      * We know that argv[0] is valid because JS_DefineFunctions, which is our
03643      * only (indirect) referrer, defined us as requiring at least one argument
03644      * (notice how it passes fs->nargs + 1 as the next-to-last argument to
03645      * JS_DefineFunction).
03646      */
03647     if (JSVAL_IS_PRIMITIVE(argv[0])) {
03648         /*
03649          * Make sure that this is an object or null, as required by the generic
03650          * functions.
03651          */
03652         if (!js_ValueToObject(cx, argv[0], &tmp))
03653             return JS_FALSE;
03654         argv[0] = OBJECT_TO_JSVAL(tmp);
03655     }
03656 
03657     /*
03658      * Copy all actual (argc) and required but missing (fs->nargs + 1 - argc)
03659      * args down over our |this| parameter, argv[-1], which is almost always
03660      * the class constructor object, e.g. Array.  Then call the corresponding
03661      * prototype native method with our first argument passed as |this|.
03662      */
03663     memmove(argv - 1, argv, JS_MAX(fs->nargs + 1U, argc) * sizeof(jsval));
03664 
03665     /*
03666      * Follow Function.prototype.apply and .call by using the global object as
03667      * the 'this' param if no args.
03668      */
03669     JS_ASSERT(cx->fp->argv == argv);
03670     tmp = js_ComputeThis(cx, JSVAL_TO_OBJECT(argv[-1]), argv);
03671     if (!tmp)
03672         return JS_FALSE;
03673     cx->fp->thisp = tmp;
03674 
03675     /*
03676      * Protect against argc - 1 underflowing below. By calling js_ComputeThis,
03677      * we made it as if the static was called with one parameter.
03678      */
03679     if (argc == 0)
03680         argc = 1;
03681 
03682     return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc - 1, argv, rval);
03683 }
03684 
03685 JS_PUBLIC_API(JSBool)
03686 JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
03687 {
03688     uintN flags;
03689     JSObject *ctor;
03690     JSFunction *fun;
03691 
03692     CHECK_REQUEST(cx);
03693     ctor = NULL;
03694     for (; fs->name; fs++) {
03695 
03696         /* High bits of fs->extra are reserved. */
03697         JS_ASSERT((fs->extra & 0xFFFF0000) == 0);
03698         flags = fs->flags;
03699 
03700         /*
03701          * Define a generic arity N+1 static method for the arity N prototype
03702          * method if flags contains JSFUN_GENERIC_NATIVE.
03703          */
03704         if (flags & JSFUN_GENERIC_NATIVE) {
03705             if (!ctor) {
03706                 ctor = JS_GetConstructor(cx, obj);
03707                 if (!ctor)
03708                     return JS_FALSE;
03709             }
03710 
03711             flags &= ~JSFUN_GENERIC_NATIVE;
03712             fun = JS_DefineFunction(cx, ctor, fs->name,
03713                                     js_generic_native_method_dispatcher,
03714                                     fs->nargs + 1, flags);
03715             if (!fun)
03716                 return JS_FALSE;
03717             fun->u.n.extra = (uint16)fs->extra;
03718 
03719             /*
03720              * As jsapi.h notes, fs must point to storage that lives as long
03721              * as fun->object lives.
03722              */
03723             if (!JS_SetReservedSlot(cx, fun->object, 0, PRIVATE_TO_JSVAL(fs)))
03724                 return JS_FALSE;
03725         }
03726 
03727         fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
03728         if (!fun)
03729             return JS_FALSE;
03730         fun->u.n.extra = (uint16)fs->extra;
03731     }
03732     return JS_TRUE;
03733 }
03734 
03735 JS_PUBLIC_API(JSFunction *)
03736 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
03737                   uintN nargs, uintN attrs)
03738 {
03739     JSAtom *atom;
03740 
03741     CHECK_REQUEST(cx);
03742     atom = js_Atomize(cx, name, strlen(name), 0);
03743     if (!atom)
03744         return NULL;
03745     return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
03746 }
03747 
03748 JS_PUBLIC_API(JSFunction *)
03749 JS_DefineUCFunction(JSContext *cx, JSObject *obj,
03750                     const jschar *name, size_t namelen, JSNative call,
03751                     uintN nargs, uintN attrs)
03752 {
03753     JSAtom *atom;
03754 
03755     atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
03756     if (!atom)
03757         return NULL;
03758     return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
03759 }
03760 
03761 static JSScript *
03762 CompileTokenStream(JSContext *cx, JSObject *obj, JSTokenStream *ts,
03763                    void *tempMark, JSBool *eofp)
03764 {
03765     JSBool eof;
03766     JSArenaPool codePool, notePool;
03767     JSCodeGenerator cg;
03768     JSScript *script;
03769 
03770     CHECK_REQUEST(cx);
03771     eof = JS_FALSE;
03772     JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
03773     JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));
03774     if (!js_InitCodeGenerator(cx, &cg, &codePool, &notePool,
03775                               ts->filename, ts->lineno,
03776                               ts->principals)) {
03777         script = NULL;
03778     } else if (!js_CompileTokenStream(cx, obj, ts, &cg)) {
03779         script = NULL;
03780         eof = (ts->flags & TSF_EOF) != 0;
03781     } else {
03782         script = js_NewScriptFromCG(cx, &cg, NULL);
03783     }
03784     if (eofp)
03785         *eofp = eof;
03786     if (!js_CloseTokenStream(cx, ts)) {
03787         if (script)
03788             js_DestroyScript(cx, script);
03789         script = NULL;
03790     }
03791     cg.tempMark = tempMark;
03792     js_FinishCodeGenerator(cx, &cg);
03793     JS_FinishArenaPool(&codePool);
03794     JS_FinishArenaPool(&notePool);
03795     return script;
03796 }
03797 
03798 JS_PUBLIC_API(JSScript *)
03799 JS_CompileScript(JSContext *cx, JSObject *obj,
03800                  const char *bytes, size_t length,
03801                  const char *filename, uintN lineno)
03802 {
03803     jschar *chars;
03804     JSScript *script;
03805 
03806     CHECK_REQUEST(cx);
03807     chars = js_InflateString(cx, bytes, &length);
03808     if (!chars)
03809         return NULL;
03810     script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno);
03811     JS_free(cx, chars);
03812     return script;
03813 }
03814 
03815 JS_PUBLIC_API(JSScript *)
03816 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
03817                               JSPrincipals *principals,
03818                               const char *bytes, size_t length,
03819                               const char *filename, uintN lineno)
03820 {
03821     jschar *chars;
03822     JSScript *script;
03823 
03824     CHECK_REQUEST(cx);
03825     chars = js_InflateString(cx, bytes, &length);
03826     if (!chars)
03827         return NULL;
03828     script = JS_CompileUCScriptForPrincipals(cx, obj, principals,
03829                                              chars, length, filename, lineno);
03830     JS_free(cx, chars);
03831     return script;
03832 }
03833 
03834 JS_PUBLIC_API(JSScript *)
03835 JS_CompileUCScript(JSContext *cx, JSObject *obj,
03836                    const jschar *chars, size_t length,
03837                    const char *filename, uintN lineno)
03838 {
03839     CHECK_REQUEST(cx);
03840     return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length,
03841                                            filename, lineno);
03842 }
03843 
03844 #define LAST_FRAME_EXCEPTION_CHECK(cx,result)                                 \
03845     JS_BEGIN_MACRO                                                            \
03846         if (!(result) && !((cx)->options & JSOPTION_DONT_REPORT_UNCAUGHT))    \
03847             js_ReportUncaughtException(cx);                                   \
03848     JS_END_MACRO
03849 
03850 #define LAST_FRAME_CHECKS(cx,result)                                          \
03851     JS_BEGIN_MACRO                                                            \
03852         if (!(cx)->fp) {                                                      \
03853             (cx)->weakRoots.lastInternalResult = JSVAL_NULL;                  \
03854             LAST_FRAME_EXCEPTION_CHECK(cx, result);                           \
03855         }                                                                     \
03856     JS_END_MACRO
03857 
03858 JS_PUBLIC_API(JSScript *)
03859 JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
03860                                 JSPrincipals *principals,
03861                                 const jschar *chars, size_t length,
03862                                 const char *filename, uintN lineno)
03863 {
03864     void *mark;
03865     JSTokenStream *ts;
03866     JSScript *script;
03867 
03868     CHECK_REQUEST(cx);
03869     mark = JS_ARENA_MARK(&cx->tempPool);
03870     ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
03871     if (!ts)
03872         return NULL;
03873     script = CompileTokenStream(cx, obj, ts, mark, NULL);
03874     LAST_FRAME_CHECKS(cx, script);
03875     return script;
03876 }
03877 
03878 JS_PUBLIC_API(JSBool)
03879 JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
03880                           const char *bytes, size_t length)
03881 {
03882     jschar *chars;
03883     JSBool result;
03884     JSExceptionState *exnState;
03885     void *tempMark;
03886     JSTokenStream *ts;
03887     JSErrorReporter older;
03888 
03889     CHECK_REQUEST(cx);
03890     chars = js_InflateString(cx, bytes, &length);
03891     if (!chars)
03892         return JS_TRUE;
03893 
03894     /*
03895      * Return true on any out-of-memory error, so our caller doesn't try to
03896      * collect more buffered source.
03897      */
03898     result = JS_TRUE;
03899     exnState = JS_SaveExceptionState(cx);
03900     tempMark = JS_ARENA_MARK(&cx->tempPool);
03901     ts = js_NewTokenStream(cx, chars, length, NULL, 0, NULL);
03902     if (ts) {
03903         older = JS_SetErrorReporter(cx, NULL);
03904         if (!js_ParseTokenStream(cx, obj, ts) &&
03905             (ts->flags & TSF_UNEXPECTED_EOF)) {
03906             /*
03907              * We ran into an error.  If it was because we ran out of source,
03908              * we return false, so our caller will know to try to collect more
03909              * buffered source.
03910              */
03911             result = JS_FALSE;
03912         }
03913 
03914         JS_SetErrorReporter(cx, older);
03915         js_CloseTokenStream(cx, ts);
03916         JS_ARENA_RELEASE(&cx->tempPool, tempMark);
03917     }
03918 
03919     JS_free(cx, chars);
03920     JS_RestoreExceptionState(cx, exnState);
03921     return result;
03922 }
03923 
03924 JS_PUBLIC_API(JSScript *)
03925 JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
03926 {
03927     void *mark;
03928     JSTokenStream *ts;
03929     JSScript *script;
03930 
03931     CHECK_REQUEST(cx);
03932     mark = JS_ARENA_MARK(&cx->tempPool);
03933     ts = js_NewFileTokenStream(cx, filename, stdin);
03934     if (!ts)
03935         return NULL;
03936     script = CompileTokenStream(cx, obj, ts, mark, NULL);
03937     LAST_FRAME_CHECKS(cx, script);
03938     return script;
03939 }
03940 
03941 JS_PUBLIC_API(JSScript *)
03942 JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
03943                      FILE *file)
03944 {
03945     return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
03946 }
03947 
03948 JS_PUBLIC_API(JSScript *)
03949 JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
03950                                   const char *filename, FILE *file,
03951                                   JSPrincipals *principals)
03952 {
03953     void *mark;
03954     JSTokenStream *ts;
03955     JSScript *script;
03956 
03957     CHECK_REQUEST(cx);
03958     mark = JS_ARENA_MARK(&cx->tempPool);
03959     ts = js_NewFileTokenStream(cx, NULL, file);
03960     if (!ts)
03961         return NULL;
03962     ts->filename = filename;
03963     /* XXXshaver js_NewFileTokenStream should do this, because it drops */
03964     if (principals) {
03965         ts->principals = principals;
03966         JSPRINCIPALS_HOLD(cx, ts->principals);
03967     }
03968     script = CompileTokenStream(cx, obj, ts, mark, NULL);
03969     LAST_FRAME_CHECKS(cx, script);
03970     return script;
03971 }
03972 
03973 JS_PUBLIC_API(JSObject *)
03974 JS_NewScriptObject(JSContext *cx, JSScript *script)
03975 {
03976     JSTempValueRooter tvr;
03977     JSObject *obj;
03978 
03979     if (!script)
03980         return js_NewObject(cx, &js_ScriptClass, NULL, NULL);
03981 
03982     JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
03983     obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
03984     if (obj) {
03985         JS_SetPrivate(cx, obj, script);
03986         script->object = obj;
03987     }
03988     JS_POP_TEMP_ROOT(cx, &tvr);
03989     return obj;
03990 }
03991 
03992 JS_PUBLIC_API(JSObject *)
03993 JS_GetScriptObject(JSScript *script)
03994 {
03995     return script->object;
03996 }
03997 
03998 JS_PUBLIC_API(void)
03999 JS_DestroyScript(JSContext *cx, JSScript *script)
04000 {
04001     CHECK_REQUEST(cx);
04002     js_DestroyScript(cx, script);
04003 }
04004 
04005 JS_PUBLIC_API(JSFunction *)
04006 JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
04007                    uintN nargs, const char **argnames,
04008                    const char *bytes, size_t length,
04009                    const char *filename, uintN lineno)
04010 {
04011     jschar *chars;
04012     JSFunction *fun;
04013 
04014     CHECK_REQUEST(cx);
04015     chars = js_InflateString(cx, bytes, &length);
04016     if (!chars)
04017         return NULL;
04018     fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length,
04019                                filename, lineno);
04020     JS_free(cx, chars);
04021     return fun;
04022 }
04023 
04024 JS_PUBLIC_API(JSFunction *)
04025 JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
04026                                 JSPrincipals *principals, const char *name,
04027                                 uintN nargs, const char **argnames,
04028                                 const char *bytes, size_t length,
04029                                 const char *filename, uintN lineno)
04030 {
04031     jschar *chars;
04032     JSFunction *fun;
04033 
04034     CHECK_REQUEST(cx);
04035     chars = js_InflateString(cx, bytes, &length);
04036     if (!chars)
04037         return NULL;
04038     fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
04039                                             nargs, argnames, chars, length,
04040                                             filename, lineno);
04041     JS_free(cx, chars);
04042     return fun;
04043 }
04044 
04045 JS_PUBLIC_API(JSFunction *)
04046 JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
04047                      uintN nargs, const char **argnames,
04048                      const jschar *chars, size_t length,
04049                      const char *filename, uintN lineno)
04050 {
04051     CHECK_REQUEST(cx);
04052     return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name,
04053                                              nargs, argnames,
04054                                              chars, length,
04055                                              filename, lineno);
04056 }
04057 
04058 JS_PUBLIC_API(JSFunction *)
04059 JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
04060                                   JSPrincipals *principals, const char *name,
04061                                   uintN nargs, const char **argnames,
04062                                   const jschar *chars, size_t length,
04063                                   const char *filename, uintN lineno)
04064 {
04065     void *mark;
04066     JSTokenStream *ts;
04067     JSFunction *fun;
04068     JSAtom *funAtom, *argAtom;
04069     JSTempValueRooter tvr;
04070     uintN i;
04071 
04072     CHECK_REQUEST(cx);
04073     mark = JS_ARENA_MARK(&cx->tempPool);
04074     ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
04075     if (!ts) {
04076         fun = NULL;
04077         goto out2;
04078     }
04079     if (!name) {
04080         funAtom = NULL;
04081     } else {
04082         funAtom = js_Atomize(cx, name, strlen(name), 0);
04083         if (!funAtom) {
04084             fun = NULL;
04085             goto out2;
04086         }
04087     }
04088     fun = js_NewFunction(cx, NULL, NULL, nargs, 0, obj, funAtom);
04089     if (!fun)
04090         goto out2;
04091 
04092     /* From this point the control must flow through the label out. */
04093     JS_PUSH_TEMP_ROOT_OBJECT(cx, fun->object, &tvr);
04094     if (nargs) {
04095         for (i = 0; i < nargs; i++) {
04096             argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
04097             if (!argAtom)
04098                 break;
04099             if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(argAtom),
04100                                       js_GetArgument, js_SetArgument,
04101                                       SPROP_INVALID_SLOT,
04102                                       JSPROP_PERMANENT | JSPROP_SHARED,
04103                                       SPROP_HAS_SHORTID, i)) {
04104                 break;
04105             }
04106         }
04107         if (i < nargs) {
04108             fun = NULL;
04109             goto out;
04110         }
04111     }
04112     if (!js_CompileFunctionBody(cx, ts, fun)) {
04113         fun = NULL;
04114         goto out;
04115     }
04116     if (obj && funAtom) {
04117         if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom),
04118                                  OBJECT_TO_JSVAL(fun->object),
04119                                  NULL, NULL, JSPROP_ENUMERATE, NULL)) {
04120             fun = NULL;
04121             goto out;
04122         }
04123     }
04124     cx->weakRoots.newborn[GCX_OBJECT] = (JSGCThing *) fun->object;
04125 
04126   out:
04127     JS_POP_TEMP_ROOT(cx, &tvr);
04128 
04129   out2:
04130     if (ts)
04131         js_CloseTokenStream(cx, ts);
04132     JS_ARENA_RELEASE(&cx->tempPool, mark);
04133     LAST_FRAME_CHECKS(cx, fun);
04134     return fun;
04135 }
04136 
04137 JS_PUBLIC_API(JSString *)
04138 JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
04139                    uintN indent)
04140 {
04141     JSPrinter *jp;
04142     JSString *str;
04143 
04144     CHECK_REQUEST(cx);
04145     jp = js_NewPrinter(cx, name,
04146                        indent & ~JS_DONT_PRETTY_PRINT,
04147                        !(indent & JS_DONT_PRETTY_PRINT));
04148     if (!jp)
04149         return NULL;
04150     if (js_DecompileScript(jp, script))
04151         str = js_GetPrinterOutput(jp);
04152     else
04153         str = NULL;
04154     js_DestroyPrinter(jp);
04155     return str;
04156 }
04157 
04158 JS_PUBLIC_API(JSString *)
04159 JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
04160 {
04161     JSPrinter *jp;
04162     JSString *str;
04163 
04164     CHECK_REQUEST(cx);
04165     jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
04166                        indent & ~JS_DONT_PRETTY_PRINT,
04167                        !(indent & JS_DONT_PRETTY_PRINT));
04168     if (!jp)
04169         return NULL;
04170     if (js_DecompileFunction(jp, fun))
04171         str = js_GetPrinterOutput(jp);
04172     else
04173         str = NULL;
04174     js_DestroyPrinter(jp);
04175     return str;
04176 }
04177 
04178 JS_PUBLIC_API(JSString *)
04179 JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
04180 {
04181     JSPrinter *jp;
04182     JSString *str;
04183 
04184     CHECK_REQUEST(cx);
04185     jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
04186                        indent & ~JS_DONT_PRETTY_PRINT,
04187                        !(indent & JS_DONT_PRETTY_PRINT));
04188     if (!jp)
04189         return NULL;
04190     if (js_DecompileFunctionBody(jp, fun))
04191         str = js_GetPrinterOutput(jp);
04192     else
04193         str = NULL;
04194     js_DestroyPrinter(jp);
04195     return str;
04196 }
04197 
04198 JS_PUBLIC_API(JSBool)
04199 JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
04200 {
04201     JSBool ok;
04202 
04203     CHECK_REQUEST(cx);
04204     ok = js_Execute(cx, obj, script, NULL, 0, rval);
04205     LAST_FRAME_CHECKS(cx, ok);
04206     return ok;
04207 }
04208 
04209 JS_PUBLIC_API(JSBool)
04210 JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
04211                      JSExecPart part, jsval *rval)
04212 {
04213     JSScript tmp;
04214     JSRuntime *rt;
04215     JSBool ok;
04216 
04217     /* Make a temporary copy of the JSScript structure and farble it a bit. */
04218     tmp = *script;
04219     if (part == JSEXEC_PROLOG) {
04220         tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode);
04221     } else {
04222         tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode);
04223         tmp.code = tmp.main;
04224     }
04225 
04226     /* Tell the debugger about our temporary copy of the script structure. */
04227     rt = cx->runtime;
04228     if (rt->newScriptHook) {
04229         rt->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL,
04230                           rt->newScriptHookData);
04231     }
04232 
04233     /* Execute the farbled struct and tell the debugger to forget about it. */
04234     ok = JS_ExecuteScript(cx, obj, &tmp, rval);
04235     if (rt->destroyScriptHook)
04236         rt->destroyScriptHook(cx, &tmp, rt->destroyScriptHookData);
04237     return ok;
04238 }
04239 
04240 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
04241 JS_PUBLIC_API(JSBool)
04242 JS_EvaluateScript(JSContext *cx, JSObject *obj,
04243                   const char *bytes, uintN nbytes,
04244                   const char *filename, uintN lineno,
04245                   jsval *rval)
04246 {
04247     size_t length = nbytes;
04248     jschar *chars;
04249     JSBool ok;
04250 
04251     CHECK_REQUEST(cx);
04252     chars = js_InflateString(cx, bytes, &length);
04253     if (!chars)
04254         return JS_FALSE;
04255     ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval);
04256     JS_free(cx, chars);
04257     return ok;
04258 }
04259 
04260 /* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
04261 JS_PUBLIC_API(JSBool)
04262 JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
04263                                JSPrincipals *principals,
04264                                const char *bytes, uintN nbytes,
04265                                const char *filename, uintN lineno,
04266                                jsval *rval)
04267 {
04268     size_t length = nbytes;
04269     jschar *chars;
04270     JSBool ok;
04271 
04272     CHECK_REQUEST(cx);
04273     chars = js_InflateString(cx, bytes, &length);
04274     if (!chars)
04275         return JS_FALSE;
04276     ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
04277                                           filename, lineno, rval);
04278     JS_free(cx, chars);
04279     return ok;
04280 }
04281 
04282 JS_PUBLIC_API(JSBool)
04283 JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
04284                     const jschar *chars, uintN length,
04285                     const char *filename, uintN lineno,
04286                     jsval *rval)
04287 {
04288     CHECK_REQUEST(cx);
04289     return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length,
04290                                             filename, lineno, rval);
04291 }
04292 
04293 JS_PUBLIC_API(JSBool)
04294 JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
04295                                  JSPrincipals *principals,
04296                                  const jschar *chars, uintN length,
04297                                  const char *filename, uintN lineno,
04298                                  jsval *rval)
04299 {
04300     uint32 options;
04301     JSScript *script;
04302     JSBool ok;
04303 
04304     CHECK_REQUEST(cx);
04305     options = cx->options;
04306     cx->options = options | JSOPTION_COMPILE_N_GO;
04307     script = JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length,
04308                                              filename, lineno);
04309     cx->options = options;
04310     if (!script)
04311         return JS_FALSE;
04312     ok = js_Execute(cx, obj, script, NULL, 0, rval);
04313     LAST_FRAME_CHECKS(cx, ok);
04314     JS_DestroyScript(cx, script);
04315     return ok;
04316 }
04317 
04318 JS_PUBLIC_API(JSBool)
04319 JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
04320                 jsval *argv, jsval *rval)
04321 {
04322     JSBool ok;
04323 
04324     CHECK_REQUEST(cx);
04325     ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv,
04326                          rval);
04327     LAST_FRAME_CHECKS(cx, ok);
04328     return ok;
04329 }
04330 
04331 JS_PUBLIC_API(JSBool)
04332 JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
04333                     jsval *argv, jsval *rval)
04334 {
04335     JSBool ok;
04336     jsval fval;
04337 
04338     CHECK_REQUEST(cx);
04339 #if JS_HAS_XML_SUPPORT
04340     if (OBJECT_IS_XML(cx, obj)) {
04341         JSXMLObjectOps *ops;
04342         JSAtom *atom;
04343 
04344         ops = (JSXMLObjectOps *) obj->map->ops;
04345         atom = js_Atomize(cx, name, strlen(name), 0);
04346         if (!atom)
04347             return JS_FALSE;
04348         obj = ops->getMethod(cx, obj, ATOM_TO_JSID(atom), &fval);
04349         if (!obj)
04350             return JS_FALSE;
04351     } else
04352 #endif
04353     if (!JS_GetProperty(cx, obj, name, &fval))
04354         return JS_FALSE;
04355     ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
04356     LAST_FRAME_CHECKS(cx, ok);
04357     return ok;
04358 }
04359 
04360 JS_PUBLIC_API(JSBool)
04361 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
04362                      jsval *argv, jsval *rval)
04363 {
04364     JSBool ok;
04365 
04366     CHECK_REQUEST(cx);
04367     ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
04368     LAST_FRAME_CHECKS(cx, ok);
04369     return ok;
04370 }
04371 
04372 JS_PUBLIC_API(JSBranchCallback)
04373 JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb)
04374 {
04375     JSBranchCallback oldcb;
04376 
04377     oldcb = cx->branchCallback;
04378     cx->branchCallback = cb;
04379     return oldcb;
04380 }
04381 
04382 JS_PUBLIC_API(JSBool)
04383 JS_IsRunning(JSContext *cx)
04384 {
04385     return cx->fp != NULL;
04386 }
04387 
04388 JS_PUBLIC_API(JSBool)
04389 JS_IsConstructing(JSContext *cx)
04390 {
04391     return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
04392 }
04393 
04394 JS_FRIEND_API(JSBool)
04395 JS_IsAssigning(JSContext *cx)
04396 {
04397     JSStackFrame *fp;
04398     jsbytecode *pc;
04399 
04400     for (fp = cx->fp; fp && !fp->script; fp = fp->down)
04401         continue;
04402     if (!fp || !(pc = fp->pc))
04403         return JS_FALSE;
04404     return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0;
04405 }
04406 
04407 JS_PUBLIC_API(void)
04408 JS_SetCallReturnValue2(JSContext *cx, jsval v)
04409 {
04410 #if JS_HAS_LVALUE_RETURN
04411     cx->rval2 = v;
04412     cx->rval2set = JS_TRUE;
04413 #endif
04414 }
04415 
04416 JS_PUBLIC_API(JSStackFrame *)
04417 JS_SaveFrameChain(JSContext *cx)
04418 {
04419     JSStackFrame *fp;
04420 
04421     fp = cx->fp;
04422     if (!fp)
04423         return fp;
04424 
04425     JS_ASSERT(!fp->dormantNext);
04426     fp->dormantNext = cx->dormantFrameChain;
04427     cx->dormantFrameChain = fp;
04428     cx->fp = NULL;
04429     return fp;
04430 }
04431 
04432 JS_PUBLIC_API(void)
04433 JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
04434 {
04435     JS_ASSERT(!cx->fp);
04436     if (!fp)
04437         return;
04438 
04439     JS_ASSERT(cx->dormantFrameChain == fp);
04440     cx->fp = fp;
04441     cx->dormantFrameChain = fp->dormantNext;
04442     fp->dormantNext = NULL;
04443 }
04444 
04445 /************************************************************************/
04446 
04447 JS_PUBLIC_API(JSString *)
04448 JS_NewString(JSContext *cx, char *bytes, size_t nbytes)
04449 {
04450     size_t length = nbytes;
04451     jschar *chars;
04452     JSString *str;
04453 
04454     CHECK_REQUEST(cx);
04455 
04456     /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
04457     chars = js_InflateString(cx, bytes, &length);
04458     if (!chars)
04459         return NULL;
04460 
04461     /* Free chars (but not bytes, which caller frees on error) if we fail. */
04462     str = js_NewString(cx, chars, length, 0);
04463     if (!str) {
04464         JS_free(cx, chars);
04465         return NULL;
04466     }
04467 
04468     /* Hand off bytes to the deflated string cache, if possible. */
04469     if (!js_SetStringBytes(cx->runtime, str, bytes, nbytes))
04470         JS_free(cx, bytes);
04471     return str;
04472 }
04473 
04474 JS_PUBLIC_API(JSString *)
04475 JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
04476 {
04477     jschar *js;
04478     JSString *str;
04479 
04480     CHECK_REQUEST(cx);
04481     js = js_InflateString(cx, s, &n);
04482     if (!js)
04483         return NULL;
04484     str = js_NewString(cx, js, n, 0);
04485     if (!str)
04486         JS_free(cx, js);
04487     return str;
04488 }
04489 
04490 JS_PUBLIC_API(JSString *)
04491 JS_NewStringCopyZ(JSContext *cx, const char *s)
04492 {
04493     size_t n;
04494     jschar *js;
04495     JSString *str;
04496 
04497     CHECK_REQUEST(cx);
04498     if (!s)
04499         return cx->runtime->emptyString;
04500     n = strlen(s);
04501     js = js_InflateString(cx, s, &n);
04502     if (!js)
04503         return NULL;
04504     str = js_NewString(cx, js, n, 0);
04505     if (!str)
04506         JS_free(cx, js);
04507     return str;
04508 }
04509 
04510 JS_PUBLIC_API(JSString *)
04511 JS_InternString(JSContext *cx, const char *s)
04512 {
04513     JSAtom *atom;
04514 
04515     CHECK_REQUEST(cx);
04516     atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
04517     if (!atom)
04518         return NULL;
04519     return ATOM_TO_STRING(atom);
04520 }
04521 
04522 JS_PUBLIC_API(JSString *)
04523 JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
04524 {
04525     CHECK_REQUEST(cx);
04526     return js_NewString(cx, chars, length, 0);
04527 }
04528 
04529 JS_PUBLIC_API(JSString *)
04530 JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
04531 {
04532     CHECK_REQUEST(cx);
04533     return js_NewStringCopyN(cx, s, n, 0);
04534 }
04535 
04536 JS_PUBLIC_API(JSString *)
04537 JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
04538 {
04539     CHECK_REQUEST(cx);
04540     if (!s)
04541         return cx->runtime->emptyString;
04542     return js_NewStringCopyZ(cx, s, 0);
04543 }
04544 
04545 JS_PUBLIC_API(JSString *)
04546 JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
04547 {
04548     JSAtom *atom;
04549 
04550     CHECK_REQUEST(cx);
04551     atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
04552     if (!atom)
04553         return NULL;
04554     return ATOM_TO_STRING(atom);
04555 }
04556 
04557 JS_PUBLIC_API(JSString *)
04558 JS_InternUCString(JSContext *cx, const jschar *s)
04559 {
04560     return JS_InternUCStringN(cx, s, js_strlen(s));
04561 }
04562 
04563 JS_PUBLIC_API(char *)
04564 JS_GetStringBytes(JSString *str)
04565 {
04566     JSRuntime *rt;
04567     char *bytes;
04568 
04569     rt = js_GetGCStringRuntime(str);
04570     bytes = js_GetStringBytes(rt, str);
04571     return bytes ? bytes : "";
04572 }
04573 
04574 JS_PUBLIC_API(jschar *)
04575 JS_GetStringChars(JSString *str)
04576 {
04577     /*
04578      * API botch (again, shades of JS_GetStringBytes): we have no cx to pass
04579      * to js_UndependString (called by js_GetStringChars) for out-of-memory
04580      * error reports, so js_UndependString passes NULL and suppresses errors.
04581      * If it fails to convert a dependent string into an independent one, our
04582      * caller will not be guaranteed a \u0000 terminator as a backstop.  This
04583      * may break some clients who already misbehave on embedded NULs.
04584      *
04585      * The gain of dependent strings, which cure quadratic and cubic growth
04586      * rate bugs in string concatenation, is worth this slight loss in API
04587      * compatibility.
04588      */
04589     jschar *chars;
04590 
04591     chars = js_GetStringChars(str);
04592     return chars ? chars : JSSTRING_CHARS(str);
04593 }
04594 
04595 JS_PUBLIC_API(size_t)
04596 JS_GetStringLength(JSString *str)
04597 {
04598     return JSSTRING_LENGTH(str);
04599 }
04600 
04601 JS_PUBLIC_API(intN)
04602 JS_CompareStrings(JSString *str1, JSString *str2)
04603 {
04604     return js_CompareStrings(str1, str2);
04605 }
04606 
04607 JS_PUBLIC_API(JSString *)
04608 JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
04609 {
04610     CHECK_REQUEST(cx);
04611     return js_NewString(cx, chars, length, GCF_MUTABLE);
04612 }
04613 
04614 JS_PUBLIC_API(JSString *)
04615 JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
04616                       size_t length)
04617 {
04618     CHECK_REQUEST(cx);
04619     return js_NewDependentString(cx, str, start, length, 0);
04620 }
04621 
04622 JS_PUBLIC_API(JSString *)
04623 JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
04624 {
04625     CHECK_REQUEST(cx);
04626     return js_ConcatStrings(cx, left, right);
04627 }
04628 
04629 JS_PUBLIC_API(const jschar *)
04630 JS_UndependString(JSContext *cx, JSString *str)
04631 {
04632     CHECK_REQUEST(cx);
04633     return js_UndependString(cx, str);
04634 }
04635 
04636 JS_PUBLIC_API(JSBool)
04637 JS_MakeStringImmutable(JSContext *cx, JSString *str)
04638 {
04639     CHECK_REQUEST(cx);
04640     if (!js_UndependString(cx, str))
04641         return JS_FALSE;
04642 
04643     *js_GetGCThingFlags(str) &= ~GCF_MUTABLE;
04644     return JS_TRUE;
04645 }
04646 
04647 JS_PUBLIC_API(JSBool)
04648 JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
04649                     size_t *dstlenp)
04650 {
04651     return js_DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
04652 }
04653 
04654 JS_PUBLIC_API(JSBool)
04655 JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
04656                size_t *dstlenp)
04657 {
04658     return js_InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
04659 }
04660 
04661 JS_PUBLIC_API(JSBool)
04662 JS_CStringsAreUTF8()
04663 {
04664 #ifdef JS_C_STRINGS_ARE_UTF8
04665     return JS_TRUE;
04666 #else
04667     return JS_FALSE;
04668 #endif
04669 }
04670 
04671 /************************************************************************/
04672 
04673 JS_PUBLIC_API(void)
04674 JS_ReportError(JSContext *cx, const char *format, ...)
04675 {
04676     va_list ap;
04677 
04678     va_start(ap, format);
04679     js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
04680     va_end(ap);
04681 }
04682 
04683 JS_PUBLIC_API(void)
04684 JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
04685                      void *userRef, const uintN errorNumber, ...)
04686 {
04687     va_list ap;
04688 
04689     va_start(ap, errorNumber);
04690     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
04691                            errorNumber, JS_TRUE, ap);
04692     va_end(ap);
04693 }
04694 
04695 JS_PUBLIC_API(void)
04696 JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
04697                      void *userRef, const uintN errorNumber, ...)
04698 {
04699     va_list ap;
04700 
04701     va_start(ap, errorNumber);
04702     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
04703                            errorNumber, JS_FALSE, ap);
04704     va_end(ap);
04705 }
04706 
04707 JS_PUBLIC_API(JSBool)
04708 JS_ReportWarning(JSContext *cx, const char *format, ...)
04709 {
04710     va_list ap;
04711     JSBool ok;
04712 
04713     va_start(ap, format);
04714     ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
04715     va_end(ap);
04716     return ok;
04717 }
04718 
04719 JS_PUBLIC_API(JSBool)
04720 JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
04721                              JSErrorCallback errorCallback, void *userRef,
04722                              const uintN errorNumber, ...)
04723 {
04724     va_list ap;
04725     JSBool ok;
04726 
04727     va_start(ap, errorNumber);
04728     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
04729                                 errorNumber, JS_TRUE, ap);
04730     va_end(ap);
04731     return ok;
04732 }
04733 
04734 JS_PUBLIC_API(JSBool)
04735 JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
04736                                JSErrorCallback errorCallback, void *userRef,
04737                                const uintN errorNumber, ...)
04738 {
04739     va_list ap;
04740     JSBool ok;
04741 
04742     va_start(ap, errorNumber);
04743     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
04744                                 errorNumber, JS_FALSE, ap);
04745     va_end(ap);
04746     return ok;
04747 }
04748 
04749 JS_PUBLIC_API(void)
04750 JS_ReportOutOfMemory(JSContext *cx)
04751 {
04752     js_ReportOutOfMemory(cx);
04753 }
04754 
04755 JS_PUBLIC_API(JSErrorReporter)
04756 JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
04757 {
04758     JSErrorReporter older;
04759 
04760     older = cx->errorReporter;
04761     cx->errorReporter = er;
04762     return older;
04763 }
04764 
04765 /************************************************************************/
04766 
04767 /*
04768  * Regular Expressions.
04769  */
04770 JS_PUBLIC_API(JSObject *)
04771 JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
04772 {
04773     jschar *chars;
04774     JSObject *obj;
04775 
04776     CHECK_REQUEST(cx);
04777     chars = js_InflateString(cx, bytes, &length);
04778     if (!chars)
04779         return NULL;
04780     obj = js_NewRegExpObject(cx, NULL, chars, length, flags);
04781     JS_free(cx, chars);
04782     return obj;
04783 }
04784 
04785 JS_PUBLIC_API(JSObject *)
04786 JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
04787 {
04788     CHECK_REQUEST(cx);
04789     return js_NewRegExpObject(cx, NULL, chars, length, flags);
04790 }
04791 
04792 JS_PUBLIC_API(void)
04793 JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
04794 {
04795     JSRegExpStatics *res;
04796 
04797     CHECK_REQUEST(cx);
04798     /* No locking required, cx is thread-private and input must be live. */
04799     res = &cx->regExpStatics;
04800     res->input = input;
04801     res->multiline = multiline;
04802     cx->runtime->gcPoke = JS_TRUE;
04803 }
04804 
04805 JS_PUBLIC_API(void)
04806 JS_ClearRegExpStatics(JSContext *cx)
04807 {
04808     JSRegExpStatics *res;
04809 
04810     /* No locking required, cx is thread-private and input must be live. */
04811     res = &cx->regExpStatics;
04812     res->input = NULL;
04813     res->multiline = JS_FALSE;
04814     res->parenCount = 0;
04815     res->lastMatch = res->lastParen = js_EmptySubString;
04816     res->leftContext = res->rightContext = js_EmptySubString;
04817     cx->runtime->gcPoke = JS_TRUE;
04818 }
04819 
04820 JS_PUBLIC_API(void)
04821 JS_ClearRegExpRoots(JSContext *cx)
04822 {
04823     JSRegExpStatics *res;
04824 
04825     /* No locking required, cx is thread-private and input must be live. */
04826     res = &cx->regExpStatics;
04827     res->input = NULL;
04828     cx->runtime->gcPoke = JS_TRUE;
04829 }
04830 
04831 /* TODO: compile, execute, get/set other statics... */
04832 
04833 /************************************************************************/
04834 
04835 JS_PUBLIC_API(void)
04836 JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
04837 {
04838     cx->localeCallbacks = callbacks;
04839 }
04840 
04841 JS_PUBLIC_API(JSLocaleCallbacks *)
04842 JS_GetLocaleCallbacks(JSContext *cx)
04843 {
04844     return cx->localeCallbacks;
04845 }
04846 
04847 /************************************************************************/
04848 
04849 JS_PUBLIC_API(JSBool)
04850 JS_IsExceptionPending(JSContext *cx)
04851 {
04852     return (JSBool) cx->throwing;
04853 }
04854 
04855 JS_PUBLIC_API(JSBool)
04856 JS_GetPendingException(JSContext *cx, jsval *vp)
04857 {
04858     CHECK_REQUEST(cx);
04859     if (!cx->throwing)
04860         return JS_FALSE;
04861     *vp = cx->exception;
04862     return JS_TRUE;
04863 }
04864 
04865 JS_PUBLIC_API(void)
04866 JS_SetPendingException(JSContext *cx, jsval v)
04867 {
04868     CHECK_REQUEST(cx);
04869     cx->throwing = JS_TRUE;
04870     cx->exception = v;
04871 }
04872 
04873 JS_PUBLIC_API(void)
04874 JS_ClearPendingException(JSContext *cx)
04875 {
04876     cx->throwing = JS_FALSE;
04877     cx->exception = JSVAL_VOID;
04878 }
04879 
04880 JS_PUBLIC_API(JSBool)
04881 JS_ReportPendingException(JSContext *cx)
04882 {
04883     JSBool save, ok;
04884 
04885     CHECK_REQUEST(cx);
04886 
04887     /*
04888      * Set cx->creatingException to suppress the standard error-to-exception
04889      * conversion done by all {js,JS}_Report* functions except for OOM.  The
04890      * cx->creatingException flag was added to suppress recursive divergence
04891      * under js_ErrorToException, but it serves for our purposes here too.
04892      */
04893     save = cx->creatingException;
04894     cx->creatingException = JS_TRUE;
04895     ok = js_ReportUncaughtException(cx);
04896     cx->creatingException = save;
04897     return ok;
04898 }
04899 
04900 struct JSExceptionState {
04901     JSBool throwing;
04902     jsval  exception;
04903 };
04904 
04905 JS_PUBLIC_API(JSExceptionState *)
04906 JS_SaveExceptionState(JSContext *cx)
04907 {
04908     JSExceptionState *state;
04909 
04910     CHECK_REQUEST(cx);
04911     state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState));
04912     if (state) {
04913         state->throwing = JS_GetPendingException(cx, &state->exception);
04914         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
04915             js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
04916     }
04917     return state;
04918 }
04919 
04920 JS_PUBLIC_API(void)
04921 JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
04922 {
04923     CHECK_REQUEST(cx);
04924     if (state) {
04925         if (state->throwing)
04926             JS_SetPendingException(cx, state->exception);
04927         else
04928             JS_ClearPendingException(cx);
04929         JS_DropExceptionState(cx, state);
04930     }
04931 }
04932 
04933 JS_PUBLIC_API(void)
04934 JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
04935 {
04936     CHECK_REQUEST(cx);
04937     if (state) {
04938         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
04939             JS_RemoveRoot(cx, &state->exception);
04940         JS_free(cx, state);
04941     }
04942 }
04943 
04944 JS_PUBLIC_API(JSErrorReport *)
04945 JS_ErrorFromException(JSContext *cx, jsval v)
04946 {
04947     CHECK_REQUEST(cx);
04948     return js_ErrorFromException(cx, v);
04949 }
04950 
04951 JS_PUBLIC_API(JSBool)
04952 JS_ThrowReportedError(JSContext *cx, const char *message,
04953                       JSErrorReport *reportp)
04954 {
04955     return js_ErrorToException(cx, message, reportp);
04956 }
04957 
04958 #ifdef JS_THREADSAFE
04959 /*
04960  * Get the owning thread id of a context. Returns 0 if the context is not
04961  * owned by any thread.
04962  */
04963 JS_PUBLIC_API(jsword)
04964 JS_GetContextThread(JSContext *cx)
04965 {
04966     return JS_THREAD_ID(cx);
04967 }
04968 
04969 /*
04970  * Set the current thread as the owning thread of a context. Returns the
04971  * old owning thread id, or -1 if the operation failed.
04972  */
04973 JS_PUBLIC_API(jsword)
04974 JS_SetContextThread(JSContext *cx)
04975 {
04976     jsword old = JS_THREAD_ID(cx);
04977     if (!js_SetContextThread(cx))
04978         return -1;
04979     return old;
04980 }
04981 
04982 JS_PUBLIC_API(jsword)
04983 JS_ClearContextThread(JSContext *cx)
04984 {
04985     jsword old = JS_THREAD_ID(cx);
04986     js_ClearContextThread(cx);
04987     return old;
04988 }
04989 #endif
04990 
04991 #ifdef JS_GC_ZEAL
04992 JS_PUBLIC_API(void)
04993 JS_SetGCZeal(JSContext *cx, uint8 zeal)
04994 {
04995     cx->runtime->gcZeal = zeal;
04996 }
04997 #endif
04998 
04999 /************************************************************************/
05000 
05001 #if defined(XP_WIN)
05002 #include <windows.h>
05003 /*
05004  * Initialization routine for the JS DLL...
05005  */
05006 
05007 /*
05008  * Global Instance handle...
05009  * In Win32 this is the module handle of the DLL.
05010  *
05011  * In Win16 this is the instance handle of the application
05012  * which loaded the DLL.
05013  */
05014 
05015 #ifdef _WIN32
05016 BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
05017 {
05018     return TRUE;
05019 }
05020 
05021 #else  /* !_WIN32 */
05022 
05023 int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
05024                       WORD cbHeapSize, LPSTR lpszCmdLine )
05025 {
05026     return TRUE;
05027 }
05028 
05029 BOOL CALLBACK __loadds WEP(BOOL fSystemExit)
05030 {
05031     return TRUE;
05032 }
05033 
05034 #endif /* !_WIN32 */
05035 #endif /* XP_WIN */