LCOV - app.info - js/src/jsapi.cpp

LCOV - code coverage report
| Current view: | directory - js/src - jsapi.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 3055 | 1491 | 48.8 %
| Date: | 2012-04-07 | Functions: | 475 | 245 | 51.6 %

           1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=8 sw=4 et tw=78:
           3                 :  *
           4                 :  * ***** BEGIN LICENSE BLOCK *****
           5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           6                 :  *
           7                 :  * The contents of this file are subject to the Mozilla Public License Version
           8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           9                 :  * the License. You may obtain a copy of the License at
          10                 :  * http://www.mozilla.org/MPL/
          11                 :  *
          12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          14                 :  * for the specific language governing rights and limitations under the
          15                 :  * License.
          16                 :  *
          17                 :  * The Original Code is Mozilla Communicator client code, released
          18                 :  * March 31, 1998.
          19                 :  *
          20                 :  * The Initial Developer of the Original Code is
          21                 :  * Netscape Communications Corporation.
          22                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          23                 :  * the Initial Developer. All Rights Reserved.
          24                 :  *
          25                 :  * Contributor(s):
          26                 :  *
          27                 :  * Alternatively, the contents of this file may be used under the terms of
          28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          31                 :  * of those above. If you wish to allow use of your version of this file only
          32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          33                 :  * use your version of this file under the terms of the MPL, indicate your
          34                 :  * decision by deleting the provisions above and replace them with the notice
          35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          36                 :  * the provisions above, a recipient may use your version of this file under
          37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          38                 :  *
          39                 :  * ***** END LICENSE BLOCK ***** */
          40                 :
          41                 : /*
          42                 :  * JavaScript API.
          43                 :  */
          44                 : #include <ctype.h>
          45                 : #include <stdarg.h>
          46                 : #include <stdlib.h>
          47                 : #include <string.h>
          48                 : #include <sys/stat.h>
          49                 : #include "jstypes.h"
          50                 : #include "jsutil.h"
          51                 : #include "jsclist.h"
          52                 : #include "jsprf.h"
          53                 : #include "jsapi.h"
          54                 : #include "jsarray.h"
          55                 : #include "jsatom.h"
          56                 : #include "jsbool.h"
          57                 : #include "jsclone.h"
          58                 : #include "jscntxt.h"
          59                 : #include "jsversion.h"
          60                 : #include "jsdate.h"
          61                 : #include "jsdtoa.h"
          62                 : #include "jsexn.h"
          63                 : #include "jsfun.h"
          64                 : #include "jsgc.h"
          65                 : #include "jsgcmark.h"
          66                 : #include "jsinterp.h"
          67                 : #include "jsiter.h"
          68                 : #include "jslock.h"
          69                 : #include "jsmath.h"
          70                 : #include "jsnativestack.h"
          71                 : #include "jsnum.h"
          72                 : #include "json.h"
          73                 : #include "jsobj.h"
          74                 : #include "jsopcode.h"
          75                 : #include "jsprobes.h"
          76                 : #include "jsproxy.h"
          77                 : #include "jsscope.h"
          78                 : #include "jsscript.h"
          79                 : #include "jsstr.h"
          80                 : #include "prmjtime.h"
          81                 : #include "jsweakmap.h"
          82                 : #include "jswrapper.h"
          83                 : #include "jstypedarray.h"
          84                 : #include "jsxml.h"
          85                 :
          86                 : #include "ds/LifoAlloc.h"
          87                 : #include "builtin/MapObject.h"
          88                 : #include "builtin/RegExp.h"
          89                 : #include "frontend/BytecodeCompiler.h"
          90                 : #include "frontend/BytecodeEmitter.h"
          91                 : #include "gc/Memory.h"
          92                 : #include "js/MemoryMetrics.h"
          93                 : #include "yarr/BumpPointerAllocator.h"
          94                 : #include "vm/MethodGuard.h"
          95                 : #include "vm/StringBuffer.h"
          96                 : #include "vm/Xdr.h"
          97                 :
          98                 : #include "jsatominlines.h"
          99                 : #include "jsinferinlines.h"
         100                 : #include "jsobjinlines.h"
         101                 : #include "jsscopeinlines.h"
         102                 : #include "jsscriptinlines.h"
         103                 :
         104                 : #include "vm/ObjectImpl-inl.h"
         105                 : #include "vm/RegExpObject-inl.h"
         106                 : #include "vm/RegExpStatics-inl.h"
         107                 : #include "vm/Stack-inl.h"
         108                 : #include "vm/String-inl.h"
         109                 :
         110                 : #if ENABLE_YARR_JIT
         111                 : #include "assembler/jit/ExecutableAllocator.h"
         112                 : #include "methodjit/Logging.h"
         113                 : #endif
         114                 :
         115                 : using namespace js;
         116                 : using namespace js::gc;
         117                 : using namespace js::types;
         118                 :
         119                 : /*
         120                 :  * This class is a version-establising barrier at the head of a VM entry or
         121                 :  * re-entry. It ensures that:
         122                 :  *
         123                 :  * - |newVersion| is the starting (default) version used for the context.
         124                 :  * - The starting version state is not an override.
         125                 :  * - Overrides in the VM session are not propagated to the caller.
         126                 :  */
         127                 : class AutoVersionAPI
         128                 : {
         129                 :     JSContext   * const cx;
         130                 :     JSVersion   oldDefaultVersion;
         131                 :     bool        oldHasVersionOverride;
         132                 :     JSVersion   oldVersionOverride;
         133                 : #ifdef DEBUG
         134                 :     unsigned       oldCompileOptions;
         135                 : #endif
         136                 :     JSVersion   newVersion;
         137                 :
         138                 :   public:
         139              46 :     explicit AutoVersionAPI(JSContext *cx, JSVersion newVersion)
         140                 :       : cx(cx),
         141              46 :         oldDefaultVersion(cx->getDefaultVersion()),
         142              46 :         oldHasVersionOverride(cx->isVersionOverridden()),
         143                 :         oldVersionOverride(oldHasVersionOverride ? cx->findVersion() : JSVERSION_UNKNOWN)
         144                 : #ifdef DEBUG
         145             138 :         , oldCompileOptions(cx->getCompileOptions())
         146                 : #endif
         147                 :     {
         148              46 :         this->newVersion = newVersion;
         149              46 :         cx->clearVersionOverride();
         150              46 :         cx->setDefaultVersion(newVersion);
         151              46 :     }
         152                 :
         153              46 :     ~AutoVersionAPI() {
         154              46 :         cx->setDefaultVersion(oldDefaultVersion);
         155              46 :         if (oldHasVersionOverride)
         156               1 :             cx->overrideVersion(oldVersionOverride);
         157                 :         else
         158              45 :             cx->clearVersionOverride();
         159              46 :         JS_ASSERT(oldCompileOptions == cx->getCompileOptions());
         160              46 :     }
         161                 :
         162                 :     /* The version that this scoped-entity establishes. */
         163              46 :     JSVersion version() const { return newVersion; }
         164                 : };
         165                 :
         166                 : #ifdef HAVE_VA_LIST_AS_ARRAY
         167                 : #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
         168                 : #else
         169                 : #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
         170                 : #endif
         171                 :
         172                 : #ifdef JS_USE_JSID_STRUCT_TYPES
         173                 : jsid JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) };
         174                 : jsid JSID_VOID  = { size_t(JSID_TYPE_VOID) };
         175                 : jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
         176                 : #endif
         177                 :
         178           18667 : const jsval JSVAL_NULL  = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL,      0));
         179           18667 : const jsval JSVAL_ZERO  = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32,     0));
         180           18667 : const jsval JSVAL_ONE   = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32,     1));
         181           18667 : const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_FALSE));
         182           18667 : const jsval JSVAL_TRUE  = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_TRUE));
         183           18667 : const jsval JSVAL_VOID  = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
         184                 :
         185                 : /* Make sure that jschar is two bytes unsigned integer */
         186                 : JS_STATIC_ASSERT((jschar)-1 > 0);
         187                 : JS_STATIC_ASSERT(sizeof(jschar) == 2);
         188                 :
         189                 : JS_PUBLIC_API(int64_t)
         190               0 : JS_Now()
         191                 : {
         192               0 :     return PRMJ_Now();
         193                 : }
         194                 :
         195                 : JS_PUBLIC_API(jsval)
         196               0 : JS_GetNaNValue(JSContext *cx)
         197                 : {
         198               0 :     return cx->runtime->NaNValue;
         199                 : }
         200                 :
         201                 : JS_PUBLIC_API(jsval)
         202               0 : JS_GetNegativeInfinityValue(JSContext *cx)
         203                 : {
         204               0 :     return cx->runtime->negativeInfinityValue;
         205                 : }
         206                 :
         207                 : JS_PUBLIC_API(jsval)
         208               0 : JS_GetPositiveInfinityValue(JSContext *cx)
         209                 : {
         210               0 :     return cx->runtime->positiveInfinityValue;
         211                 : }
         212                 :
         213                 : JS_PUBLIC_API(jsval)
         214               1 : JS_GetEmptyStringValue(JSContext *cx)
         215                 : {
         216               1 :     return STRING_TO_JSVAL(cx->runtime->emptyString);
         217                 : }
         218                 :
         219                 : JS_PUBLIC_API(JSString *)
         220               0 : JS_GetEmptyString(JSRuntime *rt)
         221                 : {
         222               0 :     JS_ASSERT(rt->hasContexts());
         223               0 :     return rt->emptyString;
         224                 : }
         225                 :
         226                 : static JSBool
         227               0 : TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS, jsval **vpp, va_list *app)
         228                 : {
         229                 :     const char *format;
         230                 :     JSArgumentFormatMap *map;
         231                 :
         232               0 :     format = *formatp;
         233               0 :     for (map = cx->argumentFormatMap; map; map = map->next) {
         234               0 :         if (!strncmp(format, map->format, map->length)) {
         235               0 :             *formatp = format + map->length;
         236               0 :             return map->formatter(cx, format, fromJS, vpp, app);
         237                 :         }
         238                 :     }
         239               0 :     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
         240               0 :     return JS_FALSE;
         241                 : }
         242                 :
         243                 : static void
         244      1129704867 : AssertNoGC(JSRuntime *rt)
         245                 : {
         246      1129704867 :     JS_ASSERT(!rt->gcRunning);
         247      1129704867 : }
         248                 :
         249                 : static void
         250      1129704317 : AssertNoGC(JSContext *cx)
         251                 : {
         252      1129704317 :     AssertNoGC(cx->runtime);
         253      1129704317 : }
         254                 :
         255                 : static void
         256            1649 : AssertNoGCOrFlatString(JSContext *cx, JSString *str)
         257                 : {
         258                 :     /*
         259                 :      * We allow some functions to be called during a GC as long as the argument
         260                 :      * is a flat string, since that will not cause allocation.
         261                 :      */
         262            1649 :     JS_ASSERT_IF(cx->runtime->gcRunning, str->isFlat());
         263            1649 : }
         264                 :
         265                 : JS_PUBLIC_API(JSBool)
         266             378 : JS_ConvertArguments(JSContext *cx, unsigned argc, jsval *argv, const char *format, ...)
         267                 : {
         268                 :     va_list ap;
         269                 :     JSBool ok;
         270                 :
         271             378 :     AssertNoGC(cx);
         272                 :
         273             378 :     va_start(ap, format);
         274             378 :     ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
         275             378 :     va_end(ap);
         276             378 :     return ok;
         277                 : }
         278                 :
         279                 : JS_PUBLIC_API(JSBool)
         280             378 : JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *format, va_list ap)
         281                 : {
         282                 :     jsval *sp;
         283                 :     JSBool required;
         284                 :     char c;
         285                 :     JSFunction *fun;
         286                 :     double d;
         287                 :     JSString *str;
         288                 :     JSObject *obj;
         289                 :
         290             378 :     AssertNoGC(cx);
         291             756 :     CHECK_REQUEST(cx);
         292             378 :     assertSameCompartment(cx, JSValueArray(argv - 2, argc + 2));
         293             378 :     sp = argv;
         294             378 :     required = JS_TRUE;
         295            2331 :     while ((c = *format++) != '\0') {
         296            1800 :         if (isspace(c))
         297             711 :             continue;
         298            1089 :         if (c == '/') {
         299             369 :             required = JS_FALSE;
         300             369 :             continue;
         301                 :         }
         302             720 :         if (sp == argv + argc) {
         303             225 :             if (required) {
         304               0 :                 fun = js_ValueToFunction(cx, &argv[-2], 0);
         305               0 :                 if (fun) {
         306                 :                     char numBuf[12];
         307               0 :                     JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
         308               0 :                     JSAutoByteString funNameBytes;
         309               0 :                     if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
         310                 :                         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
         311               0 :                                              name, numBuf, (argc == 1) ? "" : "s");
         312                 :                     }
         313                 :                 }
         314               0 :                 return JS_FALSE;
         315                 :             }
         316             225 :             break;
         317                 :         }
         318             495 :         switch (c) {
         319                 :           case 'b':
         320               0 :             *va_arg(ap, JSBool *) = js_ValueToBoolean(*sp);
         321               0 :             break;
         322                 :           case 'c':
         323               0 :             if (!JS_ValueToUint16(cx, *sp, va_arg(ap, uint16_t *)))
         324               0 :                 return JS_FALSE;
         325               0 :             break;
         326                 :           case 'i':
         327              18 :             if (!JS_ValueToECMAInt32(cx, *sp, va_arg(ap, int32_t *)))
         328               0 :                 return JS_FALSE;
         329              18 :             break;
         330                 :           case 'u':
         331               9 :             if (!JS_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32_t *)))
         332               0 :                 return JS_FALSE;
         333               9 :             break;
         334                 :           case 'j':
         335               0 :             if (!JS_ValueToInt32(cx, *sp, va_arg(ap, int32_t *)))
         336               0 :                 return JS_FALSE;
         337               0 :             break;
         338                 :           case 'd':
         339               0 :             if (!JS_ValueToNumber(cx, *sp, va_arg(ap, double *)))
         340               0 :                 return JS_FALSE;
         341               0 :             break;
         342                 :           case 'I':
         343               0 :             if (!JS_ValueToNumber(cx, *sp, &d))
         344               0 :                 return JS_FALSE;
         345               0 :             *va_arg(ap, double *) = js_DoubleToInteger(d);
         346               0 :             break;
         347                 :           case 'S':
         348                 :           case 'W':
         349             342 :             str = ToString(cx, *sp);
         350             342 :             if (!str)
         351               0 :                 return JS_FALSE;
         352             342 :             *sp = STRING_TO_JSVAL(str);
         353             342 :             if (c == 'W') {
         354               0 :                 JSFixedString *fixed = str->ensureFixed(cx);
         355               0 :                 if (!fixed)
         356               0 :                     return JS_FALSE;
         357               0 :                 *va_arg(ap, const jschar **) = fixed->chars();
         358                 :             } else {
         359             342 :                 *va_arg(ap, JSString **) = str;
         360                 :             }
         361             342 :             break;
         362                 :           case 'o':
         363             126 :             if (!js_ValueToObjectOrNull(cx, *sp, &obj))
         364               0 :                 return JS_FALSE;
         365             126 :             *sp = OBJECT_TO_JSVAL(obj);
         366             126 :             *va_arg(ap, JSObject **) = obj;
         367             126 :             break;
         368                 :           case 'f':
         369               0 :             obj = js_ValueToFunction(cx, sp, 0);
         370               0 :             if (!obj)
         371               0 :                 return JS_FALSE;
         372               0 :             *sp = OBJECT_TO_JSVAL(obj);
         373               0 :             *va_arg(ap, JSFunction **) = obj->toFunction();
         374               0 :             break;
         375                 :           case 'v':
         376               0 :             *va_arg(ap, jsval *) = *sp;
         377               0 :             break;
         378                 :           case '*':
         379               0 :             break;
         380                 :           default:
         381               0 :             format--;
         382               0 :             if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
         383               0 :                                       JS_ADDRESSOF_VA_LIST(ap))) {
         384               0 :                 return JS_FALSE;
         385                 :             }
         386                 :             /* NB: the formatter already updated sp, so we continue here. */
         387               0 :             continue;
         388                 :         }
         389             495 :         sp++;
         390                 :     }
         391             378 :     return JS_TRUE;
         392                 : }
         393                 :
         394                 : JS_PUBLIC_API(JSBool)
         395               0 : JS_AddArgumentFormatter(JSContext *cx, const char *format, JSArgumentFormatter formatter)
         396                 : {
         397                 :     size_t length;
         398                 :     JSArgumentFormatMap **mpp, *map;
         399                 :
         400               0 :     length = strlen(format);
         401               0 :     mpp = &cx->argumentFormatMap;
         402               0 :     while ((map = *mpp) != NULL) {
         403                 :         /* Insert before any shorter string to match before prefixes. */
         404               0 :         if (map->length < length)
         405               0 :             break;
         406               0 :         if (map->length == length && !strcmp(map->format, format))
         407               0 :             goto out;
         408               0 :         mpp = &map->next;
         409                 :     }
         410               0 :     map = (JSArgumentFormatMap *) cx->malloc_(sizeof *map);
         411               0 :     if (!map)
         412               0 :         return JS_FALSE;
         413               0 :     map->format = format;
         414               0 :     map->length = length;
         415               0 :     map->next = *mpp;
         416               0 :     *mpp = map;
         417                 : out:
         418               0 :     map->formatter = formatter;
         419               0 :     return JS_TRUE;
         420                 : }
         421                 :
         422                 : JS_PUBLIC_API(void)
         423               0 : JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
         424                 : {
         425                 :     size_t length;
         426                 :     JSArgumentFormatMap **mpp, *map;
         427                 :
         428               0 :     length = strlen(format);
         429               0 :     mpp = &cx->argumentFormatMap;
         430               0 :     while ((map = *mpp) != NULL) {
         431               0 :         if (map->length == length && !strcmp(map->format, format)) {
         432               0 :             *mpp = map->next;
         433               0 :             cx->free_(map);
         434               0 :             return;
         435                 :         }
         436               0 :         mpp = &map->next;
         437                 :     }
         438                 : }
         439                 :
         440                 : JS_PUBLIC_API(JSBool)
         441              36 : JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
         442                 : {
         443                 :     JSBool ok;
         444                 :     JSObject *obj;
         445                 :     JSString *str;
         446                 :     double d;
         447                 :
         448              36 :     AssertNoGC(cx);
         449              72 :     CHECK_REQUEST(cx);
         450              36 :     assertSameCompartment(cx, v);
         451              36 :     switch (type) {
         452                 :       case JSTYPE_VOID:
         453               0 :         *vp = JSVAL_VOID;
         454               0 :         ok = JS_TRUE;
         455               0 :         break;
         456                 :       case JSTYPE_OBJECT:
         457               0 :         ok = js_ValueToObjectOrNull(cx, v, &obj);
         458               0 :         if (ok)
         459               0 :             *vp = OBJECT_TO_JSVAL(obj);
         460               0 :         break;
         461                 :       case JSTYPE_FUNCTION:
         462               0 :         *vp = v;
         463               0 :         obj = js_ValueToFunction(cx, vp, JSV2F_SEARCH_STACK);
         464               0 :         ok = (obj != NULL);
         465               0 :         break;
         466                 :       case JSTYPE_STRING:
         467              36 :         str = ToString(cx, v);
         468              36 :         ok = (str != NULL);
         469              36 :         if (ok)
         470              36 :             *vp = STRING_TO_JSVAL(str);
         471              36 :         break;
         472                 :       case JSTYPE_NUMBER:
         473               0 :         ok = JS_ValueToNumber(cx, v, &d);
         474               0 :         if (ok)
         475               0 :             *vp = DOUBLE_TO_JSVAL(d);
         476               0 :         break;
         477                 :       case JSTYPE_BOOLEAN:
         478               0 :         *vp = BOOLEAN_TO_JSVAL(js_ValueToBoolean(v));
         479               0 :         return JS_TRUE;
         480                 :       default: {
         481                 :         char numBuf[12];
         482               0 :         JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
         483               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE, numBuf);
         484               0 :         ok = JS_FALSE;
         485               0 :         break;
         486                 :       }
         487                 :     }
         488              36 :     return ok;
         489                 : }
         490                 :
         491                 : JS_PUBLIC_API(JSBool)
         492               1 : JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
         493                 : {
         494               1 :     AssertNoGC(cx);
         495               2 :     CHECK_REQUEST(cx);
         496               1 :     assertSameCompartment(cx, v);
         497               1 :     return js_ValueToObjectOrNull(cx, v, objp);
         498                 : }
         499                 :
         500                 : JS_PUBLIC_API(JSFunction *)
         501             443 : JS_ValueToFunction(JSContext *cx, jsval v)
         502                 : {
         503             443 :     AssertNoGC(cx);
         504             886 :     CHECK_REQUEST(cx);
         505             443 :     assertSameCompartment(cx, v);
         506             443 :     return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
         507                 : }
         508                 :
         509                 : JS_PUBLIC_API(JSFunction *)
         510               0 : JS_ValueToConstructor(JSContext *cx, jsval v)
         511                 : {
         512               0 :     AssertNoGC(cx);
         513               0 :     CHECK_REQUEST(cx);
         514               0 :     assertSameCompartment(cx, v);
         515               0 :     return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
         516                 : }
         517                 :
         518                 : JS_PUBLIC_API(JSString *)
         519           24202 : JS_ValueToString(JSContext *cx, jsval v)
         520                 : {
         521           24202 :     AssertNoGC(cx);
         522           48404 :     CHECK_REQUEST(cx);
         523           24202 :     assertSameCompartment(cx, v);
         524           24202 :     return ToString(cx, v);
         525                 : }
         526                 :
         527                 : JS_PUBLIC_API(JSString *)
         528             486 : JS_ValueToSource(JSContext *cx, jsval v)
         529                 : {
         530             486 :     AssertNoGC(cx);
         531             972 :     CHECK_REQUEST(cx);
         532             486 :     assertSameCompartment(cx, v);
         533             486 :     return js_ValueToSource(cx, v);
         534                 : }
         535                 :
         536                 : JS_PUBLIC_API(JSBool)
         537              27 : JS_ValueToNumber(JSContext *cx, jsval v, double *dp)
         538                 : {
         539              27 :     AssertNoGC(cx);
         540              54 :     CHECK_REQUEST(cx);
         541              27 :     assertSameCompartment(cx, v);
         542                 :
         543              54 :     AutoValueRooter tvr(cx, v);
         544              27 :     return ToNumber(cx, tvr.value(), dp);
         545                 : }
         546                 :
         547                 : JS_PUBLIC_API(JSBool)
         548               0 : JS_DoubleIsInt32(double d, int32_t *ip)
         549                 : {
         550               0 :     return JSDOUBLE_IS_INT32(d, ip);
         551                 : }
         552                 :
         553                 : JS_PUBLIC_API(int32_t)
         554               0 : JS_DoubleToInt32(double d)
         555                 : {
         556               0 :     return js_DoubleToECMAInt32(d);
         557                 : }
         558                 :
         559                 : JS_PUBLIC_API(uint32_t)
         560               0 : JS_DoubleToUint32(double d)
         561                 : {
         562               0 :     return js_DoubleToECMAUint32(d);
         563                 : }
         564                 :
         565                 : JS_PUBLIC_API(JSBool)
         566              18 : JS_ValueToECMAInt32(JSContext *cx, jsval v, int32_t *ip)
         567                 : {
         568              18 :     AssertNoGC(cx);
         569              36 :     CHECK_REQUEST(cx);
         570              18 :     assertSameCompartment(cx, v);
         571                 :
         572              36 :     AutoValueRooter tvr(cx, v);
         573              18 :     return ToInt32(cx, tvr.value(), ip);
         574                 : }
         575                 :
         576                 : JS_PUBLIC_API(JSBool)
         577            1836 : JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32_t *ip)
         578                 : {
         579            1836 :     AssertNoGC(cx);
         580            3672 :     CHECK_REQUEST(cx);
         581            1836 :     assertSameCompartment(cx, v);
         582                 :
         583            3672 :     AutoValueRooter tvr(cx, v);
         584            1836 :     return ToUint32(cx, tvr.value(), (uint32_t *)ip);
         585                 : }
         586                 :
         587                 : JS_PUBLIC_API(JSBool)
         588             405 : JS_ValueToInt32(JSContext *cx, jsval v, int32_t *ip)
         589                 : {
         590             405 :     AssertNoGC(cx);
         591             810 :     CHECK_REQUEST(cx);
         592             405 :     assertSameCompartment(cx, v);
         593                 :
         594             810 :     AutoValueRooter tvr(cx, v);
         595             405 :     return NonstandardToInt32(cx, tvr.value(), (int32_t *)ip);
         596                 : }
         597                 :
         598                 : JS_PUBLIC_API(JSBool)
         599               0 : JS_ValueToUint16(JSContext *cx, jsval v, uint16_t *ip)
         600                 : {
         601               0 :     AssertNoGC(cx);
         602               0 :     CHECK_REQUEST(cx);
         603               0 :     assertSameCompartment(cx, v);
         604                 :
         605               0 :     AutoValueRooter tvr(cx, v);
         606               0 :     return ValueToUint16(cx, tvr.value(), (uint16_t *)ip);
         607                 : }
         608                 :
         609                 : JS_PUBLIC_API(JSBool)
         610           15268 : JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
         611                 : {
         612           15268 :     AssertNoGC(cx);
         613           30536 :     CHECK_REQUEST(cx);
         614           15268 :     assertSameCompartment(cx, v);
         615           15268 :     *bp = js_ValueToBoolean(v);
         616           15268 :     return JS_TRUE;
         617                 : }
         618                 :
         619                 : JS_PUBLIC_API(JSType)
         620          164565 : JS_TypeOfValue(JSContext *cx, jsval v)
         621                 : {
         622          164565 :     AssertNoGC(cx);
         623          329130 :     CHECK_REQUEST(cx);
         624          164565 :     assertSameCompartment(cx, v);
         625          164565 :     return TypeOfValue(cx, v);
         626                 : }
         627                 :
         628                 : JS_PUBLIC_API(const char *)
         629               0 : JS_GetTypeName(JSContext *cx, JSType type)
         630                 : {
         631               0 :     if ((unsigned)type >= (unsigned)JSTYPE_LIMIT)
         632               0 :         return NULL;
         633               0 :     return JS_TYPE_STR(type);
         634                 : }
         635                 :
         636                 : JS_PUBLIC_API(JSBool)
         637               1 : JS_StrictlyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal)
         638                 : {
         639               1 :     AssertNoGC(cx);
         640               2 :     CHECK_REQUEST(cx);
         641               1 :     assertSameCompartment(cx, v1, v2);
         642                 :     bool eq;
         643               1 :     if (!StrictlyEqual(cx, v1, v2, &eq))
         644               0 :         return false;
         645               1 :     *equal = eq;
         646               1 :     return true;
         647                 : }
         648                 :
         649                 : JS_PUBLIC_API(JSBool)
         650              76 : JS_LooselyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal)
         651                 : {
         652              76 :     AssertNoGC(cx);
         653             152 :     CHECK_REQUEST(cx);
         654              76 :     assertSameCompartment(cx, v1, v2);
         655                 :     bool eq;
         656              76 :     if (!LooselyEqual(cx, v1, v2, &eq))
         657               0 :         return false;
         658              76 :     *equal = eq;
         659              76 :     return true;
         660                 : }
         661                 :
         662                 : JS_PUBLIC_API(JSBool)
         663         4107796 : JS_SameValue(JSContext *cx, jsval v1, jsval v2, JSBool *same)
         664                 : {
         665         4107796 :     AssertNoGC(cx);
         666         8215592 :     CHECK_REQUEST(cx);
         667         4107796 :     assertSameCompartment(cx, v1, v2);
         668                 :     bool s;
         669         4107796 :     if (!SameValue(cx, v1, v2, &s))
         670               0 :         return false;
         671         4107796 :     *same = s;
         672         4107796 :     return true;
         673                 : }
         674                 :
         675                 : JS_PUBLIC_API(JSBool)
         676               0 : JS_IsBuiltinEvalFunction(JSFunction *fun)
         677                 : {
         678               0 :     return IsAnyBuiltinEval(fun);
         679                 : }
         680                 :
         681                 : JS_PUBLIC_API(JSBool)
         682               0 : JS_IsBuiltinFunctionConstructor(JSFunction *fun)
         683                 : {
         684               0 :     return IsBuiltinFunctionConstructor(fun);
         685                 : }
         686                 :
         687                 : /************************************************************************/
         688                 :
         689                 : /*
         690                 :  * Has a new runtime ever been created?  This flag is used to detect unsafe
         691                 :  * changes to js_CStringsAreUTF8 after a runtime has been created, and to
         692                 :  * control things that should happen only once across all runtimes.
         693                 :  */
         694                 : static JSBool js_NewRuntimeWasCalled = JS_FALSE;
         695                 :
         696                 : static const JSSecurityCallbacks NullSecurityCallbacks = { };
         697                 :
         698           18761 : JSRuntime::JSRuntime()
         699                 :   : atomsCompartment(NULL),
         700                 : #ifdef JS_THREADSAFE
         701                 :     ownerThread_(NULL),
         702                 : #endif
         703                 :     tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
         704                 :     execAlloc_(NULL),
         705                 :     bumpAlloc_(NULL),
         706                 :     nativeStackBase(0),
         707                 :     nativeStackQuota(0),
         708                 :     interpreterFrames(NULL),
         709                 :     cxCallback(NULL),
         710                 :     destroyCompartmentCallback(NULL),
         711                 :     activityCallback(NULL),
         712                 :     activityCallbackArg(NULL),
         713                 : #ifdef JS_THREADSAFE
         714                 :     suspendCount(0),
         715                 :     requestDepth(0),
         716                 : # ifdef DEBUG
         717                 :     checkRequestDepth(0),
         718                 : # endif
         719                 : #endif
         720                 :     gcSystemAvailableChunkListHead(NULL),
         721                 :     gcUserAvailableChunkListHead(NULL),
         722                 :     gcKeepAtoms(0),
         723                 :     gcBytes(0),
         724                 :     gcMaxBytes(0),
         725                 :     gcMaxMallocBytes(0),
         726                 :     gcNumArenasFreeCommitted(0),
         727                 :     gcVerifyData(NULL),
         728                 :     gcChunkAllocationSinceLastGC(false),
         729                 :     gcNextFullGCTime(0),
         730                 :     gcJitReleaseTime(0),
         731                 :     gcMode(JSGC_MODE_GLOBAL),
         732                 :     gcIsNeeded(0),
         733                 :     gcWeakMapList(NULL),
         734                 :     gcStats(thisFromCtor()),
         735                 :     gcNumber(0),
         736                 :     gcStartNumber(0),
         737                 :     gcTriggerReason(gcreason::NO_REASON),
         738                 :     gcStrictCompartmentChecking(false),
         739                 :     gcIncrementalState(gc::NO_INCREMENTAL),
         740                 :     gcLastMarkSlice(false),
         741                 :     gcInterFrameGC(0),
         742                 :     gcSliceBudget(SliceBudget::Unlimited),
         743                 :     gcIncrementalEnabled(true),
         744                 :     gcPoke(false),
         745                 :     gcRunning(false),
         746                 : #ifdef JS_GC_ZEAL
         747                 :     gcZeal_(0),
         748                 :     gcZealFrequency(0),
         749                 :     gcNextScheduled(0),
         750                 :     gcDeterministicOnly(false),
         751                 : #endif
         752                 :     gcCallback(NULL),
         753                 :     gcSliceCallback(NULL),
         754                 :     gcFinalizeCallback(NULL),
         755                 :     gcMallocBytes(0),
         756                 :     gcBlackRootsTraceOp(NULL),
         757                 :     gcBlackRootsData(NULL),
         758                 :     gcGrayRootsTraceOp(NULL),
         759                 :     gcGrayRootsData(NULL),
         760                 :     autoGCRooters(NULL),
         761                 :     scriptAndCountsVector(NULL),
         762                 :     NaNValue(UndefinedValue()),
         763                 :     negativeInfinityValue(UndefinedValue()),
         764                 :     positiveInfinityValue(UndefinedValue()),
         765                 :     emptyString(NULL),
         766                 :     debugMode(false),
         767                 :     profilingScripts(false),
         768                 :     hadOutOfMemory(false),
         769                 :     data(NULL),
         770                 : #ifdef JS_THREADSAFE
         771                 :     gcLock(NULL),
         772                 :     gcHelperThread(thisFromCtor()),
         773                 : #endif
         774                 :     defaultFreeOp_(thisFromCtor(), false, false),
         775                 :     debuggerMutations(0),
         776                 :     securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
         777                 :     destroyPrincipals(NULL),
         778                 :     structuredCloneCallbacks(NULL),
         779                 :     telemetryCallback(NULL),
         780                 :     propertyRemovals(0),
         781                 :     thousandsSeparator(0),
         782                 :     decimalSeparator(0),
         783                 :     numGrouping(0),
         784                 :     anynameObject(NULL),
         785                 :     functionNamespaceObject(NULL),
         786                 :     waiveGCQuota(false),
         787                 :     dtoaState(NULL),
         788                 :     pendingProxyOperation(NULL),
         789                 :     trustedPrincipals_(NULL),
         790                 :     wrapObjectCallback(TransparentObjectWrapper),
         791                 :     preWrapObjectCallback(NULL),
         792                 :     preserveWrapperCallback(NULL),
         793                 : #ifdef DEBUG
         794                 :     noGCOrAllocationCheck(0),
         795                 : #endif
         796                 :     inOOMReport(0),
         797           18761 :     jitHardening(false)
         798                 : {
         799                 :     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
         800           18761 :     JS_INIT_CLIST(&contextList);
         801           18761 :     JS_INIT_CLIST(&debuggerList);
         802                 :
         803           18761 :     PodZero(&debugHooks);
         804           18761 :     PodZero(&atomState);
         805                 :
         806                 : #if JS_STACK_GROWTH_DIRECTION > 0
         807                 :     nativeStackLimit = UINTPTR_MAX;
         808                 : #endif
         809           18761 : }
         810                 :
         811                 : bool
         812           18761 : JSRuntime::init(uint32_t maxbytes)
         813                 : {
         814                 : #ifdef JS_THREADSAFE
         815           18761 :     ownerThread_ = PR_GetCurrentThread();
         816                 : #endif
         817                 :
         818                 : #ifdef JS_METHODJIT_SPEW
         819           18761 :     JMCheckLogging();
         820                 : #endif
         821                 :
         822           18761 :     if (!js_InitGC(this, maxbytes))
         823               0 :         return false;
         824                 :
         825           18761 :     if (!gcMarker.init())
         826               0 :         return false;
         827                 :
         828           18761 :     const char *size = getenv("JSGC_MARK_STACK_LIMIT");
         829           18761 :     if (size)
         830               0 :         SetMarkStackLimit(this, atoi(size));
         831                 :
         832           56283 :     if (!(atomsCompartment = this->new_<JSCompartment>(this)) ||
         833           18761 :         !atomsCompartment->init(NULL) ||
         834           18761 :         !compartments.append(atomsCompartment)) {
         835               0 :         Foreground::delete_(atomsCompartment);
         836               0 :         return false;
         837                 :     }
         838                 :
         839           18761 :     atomsCompartment->isSystemCompartment = true;
         840           18761 :     atomsCompartment->setGCLastBytes(8192, 8192, GC_NORMAL);
         841                 :
         842           18761 :     if (!js_InitAtomState(this))
         843               0 :         return false;
         844                 :
         845           18761 :     if (!InitRuntimeNumberState(this))
         846               0 :         return false;
         847                 :
         848           18761 :     dtoaState = js_NewDtoaState();
         849           18761 :     if (!dtoaState)
         850               0 :         return false;
         851                 :
         852           18761 :     if (!stackSpace.init())
         853               0 :         return false;
         854                 :
         855           18761 :     nativeStackBase = GetNativeStackBase();
         856           18761 :     return true;
         857                 : }
         858                 :
         859           37522 : JSRuntime::~JSRuntime()
         860                 : {
         861           18761 :     JS_ASSERT(onOwnerThread());
         862                 :
         863           18761 :     delete_<JSC::ExecutableAllocator>(execAlloc_);
         864           18761 :     delete_<WTF::BumpPointerAllocator>(bumpAlloc_);
         865                 :
         866                 : #ifdef DEBUG
         867                 :     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
         868           18761 :     if (!JS_CLIST_IS_EMPTY(&contextList)) {
         869               0 :         unsigned cxcount = 0;
         870               0 :         for (ContextIter acx(this); !acx.done(); acx.next()) {
         871                 :             fprintf(stderr,
         872                 : "JS API usage error: found live context at %p\n",
         873               0 :                     (void *) acx.get());
         874               0 :             cxcount++;
         875                 :         }
         876                 :         fprintf(stderr,
         877                 : "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
         878               0 :                 cxcount, (cxcount == 1) ? "" : "s");
         879                 :     }
         880                 : #endif
         881                 :
         882           18761 :     FinishRuntimeNumberState(this);
         883           18761 :     js_FinishAtomState(this);
         884                 :
         885           18761 :     if (dtoaState)
         886           18761 :         js_DestroyDtoaState(dtoaState);
         887                 :
         888           18761 :     js_FinishGC(this);
         889                 : #ifdef JS_THREADSAFE
         890           18761 :     if (gcLock)
         891           18761 :         PR_DestroyLock(gcLock);
         892                 : #endif
         893           18761 : }
         894                 :
         895                 : #ifdef JS_THREADSAFE
         896                 : void
         897               0 : JSRuntime::setOwnerThread()
         898                 : {
         899               0 :     JS_ASSERT(ownerThread_ == (void *)0xc1ea12);  /* "clear" */
         900               0 :     JS_ASSERT(requestDepth == 0);
         901               0 :     ownerThread_ = PR_GetCurrentThread();
         902               0 :     nativeStackBase = GetNativeStackBase();
         903               0 :     if (nativeStackQuota)
         904               0 :         JS_SetNativeStackQuota(this, nativeStackQuota);
         905               0 : }
         906                 :
         907                 : void
         908               0 : JSRuntime::clearOwnerThread()
         909                 : {
         910               0 :     JS_ASSERT(onOwnerThread());
         911               0 :     JS_ASSERT(requestDepth == 0);
         912               0 :     ownerThread_ = (void *)0xc1ea12;  /* "clear" */
         913               0 :     nativeStackBase = 0;
         914                 : #if JS_STACK_GROWTH_DIRECTION > 0
         915                 :     nativeStackLimit = UINTPTR_MAX;
         916                 : #else
         917               0 :     nativeStackLimit = 0;
         918                 : #endif
         919               0 : }
         920                 :
         921                 : JS_FRIEND_API(bool)
         922      1162488487 : JSRuntime::onOwnerThread() const
         923                 : {
         924      1162488487 :     return ownerThread_ == PR_GetCurrentThread();
         925                 : }
         926                 : #endif  /* JS_THREADSAFE */
         927                 :
         928                 : JS_PUBLIC_API(JSRuntime *)
         929           18761 : JS_NewRuntime(uint32_t maxbytes)
         930                 : {
         931           18761 :     if (!js_NewRuntimeWasCalled) {
         932                 : #ifdef DEBUG
         933                 :         /*
         934                 :          * This code asserts that the numbers associated with the error names
         935                 :          * in jsmsg.def are monotonically increasing.  It uses values for the
         936                 :          * error names enumerated in jscntxt.c.  It's not a compile-time check
         937                 :          * but it's better than nothing.
         938                 :          */
         939           18667 :         int errorNumber = 0;
         940                 : #define MSG_DEF(name, number, count, exception, format)                       \
         941                 :     JS_ASSERT(name == errorNumber++);
         942                 : #include "js.msg"
         943                 : #undef MSG_DEF
         944                 :
         945                 : #define MSG_DEF(name, number, count, exception, format)                       \
         946                 :     JS_BEGIN_MACRO                                                            \
         947                 :         unsigned numfmtspecs = 0;                                                \
         948                 :         const char *fmt;                                                      \
         949                 :         for (fmt = format; *fmt != '\0'; fmt++) {                             \
         950                 :             if (*fmt == '{' && isdigit(fmt[1]))                               \
         951                 :                 ++numfmtspecs;                                                \
         952                 :         }                                                                     \
         953                 :         JS_ASSERT(count == numfmtspecs);                                      \
         954                 :     JS_END_MACRO;
         955                 : #include "js.msg"
         956                 : #undef MSG_DEF
         957                 : #endif /* DEBUG */
         958                 :
         959           18667 :         InitMemorySubsystem();
         960                 :
         961           18667 :         js_NewRuntimeWasCalled = JS_TRUE;
         962                 :     }
         963                 :
         964           18761 :     JSRuntime *rt = OffTheBooks::new_<JSRuntime>();
         965           18761 :     if (!rt)
         966               0 :         return NULL;
         967                 :
         968           18761 :     if (!rt->init(maxbytes)) {
         969               0 :         JS_DestroyRuntime(rt);
         970               0 :         return NULL;
         971                 :     }
         972                 :
         973           18761 :     Probes::createRuntime(rt);
         974           18761 :     return rt;
         975                 : }
         976                 :
         977                 : JS_PUBLIC_API(void)
         978           18761 : JS_DestroyRuntime(JSRuntime *rt)
         979                 : {
         980           18761 :     Probes::destroyRuntime(rt);
         981           18761 :     Foreground::delete_(rt);
         982           18761 : }
         983                 :
         984                 : JS_PUBLIC_API(void)
         985           18666 : JS_ShutDown(void)
         986                 : {
         987           18666 :     Probes::shutdown();
         988                 :     PRMJ_NowShutdown();
         989           18666 : }
         990                 :
         991                 : JS_PUBLIC_API(void *)
         992               0 : JS_GetRuntimePrivate(JSRuntime *rt)
         993                 : {
         994               0 :     return rt->data;
         995                 : }
         996                 :
         997                 : JS_PUBLIC_API(void)
         998               0 : JS_SetRuntimePrivate(JSRuntime *rt, void *data)
         999                 : {
        1000               0 :     rt->data = data;
        1001               0 : }
        1002                 :
        1003                 : #ifdef JS_THREADSAFE
        1004                 : static void
        1005           37692 : StartRequest(JSContext *cx)
        1006                 : {
        1007           37692 :     JSRuntime *rt = cx->runtime;
        1008           37692 :     JS_ASSERT(rt->onOwnerThread());
        1009                 :
        1010           37692 :     if (rt->requestDepth) {
        1011              10 :         rt->requestDepth++;
        1012                 :     } else {
        1013                 :         /* Indicate that a request is running. */
        1014           37682 :         rt->requestDepth = 1;
        1015                 :
        1016           37682 :         if (rt->activityCallback)
        1017               0 :             rt->activityCallback(rt->activityCallbackArg, true);
        1018                 :     }
        1019           37692 : }
        1020                 :
        1021                 : static void
        1022           37692 : StopRequest(JSContext *cx)
        1023                 : {
        1024           37692 :     JSRuntime *rt = cx->runtime;
        1025           37692 :     JS_ASSERT(rt->onOwnerThread());
        1026           37692 :     JS_ASSERT(rt->requestDepth != 0);
        1027           37692 :     if (rt->requestDepth != 1) {
        1028              10 :         rt->requestDepth--;
        1029                 :     } else {
        1030           37682 :         rt->conservativeGC.updateForRequestEnd(rt->suspendCount);
        1031           37682 :         rt->requestDepth = 0;
        1032                 :
        1033           37682 :         if (rt->activityCallback)
        1034               0 :             rt->activityCallback(rt->activityCallbackArg, false);
        1035                 :     }
        1036           37692 : }
        1037                 : #endif /* JS_THREADSAFE */
        1038                 :
        1039                 : JS_PUBLIC_API(void)
        1040           37532 : JS_BeginRequest(JSContext *cx)
        1041                 : {
        1042                 : #ifdef JS_THREADSAFE
        1043           37532 :     cx->outstandingRequests++;
        1044           37532 :     StartRequest(cx);
        1045                 : #endif
        1046           37532 : }
        1047                 :
        1048                 : JS_PUBLIC_API(void)
        1049           37532 : JS_EndRequest(JSContext *cx)
        1050                 : {
        1051                 : #ifdef JS_THREADSAFE
        1052           37532 :     JS_ASSERT(cx->outstandingRequests != 0);
        1053           37532 :     cx->outstandingRequests--;
        1054           37532 :     StopRequest(cx);
        1055                 : #endif
        1056           37532 : }
        1057                 :
        1058                 : /* Yield to pending GC operations, regardless of request depth */
        1059                 : JS_PUBLIC_API(void)
        1060             160 : JS_YieldRequest(JSContext *cx)
        1061                 : {
        1062                 : #ifdef JS_THREADSAFE
        1063             320 :     CHECK_REQUEST(cx);
        1064             160 :     JS_ResumeRequest(cx, JS_SuspendRequest(cx));
        1065                 : #endif
        1066             160 : }
        1067                 :
        1068                 : JS_PUBLIC_API(unsigned)
        1069             160 : JS_SuspendRequest(JSContext *cx)
        1070                 : {
        1071                 : #ifdef JS_THREADSAFE
        1072             160 :     JSRuntime *rt = cx->runtime;
        1073             160 :     JS_ASSERT(rt->onOwnerThread());
        1074                 :
        1075             160 :     unsigned saveDepth = rt->requestDepth;
        1076             160 :     if (!saveDepth)
        1077               0 :         return 0;
        1078                 :
        1079             160 :     rt->suspendCount++;
        1080             160 :     rt->requestDepth = 1;
        1081             160 :     StopRequest(cx);
        1082             160 :     return saveDepth;
        1083                 : #else
        1084                 :     return 0;
        1085                 : #endif
        1086                 : }
        1087                 :
        1088                 : JS_PUBLIC_API(void)
        1089             160 : JS_ResumeRequest(JSContext *cx, unsigned saveDepth)
        1090                 : {
        1091                 : #ifdef JS_THREADSAFE
        1092             160 :     JSRuntime *rt = cx->runtime;
        1093             160 :     JS_ASSERT(rt->onOwnerThread());
        1094             160 :     if (saveDepth == 0)
        1095               0 :         return;
        1096             160 :     JS_ASSERT(saveDepth >= 1);
        1097             160 :     JS_ASSERT(!rt->requestDepth);
        1098             160 :     JS_ASSERT(rt->suspendCount);
        1099             160 :     StartRequest(cx);
        1100             160 :     rt->requestDepth = saveDepth;
        1101             160 :     rt->suspendCount--;
        1102                 : #endif
        1103                 : }
        1104                 :
        1105                 : JS_PUBLIC_API(JSBool)
        1106               0 : JS_IsInRequest(JSRuntime *rt)
        1107                 : {
        1108                 : #ifdef JS_THREADSAFE
        1109               0 :     JS_ASSERT(rt->onOwnerThread());
        1110               0 :     return rt->requestDepth != 0;
        1111                 : #else
        1112                 :     return false;
        1113                 : #endif
        1114                 : }
        1115                 :
        1116                 : JS_PUBLIC_API(JSBool)
        1117               0 : JS_IsInSuspendedRequest(JSRuntime *rt)
        1118                 : {
        1119                 : #ifdef JS_THREADSAFE
        1120               0 :     JS_ASSERT(rt->onOwnerThread());
        1121               0 :     return rt->suspendCount != 0;
        1122                 : #else
        1123                 :     return false;
        1124                 : #endif
        1125                 : }
        1126                 :
        1127                 : JS_PUBLIC_API(JSContextCallback)
        1128               0 : JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
        1129                 : {
        1130                 :     JSContextCallback old;
        1131                 :
        1132               0 :     old = rt->cxCallback;
        1133               0 :     rt->cxCallback = cxCallback;
        1134               0 :     return old;
        1135                 : }
        1136                 :
        1137                 : JS_PUBLIC_API(JSContext *)
        1138           18771 : JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
        1139                 : {
        1140           18771 :     return js_NewContext(rt, stackChunkSize);
        1141                 : }
        1142                 :
        1143                 : JS_PUBLIC_API(void)
        1144           18771 : JS_DestroyContext(JSContext *cx)
        1145                 : {
        1146           18771 :     js_DestroyContext(cx, JSDCM_FORCE_GC);
        1147           18771 : }
        1148                 :
        1149                 : JS_PUBLIC_API(void)
        1150               0 : JS_DestroyContextNoGC(JSContext *cx)
        1151                 : {
        1152               0 :     js_DestroyContext(cx, JSDCM_NO_GC);
        1153               0 : }
        1154                 :
        1155                 : JS_PUBLIC_API(void)
        1156               0 : JS_DestroyContextMaybeGC(JSContext *cx)
        1157                 : {
        1158               0 :     js_DestroyContext(cx, JSDCM_MAYBE_GC);
        1159               0 : }
        1160                 :
        1161                 : JS_PUBLIC_API(void *)
        1162           18686 : JS_GetContextPrivate(JSContext *cx)
        1163                 : {
        1164           18686 :     return cx->data;
        1165                 : }
        1166                 :
        1167                 : JS_PUBLIC_API(void)
        1168           37352 : JS_SetContextPrivate(JSContext *cx, void *data)
        1169                 : {
        1170           37352 :     cx->data = data;
        1171           37352 : }
        1172                 :
        1173                 : JS_PUBLIC_API(void *)
        1174               0 : JS_GetSecondContextPrivate(JSContext *cx)
        1175                 : {
        1176               0 :     return cx->data2;
        1177                 : }
        1178                 :
        1179                 : JS_PUBLIC_API(void)
        1180               0 : JS_SetSecondContextPrivate(JSContext *cx, void *data)
        1181                 : {
        1182               0 :     cx->data2 = data;
        1183               0 : }
        1184                 :
        1185                 : JS_PUBLIC_API(JSRuntime *)
        1186            7213 : JS_GetRuntime(JSContext *cx)
        1187                 : {
        1188            7213 :     return cx->runtime;
        1189                 : }
        1190                 :
        1191                 : JS_PUBLIC_API(JSContext *)
        1192               0 : JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
        1193                 : {
        1194               0 :     JSContext *cx = *iterp;
        1195               0 :     JSCList *next = cx ? cx->link.next : rt->contextList.next;
        1196               0 :     cx = (next == &rt->contextList) ? NULL : JSContext::fromLinkField(next);
        1197               0 :     *iterp = cx;
        1198               0 :     return cx;
        1199                 : }
        1200                 :
        1201                 : JS_PUBLIC_API(JSVersion)
        1202              12 : JS_GetVersion(JSContext *cx)
        1203                 : {
        1204              12 :     return VersionNumber(cx->findVersion());
        1205                 : }
        1206                 :
        1207                 : JS_PUBLIC_API(JSVersion)
        1208           18819 : JS_SetVersion(JSContext *cx, JSVersion newVersion)
        1209                 : {
        1210           18819 :     JS_ASSERT(VersionIsKnown(newVersion));
        1211           18819 :     JS_ASSERT(!VersionHasFlags(newVersion));
        1212           18819 :     JSVersion newVersionNumber = newVersion;
        1213                 :
        1214                 : #ifdef DEBUG
        1215           18819 :     unsigned coptsBefore = cx->getCompileOptions();
        1216                 : #endif
        1217           18819 :     JSVersion oldVersion = cx->findVersion();
        1218           18819 :     JSVersion oldVersionNumber = VersionNumber(oldVersion);
        1219           18819 :     if (oldVersionNumber == newVersionNumber)
        1220               0 :         return oldVersionNumber; /* No override actually occurs! */
        1221                 :
        1222                 :     /* We no longer support 1.4 or below. */
        1223           18819 :     if (newVersionNumber != JSVERSION_DEFAULT && newVersionNumber <= JSVERSION_1_4)
        1224               0 :         return oldVersionNumber;
        1225                 :
        1226           18819 :     VersionCopyFlags(&newVersion, oldVersion);
        1227           18819 :     cx->maybeOverrideVersion(newVersion);
        1228           18819 :     JS_ASSERT(cx->getCompileOptions() == coptsBefore);
        1229           18819 :     return oldVersionNumber;
        1230                 : }
        1231                 :
        1232                 : static struct v2smap {
        1233                 :     JSVersion   version;
        1234                 :     const char  *string;
        1235                 : } v2smap[] = {
        1236                 :     {JSVERSION_1_0,     "1.0"},
        1237                 :     {JSVERSION_1_1,     "1.1"},
        1238                 :     {JSVERSION_1_2,     "1.2"},
        1239                 :     {JSVERSION_1_3,     "1.3"},
        1240                 :     {JSVERSION_1_4,     "1.4"},
        1241                 :     {JSVERSION_ECMA_3,  "ECMAv3"},
        1242                 :     {JSVERSION_1_5,     "1.5"},
        1243                 :     {JSVERSION_1_6,     "1.6"},
        1244                 :     {JSVERSION_1_7,     "1.7"},
        1245                 :     {JSVERSION_1_8,     "1.8"},
        1246                 :     {JSVERSION_ECMA_5,  "ECMAv5"},
        1247                 :     {JSVERSION_DEFAULT, js_default_str},
        1248                 :     {JSVERSION_UNKNOWN, NULL},          /* must be last, NULL is sentinel */
        1249                 : };
        1250                 :
        1251                 : JS_PUBLIC_API(const char *)
        1252               0 : JS_VersionToString(JSVersion version)
        1253                 : {
        1254                 :     int i;
        1255                 :
        1256               0 :     for (i = 0; v2smap[i].string; i++)
        1257               0 :         if (v2smap[i].version == version)
        1258               0 :             return v2smap[i].string;
        1259               0 :     return "unknown";
        1260                 : }
        1261                 :
        1262                 : JS_PUBLIC_API(JSVersion)
        1263               0 : JS_StringToVersion(const char *string)
        1264                 : {
        1265                 :     int i;
        1266                 :
        1267               0 :     for (i = 0; v2smap[i].string; i++)
        1268               0 :         if (strcmp(v2smap[i].string, string) == 0)
        1269               0 :             return v2smap[i].version;
        1270               0 :     return JSVERSION_UNKNOWN;
        1271                 : }
        1272                 :
        1273                 : JS_PUBLIC_API(uint32_t)
        1274           38367 : JS_GetOptions(JSContext *cx)
        1275                 : {
        1276                 :     /*
        1277                 :      * Can't check option/version synchronization here.
        1278                 :      * We may have been synchronized with a script version that was formerly on
        1279                 :      * the stack, but has now been popped.
        1280                 :      */
        1281           38367 :     return cx->allOptions();
        1282                 : }
        1283                 :
        1284                 : static unsigned
        1285          109968 : SetOptionsCommon(JSContext *cx, unsigned options)
        1286                 : {
        1287          109968 :     JS_ASSERT((options & JSALLOPTION_MASK) == options);
        1288          109968 :     unsigned oldopts = cx->allOptions();
        1289          109968 :     unsigned newropts = options & JSRUNOPTION_MASK;
        1290          109968 :     unsigned newcopts = options & JSCOMPILEOPTION_MASK;
        1291          109968 :     cx->setRunOptions(newropts);
        1292          109968 :     cx->setCompileOptions(newcopts);
        1293          109968 :     cx->updateJITEnabled();
        1294          109968 :     return oldopts;
        1295                 : }
        1296                 :
        1297                 : JS_PUBLIC_API(uint32_t)
        1298           76654 : JS_SetOptions(JSContext *cx, uint32_t options)
        1299                 : {
        1300           76654 :     return SetOptionsCommon(cx, options);
        1301                 : }
        1302                 :
        1303                 : JS_PUBLIC_API(uint32_t)
        1304           33314 : JS_ToggleOptions(JSContext *cx, uint32_t options)
        1305                 : {
        1306           33314 :     unsigned oldopts = cx->allOptions();
        1307           33314 :     unsigned newopts = oldopts ^ options;
        1308           33314 :     return SetOptionsCommon(cx, newopts);
        1309                 : }
        1310                 :
        1311                 : JS_PUBLIC_API(void)
        1312               0 : JS_SetJitHardening(JSRuntime *rt, JSBool enabled)
        1313                 : {
        1314               0 :     rt->setJitHardening(!!enabled);
        1315               0 : }
        1316                 :
        1317                 : JS_PUBLIC_API(const char *)
        1318           18666 : JS_GetImplementationVersion(void)
        1319                 : {
        1320           18666 :     return "JavaScript-C 1.8.5+ 2011-04-16";
        1321                 : }
        1322                 :
        1323                 : JS_PUBLIC_API(void)
        1324               0 : JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback callback)
        1325                 : {
        1326               0 :     rt->destroyCompartmentCallback = callback;
        1327               0 : }
        1328                 :
        1329                 : JS_PUBLIC_API(JSWrapObjectCallback)
        1330               1 : JS_SetWrapObjectCallbacks(JSRuntime *rt,
        1331                 :                           JSWrapObjectCallback callback,
        1332                 :                           JSPreWrapCallback precallback)
        1333                 : {
        1334               1 :     JSWrapObjectCallback old = rt->wrapObjectCallback;
        1335               1 :     rt->wrapObjectCallback = callback;
        1336               1 :     rt->preWrapObjectCallback = precallback;
        1337               1 :     return old;
        1338                 : }
        1339                 :
        1340                 : JS_PUBLIC_API(JSCrossCompartmentCall *)
        1341              95 : JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target)
        1342                 : {
        1343              95 :     AssertNoGC(cx);
        1344             190 :     CHECK_REQUEST(cx);
        1345                 :
        1346              95 :     JS_ASSERT(target);
        1347              95 :     AutoCompartment *call = cx->new_<AutoCompartment>(cx, target);
        1348              95 :     if (!call)
        1349               0 :         return NULL;
        1350              95 :     if (!call->enter()) {
        1351               0 :         Foreground::delete_(call);
        1352               0 :         return NULL;
        1353                 :     }
        1354              95 :     return reinterpret_cast<JSCrossCompartmentCall *>(call);
        1355                 : }
        1356                 :
        1357                 : namespace js {
        1358                 :
        1359                 : // Declared in jscompartment.h
        1360                 : Class dummy_class = {
        1361                 :     "jdummy",
        1362                 :     JSCLASS_GLOBAL_FLAGS,
        1363                 :     JS_PropertyStub,  JS_PropertyStub,
        1364                 :     JS_PropertyStub,  JS_StrictPropertyStub,
        1365                 :     JS_EnumerateStub, JS_ResolveStub,
        1366                 :     JS_ConvertStub
        1367                 : };
        1368                 :
        1369                 : } /*namespace js */
        1370                 :
        1371                 : JS_PUBLIC_API(JSCrossCompartmentCall *)
        1372               0 : JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
        1373                 : {
        1374               0 :     AssertNoGC(cx);
        1375               0 :     CHECK_REQUEST(cx);
        1376               0 :     JS_ASSERT(!target->isCachedEval);
        1377               0 :     GlobalObject *global = target->globalObject;
        1378               0 :     if (!global) {
        1379               0 :         SwitchToCompartment sc(cx, target->compartment());
        1380               0 :         global = GlobalObject::create(cx, &dummy_class);
        1381               0 :         if (!global)
        1382               0 :             return NULL;
        1383                 :     }
        1384               0 :     return JS_EnterCrossCompartmentCall(cx, global);
        1385                 : }
        1386                 :
        1387                 : JS_PUBLIC_API(JSCrossCompartmentCall *)
        1388               0 : JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target)
        1389                 : {
        1390               0 :     AssertNoGC(cx);
        1391               0 :     CHECK_REQUEST(cx);
        1392                 :
        1393               0 :     return JS_EnterCrossCompartmentCall(cx, &Valueify(target)->scopeChain().global());
        1394                 : }
        1395                 :
        1396                 : JS_PUBLIC_API(void)
        1397              95 : JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
        1398                 : {
        1399              95 :     AutoCompartment *realcall = reinterpret_cast<AutoCompartment *>(call);
        1400              95 :     AssertNoGC(realcall->context);
        1401             190 :     CHECK_REQUEST(realcall->context);
        1402              95 :     realcall->leave();
        1403              95 :     Foreground::delete_(realcall);
        1404              95 : }
        1405                 :
        1406                 : bool
        1407           44849 : JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target)
        1408                 : {
        1409           44849 :     AssertNoGC(cx);
        1410           44849 :     JS_ASSERT(state == STATE_UNENTERED);
        1411           44849 :     if (cx->compartment == target->compartment()) {
        1412           19809 :         state = STATE_SAME_COMPARTMENT;
        1413           19809 :         return true;
        1414                 :     }
        1415                 :
        1416                 :     JS_STATIC_ASSERT(sizeof(bytes) == sizeof(AutoCompartment));
        1417           50080 :     CHECK_REQUEST(cx);
        1418           25040 :     AutoCompartment *call = new (bytes) AutoCompartment(cx, target);
        1419           25040 :     if (call->enter()) {
        1420           25040 :         state = STATE_OTHER_COMPARTMENT;
        1421           25040 :         return true;
        1422                 :     }
        1423               0 :     return false;
        1424                 : }
        1425                 :
        1426                 : void
        1427               0 : JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSObject *target)
        1428                 : {
        1429               0 :     (void) enter(cx, target);
        1430               0 : }
        1431                 :
        1432           44867 : JSAutoEnterCompartment::~JSAutoEnterCompartment()
        1433                 : {
        1434           44867 :     if (state == STATE_OTHER_COMPARTMENT) {
        1435           25040 :         AutoCompartment* ac = getAutoCompartment();
        1436           50080 :         CHECK_REQUEST(ac->context);
        1437           25040 :         ac->~AutoCompartment();
        1438                 :     }
        1439           44867 : }
        1440                 :
        1441                 : namespace JS {
        1442                 :
        1443                 : bool
        1444               0 : AutoEnterScriptCompartment::enter(JSContext *cx, JSScript *target)
        1445                 : {
        1446               0 :     JS_ASSERT(!call);
        1447               0 :     if (cx->compartment == target->compartment()) {
        1448               0 :         call = reinterpret_cast<JSCrossCompartmentCall*>(1);
        1449               0 :         return true;
        1450                 :     }
        1451               0 :     call = JS_EnterCrossCompartmentCallScript(cx, target);
        1452               0 :     return call != NULL;
        1453                 : }
        1454                 :
        1455                 : bool
        1456               0 : AutoEnterFrameCompartment::enter(JSContext *cx, JSStackFrame *target)
        1457                 : {
        1458               0 :     JS_ASSERT(!call);
        1459               0 :     if (cx->compartment == Valueify(target)->scopeChain().compartment()) {
        1460               0 :         call = reinterpret_cast<JSCrossCompartmentCall*>(1);
        1461               0 :         return true;
        1462                 :     }
        1463               0 :     call = JS_EnterCrossCompartmentCallStackFrame(cx, target);
        1464               0 :     return call != NULL;
        1465                 : }
        1466                 :
        1467                 : } /* namespace JS */
        1468                 :
        1469                 : JS_PUBLIC_API(void)
        1470               0 : JS_SetCompartmentPrivate(JSCompartment *compartment, void *data)
        1471                 : {
        1472               0 :     compartment->data = data;
        1473               0 : }
        1474                 :
        1475                 : JS_PUBLIC_API(void *)
        1476               0 : JS_GetCompartmentPrivate(JSCompartment *compartment)
        1477                 : {
        1478               0 :     return compartment->data;
        1479                 : }
        1480                 :
        1481                 : JS_PUBLIC_API(JSBool)
        1482           22201 : JS_WrapObject(JSContext *cx, JSObject **objp)
        1483                 : {
        1484           22201 :     AssertNoGC(cx);
        1485           44402 :     CHECK_REQUEST(cx);
        1486           22201 :     return cx->compartment->wrap(cx, objp);
        1487                 : }
        1488                 :
        1489                 : JS_PUBLIC_API(JSBool)
        1490               2 : JS_WrapValue(JSContext *cx, jsval *vp)
        1491                 : {
        1492               2 :     AssertNoGC(cx);
        1493               4 :     CHECK_REQUEST(cx);
        1494               2 :     return cx->compartment->wrap(cx, vp);
        1495                 : }
        1496                 :
        1497                 : JS_PUBLIC_API(JSObject *)
        1498               1 : JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
        1499                 : {
        1500               1 :     AssertNoGC(cx);
        1501                 :
        1502                 :      // This function is called when an object moves between two
        1503                 :      // different compartments. In that case, we need to "move" the
        1504                 :      // window from origobj's compartment to target's compartment.
        1505               1 :     JSCompartment *destination = target->compartment();
        1506               1 :     WrapperMap &map = destination->crossCompartmentWrappers;
        1507               1 :     Value origv = ObjectValue(*origobj);
        1508                 :     JSObject *obj;
        1509                 :
        1510               1 :     if (origobj->compartment() == destination) {
        1511                 :         // If the original object is in the same compartment as the
        1512                 :         // destination, then we know that we won't find wrapper in the
        1513                 :         // destination's cross compartment map and that the same
        1514                 :         // object will continue to work.  Note the rare case where
        1515                 :         // |origobj == target|. In that case, we can just treat this
        1516                 :         // as a same compartment navigation. The effect is to clear
        1517                 :         // all of the wrappers and their holders if they have
        1518                 :         // them. This would be cleaner as a separate API.
        1519               0 :         if (origobj != target && !origobj->swap(cx, target))
        1520               0 :             return NULL;
        1521               0 :         obj = origobj;
        1522               1 :     } else if (WrapperMap::Ptr p = map.lookup(origv)) {
        1523                 :         // There might already be a wrapper for the original object in
        1524                 :         // the new compartment. If there is, make it the primary outer
        1525                 :         // window proxy around the inner (accomplished by swapping
        1526                 :         // target's innards with the old, possibly security wrapper,
        1527                 :         // innards).
        1528               1 :         obj = &p->value.toObject();
        1529               1 :         map.remove(p);
        1530               1 :         if (!obj->swap(cx, target))
        1531               0 :             return NULL;
        1532                 :     } else {
        1533                 :         // Otherwise, this is going to be our outer window proxy in
        1534                 :         // the new compartment.
        1535               0 :         obj = target;
        1536                 :     }
        1537                 :
        1538                 :     // Now, iterate through other scopes looking for references to the
        1539                 :     // old outer window. They need to be updated to point at the new
        1540                 :     // outer window.  They also might transition between different
        1541                 :     // types of security wrappers based on whether the new compartment
        1542                 :     // is same origin with them.
        1543               1 :     Value targetv = ObjectValue(*obj);
        1544               1 :     CompartmentVector &vector = cx->runtime->compartments;
        1545               2 :     AutoValueVector toTransplant(cx);
        1546               1 :     if (!toTransplant.reserve(vector.length()))
        1547               0 :         return NULL;
        1548                 :
        1549               6 :     for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
        1550               5 :         WrapperMap &pmap = (*p)->crossCompartmentWrappers;
        1551               5 :         if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
        1552                 :             // We found a wrapper. Remember and root it.
        1553               2 :             toTransplant.infallibleAppend(wp->value);
        1554                 :         }
        1555                 :     }
        1556                 :
        1557               3 :     for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
        1558               2 :         JSObject *wobj = &begin->toObject();
        1559               2 :         JSCompartment *wcompartment = wobj->compartment();
        1560               2 :         WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
        1561               2 :         JS_ASSERT(pmap.lookup(origv));
        1562               2 :         pmap.remove(origv);
        1563                 :
        1564                 :         // First, we wrap it in the new compartment. This will return
        1565                 :         // a new wrapper.
        1566               4 :         AutoCompartment ac(cx, wobj);
        1567               2 :         JSObject *tobj = obj;
        1568               2 :         if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
        1569               0 :             return NULL;
        1570                 :
        1571                 :         // Now, because we need to maintain object identity, we do a
        1572                 :         // brain transplant on the old object. At the same time, we
        1573                 :         // update the entry in the compartment's wrapper map to point
        1574                 :         // to the old wrapper.
        1575               2 :         JS_ASSERT(tobj != wobj);
        1576               2 :         if (!wobj->swap(cx, tobj))
        1577               0 :             return NULL;
        1578               4 :         pmap.put(targetv, ObjectValue(*wobj));
        1579                 :     }
        1580                 :
        1581                 :     // Lastly, update the original object to point to the new one.
        1582               1 :     if (origobj->compartment() != destination) {
        1583               2 :         AutoCompartment ac(cx, origobj);
        1584               1 :         JSObject *tobj = obj;
        1585               1 :         if (!ac.enter() || !JS_WrapObject(cx, &tobj))
        1586               0 :             return NULL;
        1587               1 :         if (!origobj->swap(cx, tobj))
        1588               0 :             return NULL;
        1589               2 :         origobj->compartment()->crossCompartmentWrappers.put(targetv, origv);
        1590                 :     }
        1591                 :
        1592               1 :     return obj;
        1593                 : }
        1594                 :
        1595                 : /*
        1596                 :  * The location object is special. There is the location object itself and
        1597                 :  * then the location object wrapper. Because there are no direct references to
        1598                 :  * the location object itself, we don't want the old obj (|origobj| here) to
        1599                 :  * become the new wrapper but the wrapper itself instead. This leads to very
        1600                 :  * subtle differences between js_TransplantObjectWithWrapper and
        1601                 :  * JS_TransplantObject.
        1602                 :  */
        1603                 : JS_FRIEND_API(JSObject *)
        1604               0 : js_TransplantObjectWithWrapper(JSContext *cx,
        1605                 :                                JSObject *origobj,
        1606                 :                                JSObject *origwrapper,
        1607                 :                                JSObject *targetobj,
        1608                 :                                JSObject *targetwrapper)
        1609                 : {
        1610               0 :     AssertNoGC(cx);
        1611                 :
        1612                 :     JSObject *obj;
        1613               0 :     JSCompartment *destination = targetobj->compartment();
        1614               0 :     WrapperMap &map = destination->crossCompartmentWrappers;
        1615                 :
        1616                 :     // |origv| is the map entry we're looking up. The map entries are going to
        1617                 :     // be for the location object itself.
        1618               0 :     Value origv = ObjectValue(*origobj);
        1619                 :
        1620                 :     // There might already be a wrapper for the original object in the new
        1621                 :     // compartment.
        1622               0 :     if (WrapperMap::Ptr p = map.lookup(origv)) {
        1623                 :         // There is. Make the existing wrapper a same compartment location
        1624                 :         // wrapper (swapping it with the given new wrapper).
        1625               0 :         obj = &p->value.toObject();
        1626               0 :         map.remove(p);
        1627               0 :         if (!obj->swap(cx, targetwrapper))
        1628               0 :             return NULL;
        1629                 :     } else {
        1630                 :         // Otherwise, use the passed-in wrapper as the same compartment
        1631                 :         // location wrapper.
        1632               0 :         obj = targetwrapper;
        1633                 :     }
        1634                 :
        1635                 :     // Now, iterate through other scopes looking for references to the old
        1636                 :     // location object. Note that the entries in the maps are for |origobj|
        1637                 :     // and not |origwrapper|. They need to be updated to point at the new
        1638                 :     // location object.
        1639               0 :     Value targetv = ObjectValue(*targetobj);
        1640               0 :     CompartmentVector &vector = cx->runtime->compartments;
        1641               0 :     AutoValueVector toTransplant(cx);
        1642               0 :     if (!toTransplant.reserve(vector.length()))
        1643               0 :         return NULL;
        1644                 :
        1645               0 :     for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
        1646               0 :         WrapperMap &pmap = (*p)->crossCompartmentWrappers;
        1647               0 :         if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
        1648                 :             // We found a wrapper. Remember and root it.
        1649               0 :             toTransplant.infallibleAppend(wp->value);
        1650                 :         }
        1651                 :     }
        1652                 :
        1653               0 :     for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
        1654               0 :         JSObject *wobj = &begin->toObject();
        1655               0 :         JSCompartment *wcompartment = wobj->compartment();
        1656               0 :         WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
        1657               0 :         JS_ASSERT(pmap.lookup(origv));
        1658               0 :         pmap.remove(origv);
        1659                 :
        1660                 :         // First, we wrap it in the new compartment. This will return a
        1661                 :         // new wrapper.
        1662               0 :         AutoCompartment ac(cx, wobj);
        1663                 :
        1664               0 :         JSObject *tobj = targetobj;
        1665               0 :         if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
        1666               0 :             return NULL;
        1667                 :
        1668                 :         // Now, because we need to maintain object identity, we do a brain
        1669                 :         // transplant on the old object. At the same time, we update the
        1670                 :         // entry in the compartment's wrapper map to point to the old
        1671                 :         // wrapper.
        1672               0 :         JS_ASSERT(tobj != wobj);
        1673               0 :         if (!wobj->swap(cx, tobj))
        1674               0 :             return NULL;
        1675               0 :         pmap.put(targetv, ObjectValue(*wobj));
        1676                 :     }
        1677                 :
        1678                 :     // Lastly, update the original object to point to the new one. However, as
        1679                 :     // mentioned above, we do the transplant on the wrapper, not the object
        1680                 :     // itself, since all of the references are to the object itself.
        1681                 :     {
        1682               0 :         AutoCompartment ac(cx, origobj);
        1683               0 :         JSObject *tobj = obj;
        1684               0 :         if (!ac.enter() || !JS_WrapObject(cx, &tobj))
        1685               0 :             return NULL;
        1686               0 :         if (!origwrapper->swap(cx, tobj))
        1687               0 :             return NULL;
        1688               0 :         origwrapper->compartment()->crossCompartmentWrappers.put(targetv,
        1689               0 :                                                                  ObjectValue(*origwrapper));
        1690                 :     }
        1691                 :
        1692               0 :     return obj;
        1693                 : }
        1694                 :
        1695                 : JS_PUBLIC_API(JSObject *)
        1696              93 : JS_GetGlobalObject(JSContext *cx)
        1697                 : {
        1698              93 :     return cx->globalObject;
        1699                 : }
        1700                 :
        1701                 : JS_PUBLIC_API(void)
        1702           37427 : JS_SetGlobalObject(JSContext *cx, JSObject *obj)
        1703                 : {
        1704           37427 :     AssertNoGC(cx);
        1705           74854 :     CHECK_REQUEST(cx);
        1706                 :
        1707           37427 :     cx->globalObject = obj;
        1708           37427 :     if (!cx->hasfp())
        1709           18666 :         cx->resetCompartment();
        1710           37427 : }
        1711                 :
        1712                 : JS_PUBLIC_API(JSBool)
        1713             264 : JS_InitStandardClasses(JSContext *cx, JSObject *obj)
        1714                 : {
        1715             264 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        1716             264 :     AssertNoGC(cx);
        1717             528 :     CHECK_REQUEST(cx);
        1718                 :
        1719                 :     /*
        1720                 :      * JS_SetGlobalObject might or might not change cx's compartment, so call
        1721                 :      * it before assertSameCompartment. (The API contract is that *after* this,
        1722                 :      * cx and obj must be in the same compartment.)
        1723                 :      */
        1724             264 :     if (!cx->globalObject)
        1725              95 :         JS_SetGlobalObject(cx, obj);
        1726                 :
        1727             264 :     assertSameCompartment(cx, obj);
        1728                 :
        1729             264 :     return obj->global().initStandardClasses(cx);
        1730                 : }
        1731                 :
        1732                 : #define CLASP(name)                 (&name##Class)
        1733                 : #define TYPED_ARRAY_CLASP(type)     (&TypedArray::fastClasses[TypedArray::type])
        1734                 : #define EAGER_ATOM(name)            ATOM_OFFSET(name), NULL
        1735                 : #define EAGER_CLASS_ATOM(name)      CLASS_ATOM_OFFSET(name), NULL
        1736                 : #define EAGER_ATOM_AND_CLASP(name)  EAGER_CLASS_ATOM(name), CLASP(name)
        1737                 : #define LAZY_ATOM(name)             ATOM_OFFSET(lazy.name), js_##name##_str
        1738                 :
        1739                 : typedef struct JSStdName {
        1740                 :     JSObjectOp  init;
        1741                 :     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
        1742                 :     const char  *name;          /* null if atom is pre-pinned, else name */
        1743                 :     Class       *clasp;
        1744                 : } JSStdName;
        1745                 :
        1746                 : static JSAtom *
        1747        20745621 : StdNameToAtom(JSContext *cx, JSStdName *stdn)
        1748                 : {
        1749                 :     size_t offset;
        1750                 :     JSAtom *atom;
        1751                 :     const char *name;
        1752                 :
        1753        20745621 :     offset = stdn->atomOffset;
        1754        20745621 :     atom = OFFSET_TO_ATOM(cx->runtime, offset);
        1755        20745621 :     if (!atom) {
        1756          410652 :         name = stdn->name;
        1757          410652 :         if (name) {
        1758          410652 :             atom = js_Atomize(cx, name, strlen(name), InternAtom);
        1759          410652 :             OFFSET_TO_ATOM(cx->runtime, offset) = atom;
        1760                 :         }
        1761                 :     }
        1762        20745621 :     return atom;
        1763                 : }
        1764                 :
        1765                 : /*
        1766                 :  * Table of class initializers and their atom offsets in rt->atomState.
        1767                 :  * If you add a "standard" class, remember to update this table.
        1768                 :  */
        1769                 : static JSStdName standard_class_atoms[] = {
        1770                 :     {js_InitFunctionClass,              EAGER_ATOM_AND_CLASP(Function)},
        1771                 :     {js_InitObjectClass,                EAGER_ATOM_AND_CLASP(Object)},
        1772                 :     {js_InitArrayClass,                 EAGER_ATOM_AND_CLASP(Array)},
        1773                 :     {js_InitBooleanClass,               EAGER_ATOM_AND_CLASP(Boolean)},
        1774                 :     {js_InitDateClass,                  EAGER_ATOM_AND_CLASP(Date)},
        1775                 :     {js_InitMathClass,                  EAGER_ATOM_AND_CLASP(Math)},
        1776                 :     {js_InitNumberClass,                EAGER_ATOM_AND_CLASP(Number)},
        1777                 :     {js_InitStringClass,                EAGER_ATOM_AND_CLASP(String)},
        1778                 :     {js_InitExceptionClasses,           EAGER_ATOM_AND_CLASP(Error)},
        1779                 :     {js_InitRegExpClass,                EAGER_ATOM_AND_CLASP(RegExp)},
        1780                 : #if JS_HAS_XML_SUPPORT
        1781                 :     {js_InitXMLClass,                   EAGER_ATOM_AND_CLASP(XML)},
        1782                 :     {js_InitNamespaceClass,             EAGER_ATOM_AND_CLASP(Namespace)},
        1783                 :     {js_InitQNameClass,                 EAGER_ATOM_AND_CLASP(QName)},
        1784                 : #endif
        1785                 : #if JS_HAS_GENERATORS
        1786                 :     {js_InitIteratorClasses,            EAGER_ATOM_AND_CLASP(StopIteration)},
        1787                 : #endif
        1788                 :     {js_InitJSONClass,                  EAGER_ATOM_AND_CLASP(JSON)},
        1789                 :     {js_InitTypedArrayClasses,          EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::slowClass},
        1790                 :     {js_InitWeakMapClass,               EAGER_CLASS_ATOM(WeakMap), &js::WeakMapClass},
        1791                 :     {js_InitMapClass,                   EAGER_CLASS_ATOM(Map), &js::MapObject::class_},
        1792                 :     {js_InitSetClass,                   EAGER_CLASS_ATOM(Set), &js::SetObject::class_},
        1793                 :     {NULL,                              0, NULL, NULL}
        1794                 : };
        1795                 :
        1796                 : /*
        1797                 :  * Table of top-level function and constant names and their init functions.
        1798                 :  * If you add a "standard" global function or property, remember to update
        1799                 :  * this table.
        1800                 :  */
        1801                 : static JSStdName standard_class_names[] = {
        1802                 :     {js_InitObjectClass,        EAGER_ATOM(eval), CLASP(Object)},
        1803                 :
        1804                 :     /* Global properties and functions defined by the Number class. */
        1805                 :     {js_InitNumberClass,        EAGER_ATOM(NaN), CLASP(Number)},
        1806                 :     {js_InitNumberClass,        EAGER_ATOM(Infinity), CLASP(Number)},
        1807                 :     {js_InitNumberClass,        LAZY_ATOM(isNaN), CLASP(Number)},
        1808                 :     {js_InitNumberClass,        LAZY_ATOM(isFinite), CLASP(Number)},
        1809                 :     {js_InitNumberClass,        LAZY_ATOM(parseFloat), CLASP(Number)},
        1810                 :     {js_InitNumberClass,        LAZY_ATOM(parseInt), CLASP(Number)},
        1811                 :
        1812                 :     /* String global functions. */
        1813                 :     {js_InitStringClass,        LAZY_ATOM(escape), CLASP(String)},
        1814                 :     {js_InitStringClass,        LAZY_ATOM(unescape), CLASP(String)},
        1815                 :     {js_InitStringClass,        LAZY_ATOM(decodeURI), CLASP(String)},
        1816                 :     {js_InitStringClass,        LAZY_ATOM(encodeURI), CLASP(String)},
        1817                 :     {js_InitStringClass,        LAZY_ATOM(decodeURIComponent), CLASP(String)},
        1818                 :     {js_InitStringClass,        LAZY_ATOM(encodeURIComponent), CLASP(String)},
        1819                 : #if JS_HAS_UNEVAL
        1820                 :     {js_InitStringClass,        LAZY_ATOM(uneval), CLASP(String)},
        1821                 : #endif
        1822                 :
        1823                 :     /* Exception constructors. */
        1824                 :     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(Error), CLASP(Error)},
        1825                 :     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(InternalError), CLASP(Error)},
        1826                 :     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(EvalError), CLASP(Error)},
        1827                 :     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(RangeError), CLASP(Error)},
        1828                 :     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)},
        1829                 :     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)},
        1830                 :     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(TypeError), CLASP(Error)},
        1831                 :     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(URIError), CLASP(Error)},
        1832                 :
        1833                 : #if JS_HAS_XML_SUPPORT
        1834                 :     {js_InitXMLClass,           LAZY_ATOM(XMLList), CLASP(XML)},
        1835                 :     {js_InitXMLClass,           LAZY_ATOM(isXMLName), CLASP(XML)},
        1836                 : #endif
        1837                 :
        1838                 : #if JS_HAS_GENERATORS
        1839                 :     {js_InitIteratorClasses,    EAGER_ATOM_AND_CLASP(Iterator)},
        1840                 : #endif
        1841                 :
        1842                 :     /* Typed Arrays */
        1843                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(ArrayBuffer),  &ArrayBufferClass},
        1844                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Int8Array),    TYPED_ARRAY_CLASP(TYPE_INT8)},
        1845                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint8Array),   TYPED_ARRAY_CLASP(TYPE_UINT8)},
        1846                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Int16Array),   TYPED_ARRAY_CLASP(TYPE_INT16)},
        1847                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint16Array),  TYPED_ARRAY_CLASP(TYPE_UINT16)},
        1848                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Int32Array),   TYPED_ARRAY_CLASP(TYPE_INT32)},
        1849                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint32Array),  TYPED_ARRAY_CLASP(TYPE_UINT32)},
        1850                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Float32Array), TYPED_ARRAY_CLASP(TYPE_FLOAT32)},
        1851                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Float64Array), TYPED_ARRAY_CLASP(TYPE_FLOAT64)},
        1852                 :     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint8ClampedArray),
        1853                 :                                 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED)},
        1854                 :
        1855                 :     {js_InitWeakMapClass,       EAGER_ATOM_AND_CLASP(WeakMap)},
        1856                 :     {js_InitProxyClass,         EAGER_ATOM_AND_CLASP(Proxy)},
        1857                 :
        1858                 :     {NULL,                      0, NULL, NULL}
        1859                 : };
        1860                 :
        1861                 : static JSStdName object_prototype_names[] = {
        1862                 :     /* Object.prototype properties (global delegates to Object.prototype). */
        1863                 :     {js_InitObjectClass,        EAGER_ATOM(proto), CLASP(Object)},
        1864                 : #if JS_HAS_TOSOURCE
        1865                 :     {js_InitObjectClass,        EAGER_ATOM(toSource), CLASP(Object)},
        1866                 : #endif
        1867                 :     {js_InitObjectClass,        EAGER_ATOM(toString), CLASP(Object)},
        1868                 :     {js_InitObjectClass,        EAGER_ATOM(toLocaleString), CLASP(Object)},
        1869                 :     {js_InitObjectClass,        EAGER_ATOM(valueOf), CLASP(Object)},
        1870                 : #if JS_HAS_OBJ_WATCHPOINT
        1871                 :     {js_InitObjectClass,        LAZY_ATOM(watch), CLASP(Object)},
        1872                 :     {js_InitObjectClass,        LAZY_ATOM(unwatch), CLASP(Object)},
        1873                 : #endif
        1874                 :     {js_InitObjectClass,        LAZY_ATOM(hasOwnProperty), CLASP(Object)},
        1875                 :     {js_InitObjectClass,        LAZY_ATOM(isPrototypeOf), CLASP(Object)},
        1876                 :     {js_InitObjectClass,        LAZY_ATOM(propertyIsEnumerable), CLASP(Object)},
        1877                 : #if OLD_GETTER_SETTER_METHODS
        1878                 :     {js_InitObjectClass,        LAZY_ATOM(defineGetter), CLASP(Object)},
        1879                 :     {js_InitObjectClass,        LAZY_ATOM(defineSetter), CLASP(Object)},
        1880                 :     {js_InitObjectClass,        LAZY_ATOM(lookupGetter), CLASP(Object)},
        1881                 :     {js_InitObjectClass,        LAZY_ATOM(lookupSetter), CLASP(Object)},
        1882                 : #endif
        1883                 :
        1884                 :     {NULL,                      0, NULL, NULL}
        1885                 : };
        1886                 :
        1887                 : JS_PUBLIC_API(JSBool)
        1888          649134 : JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved)
        1889                 : {
        1890                 :     JSString *idstr;
        1891                 :     JSRuntime *rt;
        1892                 :     JSAtom *atom;
        1893                 :     JSStdName *stdnm;
        1894                 :     unsigned i;
        1895                 :
        1896         1298268 :     RootObject objRoot(cx, &obj);
        1897                 :
        1898          649134 :     AssertNoGC(cx);
        1899         1298268 :     CHECK_REQUEST(cx);
        1900          649134 :     assertSameCompartment(cx, obj, id);
        1901          649134 :     *resolved = JS_FALSE;
        1902                 :
        1903          649134 :     rt = cx->runtime;
        1904          649134 :     if (!rt->hasContexts() || !JSID_IS_ATOM(id))
        1905           90351 :         return JS_TRUE;
        1906                 :
        1907          558783 :     idstr = JSID_TO_STRING(id);
        1908                 :
        1909                 :     /* Check whether we're resolving 'undefined', and define it if so. */
        1910          558783 :     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
        1911          558783 :     if (idstr == atom) {
        1912            1405 :         *resolved = JS_TRUE;
        1913                 :         return obj->defineProperty(cx, atom->asPropertyName(), UndefinedValue(),
        1914                 :                                    JS_PropertyStub, JS_StrictPropertyStub,
        1915            1405 :                                    JSPROP_PERMANENT | JSPROP_READONLY);
        1916                 :     }
        1917                 :
        1918                 :     /* Try for class constructors/prototypes named by well-known atoms. */
        1919          557378 :     stdnm = NULL;
        1920        11104025 :     for (i = 0; standard_class_atoms[i].init; i++) {
        1921        10550569 :         JS_ASSERT(standard_class_atoms[i].clasp);
        1922        10550569 :         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
        1923        10550569 :         if (idstr == atom) {
        1924            3922 :             stdnm = &standard_class_atoms[i];
        1925            3922 :             break;
        1926                 :         }
        1927                 :     }
        1928                 :
        1929          557378 :     if (!stdnm) {
        1930                 :         /* Try less frequently used top-level functions and constants. */
        1931        20985101 :         for (i = 0; standard_class_names[i].init; i++) {
        1932        20434095 :             JS_ASSERT(standard_class_names[i].clasp);
        1933        20434095 :             atom = StdNameToAtom(cx, &standard_class_names[i]);
        1934        20434095 :             if (!atom)
        1935               0 :                 return JS_FALSE;
        1936        20434095 :             if (idstr == atom) {
        1937            2450 :                 stdnm = &standard_class_names[i];
        1938            2450 :                 break;
        1939                 :             }
        1940                 :         }
        1941                 :
        1942          553456 :         if (!stdnm && !obj->getProto()) {
        1943                 :             /*
        1944                 :              * Try even less frequently used names delegated from the global
        1945                 :              * object to Object.prototype, but only if the Object class hasn't
        1946                 :              * yet been initialized.
        1947                 :              */
        1948          333774 :             for (i = 0; object_prototype_names[i].init; i++) {
        1949          311526 :                 JS_ASSERT(object_prototype_names[i].clasp);
        1950          311526 :                 atom = StdNameToAtom(cx, &object_prototype_names[i]);
        1951          311526 :                 if (!atom)
        1952               0 :                     return JS_FALSE;
        1953          311526 :                 if (idstr == atom) {
        1954               9 :                     stdnm = &object_prototype_names[i];
        1955               9 :                     break;
        1956                 :                 }
        1957                 :             }
        1958                 :         }
        1959                 :     }
        1960                 :
        1961          557378 :     if (stdnm) {
        1962                 :         /*
        1963                 :          * If this standard class is anonymous, then we don't want to resolve
        1964                 :          * by name.
        1965                 :          */
        1966            6381 :         JS_ASSERT(obj->isGlobal());
        1967            6381 :         if (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS)
        1968               0 :             return JS_TRUE;
        1969                 :
        1970            6381 :         if (IsStandardClassResolved(obj, stdnm->clasp))
        1971             274 :             return JS_TRUE;
        1972                 :
        1973            6107 :         if (!stdnm->init(cx, obj))
        1974               0 :             return JS_FALSE;
        1975            6107 :         *resolved = JS_TRUE;
        1976                 :     }
        1977          557104 :     return JS_TRUE;
        1978                 : }
        1979                 :
        1980                 : JS_PUBLIC_API(JSBool)
        1981          144738 : JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
        1982                 : {
        1983                 :     JSRuntime *rt;
        1984                 :     unsigned i;
        1985                 :
        1986          144738 :     AssertNoGC(cx);
        1987          289476 :     CHECK_REQUEST(cx);
        1988          144738 :     assertSameCompartment(cx, obj);
        1989          144738 :     rt = cx->runtime;
        1990                 :
        1991                 :     /*
        1992                 :      * Check whether we need to bind 'undefined' and define it if so.
        1993                 :      * Since ES5 15.1.1.3 undefined can't be deleted.
        1994                 :      */
        1995          144738 :     PropertyName *name = rt->atomState.typeAtoms[JSTYPE_VOID];
        1996          144954 :     if (!obj->nativeContains(cx, ATOM_TO_JSID(name)) &&
        1997                 :         !obj->defineProperty(cx, name, UndefinedValue(),
        1998                 :                              JS_PropertyStub, JS_StrictPropertyStub,
        1999             216 :                              JSPROP_PERMANENT | JSPROP_READONLY)) {
        2000               0 :         return JS_FALSE;
        2001                 :     }
        2002                 :
        2003                 :     /* Initialize any classes that have not been initialized yet. */
        2004         2894760 :     for (i = 0; standard_class_atoms[i].init; i++) {
        2005         2753361 :         if (!js::IsStandardClassResolved(obj, standard_class_atoms[i].clasp) &&
        2006            3339 :             !standard_class_atoms[i].init(cx, obj))
        2007                 :         {
        2008               0 :                 return JS_FALSE;
        2009                 :         }
        2010                 :     }
        2011                 :
        2012          144738 :     return JS_TRUE;
        2013                 : }
        2014                 :
        2015                 : static JSIdArray *
        2016               0 : NewIdArray(JSContext *cx, int length)
        2017                 : {
        2018                 :     JSIdArray *ida;
        2019                 :
        2020                 :     ida = (JSIdArray *)
        2021               0 :         cx->calloc_(offsetof(JSIdArray, vector) + length * sizeof(jsval));
        2022               0 :     if (ida)
        2023               0 :         ida->length = length;
        2024               0 :     return ida;
        2025                 : }
        2026                 :
        2027                 : /*
        2028                 :  * Unlike realloc(3), this function frees ida on failure.
        2029                 :  */
        2030                 : static JSIdArray *
        2031               0 : SetIdArrayLength(JSContext *cx, JSIdArray *ida, int length)
        2032                 : {
        2033                 :     JSIdArray *rida;
        2034                 :
        2035                 :     rida = (JSIdArray *)
        2036                 :            JS_realloc(cx, ida,
        2037               0 :                       offsetof(JSIdArray, vector) + length * sizeof(jsval));
        2038               0 :     if (!rida) {
        2039               0 :         JS_DestroyIdArray(cx, ida);
        2040                 :     } else {
        2041               0 :         rida->length = length;
        2042                 :     }
        2043               0 :     return rida;
        2044                 : }
        2045                 :
        2046                 : static JSIdArray *
        2047               0 : AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, int *ip)
        2048                 : {
        2049               0 :     int i = *ip;
        2050               0 :     int length = ida->length;
        2051               0 :     if (i >= length) {
        2052               0 :         ida = SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8));
        2053               0 :         if (!ida)
        2054               0 :             return NULL;
        2055               0 :         JS_ASSERT(i < ida->length);
        2056                 :     }
        2057               0 :     ida->vector[i].init(ATOM_TO_JSID(atom));
        2058               0 :     *ip = i + 1;
        2059               0 :     return ida;
        2060                 : }
        2061                 :
        2062                 : static JSIdArray *
        2063               0 : EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
        2064                 :                     int *ip, JSBool *foundp)
        2065                 : {
        2066               0 :     *foundp = obj->nativeContains(cx, ATOM_TO_JSID(atom));
        2067               0 :     if (*foundp)
        2068               0 :         ida = AddAtomToArray(cx, atom, ida, ip);
        2069               0 :     return ida;
        2070                 : }
        2071                 :
        2072                 : JS_PUBLIC_API(JSIdArray *)
        2073               0 : JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, JSIdArray *ida)
        2074                 : {
        2075                 :     JSRuntime *rt;
        2076                 :     int i, j, k;
        2077                 :     JSAtom *atom;
        2078                 :     JSBool found;
        2079                 :     JSObjectOp init;
        2080                 :
        2081               0 :     AssertNoGC(cx);
        2082               0 :     CHECK_REQUEST(cx);
        2083               0 :     assertSameCompartment(cx, obj, ida);
        2084               0 :     rt = cx->runtime;
        2085               0 :     if (ida) {
        2086               0 :         i = ida->length;
        2087                 :     } else {
        2088               0 :         ida = NewIdArray(cx, 8);
        2089               0 :         if (!ida)
        2090               0 :             return NULL;
        2091               0 :         i = 0;
        2092                 :     }
        2093                 :
        2094                 :     /* Check whether 'undefined' has been resolved and enumerate it if so. */
        2095               0 :     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
        2096               0 :     ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
        2097               0 :     if (!ida)
        2098               0 :         return NULL;
        2099                 :
        2100                 :     /* Enumerate only classes that *have* been resolved. */
        2101               0 :     for (j = 0; standard_class_atoms[j].init; j++) {
        2102               0 :         atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
        2103               0 :         ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
        2104               0 :         if (!ida)
        2105               0 :             return NULL;
        2106                 :
        2107               0 :         if (found) {
        2108               0 :             init = standard_class_atoms[j].init;
        2109                 :
        2110               0 :             for (k = 0; standard_class_names[k].init; k++) {
        2111               0 :                 if (standard_class_names[k].init == init) {
        2112               0 :                     atom = StdNameToAtom(cx, &standard_class_names[k]);
        2113               0 :                     ida = AddAtomToArray(cx, atom, ida, &i);
        2114               0 :                     if (!ida)
        2115               0 :                         return NULL;
        2116                 :                 }
        2117                 :             }
        2118                 :
        2119               0 :             if (init == js_InitObjectClass) {
        2120               0 :                 for (k = 0; object_prototype_names[k].init; k++) {
        2121               0 :                     atom = StdNameToAtom(cx, &object_prototype_names[k]);
        2122               0 :                     ida = AddAtomToArray(cx, atom, ida, &i);
        2123               0 :                     if (!ida)
        2124               0 :                         return NULL;
        2125                 :                 }
        2126                 :             }
        2127                 :         }
        2128                 :     }
        2129                 :
        2130                 :     /* Trim to exact length. */
        2131               0 :     return SetIdArrayLength(cx, ida, i);
        2132                 : }
        2133                 :
        2134                 : #undef CLASP
        2135                 : #undef EAGER_ATOM
        2136                 : #undef EAGER_CLASS_ATOM
        2137                 : #undef EAGER_ATOM_CLASP
        2138                 : #undef LAZY_ATOM
        2139                 :
        2140                 : JS_PUBLIC_API(JSBool)
        2141               0 : JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp)
        2142                 : {
        2143               0 :     AssertNoGC(cx);
        2144               0 :     CHECK_REQUEST(cx);
        2145               0 :     assertSameCompartment(cx, obj);
        2146               0 :     return js_GetClassObject(cx, obj, key, objp);
        2147                 : }
        2148                 :
        2149                 : JS_PUBLIC_API(JSObject *)
        2150               0 : JS_GetObjectPrototype(JSContext *cx, JSObject *forObj)
        2151                 : {
        2152               0 :     CHECK_REQUEST(cx);
        2153               0 :     assertSameCompartment(cx, forObj);
        2154               0 :     return forObj->global().getOrCreateObjectPrototype(cx);
        2155                 : }
        2156                 :
        2157                 : JS_PUBLIC_API(JSObject *)
        2158               0 : JS_GetFunctionPrototype(JSContext *cx, JSObject *forObj)
        2159                 : {
        2160               0 :     CHECK_REQUEST(cx);
        2161               0 :     assertSameCompartment(cx, forObj);
        2162               0 :     return forObj->global().getOrCreateFunctionPrototype(cx);
        2163                 : }
        2164                 :
        2165                 : JS_PUBLIC_API(JSObject *)
        2166               0 : JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
        2167                 : {
        2168               0 :     AssertNoGC(cx);
        2169               0 :     assertSameCompartment(cx, obj);
        2170               0 :     return &obj->global();
        2171                 : }
        2172                 :
        2173                 : JS_PUBLIC_API(JSObject *)
        2174       912193789 : JS_GetGlobalForScopeChain(JSContext *cx)
        2175                 : {
        2176       912193789 :     AssertNoGC(cx);
        2177      1824387578 :     CHECK_REQUEST(cx);
        2178       912193789 :     return GetGlobalForScopeChain(cx);
        2179                 : }
        2180                 :
        2181                 : JS_PUBLIC_API(jsval)
        2182             972 : JS_ComputeThis(JSContext *cx, jsval *vp)
        2183                 : {
        2184             972 :     AssertNoGC(cx);
        2185             972 :     assertSameCompartment(cx, JSValueArray(vp, 2));
        2186             972 :     CallReceiver call = CallReceiverFromVp(vp);
        2187             972 :     if (!BoxNonStrictThis(cx, call))
        2188               0 :         return JSVAL_NULL;
        2189             972 :     return call.thisv();
        2190                 : }
        2191                 :
        2192                 : JS_PUBLIC_API(void)
        2193               0 : JS_MallocInCompartment(JSCompartment *comp, size_t nbytes)
        2194                 : {
        2195               0 :     comp->mallocInCompartment(nbytes);
        2196               0 : }
        2197                 :
        2198                 : JS_PUBLIC_API(void)
        2199               0 : JS_FreeInCompartment(JSCompartment *comp, size_t nbytes)
        2200                 : {
        2201               0 :     comp->freeInCompartment(nbytes);
        2202               0 : }
        2203                 :
        2204                 : JS_PUBLIC_API(void *)
        2205              18 : JS_malloc(JSContext *cx, size_t nbytes)
        2206                 : {
        2207              18 :     AssertNoGC(cx);
        2208              36 :     CHECK_REQUEST(cx);
        2209              18 :     return cx->malloc_(nbytes);
        2210                 : }
        2211                 :
        2212                 : JS_PUBLIC_API(void *)
        2213               0 : JS_realloc(JSContext *cx, void *p, size_t nbytes)
        2214                 : {
        2215               0 :     AssertNoGC(cx);
        2216               0 :     CHECK_REQUEST(cx);
        2217               0 :     return cx->realloc_(p, nbytes);
        2218                 : }
        2219                 :
        2220                 : JS_PUBLIC_API(void)
        2221           24725 : JS_free(JSContext *cx, void *p)
        2222                 : {
        2223           24725 :     return cx->free_(p);
        2224                 : }
        2225                 :
        2226                 : JS_PUBLIC_API(void)
        2227               0 : JS_freeop(JSFreeOp *fop, void *p)
        2228                 : {
        2229               0 :     return FreeOp::get(fop)->free_(p);
        2230                 : }
        2231                 :
        2232                 : JS_PUBLIC_API(JSFreeOp *)
        2233               0 : JS_GetDefaultFreeOp(JSRuntime *rt)
        2234                 : {
        2235               0 :     return rt->defaultFreeOp();
        2236                 : }
        2237                 :
        2238                 : JS_PUBLIC_API(void)
        2239               0 : JS_updateMallocCounter(JSContext *cx, size_t nbytes)
        2240                 : {
        2241               0 :     return cx->runtime->updateMallocCounter(cx, nbytes);
        2242                 : }
        2243                 :
        2244                 : JS_PUBLIC_API(char *)
        2245          971786 : JS_strdup(JSContext *cx, const char *s)
        2246                 : {
        2247          971786 :     AssertNoGC(cx);
        2248          971786 :     size_t n = strlen(s) + 1;
        2249          971786 :     void *p = cx->malloc_(n);
        2250          971786 :     if (!p)
        2251               0 :         return NULL;
        2252          971786 :     return (char *)js_memcpy(p, s, n);
        2253                 : }
        2254                 :
        2255                 : JS_PUBLIC_API(JSBool)
        2256             378 : JS_NewNumberValue(JSContext *cx, double d, jsval *rval)
        2257                 : {
        2258             378 :     AssertNoGC(cx);
        2259             378 :     d = JS_CANONICALIZE_NAN(d);
        2260             378 :     rval->setNumber(d);
        2261             378 :     return JS_TRUE;
        2262                 : }
        2263                 :
        2264                 : #undef JS_AddRoot
        2265                 :
        2266                 : JS_PUBLIC_API(JSBool)
        2267             171 : JS_AddValueRoot(JSContext *cx, jsval *vp)
        2268                 : {
        2269             171 :     AssertNoGC(cx);
        2270             342 :     CHECK_REQUEST(cx);
        2271             171 :     return js_AddRoot(cx, vp, NULL);
        2272                 : }
        2273                 :
        2274                 : JS_PUBLIC_API(JSBool)
        2275               0 : JS_AddStringRoot(JSContext *cx, JSString **rp)
        2276                 : {
        2277               0 :     AssertNoGC(cx);
        2278               0 :     CHECK_REQUEST(cx);
        2279               0 :     return js_AddGCThingRoot(cx, (void **)rp, NULL);
        2280                 : }
        2281                 :
        2282                 : JS_PUBLIC_API(JSBool)
        2283               0 : JS_AddObjectRoot(JSContext *cx, JSObject **rp)
        2284                 : {
        2285               0 :     AssertNoGC(cx);
        2286               0 :     CHECK_REQUEST(cx);
        2287               0 :     return js_AddGCThingRoot(cx, (void **)rp, NULL);
        2288                 : }
        2289                 :
        2290                 : JS_PUBLIC_API(JSBool)
        2291               0 : JS_AddGCThingRoot(JSContext *cx, void **rp)
        2292                 : {
        2293               0 :     AssertNoGC(cx);
        2294               0 :     CHECK_REQUEST(cx);
        2295               0 :     return js_AddGCThingRoot(cx, (void **)rp, NULL);
        2296                 : }
        2297                 :
        2298                 : JS_PUBLIC_API(JSBool)
        2299               0 : JS_AddNamedValueRoot(JSContext *cx, jsval *vp, const char *name)
        2300                 : {
        2301               0 :     AssertNoGC(cx);
        2302               0 :     CHECK_REQUEST(cx);
        2303               0 :     return js_AddRoot(cx, vp, name);
        2304                 : }
        2305                 :
        2306                 : JS_PUBLIC_API(JSBool)
        2307               0 : JS_AddNamedStringRoot(JSContext *cx, JSString **rp, const char *name)
        2308                 : {
        2309               0 :     AssertNoGC(cx);
        2310               0 :     CHECK_REQUEST(cx);
        2311               0 :     return js_AddGCThingRoot(cx, (void **)rp, name);
        2312                 : }
        2313                 :
        2314                 : JS_PUBLIC_API(JSBool)
        2315           18666 : JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name)
        2316                 : {
        2317           18666 :     AssertNoGC(cx);
        2318           37332 :     CHECK_REQUEST(cx);
        2319           18666 :     return js_AddGCThingRoot(cx, (void **)rp, name);
        2320                 : }
        2321                 :
        2322                 : JS_PUBLIC_API(JSBool)
        2323               0 : JS_AddNamedScriptRoot(JSContext *cx, JSScript **rp, const char *name)
        2324                 : {
        2325               0 :     AssertNoGC(cx);
        2326               0 :     CHECK_REQUEST(cx);
        2327               0 :     return js_AddGCThingRoot(cx, (void **)rp, name);
        2328                 : }
        2329                 :
        2330                 : JS_PUBLIC_API(JSBool)
        2331               0 : JS_AddNamedGCThingRoot(JSContext *cx, void **rp, const char *name)
        2332                 : {
        2333               0 :     AssertNoGC(cx);
        2334               0 :     CHECK_REQUEST(cx);
        2335               0 :     return js_AddGCThingRoot(cx, (void **)rp, name);
        2336                 : }
        2337                 :
        2338                 : /* We allow unrooting from finalizers within the GC */
        2339                 :
        2340                 : JS_PUBLIC_API(void)
        2341             171 : JS_RemoveValueRoot(JSContext *cx, jsval *vp)
        2342                 : {
        2343             342 :     CHECK_REQUEST(cx);
        2344             171 :     js_RemoveRoot(cx->runtime, (void *)vp);
        2345             171 : }
        2346                 :
        2347                 : JS_PUBLIC_API(void)
        2348               0 : JS_RemoveStringRoot(JSContext *cx, JSString **rp)
        2349                 : {
        2350               0 :     CHECK_REQUEST(cx);
        2351               0 :     js_RemoveRoot(cx->runtime, (void *)rp);
        2352               0 : }
        2353                 :
        2354                 : JS_PUBLIC_API(void)
        2355           18666 : JS_RemoveObjectRoot(JSContext *cx, JSObject **rp)
        2356                 : {
        2357           37332 :     CHECK_REQUEST(cx);
        2358           18666 :     js_RemoveRoot(cx->runtime, (void *)rp);
        2359           18666 : }
        2360                 :
        2361                 : JS_PUBLIC_API(void)
        2362               0 : JS_RemoveScriptRoot(JSContext *cx, JSScript **rp)
        2363                 : {
        2364               0 :     CHECK_REQUEST(cx);
        2365               0 :     js_RemoveRoot(cx->runtime, (void *)rp);
        2366               0 : }
        2367                 :
        2368                 : JS_PUBLIC_API(void)
        2369               0 : JS_RemoveGCThingRoot(JSContext *cx, void **rp)
        2370                 : {
        2371               0 :     CHECK_REQUEST(cx);
        2372               0 :     js_RemoveRoot(cx->runtime, (void *)rp);
        2373               0 : }
        2374                 :
        2375                 : JS_PUBLIC_API(void)
        2376               0 : JS_RemoveValueRootRT(JSRuntime *rt, jsval *vp)
        2377                 : {
        2378               0 :     js_RemoveRoot(rt, (void *)vp);
        2379               0 : }
        2380                 :
        2381                 : JS_PUBLIC_API(void)
        2382               0 : JS_RemoveStringRootRT(JSRuntime *rt, JSString **rp)
        2383                 : {
        2384               0 :     js_RemoveRoot(rt, (void *)rp);
        2385               0 : }
        2386                 :
        2387                 : JS_PUBLIC_API(void)
        2388               0 : JS_RemoveObjectRootRT(JSRuntime *rt, JSObject **rp)
        2389                 : {
        2390               0 :     js_RemoveRoot(rt, (void *)rp);
        2391               0 : }
        2392                 :
        2393                 : JS_PUBLIC_API(void)
        2394               0 : JS_RemoveScriptRoot(JSRuntime *rt, JSScript **rp)
        2395                 : {
        2396               0 :     js_RemoveRoot(rt, (void *)rp);
        2397               0 : }
        2398                 :
        2399                 : JS_NEVER_INLINE JS_PUBLIC_API(void)
        2400               0 : JS_AnchorPtr(void *p)
        2401                 : {
        2402               0 : }
        2403                 :
        2404                 : #ifdef DEBUG
        2405                 :
        2406                 : JS_PUBLIC_API(void)
        2407               0 : JS_DumpNamedRoots(JSRuntime *rt,
        2408                 :                   void (*dump)(const char *name, void *rp, JSGCRootType type, void *data),
        2409                 :                   void *data)
        2410                 : {
        2411               0 :     js_DumpNamedRoots(rt, dump, data);
        2412               0 : }
        2413                 :
        2414                 : #endif /* DEBUG */
        2415                 :
        2416                 : JS_PUBLIC_API(uint32_t)
        2417               0 : JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
        2418                 : {
        2419               0 :     return js_MapGCRoots(rt, map, data);
        2420                 : }
        2421                 :
        2422                 : JS_PUBLIC_API(JSBool)
        2423               0 : JS_LockGCThing(JSContext *cx, void *thing)
        2424                 : {
        2425                 :     JSBool ok;
        2426                 :
        2427               0 :     AssertNoGC(cx);
        2428               0 :     CHECK_REQUEST(cx);
        2429               0 :     ok = js_LockGCThingRT(cx->runtime, thing);
        2430               0 :     if (!ok)
        2431               0 :         JS_ReportOutOfMemory(cx);
        2432               0 :     return ok;
        2433                 : }
        2434                 :
        2435                 : JS_PUBLIC_API(JSBool)
        2436               0 : JS_LockGCThingRT(JSRuntime *rt, void *thing)
        2437                 : {
        2438               0 :     return js_LockGCThingRT(rt, thing);
        2439                 : }
        2440                 :
        2441                 : JS_PUBLIC_API(JSBool)
        2442               0 : JS_UnlockGCThing(JSContext *cx, void *thing)
        2443                 : {
        2444               0 :     AssertNoGC(cx);
        2445               0 :     CHECK_REQUEST(cx);
        2446               0 :     js_UnlockGCThingRT(cx->runtime, thing);
        2447               0 :     return true;
        2448                 : }
        2449                 :
        2450                 : JS_PUBLIC_API(JSBool)
        2451               0 : JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
        2452                 : {
        2453               0 :     js_UnlockGCThingRT(rt, thing);
        2454               0 :     return true;
        2455                 : }
        2456                 :
        2457                 : JS_PUBLIC_API(void)
        2458               0 : JS_SetExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
        2459                 : {
        2460               0 :     AssertNoGC(rt);
        2461               0 :     rt->gcBlackRootsTraceOp = traceOp;
        2462               0 :     rt->gcBlackRootsData = data;
        2463               0 : }
        2464                 :
        2465                 : JS_PUBLIC_API(void)
        2466            6097 : JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback)
        2467                 : {
        2468            6097 :     InitTracer(trc, rt, callback);
        2469            6097 : }
        2470                 :
        2471                 : JS_PUBLIC_API(void)
        2472             549 : JS_TraceRuntime(JSTracer *trc)
        2473                 : {
        2474             549 :     AssertNoGC(trc->runtime);
        2475             549 :     TraceRuntime(trc);
        2476             549 : }
        2477                 :
        2478                 : JS_PUBLIC_API(void)
        2479        25175500 : JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
        2480                 : {
        2481        25175500 :     js::TraceChildren(trc, thing, kind);
        2482        25175500 : }
        2483                 :
        2484                 : JS_PUBLIC_API(void)
        2485               0 : JS_CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind)
        2486                 : {
        2487               0 :     js::CallTracer(trc, thing, kind);
        2488               0 : }
        2489                 :
        2490                 : #ifdef DEBUG
        2491                 :
        2492                 : JS_PUBLIC_API(void)
        2493               0 : JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
        2494                 :                        JSGCTraceKind kind, JSBool details)
        2495                 : {
        2496               0 :     const char *name = NULL; /* silence uninitialized warning */
        2497                 :     size_t n;
        2498                 :
        2499               0 :     if (bufsize == 0)
        2500               0 :         return;
        2501                 :
        2502               0 :     switch (kind) {
        2503                 :       case JSTRACE_OBJECT:
        2504                 :       {
        2505               0 :         name = static_cast<JSObject *>(thing)->getClass()->name;
        2506               0 :         break;
        2507                 :       }
        2508                 :
        2509                 :       case JSTRACE_STRING:
        2510               0 :         name = ((JSString *)thing)->isDependent()
        2511                 :                ? "substring"
        2512               0 :                : "string";
        2513               0 :         break;
        2514                 :
        2515                 :       case JSTRACE_SCRIPT:
        2516               0 :         name = "script";
        2517               0 :         break;
        2518                 :
        2519                 :       case JSTRACE_SHAPE:
        2520               0 :         name = "shape";
        2521               0 :         break;
        2522                 :
        2523                 :       case JSTRACE_BASE_SHAPE:
        2524               0 :         name = "base_shape";
        2525               0 :         break;
        2526                 :
        2527                 :       case JSTRACE_TYPE_OBJECT:
        2528               0 :         name = "type_object";
        2529               0 :         break;
        2530                 :
        2531                 : #if JS_HAS_XML_SUPPORT
        2532                 :       case JSTRACE_XML:
        2533               0 :         name = "xml";
        2534               0 :         break;
        2535                 : #endif
        2536                 :     }
        2537                 :
        2538               0 :     n = strlen(name);
        2539               0 :     if (n > bufsize - 1)
        2540               0 :         n = bufsize - 1;
        2541               0 :     js_memcpy(buf, name, n + 1);
        2542               0 :     buf += n;
        2543               0 :     bufsize -= n;
        2544               0 :     *buf = '\0';
        2545                 :
        2546               0 :     if (details && bufsize > 2) {
        2547               0 :         switch (kind) {
        2548                 :           case JSTRACE_OBJECT:
        2549                 :           {
        2550               0 :             JSObject *obj = (JSObject *)thing;
        2551               0 :             Class *clasp = obj->getClass();
        2552               0 :             if (clasp == &FunctionClass) {
        2553               0 :                 JSFunction *fun = obj->toFunction();
        2554               0 :                 if (!fun) {
        2555               0 :                     JS_snprintf(buf, bufsize, " <newborn>");
        2556               0 :                 } else if (fun != obj) {
        2557               0 :                     JS_snprintf(buf, bufsize, " %p", fun);
        2558                 :                 } else {
        2559               0 :                     if (fun->atom) {
        2560               0 :                         *buf++ = ' ';
        2561               0 :                         bufsize--;
        2562               0 :                         PutEscapedString(buf, bufsize, fun->atom, 0);
        2563                 :                     }
        2564                 :                 }
        2565               0 :             } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
        2566               0 :                 JS_snprintf(buf, bufsize, " %p", obj->getPrivate());
        2567                 :             } else {
        2568               0 :                 JS_snprintf(buf, bufsize, " <no private>");
        2569                 :             }
        2570               0 :             break;
        2571                 :           }
        2572                 :
        2573                 :           case JSTRACE_STRING:
        2574                 :           {
        2575               0 :             *buf++ = ' ';
        2576               0 :             bufsize--;
        2577               0 :             JSString *str = (JSString *)thing;
        2578               0 :             if (str->isLinear())
        2579               0 :                 PutEscapedString(buf, bufsize, &str->asLinear(), 0);
        2580                 :             else
        2581               0 :                 JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length());
        2582               0 :             break;
        2583                 :           }
        2584                 :
        2585                 :           case JSTRACE_SCRIPT:
        2586                 :           {
        2587               0 :             JSScript *script = static_cast<JSScript *>(thing);
        2588               0 :             JS_snprintf(buf, bufsize, " %s:%u", script->filename, unsigned(script->lineno));
        2589               0 :             break;
        2590                 :           }
        2591                 :
        2592                 :           case JSTRACE_SHAPE:
        2593                 :           case JSTRACE_BASE_SHAPE:
        2594                 :           case JSTRACE_TYPE_OBJECT:
        2595               0 :             break;
        2596                 :
        2597                 : #if JS_HAS_XML_SUPPORT
        2598                 :           case JSTRACE_XML:
        2599                 :           {
        2600                 :             extern const char *js_xml_class_str[];
        2601               0 :             JSXML *xml = (JSXML *)thing;
        2602                 :
        2603               0 :             JS_snprintf(buf, bufsize, " %s", js_xml_class_str[xml->xml_class]);
        2604               0 :             break;
        2605                 :           }
        2606                 : #endif
        2607                 :         }
        2608                 :     }
        2609               0 :     buf[bufsize - 1] = '\0';
        2610                 : }
        2611                 :
        2612                 : extern JS_PUBLIC_API(const char *)
        2613               0 : JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize)
        2614                 : {
        2615               0 :     if (trc->debugPrinter) {
        2616               0 :         trc->debugPrinter(trc, buffer, bufferSize);
        2617               0 :         return buffer;
        2618                 :     }
        2619               0 :     if (trc->debugPrintIndex != (size_t) - 1) {
        2620                 :         JS_snprintf(buffer, bufferSize, "%s[%lu]",
        2621                 :                     (const char *)trc->debugPrintArg,
        2622               0 :                     trc->debugPrintIndex);
        2623               0 :         return buffer;
        2624                 :     }
        2625               0 :     return (const char*)trc->debugPrintArg;
        2626                 : }
        2627                 :
        2628                 : typedef struct JSHeapDumpNode JSHeapDumpNode;
        2629                 :
        2630                 : struct JSHeapDumpNode {
        2631                 :     void            *thing;
        2632                 :     JSGCTraceKind   kind;
        2633                 :     JSHeapDumpNode  *next;          /* next sibling */
        2634                 :     JSHeapDumpNode  *parent;        /* node with the thing that refer to thing
        2635                 :                                        from this node */
        2636                 :     char            edgeName[1];    /* name of the edge from parent->thing
        2637                 :                                        into thing */
        2638                 : };
        2639                 :
        2640                 : typedef HashSet<void *, PointerHasher<void *, 3>, SystemAllocPolicy> VisitedSet;
        2641                 :
        2642               0 : typedef struct JSDumpingTracer {
        2643                 :     JSTracer            base;
        2644                 :     VisitedSet          visited;
        2645                 :     bool                ok;
        2646                 :     void                *startThing;
        2647                 :     void                *thingToFind;
        2648                 :     void                *thingToIgnore;
        2649                 :     JSHeapDumpNode      *parentNode;
        2650                 :     JSHeapDumpNode      **lastNodep;
        2651                 :     char                buffer[200];
        2652                 : } JSDumpingTracer;
        2653                 :
        2654                 : static void
        2655               0 : DumpNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
        2656                 : {
        2657               0 :     JS_ASSERT(trc->callback == DumpNotify);
        2658                 :
        2659               0 :     JSDumpingTracer *dtrc = (JSDumpingTracer *)trc;
        2660               0 :     void *thing = *thingp;
        2661                 :
        2662               0 :     if (!dtrc->ok || thing == dtrc->thingToIgnore)
        2663               0 :         return;
        2664                 :
        2665                 :     /*
        2666                 :      * Check if we have already seen thing unless it is thingToFind to include
        2667                 :      * it to the graph each time we reach it and print all live things that
        2668                 :      * refer to thingToFind.
        2669                 :      *
        2670                 :      * This does not print all possible paths leading to thingToFind since
        2671                 :      * when a thing A refers directly or indirectly to thingToFind and A is
        2672                 :      * present several times in the graph, we will print only the first path
        2673                 :      * leading to A and thingToFind, other ways to reach A will be ignored.
        2674                 :      */
        2675               0 :     if (dtrc->thingToFind != thing) {
        2676                 :         /*
        2677                 :          * The startThing check allows to avoid putting startThing into the
        2678                 :          * hash table before tracing startThing in JS_DumpHeap.
        2679                 :          */
        2680               0 :         if (thing == dtrc->startThing)
        2681               0 :             return;
        2682               0 :         VisitedSet::AddPtr p = dtrc->visited.lookupForAdd(thing);
        2683               0 :         if (p)
        2684                 :             return;
        2685               0 :         if (!dtrc->visited.add(p, thing)) {
        2686               0 :             dtrc->ok = false;
        2687                 :             return;
        2688                 :         }
        2689                 :     }
        2690                 :
        2691               0 :     const char *edgeName = JS_GetTraceEdgeName(&dtrc->base, dtrc->buffer, sizeof(dtrc->buffer));
        2692               0 :     size_t edgeNameSize = strlen(edgeName) + 1;
        2693               0 :     size_t bytes = offsetof(JSHeapDumpNode, edgeName) + edgeNameSize;
        2694               0 :     JSHeapDumpNode *node = (JSHeapDumpNode *) OffTheBooks::malloc_(bytes);
        2695               0 :     if (!node) {
        2696               0 :         dtrc->ok = false;
        2697               0 :         return;
        2698                 :     }
        2699                 :
        2700               0 :     node->thing = thing;
        2701               0 :     node->kind = kind;
        2702               0 :     node->next = NULL;
        2703               0 :     node->parent = dtrc->parentNode;
        2704               0 :     js_memcpy(node->edgeName, edgeName, edgeNameSize);
        2705                 :
        2706               0 :     JS_ASSERT(!*dtrc->lastNodep);
        2707               0 :     *dtrc->lastNodep = node;
        2708               0 :     dtrc->lastNodep = &node->next;
        2709                 : }
        2710                 :
        2711                 : /* Dump node and the chain that leads to thing it contains. */
        2712                 : static JSBool
        2713               0 : DumpNode(JSDumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
        2714                 : {
        2715                 :     JSHeapDumpNode *prev, *following;
        2716                 :     size_t chainLimit;
        2717                 :     enum { MAX_PARENTS_TO_PRINT = 10 };
        2718                 :
        2719                 :     JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
        2720               0 :                            &dtrc->base, node->thing, node->kind, JS_TRUE);
        2721               0 :     if (fprintf(fp, "%p %-22s via ", node->thing, dtrc->buffer) < 0)
        2722               0 :         return JS_FALSE;
        2723                 :
        2724                 :     /*
        2725                 :      * We need to print the parent chain in the reverse order. To do it in
        2726                 :      * O(N) time where N is the chain length we first reverse the chain while
        2727                 :      * searching for the top and then print each node while restoring the
        2728                 :      * chain order.
        2729                 :      */
        2730               0 :     chainLimit = MAX_PARENTS_TO_PRINT;
        2731               0 :     prev = NULL;
        2732               0 :     for (;;) {
        2733               0 :         following = node->parent;
        2734               0 :         node->parent = prev;
        2735               0 :         prev = node;
        2736               0 :         node = following;
        2737               0 :         if (!node)
        2738               0 :             break;
        2739               0 :         if (chainLimit == 0) {
        2740               0 :             if (fputs("...", fp) < 0)
        2741               0 :                 return JS_FALSE;
        2742               0 :             break;
        2743                 :         }
        2744               0 :         --chainLimit;
        2745                 :     }
        2746                 :
        2747               0 :     node = prev;
        2748               0 :     prev = following;
        2749               0 :     bool ok = true;
        2750               0 :     do {
        2751                 :         /* Loop must continue even when !ok to restore the parent chain. */
        2752               0 :         if (ok) {
        2753               0 :             if (!prev) {
        2754                 :                 /* Print edge from some runtime root or startThing. */
        2755               0 :                 if (fputs(node->edgeName, fp) < 0)
        2756               0 :                     ok = false;
        2757                 :             } else {
        2758                 :                 JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
        2759                 :                                        &dtrc->base, prev->thing, prev->kind,
        2760               0 :                                        JS_FALSE);
        2761               0 :                 if (fprintf(fp, "(%p %s).%s",
        2762               0 :                            prev->thing, dtrc->buffer, node->edgeName) < 0) {
        2763               0 :                     ok = false;
        2764                 :                 }
        2765                 :             }
        2766                 :         }
        2767               0 :         following = node->parent;
        2768               0 :         node->parent = prev;
        2769               0 :         prev = node;
        2770               0 :         node = following;
        2771                 :     } while (node);
        2772                 :
        2773               0 :     return ok && putc('\n', fp) >= 0;
        2774                 : }
        2775                 :
        2776                 : JS_PUBLIC_API(JSBool)
        2777               0 : JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind startKind,
        2778                 :             void *thingToFind, size_t maxDepth, void *thingToIgnore)
        2779                 : {
        2780               0 :     if (maxDepth == 0)
        2781               0 :         return true;
        2782                 :
        2783               0 :     JSDumpingTracer dtrc;
        2784               0 :     if (!dtrc.visited.init())
        2785               0 :         return false;
        2786               0 :     JS_TracerInit(&dtrc.base, rt, DumpNotify);
        2787               0 :     dtrc.ok = true;
        2788               0 :     dtrc.startThing = startThing;
        2789               0 :     dtrc.thingToFind = thingToFind;
        2790               0 :     dtrc.thingToIgnore = thingToIgnore;
        2791               0 :     dtrc.parentNode = NULL;
        2792               0 :     JSHeapDumpNode *node = NULL;
        2793               0 :     dtrc.lastNodep = &node;
        2794               0 :     if (!startThing) {
        2795               0 :         JS_ASSERT(startKind == JSTRACE_OBJECT);
        2796               0 :         TraceRuntime(&dtrc.base);
        2797                 :     } else {
        2798               0 :         JS_TraceChildren(&dtrc.base, startThing, startKind);
        2799                 :     }
        2800                 :
        2801               0 :     if (!node)
        2802               0 :         return dtrc.ok;
        2803                 :
        2804               0 :     size_t depth = 1;
        2805                 :     JSHeapDumpNode *children, *next, *parent;
        2806               0 :     bool thingToFindWasTraced = thingToFind && thingToFind == startThing;
        2807               0 :     for (;;) {
        2808                 :         /*
        2809                 :          * Loop must continue even when !dtrc.ok to free all nodes allocated
        2810                 :          * so far.
        2811                 :          */
        2812               0 :         if (dtrc.ok) {
        2813               0 :             if (thingToFind == NULL || thingToFind == node->thing)
        2814               0 :                 dtrc.ok = DumpNode(&dtrc, fp, node);
        2815                 :
        2816                 :             /* Descend into children. */
        2817               0 :             if (dtrc.ok &&
        2818                 :                 depth < maxDepth &&
        2819               0 :                 (thingToFind != node->thing || !thingToFindWasTraced)) {
        2820               0 :                 dtrc.parentNode = node;
        2821               0 :                 children = NULL;
        2822               0 :                 dtrc.lastNodep = &children;
        2823               0 :                 JS_TraceChildren(&dtrc.base, node->thing, node->kind);
        2824               0 :                 if (thingToFind == node->thing)
        2825               0 :                     thingToFindWasTraced = JS_TRUE;
        2826               0 :                 if (children != NULL) {
        2827               0 :                     ++depth;
        2828               0 :                     node = children;
        2829               0 :                     continue;
        2830                 :                 }
        2831                 :             }
        2832                 :         }
        2833                 :
        2834                 :         /* Move to next or parents next and free the node. */
        2835               0 :         for (;;) {
        2836               0 :             next = node->next;
        2837               0 :             parent = node->parent;
        2838               0 :             Foreground::free_(node);
        2839               0 :             node = next;
        2840               0 :             if (node)
        2841               0 :                 break;
        2842               0 :             if (!parent)
        2843               0 :                 return dtrc.ok;
        2844               0 :             JS_ASSERT(depth > 1);
        2845               0 :             --depth;
        2846               0 :             node = parent;
        2847                 :         }
        2848                 :     }
        2849                 :
        2850                 :     JS_ASSERT(depth == 1);
        2851                 :     return dtrc.ok;
        2852                 : }
        2853                 :
        2854                 : #endif /* DEBUG */
        2855                 :
        2856                 : extern JS_PUBLIC_API(JSBool)
        2857               0 : JS_IsGCMarkingTracer(JSTracer *trc)
        2858                 : {
        2859               0 :     return IS_GC_MARKING_TRACER(trc);
        2860                 : }
        2861                 :
        2862                 : JS_PUBLIC_API(void)
        2863              63 : JS_GC(JSContext *cx)
        2864                 : {
        2865              63 :     AssertNoGC(cx);
        2866              63 :     PrepareForFullGC(cx->runtime);
        2867              63 :     GC(cx, GC_NORMAL, gcreason::API);
        2868              63 : }
        2869                 :
        2870                 : JS_PUBLIC_API(void)
        2871               0 : JS_MaybeGC(JSContext *cx)
        2872                 : {
        2873               0 :     MaybeGC(cx);
        2874               0 : }
        2875                 :
        2876                 : JS_PUBLIC_API(void)
        2877               0 : JS_SetGCCallback(JSRuntime *rt, JSGCCallback cb)
        2878                 : {
        2879               0 :     AssertNoGC(rt);
        2880               0 :     rt->gcCallback = cb;
        2881               0 : }
        2882                 :
        2883                 : JS_PUBLIC_API(void)
        2884               1 : JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb)
        2885                 : {
        2886               1 :     AssertNoGC(rt);
        2887               1 :     rt->gcFinalizeCallback = cb;
        2888               1 : }
        2889                 :
        2890                 : JS_PUBLIC_API(JSBool)
        2891               2 : JS_IsAboutToBeFinalized(void *thing)
        2892                 : {
        2893               2 :     gc::Cell *t = static_cast<gc::Cell *>(thing);
        2894               2 :     return IsAboutToBeFinalized(t);
        2895                 : }
        2896                 :
        2897                 : JS_PUBLIC_API(void)
        2898           37342 : JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32_t value)
        2899                 : {
        2900           37342 :     switch (key) {
        2901                 :       case JSGC_MAX_BYTES: {
        2902           18676 :         JS_ASSERT(value >= rt->gcBytes);
        2903           18676 :         rt->gcMaxBytes = value;
        2904           18676 :         break;
        2905                 :       }
        2906                 :       case JSGC_MAX_MALLOC_BYTES:
        2907               0 :         rt->setGCMaxMallocBytes(value);
        2908               0 :         break;
        2909                 :       case JSGC_SLICE_TIME_BUDGET:
        2910               0 :         rt->gcSliceBudget = SliceBudget::TimeBudget(value);
        2911               0 :         break;
        2912                 :       case JSGC_MARK_STACK_LIMIT:
        2913               0 :         js::SetMarkStackLimit(rt, value);
        2914               0 :         break;
        2915                 :       default:
        2916           18666 :         JS_ASSERT(key == JSGC_MODE);
        2917           18666 :         rt->gcMode = JSGCMode(value);
        2918               0 :         JS_ASSERT(rt->gcMode == JSGC_MODE_GLOBAL ||
        2919                 :                   rt->gcMode == JSGC_MODE_COMPARTMENT ||
        2920           18666 :                   rt->gcMode == JSGC_MODE_INCREMENTAL);
        2921           18666 :         return;
        2922                 :     }
        2923                 : }
        2924                 :
        2925                 : JS_PUBLIC_API(uint32_t)
        2926              18 : JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
        2927                 : {
        2928              18 :     switch (key) {
        2929                 :       case JSGC_MAX_BYTES:
        2930               0 :         return uint32_t(rt->gcMaxBytes);
        2931                 :       case JSGC_MAX_MALLOC_BYTES:
        2932               0 :         return rt->gcMaxMallocBytes;
        2933                 :       case JSGC_BYTES:
        2934              18 :         return uint32_t(rt->gcBytes);
        2935                 :       case JSGC_MODE:
        2936               0 :         return uint32_t(rt->gcMode);
        2937                 :       case JSGC_UNUSED_CHUNKS:
        2938               0 :         return uint32_t(rt->gcChunkPool.getEmptyCount());
        2939                 :       case JSGC_TOTAL_CHUNKS:
        2940               0 :         return uint32_t(rt->gcChunkSet.count() + rt->gcChunkPool.getEmptyCount());
        2941                 :       case JSGC_SLICE_TIME_BUDGET:
        2942               0 :         return uint32_t(rt->gcSliceBudget > 0 ? rt->gcSliceBudget / PRMJ_USEC_PER_MSEC : 0);
        2943                 :       case JSGC_MARK_STACK_LIMIT:
        2944               0 :         return rt->gcMarker.sizeLimit();
        2945                 :       default:
        2946               0 :         JS_ASSERT(key == JSGC_NUMBER);
        2947               0 :         return uint32_t(rt->gcNumber);
        2948                 :     }
        2949                 : }
        2950                 :
        2951                 : JS_PUBLIC_API(void)
        2952           18666 : JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value)
        2953                 : {
        2954           18666 :     JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
        2955           18666 : }
        2956                 :
        2957                 : JS_PUBLIC_API(uint32_t)
        2958               0 : JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
        2959                 : {
        2960               0 :     JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
        2961               0 :     return 0;
        2962                 : }
        2963                 :
        2964                 : JS_PUBLIC_API(void)
        2965               0 : JS_FlushCaches(JSContext *cx)
        2966                 : {
        2967               0 : }
        2968                 :
        2969                 : JS_PUBLIC_API(JSString *)
        2970            2000 : JS_NewExternalString(JSContext *cx, const jschar *chars, size_t length,
        2971                 :                      const JSStringFinalizer *fin)
        2972                 : {
        2973            2000 :     AssertNoGC(cx);
        2974            4000 :     CHECK_REQUEST(cx);
        2975            2000 :     JSString *s = JSExternalString::new_(cx, chars, length, fin);
        2976            2000 :     Probes::createString(cx, s, length);
        2977            2000 :     return s;
        2978                 : }
        2979                 :
        2980                 : extern JS_PUBLIC_API(JSBool)
        2981               0 : JS_IsExternalString(JSString *str)
        2982                 : {
        2983               0 :     return str->isExternal();
        2984                 : }
        2985                 :
        2986                 : extern JS_PUBLIC_API(const JSStringFinalizer *)
        2987               0 : JS_GetExternalStringFinalizer(JSString *str)
        2988                 : {
        2989               0 :     return str->asExternal().externalFinalizer();
        2990                 : }
        2991                 :
        2992                 : JS_PUBLIC_API(void)
        2993           18759 : JS_SetNativeStackQuota(JSRuntime *rt, size_t stackSize)
        2994                 : {
        2995           18759 :     rt->nativeStackQuota = stackSize;
        2996           18759 :     if (!rt->nativeStackBase)
        2997               0 :         return;
        2998                 :
        2999                 : #if JS_STACK_GROWTH_DIRECTION > 0
        3000                 :     if (stackSize == 0) {
        3001                 :         rt->nativeStackLimit = UINTPTR_MAX;
        3002                 :     } else {
        3003                 :         JS_ASSERT(rt->nativeStackBase <= size_t(-1) - stackSize);
        3004                 :         rt->nativeStackLimit = rt->nativeStackBase + stackSize - 1;
        3005                 :     }
        3006                 : #else
        3007           18759 :     if (stackSize == 0) {
        3008               0 :         rt->nativeStackLimit = 0;
        3009                 :     } else {
        3010           18759 :         JS_ASSERT(rt->nativeStackBase >= stackSize);
        3011           18759 :         rt->nativeStackLimit = rt->nativeStackBase - (stackSize - 1);
        3012                 :     }
        3013                 : #endif
        3014                 : }
        3015                 :
        3016                 : /************************************************************************/
        3017                 :
        3018                 : JS_PUBLIC_API(int)
        3019               0 : JS_IdArrayLength(JSContext *cx, JSIdArray *ida)
        3020                 : {
        3021               0 :     return ida->length;
        3022                 : }
        3023                 :
        3024                 : JS_PUBLIC_API(jsid)
        3025               0 : JS_IdArrayGet(JSContext *cx, JSIdArray *ida, int index)
        3026                 : {
        3027               0 :     JS_ASSERT(index >= 0 && index < ida->length);
        3028               0 :     return ida->vector[index];
        3029                 : }
        3030                 :
        3031                 : JS_PUBLIC_API(void)
        3032           25246 : JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
        3033                 : {
        3034           25246 :     DestroyIdArray(cx->runtime->defaultFreeOp(), ida);
        3035           25246 : }
        3036                 :
        3037                 : JS_PUBLIC_API(JSBool)
        3038               2 : JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
        3039                 : {
        3040               2 :     AssertNoGC(cx);
        3041               4 :     CHECK_REQUEST(cx);
        3042               2 :     assertSameCompartment(cx, v);
        3043               2 :     return ValueToId(cx, v, idp);
        3044                 : }
        3045                 :
        3046                 : JS_PUBLIC_API(JSBool)
        3047               3 : JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
        3048                 : {
        3049               3 :     AssertNoGC(cx);
        3050               6 :     CHECK_REQUEST(cx);
        3051               3 :     *vp = IdToJsval(id);
        3052               3 :     assertSameCompartment(cx, *vp);
        3053               3 :     return JS_TRUE;
        3054                 : }
        3055                 :
        3056                 : JS_PUBLIC_API(JSBool)
        3057               0 : JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
        3058                 : {
        3059               0 :     AssertNoGC(cx);
        3060               0 :     CHECK_REQUEST(cx);
        3061               0 :     JS_ASSERT(obj != NULL);
        3062               0 :     JS_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
        3063               0 :     return obj->defaultValue(cx, hint, vp);
        3064                 : }
        3065                 :
        3066                 : JS_PUBLIC_API(JSBool)
        3067         1114436 : JS_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
        3068                 : {
        3069         1114436 :     return JS_TRUE;
        3070                 : }
        3071                 :
        3072                 : JS_PUBLIC_API(JSBool)
        3073               0 : JS_StrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
        3074                 : {
        3075               0 :     return JS_TRUE;
        3076                 : }
        3077                 :
        3078                 : JS_PUBLIC_API(JSBool)
        3079         1666515 : JS_EnumerateStub(JSContext *cx, JSObject *obj)
        3080                 : {
        3081         1666515 :     return JS_TRUE;
        3082                 : }
        3083                 :
        3084                 : JS_PUBLIC_API(JSBool)
        3085               0 : JS_ResolveStub(JSContext *cx, JSObject *obj, jsid id)
        3086                 : {
        3087               0 :     return JS_TRUE;
        3088                 : }
        3089                 :
        3090                 : JS_PUBLIC_API(JSBool)
        3091               0 : JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
        3092                 : {
        3093               0 :     JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
        3094               0 :     JS_ASSERT(obj);
        3095               0 :     return DefaultValue(cx, obj, type, vp);
        3096                 : }
        3097                 :
        3098                 : JS_PUBLIC_API(JSObject *)
        3099           69988 : JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
        3100                 :              JSClass *clasp, JSNative constructor, unsigned nargs,
        3101                 :              JSPropertySpec *ps, JSFunctionSpec *fs,
        3102                 :              JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
        3103                 : {
        3104           69988 :     AssertNoGC(cx);
        3105          139976 :     CHECK_REQUEST(cx);
        3106           69988 :     assertSameCompartment(cx, obj, parent_proto);
        3107          139976 :     RootObject objRoot(cx, &obj);
        3108                 :     return js_InitClass(cx, objRoot, parent_proto, Valueify(clasp), constructor,
        3109           69988 :                         nargs, ps, fs, static_ps, static_fs);
        3110                 : }
        3111                 :
        3112                 : JS_PUBLIC_API(JSBool)
        3113               0 : JS_LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto)
        3114                 : {
        3115               0 :     return LinkConstructorAndPrototype(cx, ctor, proto);
        3116                 : }
        3117                 :
        3118                 : JS_PUBLIC_API(JSClass *)
        3119         2323849 : JS_GetClass(JSObject *obj)
        3120                 : {
        3121         2323849 :     return obj->getJSClass();
        3122                 : }
        3123                 :
        3124                 : JS_PUBLIC_API(JSBool)
        3125               9 : JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
        3126                 : {
        3127               9 :     AssertNoGC(cx);
        3128              18 :     CHECK_REQUEST(cx);
        3129                 : #ifdef DEBUG
        3130               9 :     if (argv) {
        3131               0 :         assertSameCompartment(cx, obj);
        3132               0 :         assertSameCompartment(cx, JSValueArray(argv - 2, 2));
        3133                 :     }
        3134                 : #endif
        3135               9 :     if (!obj || obj->getJSClass() != clasp) {
        3136               0 :         if (argv)
        3137               0 :             ReportIncompatibleMethod(cx, CallReceiverFromArgv(argv), Valueify(clasp));
        3138               0 :         return false;
        3139                 :     }
        3140               9 :     return true;
        3141                 : }
        3142                 :
        3143                 : JS_PUBLIC_API(JSBool)
        3144               0 : JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
        3145                 : {
        3146               0 :     AssertNoGC(cx);
        3147               0 :     assertSameCompartment(cx, obj, v);
        3148               0 :     return HasInstance(cx, obj, &v, bp);
        3149                 : }
        3150                 :
        3151                 : JS_PUBLIC_API(void *)
        3152          153032 : JS_GetPrivate(JSObject *obj)
        3153                 : {
        3154                 :     /* This function can be called by a finalizer. */
        3155          153032 :     return obj->getPrivate();
        3156                 : }
        3157                 :
        3158                 : JS_PUBLIC_API(void)
        3159           37343 : JS_SetPrivate(JSObject *obj, void *data)
        3160                 : {
        3161                 :     /* This function can be called by a finalizer. */
        3162           37343 :     obj->setPrivate(data);
        3163           37343 : }
        3164                 :
        3165                 : JS_PUBLIC_API(void *)
        3166               9 : JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
        3167                 : {
        3168               9 :     if (!JS_InstanceOf(cx, obj, clasp, argv))
        3169               0 :         return NULL;
        3170               9 :     return obj->getPrivate();
        3171                 : }
        3172                 :
        3173                 : JS_PUBLIC_API(JSObject *)
        3174           69984 : JS_GetPrototype(JSObject *obj)
        3175                 : {
        3176           69984 :     return obj->getProto();
        3177                 : }
        3178                 :
        3179                 : JS_PUBLIC_API(JSBool)
        3180           23328 : JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
        3181                 : {
        3182           23328 :     AssertNoGC(cx);
        3183           46656 :     CHECK_REQUEST(cx);
        3184           23328 :     assertSameCompartment(cx, obj, proto);
        3185           23328 :     return SetProto(cx, obj, proto, JS_FALSE);
        3186                 : }
        3187                 :
        3188                 : JS_PUBLIC_API(JSObject *)
        3189          725536 : JS_GetParent(JSObject *obj)
        3190                 : {
        3191          725536 :     JS_ASSERT(!obj->isScope());
        3192          725536 :     return obj->getParent();
        3193                 : }
        3194                 :
        3195                 : JS_PUBLIC_API(JSBool)
        3196               0 : JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
        3197                 : {
        3198               0 :     AssertNoGC(cx);
        3199               0 :     CHECK_REQUEST(cx);
        3200               0 :     JS_ASSERT(!obj->isScope());
        3201               0 :     JS_ASSERT(parent || !obj->getParent());
        3202               0 :     assertSameCompartment(cx, obj, parent);
        3203               0 :     return obj->setParent(cx, parent);
        3204                 : }
        3205                 :
        3206                 : JS_PUBLIC_API(JSObject *)
        3207          120731 : JS_GetConstructor(JSContext *cx, JSObject *proto)
        3208                 : {
        3209                 :     Value cval;
        3210                 :
        3211          120731 :     AssertNoGC(cx);
        3212          241462 :     CHECK_REQUEST(cx);
        3213          120731 :     assertSameCompartment(cx, proto);
        3214                 :     {
        3215          241462 :         JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
        3216                 :
        3217          120731 :         if (!proto->getProperty(cx, cx->runtime->atomState.constructorAtom, &cval))
        3218               0 :             return NULL;
        3219                 :     }
        3220          120731 :     if (!IsFunctionObject(cval)) {
        3221                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
        3222               0 :                              proto->getClass()->name);
        3223               0 :         return NULL;
        3224                 :     }
        3225          120731 :     return &cval.toObject();
        3226                 : }
        3227                 :
        3228                 : JS_PUBLIC_API(JSBool)
        3229               0 : JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
        3230                 : {
        3231               0 :     AssertNoGC(cx);
        3232               0 :     assertSameCompartment(cx, obj);
        3233               0 :     *idp = OBJECT_TO_JSID(obj);
        3234               0 :     return JS_TRUE;
        3235                 : }
        3236                 :
        3237                 : JS_PUBLIC_API(JSObject *)
        3238           23659 : JS_NewGlobalObject(JSContext *cx, JSClass *clasp)
        3239                 : {
        3240           23659 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        3241           23659 :     AssertNoGC(cx);
        3242           47318 :     CHECK_REQUEST(cx);
        3243                 :
        3244           23659 :     return GlobalObject::create(cx, Valueify(clasp));
        3245                 : }
        3246                 :
        3247                 : class AutoHoldCompartment {
        3248                 :   public:
        3249           22524 :     explicit AutoHoldCompartment(JSCompartment *compartment JS_GUARD_OBJECT_NOTIFIER_PARAM)
        3250           22524 :       : holdp(&compartment->hold)
        3251                 :     {
        3252           22524 :         JS_GUARD_OBJECT_NOTIFIER_INIT;
        3253           22524 :         *holdp = true;
        3254           22524 :     }
        3255                 :
        3256           45048 :     ~AutoHoldCompartment() {
        3257           22524 :         *holdp = false;
        3258           22524 :     }
        3259                 :   private:
        3260                 :     bool *holdp;
        3261                 :     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
        3262                 : };
        3263                 :
        3264                 : JS_PUBLIC_API(JSObject *)
        3265           22524 : JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals)
        3266                 : {
        3267           22524 :     AssertNoGC(cx);
        3268           45048 :     CHECK_REQUEST(cx);
        3269           22524 :     JSCompartment *compartment = NewCompartment(cx, principals);
        3270           22524 :     if (!compartment)
        3271               0 :         return NULL;
        3272                 :
        3273           45048 :     AutoHoldCompartment hold(compartment);
        3274                 :
        3275           22524 :     JSCompartment *saved = cx->compartment;
        3276           22524 :     cx->setCompartment(compartment);
        3277           22524 :     JSObject *obj = JS_NewGlobalObject(cx, clasp);
        3278           22524 :     cx->setCompartment(saved);
        3279                 :
        3280           22524 :     return obj;
        3281                 : }
        3282                 :
        3283                 : JS_PUBLIC_API(JSObject *)
        3284         1722270 : JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
        3285                 : {
        3286         1722270 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        3287         1722270 :     AssertNoGC(cx);
        3288         3444540 :     CHECK_REQUEST(cx);
        3289         1722270 :     assertSameCompartment(cx, proto, parent);
        3290                 :
        3291         1722270 :     Class *clasp = Valueify(jsclasp);
        3292         1722270 :     if (!clasp)
        3293             547 :         clasp = &ObjectClass;    /* default class is Object */
        3294                 :
        3295         1722270 :     JS_ASSERT(clasp != &FunctionClass);
        3296         1722270 :     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
        3297                 :
        3298         1722270 :     if (proto && !proto->setNewTypeUnknown(cx))
        3299               0 :         return NULL;
        3300                 :
        3301         1722270 :     JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
        3302         1722270 :     if (obj) {
        3303         1722270 :         if (clasp->ext.equality)
        3304               0 :             MarkTypeObjectFlags(cx, obj, OBJECT_FLAG_SPECIAL_EQUALITY);
        3305         1722270 :         MarkTypeObjectUnknownProperties(cx, obj->type());
        3306                 :     }
        3307                 :
        3308         1722270 :     JS_ASSERT_IF(obj, obj->getParent());
        3309         1722270 :     return obj;
        3310                 : }
        3311                 :
        3312                 : JS_PUBLIC_API(JSObject *)
        3313              90 : JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
        3314                 : {
        3315              90 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        3316              90 :     AssertNoGC(cx);
        3317             180 :     CHECK_REQUEST(cx);
        3318              90 :     assertSameCompartment(cx, proto, parent);
        3319                 :
        3320              90 :     Class *clasp = Valueify(jsclasp);
        3321              90 :     if (!clasp)
        3322               0 :         clasp = &ObjectClass;    /* default class is Object */
        3323                 :
        3324              90 :     JS_ASSERT(clasp != &FunctionClass);
        3325              90 :     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
        3326                 :
        3327              90 :     JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
        3328              90 :     if (obj)
        3329              90 :         MarkTypeObjectUnknownProperties(cx, obj->type());
        3330              90 :     return obj;
        3331                 : }
        3332                 :
        3333                 : JS_PUBLIC_API(JSObject *)
        3334              19 : JS_NewObjectForConstructor(JSContext *cx, JSClass *clasp, const jsval *vp)
        3335                 : {
        3336              19 :     AssertNoGC(cx);
        3337              38 :     CHECK_REQUEST(cx);
        3338              19 :     assertSameCompartment(cx, *vp);
        3339                 :
        3340              19 :     return js_CreateThis(cx, Valueify(clasp), JSVAL_TO_OBJECT(*vp));
        3341                 : }
        3342                 :
        3343                 : JS_PUBLIC_API(JSBool)
        3344               0 : JS_IsExtensible(JSObject *obj)
        3345                 : {
        3346               0 :     return obj->isExtensible();
        3347                 : }
        3348                 :
        3349                 : JS_PUBLIC_API(JSBool)
        3350               0 : JS_IsNative(JSObject *obj)
        3351                 : {
        3352               0 :     return obj->isNative();
        3353                 : }
        3354                 :
        3355                 : JS_PUBLIC_API(JSRuntime *)
        3356               0 : JS_GetObjectRuntime(JSObject *obj)
        3357                 : {
        3358               0 :     return obj->compartment()->rt;
        3359                 : }
        3360                 :
        3361                 : JS_PUBLIC_API(JSBool)
        3362         1213065 : JS_FreezeObject(JSContext *cx, JSObject *obj)
        3363                 : {
        3364         1213065 :     AssertNoGC(cx);
        3365         2426130 :     CHECK_REQUEST(cx);
        3366         1213065 :     assertSameCompartment(cx, obj);
        3367                 :
        3368         1213065 :     return obj->freeze(cx);
        3369                 : }
        3370                 :
        3371                 : JS_PUBLIC_API(JSBool)
        3372           10007 : JS_DeepFreezeObject(JSContext *cx, JSObject *obj)
        3373                 : {
        3374           10007 :     AssertNoGC(cx);
        3375           20014 :     CHECK_REQUEST(cx);
        3376           10007 :     assertSameCompartment(cx, obj);
        3377                 :
        3378                 :     /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
        3379           10007 :     if (!obj->isExtensible())
        3380            5003 :         return true;
        3381                 :
        3382            5004 :     if (!obj->freeze(cx))
        3383               0 :         return false;
        3384                 :
        3385                 :     /* Walk slots in obj and if any value is a non-null object, seal it. */
        3386           15008 :     for (uint32_t i = 0, n = obj->slotSpan(); i < n; ++i) {
        3387           10004 :         const Value &v = obj->getSlot(i);
        3388           10004 :         if (v.isPrimitive())
        3389               0 :             continue;
        3390           10004 :         if (!JS_DeepFreezeObject(cx, &v.toObject()))
        3391               0 :             return false;
        3392                 :     }
        3393                 :
        3394            5004 :     return true;
        3395                 : }
        3396                 :
        3397                 : JS_PUBLIC_API(JSObject *)
        3398               0 : JS_ConstructObject(JSContext *cx, JSClass *jsclasp, JSObject *parent)
        3399                 : {
        3400               0 :     return JS_ConstructObjectWithArguments(cx, jsclasp, parent, 0, NULL);
        3401                 : }
        3402                 :
        3403                 : JS_PUBLIC_API(JSObject *)
        3404           12520 : JS_ConstructObjectWithArguments(JSContext *cx, JSClass *jsclasp, JSObject *parent,
        3405                 :                                 unsigned argc, jsval *argv)
        3406                 : {
        3407           12520 :     AssertNoGC(cx);
        3408           25040 :     CHECK_REQUEST(cx);
        3409           12520 :     assertSameCompartment(cx, parent, JSValueArray(argv, argc));
        3410                 :
        3411           25040 :     AutoArrayRooter argtvr(cx, argc, argv);
        3412                 :
        3413           12520 :     Class *clasp = Valueify(jsclasp);
        3414           12520 :     if (!clasp)
        3415               0 :         clasp = &ObjectClass;    /* default class is Object */
        3416                 :
        3417           12520 :     JSProtoKey protoKey = GetClassProtoKey(clasp);
        3418                 :
        3419                 :     /* Protect constructor in case a crazy getter for .prototype uproots it. */
        3420           25040 :     AutoValueRooter tvr(cx);
        3421           12520 :     if (!js_FindClassObject(cx, parent, protoKey, tvr.addr(), clasp))
        3422               0 :         return NULL;
        3423                 :
        3424                 :     Value rval;
        3425           12520 :     if (!InvokeConstructor(cx, tvr.value(), argc, argv, &rval))
        3426               0 :         return NULL;
        3427                 :
        3428                 :     /*
        3429                 :      * If the instance's class differs from what was requested, throw a type
        3430                 :      * error.
        3431                 :      */
        3432           12520 :     if (!rval.isObject() || rval.toObject().getClass() != clasp) {
        3433                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
        3434               0 :                              JSMSG_WRONG_CONSTRUCTOR, clasp->name);
        3435               0 :         return NULL;
        3436                 :     }
        3437           12520 :     return &rval.toObject();
        3438                 : }
        3439                 :
        3440                 : static JSBool
        3441           23870 : LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
        3442                 :                    JSObject **objp, JSProperty **propp)
        3443                 : {
        3444           23870 :     AssertNoGC(cx);
        3445           47740 :     CHECK_REQUEST(cx);
        3446           23870 :     assertSameCompartment(cx, obj, id);
        3447                 :
        3448           47740 :     JSAutoResolveFlags rf(cx, flags);
        3449           23870 :     id = js_CheckForStringIndex(id);
        3450           23870 :     return obj->lookupGeneric(cx, id, objp, propp);
        3451                 : }
        3452                 :
        3453                 : #define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
        3454                 :
        3455                 : static JSBool
        3456               1 : LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id,
        3457                 :              JSProperty *prop, Value *vp)
        3458                 : {
        3459               1 :     if (!prop) {
        3460                 :         /* XXX bad API: no way to tell "not defined" from "void value" */
        3461               0 :         vp->setUndefined();
        3462               0 :         return JS_TRUE;
        3463                 :     }
        3464                 :
        3465               1 :     if (obj2->isNative()) {
        3466               1 :         Shape *shape = (Shape *) prop;
        3467                 :
        3468                 :         /* Peek at the native property's slot value, without doing a Get. */
        3469               1 :         if (shape->hasSlot()) {
        3470               1 :             *vp = obj2->nativeGetSlot(shape->slot());
        3471               1 :             return true;
        3472                 :         }
        3473                 :     } else {
        3474               0 :         if (obj2->isDenseArray())
        3475               0 :             return js_GetDenseArrayElementValue(cx, obj2, id, vp);
        3476               0 :         if (obj2->isProxy()) {
        3477               0 :             AutoPropertyDescriptorRooter desc(cx);
        3478               0 :             if (!Proxy::getPropertyDescriptor(cx, obj2, id, false, &desc))
        3479               0 :                 return false;
        3480               0 :             if (!(desc.attrs & JSPROP_SHARED)) {
        3481               0 :                 *vp = desc.value;
        3482               0 :                 return true;
        3483                 :             }
        3484                 :         }
        3485                 :     }
        3486                 :
        3487                 :     /* XXX bad API: no way to return "defined but value unknown" */
        3488               0 :     vp->setBoolean(true);
        3489               0 :     return true;
        3490                 : }
        3491                 :
        3492                 : JS_PUBLIC_API(JSBool)
        3493               1 : JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
        3494                 : {
        3495                 :     JSObject *obj2;
        3496                 :     JSProperty *prop;
        3497               1 :     return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) &&
        3498               1 :            LookupResult(cx, obj, obj2, id, prop, vp);
        3499                 : }
        3500                 :
        3501                 : JS_PUBLIC_API(JSBool)
        3502               0 : JS_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
        3503                 : {
        3504               0 :     CHECK_REQUEST(cx);
        3505                 :     jsid id;
        3506               0 :     if (!IndexToId(cx, index, &id))
        3507               0 :         return false;
        3508               0 :     return JS_LookupPropertyById(cx, obj, id, vp);
        3509                 : }
        3510                 :
        3511                 : JS_PUBLIC_API(JSBool)
        3512               1 : JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
        3513                 : {
        3514               1 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        3515               1 :     return atom && JS_LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
        3516                 : }
        3517                 :
        3518                 : JS_PUBLIC_API(JSBool)
        3519               0 : JS_LookupUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
        3520                 : {
        3521               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        3522               0 :     return atom && JS_LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
        3523                 : }
        3524                 :
        3525                 : JS_PUBLIC_API(JSBool)
        3526               0 : JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
        3527                 :                                JSObject **objp, jsval *vp)
        3528                 : {
        3529                 :     JSBool ok;
        3530                 :     JSProperty *prop;
        3531                 :
        3532               0 :     AssertNoGC(cx);
        3533               0 :     CHECK_REQUEST(cx);
        3534               0 :     assertSameCompartment(cx, obj, id);
        3535               0 :     ok = obj->isNative()
        3536               0 :          ? LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop)
        3537               0 :          : obj->lookupGeneric(cx, id, objp, &prop);
        3538               0 :     return ok && LookupResult(cx, obj, *objp, id, prop, vp);
        3539                 : }
        3540                 :
        3541                 : JS_PUBLIC_API(JSBool)
        3542               0 : JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, unsigned flags, jsval *vp)
        3543                 : {
        3544                 :     JSObject *obj2;
        3545               0 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        3546               0 :     return atom && JS_LookupPropertyWithFlagsById(cx, obj, ATOM_TO_JSID(atom), flags, &obj2, vp);
        3547                 : }
        3548                 :
        3549                 : JS_PUBLIC_API(JSBool)
        3550           23832 : JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
        3551                 : {
        3552                 :     JSObject *obj2;
        3553                 :     JSProperty *prop;
        3554                 :     JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
        3555           23832 :                                    &obj2, &prop);
        3556           23832 :     *foundp = (prop != NULL);
        3557           23832 :     return ok;
        3558                 : }
        3559                 :
        3560                 : JS_PUBLIC_API(JSBool)
        3561               0 : JS_HasElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *foundp)
        3562                 : {
        3563               0 :     AssertNoGC(cx);
        3564               0 :     CHECK_REQUEST(cx);
        3565                 :     jsid id;
        3566               0 :     if (!IndexToId(cx, index, &id))
        3567               0 :         return false;
        3568               0 :     return JS_HasPropertyById(cx, obj, id, foundp);
        3569                 : }
        3570                 :
        3571                 : JS_PUBLIC_API(JSBool)
        3572              81 : JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
        3573                 : {
        3574              81 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        3575              81 :     return atom && JS_HasPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
        3576                 : }
        3577                 :
        3578                 : JS_PUBLIC_API(JSBool)
        3579               0 : JS_HasUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, JSBool *foundp)
        3580                 : {
        3581               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        3582               0 :     return atom && JS_HasPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
        3583                 : }
        3584                 :
        3585                 : JS_PUBLIC_API(JSBool)
        3586               0 : JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
        3587                 : {
        3588               0 :     AssertNoGC(cx);
        3589               0 :     CHECK_REQUEST(cx);
        3590               0 :     assertSameCompartment(cx, obj, id);
        3591                 :
        3592               0 :     if (!obj->isNative()) {
        3593                 :         JSObject *obj2;
        3594                 :         JSProperty *prop;
        3595                 :
        3596               0 :         if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
        3597               0 :                                 &obj2, &prop)) {
        3598               0 :             return JS_FALSE;
        3599                 :         }
        3600               0 :         *foundp = (obj == obj2);
        3601               0 :         return JS_TRUE;
        3602                 :     }
        3603                 :
        3604               0 :     *foundp = obj->nativeContains(cx, id);
        3605               0 :     return JS_TRUE;
        3606                 : }
        3607                 :
        3608                 : JS_PUBLIC_API(JSBool)
        3609               0 : JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *foundp)
        3610                 : {
        3611               0 :     AssertNoGC(cx);
        3612               0 :     CHECK_REQUEST(cx);
        3613                 :     jsid id;
        3614               0 :     if (!IndexToId(cx, index, &id))
        3615               0 :         return false;
        3616               0 :     return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
        3617                 : }
        3618                 :
        3619                 : JS_PUBLIC_API(JSBool)
        3620               0 : JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
        3621                 : {
        3622               0 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        3623               0 :     return atom && JS_AlreadyHasOwnPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
        3624                 : }
        3625                 :
        3626                 : JS_PUBLIC_API(JSBool)
        3627               0 : JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
        3628                 :                            JSBool *foundp)
        3629                 : {
        3630               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        3631               0 :     return atom && JS_AlreadyHasOwnPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
        3632                 : }
        3633                 :
        3634                 : static JSBool
        3635        17105027 : DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, const Value &value,
        3636                 :                    PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
        3637                 :                    unsigned flags, int tinyid)
        3638                 : {
        3639                 :     /*
        3640                 :      * JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
        3641                 :      * throw if this happens, but we've accepted it for long enough that it's
        3642                 :      * not worth trying to make callers change their ways. Just flip it off on
        3643                 :      * its way through the API layer so that we can enforce this internally.
        3644                 :      */
        3645        17105027 :     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
        3646              20 :         attrs &= ~JSPROP_READONLY;
        3647                 :
        3648                 :     /*
        3649                 :      * When we use DefineProperty, we need full scriptable Function objects rather
        3650                 :      * than JSNatives. However, we might be pulling this property descriptor off
        3651                 :      * of something with JSNative property descriptors. If we are, wrap them in
        3652                 :      * JS Function objects.
        3653                 :      */
        3654        17105027 :     if (attrs & JSPROP_NATIVE_ACCESSORS) {
        3655         1493120 :         RootId idRoot(cx, &id);
        3656                 :
        3657          746560 :         JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
        3658          746560 :         attrs &= ~JSPROP_NATIVE_ACCESSORS;
        3659          746560 :         if (getter) {
        3660          746560 :             JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, &obj->global(), NULL);
        3661          746560 :             if (!getobj)
        3662               0 :                 return false;
        3663          746560 :             getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj);
        3664          746560 :             attrs |= JSPROP_GETTER;
        3665                 :         }
        3666          746560 :         if (setter) {
        3667          186640 :             JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, &obj->global(), NULL);
        3668          186640 :             if (!setobj)
        3669               0 :                 return false;
        3670          186640 :             setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj);
        3671          186640 :             attrs |= JSPROP_SETTER;
        3672                 :         }
        3673                 :     }
        3674                 :
        3675                 :
        3676        17105027 :     AssertNoGC(cx);
        3677        34210054 :     CHECK_REQUEST(cx);
        3678                 :     assertSameCompartment(cx, obj, id, value,
        3679                 :                             (attrs & JSPROP_GETTER)
        3680                 :                             ? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
        3681                 :                             : NULL,
        3682                 :                             (attrs & JSPROP_SETTER)
        3683                 :                             ? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
        3684        17105027 :                             : NULL);
        3685                 :
        3686        34210054 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
        3687        17105027 :     if (flags != 0 && obj->isNative()) {
        3688                 :         return !!DefineNativeProperty(cx, obj, id, value, getter, setter,
        3689        11158621 :                                       attrs, flags, tinyid);
        3690                 :     }
        3691         5946406 :     return obj->defineGeneric(cx, id, value, getter, setter, attrs);
        3692                 : }
        3693                 :
        3694                 : JS_PUBLIC_API(JSBool)
        3695              38 : JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
        3696                 :                       JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
        3697                 : {
        3698              38 :     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
        3699                 : }
        3700                 :
        3701                 : JS_PUBLIC_API(JSBool)
        3702             100 : JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value,
        3703                 :                  JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
        3704                 : {
        3705             100 :     AssertNoGC(cx);
        3706             200 :     CHECK_REQUEST(cx);
        3707                 :     jsid id;
        3708             100 :     if (!IndexToId(cx, index, &id))
        3709               0 :         return false;
        3710             100 :     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
        3711                 : }
        3712                 :
        3713                 : static JSBool
        3714        17104889 : DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &value,
        3715                 :                PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
        3716                 :                unsigned flags, int tinyid)
        3717                 : {
        3718                 :     jsid id;
        3719                 :     JSAtom *atom;
        3720                 :
        3721        34209778 :     RootObject objRoot(cx, &obj);
        3722        34209778 :     RootValue valueRoot(cx, &value);
        3723                 :
        3724        17104889 :     if (attrs & JSPROP_INDEX) {
        3725               0 :         id = INT_TO_JSID(intptr_t(name));
        3726               0 :         atom = NULL;
        3727               0 :         attrs &= ~JSPROP_INDEX;
        3728                 :     } else {
        3729        17104889 :         atom = js_Atomize(cx, name, strlen(name));
        3730        17104889 :         if (!atom)
        3731               0 :             return JS_FALSE;
        3732        17104889 :         id = ATOM_TO_JSID(atom);
        3733                 :     }
        3734                 :
        3735        17104889 :     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
        3736                 : }
        3737                 :
        3738                 : JS_PUBLIC_API(JSBool)
        3739         5810047 : JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
        3740                 :                   PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
        3741                 : {
        3742         5810047 :     return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
        3743                 : }
        3744                 :
        3745                 : JS_PUBLIC_API(JSBool)
        3746               0 : JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, int8_t tinyid,
        3747                 :                             jsval value, PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
        3748                 : {
        3749               0 :     return DefineProperty(cx, obj, name, value, getter, setter, attrs, Shape::HAS_SHORTID, tinyid);
        3750                 : }
        3751                 :
        3752                 : static JSBool
        3753               0 : DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
        3754                 :                  const Value &value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
        3755                 :                  unsigned flags, int tinyid)
        3756                 : {
        3757               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        3758                 :     return atom && DefinePropertyById(cx, obj, ATOM_TO_JSID(atom), value, getter, setter, attrs,
        3759               0 :                                       flags, tinyid);
        3760                 : }
        3761                 :
        3762                 : JS_PUBLIC_API(JSBool)
        3763               0 : JS_DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
        3764                 :                     jsval value, JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
        3765                 : {
        3766               0 :     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0, 0);
        3767                 : }
        3768                 :
        3769                 : JS_PUBLIC_API(JSBool)
        3770               0 : JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
        3771                 :                               int8_t tinyid, jsval value,
        3772                 :                               JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
        3773                 : {
        3774                 :     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs,
        3775               0 :                             Shape::HAS_SHORTID, tinyid);
        3776                 : }
        3777                 :
        3778                 : JS_PUBLIC_API(JSBool)
        3779               0 : JS_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, JSBool *bp)
        3780                 : {
        3781               0 :     AssertNoGC(cx);
        3782               0 :     CHECK_REQUEST(cx);
        3783               0 :     assertSameCompartment(cx, obj, id, descriptor);
        3784               0 :     return js_DefineOwnProperty(cx, obj, id, descriptor, bp);
        3785                 : }
        3786                 :
        3787                 : JS_PUBLIC_API(JSObject *)
        3788          111981 : JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp,
        3789                 :                 JSObject *proto, unsigned attrs)
        3790                 : {
        3791          111981 :     AssertNoGC(cx);
        3792          223962 :     CHECK_REQUEST(cx);
        3793          111981 :     assertSameCompartment(cx, obj, proto);
        3794                 :
        3795          111981 :     Class *clasp = Valueify(jsclasp);
        3796          111981 :     if (!clasp)
        3797               0 :         clasp = &ObjectClass;    /* default class is Object */
        3798                 :
        3799          223962 :     RootObject root(cx, &obj);
        3800          223962 :     RootedVarObject nobj(cx);
        3801                 :
        3802          111981 :     nobj = NewObjectWithClassProto(cx, clasp, proto, obj);
        3803          111981 :     if (!nobj)
        3804               0 :         return NULL;
        3805                 :
        3806          111981 :     if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), NULL, NULL, attrs, 0, 0))
        3807               0 :         return NULL;
        3808                 :
        3809          111981 :     return nobj;
        3810                 : }
        3811                 :
        3812                 : JS_PUBLIC_API(JSBool)
        3813            3786 : JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
        3814                 : {
        3815                 :     JSBool ok;
        3816                 :     unsigned attrs;
        3817                 :
        3818            3786 :     AssertNoGC(cx);
        3819            7572 :     CHECK_REQUEST(cx);
        3820           28026 :     for (ok = JS_TRUE; cds->name; cds++) {
        3821           24240 :         Value value = DoubleValue(cds->dval);
        3822           24240 :         attrs = cds->flags;
        3823           24240 :         if (!attrs)
        3824           24240 :             attrs = JSPROP_READONLY | JSPROP_PERMANENT;
        3825           24240 :         ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, attrs, 0, 0);
        3826           24240 :         if (!ok)
        3827               0 :             break;
        3828                 :     }
        3829            3786 :     return ok;
        3830                 : }
        3831                 :
        3832                 : JS_PUBLIC_API(JSBool)
        3833         5146143 : JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
        3834                 : {
        3835                 :     JSBool ok;
        3836        10292286 :     RootObject root(cx, &obj);
        3837                 :
        3838        16304764 :     for (ok = true; ps->name; ps++) {
        3839                 :         ok = DefineProperty(cx, obj, ps->name, UndefinedValue(), ps->getter, ps->setter,
        3840        11158621 :                             ps->flags, Shape::HAS_SHORTID, ps->tinyid);
        3841        11158621 :         if (!ok)
        3842               0 :             break;
        3843                 :     }
        3844         5146143 :     return ok;
        3845                 : }
        3846                 :
        3847                 : static JSBool
        3848              37 : GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
        3849                 :                           JSBool own, PropertyDescriptor *desc)
        3850                 : {
        3851                 :     JSObject *obj2;
        3852                 :     JSProperty *prop;
        3853                 :
        3854              37 :     if (!LookupPropertyById(cx, obj, id, flags, &obj2, &prop))
        3855               0 :         return JS_FALSE;
        3856                 :
        3857              37 :     if (!prop || (own && obj != obj2)) {
        3858               0 :         desc->obj = NULL;
        3859               0 :         desc->attrs = 0;
        3860               0 :         desc->getter = NULL;
        3861               0 :         desc->setter = NULL;
        3862               0 :         desc->value.setUndefined();
        3863               0 :         return JS_TRUE;
        3864                 :     }
        3865                 :
        3866              37 :     desc->obj = obj2;
        3867              37 :     if (obj2->isNative()) {
        3868              37 :         Shape *shape = (Shape *) prop;
        3869              37 :         desc->attrs = shape->attributes();
        3870              37 :         desc->getter = shape->getter();
        3871              37 :         desc->setter = shape->setter();
        3872              37 :         if (shape->hasSlot())
        3873              28 :             desc->value = obj2->nativeGetSlot(shape->slot());
        3874                 :         else
        3875               9 :             desc->value.setUndefined();
        3876                 :     } else {
        3877               0 :         if (obj2->isProxy()) {
        3878               0 :             JSAutoResolveFlags rf(cx, flags);
        3879                 :             return own
        3880               0 :                    ? Proxy::getOwnPropertyDescriptor(cx, obj2, id, false, desc)
        3881               0 :                    : Proxy::getPropertyDescriptor(cx, obj2, id, false, desc);
        3882                 :         }
        3883               0 :         if (!obj2->getGenericAttributes(cx, id, &desc->attrs))
        3884               0 :             return false;
        3885               0 :         desc->getter = NULL;
        3886               0 :         desc->setter = NULL;
        3887               0 :         desc->value.setUndefined();
        3888                 :     }
        3889              37 :     return true;
        3890                 : }
        3891                 :
        3892                 : JS_PUBLIC_API(JSBool)
        3893              36 : JS_GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
        3894                 :                              JSPropertyDescriptor *desc)
        3895                 : {
        3896              36 :     return GetPropertyDescriptorById(cx, obj, id, flags, JS_FALSE, desc);
        3897                 : }
        3898                 :
        3899                 : JS_PUBLIC_API(JSBool)
        3900               1 : JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj, jsid id,
        3901                 :                                        unsigned *attrsp, JSBool *foundp,
        3902                 :                                        JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
        3903                 : {
        3904                 :     PropertyDescriptor desc;
        3905               1 :     if (!GetPropertyDescriptorById(cx, obj, id, JSRESOLVE_QUALIFIED, JS_FALSE, &desc))
        3906               0 :         return false;
        3907                 :
        3908               1 :     *attrsp = desc.attrs;
        3909               1 :     *foundp = (desc.obj != NULL);
        3910               1 :     if (getterp)
        3911               0 :         *getterp = desc.getter;
        3912               1 :     if (setterp)
        3913               0 :         *setterp = desc.setter;
        3914               1 :     return true;
        3915                 : }
        3916                 :
        3917                 : JS_PUBLIC_API(JSBool)
        3918               1 : JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
        3919                 :                          unsigned *attrsp, JSBool *foundp)
        3920                 : {
        3921               1 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        3922                 :     return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
        3923               1 :                                                           attrsp, foundp, NULL, NULL);
        3924                 : }
        3925                 :
        3926                 : JS_PUBLIC_API(JSBool)
        3927               0 : JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
        3928                 :                            unsigned *attrsp, JSBool *foundp)
        3929                 : {
        3930               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        3931                 :     return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
        3932               0 :                                                           attrsp, foundp, NULL, NULL);
        3933                 : }
        3934                 :
        3935                 : JS_PUBLIC_API(JSBool)
        3936               0 : JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj, const char *name,
        3937                 :                                    unsigned *attrsp, JSBool *foundp,
        3938                 :                                    JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
        3939                 : {
        3940               0 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        3941                 :     return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
        3942               0 :                                                           attrsp, foundp, getterp, setterp);
        3943                 : }
        3944                 :
        3945                 : JS_PUBLIC_API(JSBool)
        3946               0 : JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
        3947                 :                                      const jschar *name, size_t namelen,
        3948                 :                                      unsigned *attrsp, JSBool *foundp,
        3949                 :                                      JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
        3950                 : {
        3951               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        3952                 :     return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
        3953               0 :                                                           attrsp, foundp, getterp, setterp);
        3954                 : }
        3955                 :
        3956                 : JS_PUBLIC_API(JSBool)
        3957               0 : JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
        3958                 : {
        3959               0 :     AssertNoGC(cx);
        3960               0 :     CHECK_REQUEST(cx);
        3961               0 :     return GetOwnPropertyDescriptor(cx, obj, id, vp);
        3962                 : }
        3963                 :
        3964                 : static JSBool
        3965               0 : SetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, unsigned attrs, JSBool *foundp)
        3966                 : {
        3967                 :     JSObject *obj2;
        3968                 :     JSProperty *prop;
        3969                 :
        3970               0 :     if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
        3971               0 :         return false;
        3972               0 :     if (!prop || obj != obj2) {
        3973               0 :         *foundp = false;
        3974               0 :         return true;
        3975                 :     }
        3976               0 :     Shape *shape = (Shape *) prop;
        3977               0 :     JSBool ok = obj->isNative()
        3978               0 :                 ? obj->changePropertyAttributes(cx, shape, attrs)
        3979               0 :                 : obj->setGenericAttributes(cx, id, &attrs);
        3980               0 :     if (ok)
        3981               0 :         *foundp = true;
        3982               0 :     return ok;
        3983                 : }
        3984                 :
        3985                 : JS_PUBLIC_API(JSBool)
        3986               0 : JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
        3987                 :                          unsigned attrs, JSBool *foundp)
        3988                 : {
        3989               0 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        3990               0 :     return atom && SetPropertyAttributesById(cx, obj, ATOM_TO_JSID(atom), attrs, foundp);
        3991                 : }
        3992                 :
        3993                 : JS_PUBLIC_API(JSBool)
        3994               0 : JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
        3995                 :                            unsigned attrs, JSBool *foundp)
        3996                 : {
        3997               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        3998               0 :     return atom && SetPropertyAttributesById(cx, obj, ATOM_TO_JSID(atom), attrs, foundp);
        3999                 : }
        4000                 :
        4001                 : JS_PUBLIC_API(JSBool)
        4002           17632 : JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
        4003                 : {
        4004           17632 :     return JS_ForwardGetPropertyTo(cx, obj, id, obj, vp);
        4005                 : }
        4006                 :
        4007                 : JS_PUBLIC_API(JSBool)
        4008           17632 : JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id, JSObject *onBehalfOf, jsval *vp)
        4009                 : {
        4010           17632 :     AssertNoGC(cx);
        4011           35264 :     CHECK_REQUEST(cx);
        4012           17632 :     assertSameCompartment(cx, obj, id);
        4013           17632 :     assertSameCompartment(cx, onBehalfOf);
        4014           35264 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
        4015           17632 :     return obj->getGeneric(cx, onBehalfOf, id, vp);
        4016                 : }
        4017                 :
        4018                 : JS_PUBLIC_API(JSBool)
        4019               4 : JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj, jsid id, jsval def, jsval *vp)
        4020                 : {
        4021               4 :     return GetPropertyDefault(cx, obj, id, def, vp);
        4022                 : }
        4023                 :
        4024                 : JS_PUBLIC_API(JSBool)
        4025               2 : JS_GetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
        4026                 : {
        4027               2 :     return JS_ForwardGetElementTo(cx, obj, index, obj, vp);
        4028                 : }
        4029                 :
        4030                 : JS_PUBLIC_API(JSBool)
        4031               2 : JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf, jsval *vp)
        4032                 : {
        4033               2 :     AssertNoGC(cx);
        4034               4 :     CHECK_REQUEST(cx);
        4035               2 :     assertSameCompartment(cx, obj);
        4036               4 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
        4037               2 :     return obj->getElement(cx, onBehalfOf, index, vp);
        4038                 : }
        4039                 :
        4040                 : JS_PUBLIC_API(JSBool)
        4041               0 : JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf, jsval *vp, JSBool* present)
        4042                 : {
        4043               0 :     AssertNoGC(cx);
        4044               0 :     CHECK_REQUEST(cx);
        4045               0 :     assertSameCompartment(cx, obj);
        4046               0 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
        4047                 :     bool isPresent;
        4048               0 :     if (!obj->getElementIfPresent(cx, onBehalfOf, index, vp, &isPresent))
        4049               0 :         return false;
        4050               0 :     *present = isPresent;
        4051               0 :     return true;
        4052                 : }
        4053                 :
        4054                 : JS_PUBLIC_API(JSBool)
        4055           17632 : JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
        4056                 : {
        4057           17632 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        4058           17632 :     return atom && JS_GetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
        4059                 : }
        4060                 :
        4061                 : JS_PUBLIC_API(JSBool)
        4062               2 : JS_GetPropertyDefault(JSContext *cx, JSObject *obj, const char *name, jsval def, jsval *vp)
        4063                 : {
        4064               2 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        4065               2 :     return atom && JS_GetPropertyByIdDefault(cx, obj, ATOM_TO_JSID(atom), def, vp);
        4066                 : }
        4067                 :
        4068                 : JS_PUBLIC_API(JSBool)
        4069               0 : JS_GetUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
        4070                 : {
        4071               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        4072               0 :     return atom && JS_GetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
        4073                 : }
        4074                 :
        4075                 : JS_PUBLIC_API(JSBool)
        4076               0 : JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, jsval *vp)
        4077                 : {
        4078               0 :     AssertNoGC(cx);
        4079               0 :     CHECK_REQUEST(cx);
        4080               0 :     assertSameCompartment(cx, obj, id);
        4081               0 :     if (!js_GetMethod(cx, obj, id, 0, vp))
        4082               0 :         return JS_FALSE;
        4083               0 :     if (objp)
        4084               0 :         *objp = obj;
        4085               0 :     return JS_TRUE;
        4086                 : }
        4087                 :
        4088                 : JS_PUBLIC_API(JSBool)
        4089               0 : JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, jsval *vp)
        4090                 : {
        4091               0 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        4092               0 :     return atom && JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), objp, vp);
        4093                 : }
        4094                 :
        4095                 : JS_PUBLIC_API(JSBool)
        4096            6277 : JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
        4097                 : {
        4098            6277 :     AssertNoGC(cx);
        4099           12554 :     CHECK_REQUEST(cx);
        4100            6277 :     assertSameCompartment(cx, obj, id);
        4101           12554 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
        4102            6277 :     return obj->setGeneric(cx, id, vp, false);
        4103                 : }
        4104                 :
        4105                 : JS_PUBLIC_API(JSBool)
        4106            3636 : JS_SetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
        4107                 : {
        4108            3636 :     AssertNoGC(cx);
        4109            7272 :     CHECK_REQUEST(cx);
        4110            3636 :     assertSameCompartment(cx, obj, *vp);
        4111            7272 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
        4112            3636 :     return obj->setElement(cx, index, vp, false);
        4113                 : }
        4114                 :
        4115                 : JS_PUBLIC_API(JSBool)
        4116            6276 : JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
        4117                 : {
        4118            6276 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        4119            6276 :     return atom && JS_SetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
        4120                 : }
        4121                 :
        4122                 : JS_PUBLIC_API(JSBool)
        4123               0 : JS_SetUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
        4124                 : {
        4125               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        4126               0 :     return atom && JS_SetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
        4127                 : }
        4128                 :
        4129                 : JS_PUBLIC_API(JSBool)
        4130               9 : JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
        4131                 : {
        4132               9 :     AssertNoGC(cx);
        4133              18 :     CHECK_REQUEST(cx);
        4134               9 :     assertSameCompartment(cx, obj, id);
        4135              18 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
        4136                 :
        4137               9 :     if (JSID_IS_SPECIAL(id))
        4138               0 :         return obj->deleteSpecial(cx, JSID_TO_SPECIALID(id), rval, false);
        4139                 :
        4140               9 :     return obj->deleteByValue(cx, IdToValue(id), rval, false);
        4141                 : }
        4142                 :
        4143                 : JS_PUBLIC_API(JSBool)
        4144               0 : JS_DeleteElement2(JSContext *cx, JSObject *obj, uint32_t index, jsval *rval)
        4145                 : {
        4146               0 :     AssertNoGC(cx);
        4147               0 :     CHECK_REQUEST(cx);
        4148               0 :     assertSameCompartment(cx, obj);
        4149               0 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
        4150               0 :     return obj->deleteElement(cx, index, rval, false);
        4151                 : }
        4152                 :
        4153                 : JS_PUBLIC_API(JSBool)
        4154               0 : JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, jsval *rval)
        4155                 : {
        4156               0 :     CHECK_REQUEST(cx);
        4157               0 :     assertSameCompartment(cx, obj);
        4158               0 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
        4159                 :
        4160               0 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        4161               0 :     if (!atom)
        4162               0 :         return false;
        4163                 :
        4164               0 :     return obj->deleteByValue(cx, StringValue(atom), rval, false);
        4165                 : }
        4166                 :
        4167                 : JS_PUBLIC_API(JSBool)
        4168               0 : JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *rval)
        4169                 : {
        4170               0 :     CHECK_REQUEST(cx);
        4171               0 :     assertSameCompartment(cx, obj);
        4172               0 :     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
        4173                 :
        4174               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        4175               0 :     if (!atom)
        4176               0 :         return false;
        4177                 :
        4178               0 :     return obj->deleteByValue(cx, StringValue(atom), rval, false);
        4179                 : }
        4180                 :
        4181                 : JS_PUBLIC_API(JSBool)
        4182               0 : JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id)
        4183                 : {
        4184                 :     jsval junk;
        4185               0 :     return JS_DeletePropertyById2(cx, obj, id, &junk);
        4186                 : }
        4187                 :
        4188                 : JS_PUBLIC_API(JSBool)
        4189               0 : JS_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index)
        4190                 : {
        4191                 :     jsval junk;
        4192               0 :     return JS_DeleteElement2(cx, obj, index, &junk);
        4193                 : }
        4194                 :
        4195                 : JS_PUBLIC_API(JSBool)
        4196               0 : JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
        4197                 : {
        4198                 :     jsval junk;
        4199               0 :     return JS_DeleteProperty2(cx, obj, name, &junk);
        4200                 : }
        4201                 :
        4202                 : JS_PUBLIC_API(void)
        4203               0 : JS_ClearScope(JSContext *cx, JSObject *obj)
        4204                 : {
        4205               0 :     AssertNoGC(cx);
        4206               0 :     CHECK_REQUEST(cx);
        4207               0 :     assertSameCompartment(cx, obj);
        4208                 :
        4209               0 :     ClearOp clearOp = obj->getOps()->clear;
        4210               0 :     if (clearOp)
        4211               0 :         clearOp(cx, obj);
        4212                 :
        4213               0 :     if (obj->isNative())
        4214               0 :         js_ClearNative(cx, obj);
        4215                 :
        4216                 :     /* Clear cached class objects on the global object. */
        4217               0 :     if (obj->isGlobal())
        4218               0 :         obj->asGlobal().clear(cx);
        4219                 :
        4220               0 :     js_InitRandom(cx);
        4221               0 : }
        4222                 :
        4223                 : JS_PUBLIC_API(JSIdArray *)
        4224           25246 : JS_Enumerate(JSContext *cx, JSObject *obj)
        4225                 : {
        4226           25246 :     AssertNoGC(cx);
        4227           50492 :     CHECK_REQUEST(cx);
        4228           25246 :     assertSameCompartment(cx, obj);
        4229                 :
        4230           50492 :     AutoIdVector props(cx);
        4231                 :     JSIdArray *ida;
        4232           25246 :     if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
        4233               0 :         return NULL;
        4234           52291 :     for (size_t n = 0; n < size_t(ida->length); ++n)
        4235           27045 :         JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
        4236           25246 :     return ida;
        4237                 : }
        4238                 :
        4239                 : /*
        4240                 :  * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
        4241                 :  *     prop_iterator_class somehow...
        4242                 :  * + preserve the obj->enumerate API while optimizing the native object case
        4243                 :  * + native case here uses a Shape *, but that iterates in reverse!
        4244                 :  * + so we make non-native match, by reverse-iterating after JS_Enumerating
        4245                 :  */
        4246                 : const uint32_t JSSLOT_ITER_INDEX = 0;
        4247                 :
        4248                 : static void
        4249               0 : prop_iter_finalize(FreeOp *fop, JSObject *obj)
        4250                 : {
        4251               0 :     void *pdata = obj->getPrivate();
        4252               0 :     if (!pdata)
        4253               0 :         return;
        4254                 :
        4255               0 :     if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
        4256                 :         /* Non-native case: destroy the ida enumerated when obj was created. */
        4257               0 :         JSIdArray *ida = (JSIdArray *) pdata;
        4258               0 :         DestroyIdArray(fop, ida);
        4259                 :     }
        4260                 : }
        4261                 :
        4262                 : static void
        4263               0 : prop_iter_trace(JSTracer *trc, JSObject *obj)
        4264                 : {
        4265               0 :     void *pdata = obj->getPrivate();
        4266               0 :     if (!pdata)
        4267               0 :         return;
        4268                 :
        4269               0 :     if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) {
        4270                 :         /*
        4271                 :          * Native case: just mark the next property to visit. We don't need a
        4272                 :          * barrier here because the pointer is updated via setPrivate, which
        4273                 :          * always takes a barrier.
        4274                 :          */
        4275               0 :         Shape *tmp = (Shape *)pdata;
        4276               0 :         MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
        4277               0 :         obj->setPrivateUnbarriered(tmp);
        4278                 :     } else {
        4279                 :         /* Non-native case: mark each id in the JSIdArray private. */
        4280               0 :         JSIdArray *ida = (JSIdArray *) pdata;
        4281               0 :         MarkIdRange(trc, ida->length, ida->vector, "prop iter");
        4282                 :     }
        4283                 : }
        4284                 :
        4285                 : static Class prop_iter_class = {
        4286                 :     "PropertyIterator",
        4287                 :     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1),
        4288                 :     JS_PropertyStub,         /* addProperty */
        4289                 :     JS_PropertyStub,         /* delProperty */
        4290                 :     JS_PropertyStub,         /* getProperty */
        4291                 :     JS_StrictPropertyStub,   /* setProperty */
        4292                 :     JS_EnumerateStub,
        4293                 :     JS_ResolveStub,
        4294                 :     JS_ConvertStub,
        4295                 :     prop_iter_finalize,
        4296                 :     NULL,           /* checkAccess */
        4297                 :     NULL,           /* call        */
        4298                 :     NULL,           /* construct   */
        4299                 :     NULL,           /* hasInstance */
        4300                 :     prop_iter_trace
        4301                 : };
        4302                 :
        4303                 : JS_PUBLIC_API(JSObject *)
        4304               0 : JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
        4305                 : {
        4306                 :     JSObject *iterobj;
        4307                 :     void *pdata;
        4308                 :     int index;
        4309                 :     JSIdArray *ida;
        4310                 :
        4311               0 :     AssertNoGC(cx);
        4312               0 :     CHECK_REQUEST(cx);
        4313               0 :     assertSameCompartment(cx, obj);
        4314               0 :     iterobj = NewObjectWithClassProto(cx, &prop_iter_class, NULL, obj);
        4315               0 :     if (!iterobj)
        4316               0 :         return NULL;
        4317                 :
        4318               0 :     if (obj->isNative()) {
        4319                 :         /* Native case: start with the last property in obj. */
        4320               0 :         pdata = (void *)obj->lastProperty();
        4321               0 :         index = -1;
        4322                 :     } else {
        4323                 :         /*
        4324                 :          * Non-native case: enumerate a JSIdArray and keep it via private.
        4325                 :          *
        4326                 :          * Note: we have to make sure that we root obj around the call to
        4327                 :          * JS_Enumerate to protect against multiple allocations under it.
        4328                 :          */
        4329               0 :         ida = JS_Enumerate(cx, obj);
        4330               0 :         if (!ida)
        4331               0 :             return NULL;
        4332               0 :         pdata = ida;
        4333               0 :         index = ida->length;
        4334                 :     }
        4335                 :
        4336                 :     /* iterobj cannot escape to other threads here. */
        4337               0 :     iterobj->setPrivate(pdata);
        4338               0 :     iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
        4339               0 :     return iterobj;
        4340                 : }
        4341                 :
        4342                 : JS_PUBLIC_API(JSBool)
        4343               0 : JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
        4344                 : {
        4345                 :     int32_t i;
        4346                 :     const Shape *shape;
        4347                 :     JSIdArray *ida;
        4348                 :
        4349               0 :     AssertNoGC(cx);
        4350               0 :     CHECK_REQUEST(cx);
        4351               0 :     assertSameCompartment(cx, iterobj);
        4352               0 :     i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
        4353               0 :     if (i < 0) {
        4354                 :         /* Native case: private data is a property tree node pointer. */
        4355               0 :         JS_ASSERT(iterobj->getParent()->isNative());
        4356               0 :         shape = (Shape *) iterobj->getPrivate();
        4357                 :
        4358               0 :         while (shape->previous() && !shape->enumerable())
        4359               0 :             shape = shape->previous();
        4360                 :
        4361               0 :         if (!shape->previous()) {
        4362               0 :             JS_ASSERT(shape->isEmptyShape());
        4363               0 :             *idp = JSID_VOID;
        4364                 :         } else {
        4365               0 :             iterobj->setPrivate(const_cast<Shape *>(shape->previous().get()));
        4366               0 :             *idp = shape->propid();
        4367                 :         }
        4368                 :     } else {
        4369                 :         /* Non-native case: use the ida enumerated when iterobj was created. */
        4370               0 :         ida = (JSIdArray *) iterobj->getPrivate();
        4371               0 :         JS_ASSERT(i <= ida->length);
        4372                 :         STATIC_ASSUME(i <= ida->length);
        4373               0 :         if (i == 0) {
        4374               0 :             *idp = JSID_VOID;
        4375                 :         } else {
        4376               0 :             *idp = ida->vector[--i];
        4377               0 :             iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(i));
        4378                 :         }
        4379                 :     }
        4380               0 :     return JS_TRUE;
        4381                 : }
        4382                 :
        4383                 : JS_PUBLIC_API(JSObject *)
        4384             927 : JS_NewElementIterator(JSContext *cx, JSObject *obj)
        4385                 : {
        4386             927 :     AssertNoGC(cx);
        4387            1854 :     CHECK_REQUEST(cx);
        4388             927 :     assertSameCompartment(cx, obj);
        4389             927 :     return ElementIteratorObject::create(cx, obj);
        4390                 : }
        4391                 :
        4392                 : JS_PUBLIC_API(JSObject *)
        4393             927 : JS_ElementIteratorStub(JSContext *cx, JSObject *obj, JSBool keysonly)
        4394                 : {
        4395             927 :     JS_ASSERT(!keysonly);
        4396             927 :     return JS_NewElementIterator(cx, obj);
        4397                 : }
        4398                 :
        4399                 : JS_PUBLIC_API(jsval)
        4400         3055968 : JS_GetReservedSlot(JSObject *obj, uint32_t index)
        4401                 : {
        4402         3055968 :     return obj->getReservedSlot(index);
        4403                 : }
        4404                 :
        4405                 : JS_PUBLIC_API(void)
        4406         5948640 : JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v)
        4407                 : {
        4408         5948640 :     obj->setReservedSlot(index, v);
        4409         5948640 : }
        4410                 :
        4411                 : JS_PUBLIC_API(JSObject *)
        4412           21421 : JS_NewArrayObject(JSContext *cx, int length, jsval *vector)
        4413                 : {
        4414           21421 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4415           21421 :     AssertNoGC(cx);
        4416           42842 :     CHECK_REQUEST(cx);
        4417                 :
        4418           21421 :     assertSameCompartment(cx, JSValueArray(vector, vector ? (uint32_t)length : 0));
        4419           21421 :     return NewDenseCopiedArray(cx, (uint32_t)length, vector);
        4420                 : }
        4421                 :
        4422                 : JS_PUBLIC_API(JSBool)
        4423              25 : JS_IsArrayObject(JSContext *cx, JSObject *obj)
        4424                 : {
        4425              25 :     assertSameCompartment(cx, obj);
        4426              25 :     return ObjectClassIs(*obj, ESClass_Array, cx);
        4427                 : }
        4428                 :
        4429                 : JS_PUBLIC_API(JSBool)
        4430               3 : JS_GetArrayLength(JSContext *cx, JSObject *obj, uint32_t *lengthp)
        4431                 : {
        4432               3 :     AssertNoGC(cx);
        4433               6 :     CHECK_REQUEST(cx);
        4434               3 :     assertSameCompartment(cx, obj);
        4435               3 :     return js_GetLengthProperty(cx, obj, lengthp);
        4436                 : }
        4437                 :
        4438                 : JS_PUBLIC_API(JSBool)
        4439               0 : JS_SetArrayLength(JSContext *cx, JSObject *obj, uint32_t length)
        4440                 : {
        4441               0 :     AssertNoGC(cx);
        4442               0 :     CHECK_REQUEST(cx);
        4443               0 :     assertSameCompartment(cx, obj);
        4444               0 :     return js_SetLengthProperty(cx, obj, length);
        4445                 : }
        4446                 :
        4447                 : JS_PUBLIC_API(JSBool)
        4448               0 : JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
        4449                 :                jsval *vp, unsigned *attrsp)
        4450                 : {
        4451               0 :     AssertNoGC(cx);
        4452               0 :     CHECK_REQUEST(cx);
        4453               0 :     assertSameCompartment(cx, obj, id);
        4454               0 :     return CheckAccess(cx, obj, id, mode, vp, attrsp);
        4455                 : }
        4456                 :
        4457                 : JS_PUBLIC_API(void)
        4458             448 : JS_HoldPrincipals(JSPrincipals *principals)
        4459                 : {
        4460             448 :     JS_ATOMIC_INCREMENT(&principals->refcount);
        4461             448 : }
        4462                 :
        4463                 : JS_PUBLIC_API(void)
        4464             448 : JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals)
        4465                 : {
        4466             448 :     int rc = JS_ATOMIC_DECREMENT(&principals->refcount);
        4467             448 :     if (rc == 0)
        4468               2 :         rt->destroyPrincipals(principals);
        4469             448 : }
        4470                 :
        4471                 : JS_PUBLIC_API(void)
        4472           18667 : JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *scb)
        4473                 : {
        4474           18667 :     JS_ASSERT(scb != &NullSecurityCallbacks);
        4475           18667 :     rt->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
        4476           18667 : }
        4477                 :
        4478                 : JS_PUBLIC_API(const JSSecurityCallbacks *)
        4479               0 : JS_GetSecurityCallbacks(JSRuntime *rt)
        4480                 : {
        4481               0 :     return (rt->securityCallbacks != &NullSecurityCallbacks) ? rt->securityCallbacks : NULL;
        4482                 : }
        4483                 :
        4484                 : JS_PUBLIC_API(void)
        4485           18667 : JS_SetTrustedPrincipals(JSRuntime *rt, JSPrincipals *prin)
        4486                 : {
        4487           18667 :     rt->setTrustedPrincipals(prin);
        4488           18667 : }
        4489                 :
        4490                 : extern JS_PUBLIC_API(void)
        4491               1 : JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals)
        4492                 : {
        4493               1 :     JS_ASSERT(destroyPrincipals);
        4494               1 :     JS_ASSERT(!rt->destroyPrincipals);
        4495               1 :     rt->destroyPrincipals = destroyPrincipals;
        4496               1 : }
        4497                 :
        4498                 : JS_PUBLIC_API(JSFunction *)
        4499          933204 : JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
        4500                 :                JSObject *parent, const char *name)
        4501                 : {
        4502          933204 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4503                 :     JSAtom *atom;
        4504                 :
        4505          933204 :     AssertNoGC(cx);
        4506         1866408 :     CHECK_REQUEST(cx);
        4507          933204 :     assertSameCompartment(cx, parent);
        4508                 :
        4509          933204 :     if (!name) {
        4510          933200 :         atom = NULL;
        4511                 :     } else {
        4512               4 :         atom = js_Atomize(cx, name, strlen(name));
        4513               4 :         if (!atom)
        4514               0 :             return NULL;
        4515                 :     }
        4516                 :
        4517         1866408 :     RootObject parentRoot(cx, &parent);
        4518          933204 :     return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, atom);
        4519                 : }
        4520                 :
        4521                 : JS_PUBLIC_API(JSFunction *)
        4522               0 : JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parent,
        4523                 :                    jsid id)
        4524                 : {
        4525               0 :     JS_ASSERT(JSID_IS_STRING(id));
        4526               0 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4527               0 :     AssertNoGC(cx);
        4528               0 :     CHECK_REQUEST(cx);
        4529               0 :     assertSameCompartment(cx, parent);
        4530                 :
        4531               0 :     RootObject parentRoot(cx, &parent);
        4532               0 :     return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, JSID_TO_ATOM(id));
        4533                 : }
        4534                 :
        4535                 : JS_PUBLIC_API(JSObject *)
        4536            2369 : JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
        4537                 : {
        4538            2369 :     AssertNoGC(cx);
        4539            4738 :     CHECK_REQUEST(cx);
        4540            2369 :     assertSameCompartment(cx, parent);  // XXX no funobj for now
        4541            2369 :     if (!parent) {
        4542               0 :         if (cx->hasfp())
        4543               0 :             parent = &cx->fp()->scopeChain();
        4544               0 :         if (!parent)
        4545               0 :             parent = cx->globalObject;
        4546               0 :         JS_ASSERT(parent);
        4547                 :     }
        4548                 :
        4549            2369 :     if (!funobj->isFunction()) {
        4550                 :         /*
        4551                 :          * We cannot clone this object, so fail (we used to return funobj, bad
        4552                 :          * idea, but we changed incompatibly to teach any abusers a lesson!).
        4553                 :          */
        4554               0 :         Value v = ObjectValue(*funobj);
        4555               0 :         js_ReportIsNotFunction(cx, &v, 0);
        4556               0 :         return NULL;
        4557                 :     }
        4558                 :
        4559            2369 :     JSFunction *fun = funobj->toFunction();
        4560            2369 :     if (fun->isInterpreted() && fun->script()->compileAndGo) {
        4561                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
        4562               0 :                              JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
        4563               0 :         return NULL;
        4564                 :     }
        4565                 :
        4566                 :
        4567            2369 :     return CloneFunctionObject(cx, fun, parent, fun->getAllocKind());
        4568                 : }
        4569                 :
        4570                 : JS_PUBLIC_API(JSObject *)
        4571          139977 : JS_GetFunctionObject(JSFunction *fun)
        4572                 : {
        4573          139977 :     return fun;
        4574                 : }
        4575                 :
        4576                 : JS_PUBLIC_API(JSString *)
        4577               0 : JS_GetFunctionId(JSFunction *fun)
        4578                 : {
        4579               0 :     return fun->atom;
        4580                 : }
        4581                 :
        4582                 : JS_PUBLIC_API(unsigned)
        4583               0 : JS_GetFunctionFlags(JSFunction *fun)
        4584                 : {
        4585               0 :     return fun->flags;
        4586                 : }
        4587                 :
        4588                 : JS_PUBLIC_API(uint16_t)
        4589               0 : JS_GetFunctionArity(JSFunction *fun)
        4590                 : {
        4591               0 :     return fun->nargs;
        4592                 : }
        4593                 :
        4594                 : JS_PUBLIC_API(JSBool)
        4595       138115038 : JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
        4596                 : {
        4597       138115038 :     return obj->isFunction();
        4598                 : }
        4599                 :
        4600                 : JS_PUBLIC_API(JSBool)
        4601               0 : JS_ObjectIsCallable(JSContext *cx, JSObject *obj)
        4602                 : {
        4603               0 :     return obj->isCallable();
        4604                 : }
        4605                 :
        4606                 : JS_PUBLIC_API(JSBool)
        4607               0 : JS_IsNativeFunction(JSObject *funobj, JSNative call)
        4608                 : {
        4609               0 :     if (!funobj->isFunction())
        4610               0 :         return false;
        4611               0 :     JSFunction *fun = funobj->toFunction();
        4612               0 :     return fun->isNative() && fun->native() == call;
        4613                 : }
        4614                 :
        4615                 : JS_PUBLIC_API(JSObject*)
        4616               1 : JS_BindCallable(JSContext *cx, JSObject *callable, JSObject *newThis)
        4617                 : {
        4618               2 :     RootedVarObject target(cx);
        4619               1 :     target = callable;
        4620               1 :     return js_fun_bind(cx, target, ObjectValue(*newThis), NULL, 0);
        4621                 : }
        4622                 :
        4623                 : JSBool
        4624            1296 : js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp)
        4625                 : {
        4626                 :     JSFunctionSpec *fs = (JSFunctionSpec *)
        4627            1296 :         vp->toObject().toFunction()->getExtendedSlot(0).toPrivate();
        4628            1296 :     JS_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0);
        4629                 :
        4630            1296 :     if (argc < 1) {
        4631               0 :         js_ReportMissingArg(cx, *vp, 0);
        4632               0 :         return JS_FALSE;
        4633                 :     }
        4634                 :
        4635                 :     /*
        4636                 :      * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
        4637                 :      * which is almost always the class constructor object, e.g. Array.  Then
        4638                 :      * call the corresponding prototype native method with our first argument
        4639                 :      * passed as |this|.
        4640                 :      */
        4641            1296 :     memmove(vp + 1, vp + 2, argc * sizeof(jsval));
        4642                 :
        4643                 :     /* Clear the last parameter in case too few arguments were passed. */
        4644            1296 :     vp[2 + --argc].setUndefined();
        4645                 :
        4646            1296 :     return fs->call(cx, argc, vp);
        4647                 : }
        4648                 :
        4649                 : JS_PUBLIC_API(JSBool)
        4650          610915 : JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
        4651                 : {
        4652         1221830 :     RootObject objRoot(cx, &obj);
        4653                 :
        4654          610915 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4655                 :     unsigned flags;
        4656         1221830 :     RootedVarObject ctor(cx);
        4657                 :     JSFunction *fun;
        4658                 :
        4659          610915 :     AssertNoGC(cx);
        4660         1221830 :     CHECK_REQUEST(cx);
        4661          610915 :     assertSameCompartment(cx, obj);
        4662         3744852 :     for (; fs->name; fs++) {
        4663         3133937 :         flags = fs->flags;
        4664                 :
        4665         3133937 :         JSAtom *atom = js_Atomize(cx, fs->name, strlen(fs->name));
        4666         3133937 :         if (!atom)
        4667               0 :             return JS_FALSE;
        4668                 :
        4669                 :         /*
        4670                 :          * Define a generic arity N+1 static method for the arity N prototype
        4671                 :          * method if flags contains JSFUN_GENERIC_NATIVE.
        4672                 :          */
        4673         3133937 :         if (flags & JSFUN_GENERIC_NATIVE) {
        4674          870068 :             RootAtom root(cx, &atom);
        4675                 :
        4676          435034 :             if (!ctor) {
        4677           32081 :                 ctor = JS_GetConstructor(cx, obj);
        4678           32081 :                 if (!ctor)
        4679               0 :                     return JS_FALSE;
        4680                 :             }
        4681                 :
        4682          435034 :             flags &= ~JSFUN_GENERIC_NATIVE;
        4683          435034 :             fun = js_DefineFunction(cx, ctor, ATOM_TO_JSID(atom),
        4684                 :                                     js_generic_native_method_dispatcher,
        4685                 :                                     fs->nargs + 1,
        4686                 :                                     flags,
        4687          870068 :                                     JSFunction::ExtendedFinalizeKind);
        4688          435034 :             if (!fun)
        4689               0 :                 return JS_FALSE;
        4690                 :
        4691                 :             /*
        4692                 :              * As jsapi.h notes, fs must point to storage that lives as long
        4693                 :              * as fun->object lives.
        4694                 :              */
        4695          870068 :             fun->setExtendedSlot(0, PrivateValue(fs));
        4696                 :         }
        4697                 :
        4698                 :         fun = js_DefineFunction(cx, objRoot,
        4699         3133937 :                                 ATOM_TO_JSID(atom), fs->call, fs->nargs, flags);
        4700         3133937 :         if (!fun)
        4701               0 :             return JS_FALSE;
        4702                 :     }
        4703          610915 :     return JS_TRUE;
        4704                 : }
        4705                 :
        4706                 : JS_PUBLIC_API(JSFunction *)
        4707           48245 : JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
        4708                 :                   unsigned nargs, unsigned attrs)
        4709                 : {
        4710           96490 :     RootObject objRoot(cx, &obj);
        4711                 :
        4712           48245 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4713           48245 :     AssertNoGC(cx);
        4714           96490 :     CHECK_REQUEST(cx);
        4715           48245 :     assertSameCompartment(cx, obj);
        4716           48245 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        4717           48245 :     if (!atom)
        4718               0 :         return NULL;
        4719           48245 :     return js_DefineFunction(cx, objRoot, ATOM_TO_JSID(atom), call, nargs, attrs);
        4720                 : }
        4721                 :
        4722                 : JS_PUBLIC_API(JSFunction *)
        4723               0 : JS_DefineUCFunction(JSContext *cx, JSObject *obj,
        4724                 :                     const jschar *name, size_t namelen, JSNative call,
        4725                 :                     unsigned nargs, unsigned attrs)
        4726                 : {
        4727               0 :     RootObject objRoot(cx, &obj);
        4728                 :
        4729               0 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4730               0 :     AssertNoGC(cx);
        4731               0 :     CHECK_REQUEST(cx);
        4732               0 :     assertSameCompartment(cx, obj);
        4733               0 :     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
        4734               0 :     if (!atom)
        4735               0 :         return NULL;
        4736               0 :     return js_DefineFunction(cx, objRoot, ATOM_TO_JSID(atom), call, nargs, attrs);
        4737                 : }
        4738                 :
        4739                 : extern JS_PUBLIC_API(JSFunction *)
        4740               0 : JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
        4741                 :                     unsigned nargs, unsigned attrs)
        4742                 : {
        4743               0 :     RootObject objRoot(cx, &obj);
        4744                 :
        4745               0 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4746               0 :     AssertNoGC(cx);
        4747               0 :     CHECK_REQUEST(cx);
        4748               0 :     assertSameCompartment(cx, obj);
        4749               0 :     return js_DefineFunction(cx, objRoot, id, call, nargs, attrs);
        4750                 : }
        4751                 :
        4752                 : struct AutoLastFrameCheck {
        4753           95970 :     AutoLastFrameCheck(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
        4754           95970 :       : cx(cx) {
        4755           95970 :         JS_ASSERT(cx);
        4756           95970 :         JS_GUARD_OBJECT_NOTIFIER_INIT;
        4757           95970 :     }
        4758                 :
        4759          191940 :     ~AutoLastFrameCheck() {
        4760           97735 :         if (cx->isExceptionPending() &&
        4761             942 :             !JS_IsRunning(cx) &&
        4762             823 :             !cx->hasRunOption(JSOPTION_DONT_REPORT_UNCAUGHT)) {
        4763             823 :             js_ReportUncaughtException(cx);
        4764                 :         }
        4765           95970 :     }
        4766                 :
        4767                 :   private:
        4768                 :     JSContext       *cx;
        4769                 :     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
        4770                 : };
        4771                 :
        4772                 : inline static uint32_t
        4773           38313 : JS_OPTIONS_TO_TCFLAGS(JSContext *cx)
        4774                 : {
        4775           38313 :     return (cx->hasRunOption(JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) |
        4776           38313 :            (cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0);
        4777                 : }
        4778                 :
        4779                 : static JSScript *
        4780              31 : CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
        4781                 :                                    JSPrincipals *principals, JSPrincipals *originPrincipals,
        4782                 :                                    const jschar *chars, size_t length,
        4783                 :                                    const char *filename, unsigned lineno, JSVersion version)
        4784                 : {
        4785              31 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4786              31 :     AssertNoGC(cx);
        4787              62 :     CHECK_REQUEST(cx);
        4788              31 :     assertSameCompartment(cx, obj, principals);
        4789              62 :     AutoLastFrameCheck lfc(cx);
        4790                 :
        4791              31 :     uint32_t tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_SCRIPT_GLOBAL;
        4792                 :     return frontend::CompileScript(cx, obj, NULL, principals, originPrincipals, tcflags,
        4793              31 :                                    chars, length, filename, lineno, version);
        4794                 : }
        4795                 :
        4796                 : extern JS_PUBLIC_API(JSScript *)
        4797               0 : JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
        4798                 :                                        JSPrincipals *principals,
        4799                 :                                        const jschar *chars, size_t length,
        4800                 :                                        const char *filename, unsigned lineno,
        4801                 :                                        JSVersion version)
        4802                 : {
        4803               0 :     AutoVersionAPI avi(cx, version);
        4804                 :     return CompileUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
        4805               0 :                                               filename, lineno, avi.version());
        4806                 : }
        4807                 :
        4808                 : extern JS_PUBLIC_API(JSScript *)
        4809              18 : JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
        4810                 :                                              JSPrincipals *principals,
        4811                 :                                              JSPrincipals *originPrincipals,
        4812                 :                                              const jschar *chars, size_t length,
        4813                 :                                              const char *filename, unsigned lineno,
        4814                 :                                              JSVersion version)
        4815                 : {
        4816              36 :     AutoVersionAPI avi(cx, version);
        4817                 :     return CompileUCScriptForPrincipalsCommon(cx, obj, principals, originPrincipals,
        4818              18 :                                               chars, length, filename, lineno, avi.version());
        4819                 : }
        4820                 :
        4821                 : JS_PUBLIC_API(JSScript *)
        4822              13 : JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals,
        4823                 :                                 const jschar *chars, size_t length,
        4824                 :                                 const char *filename, unsigned lineno)
        4825                 : {
        4826                 :     return CompileUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
        4827              13 :                                               filename, lineno, cx->findVersion());
        4828                 : }
        4829                 :
        4830                 : JS_PUBLIC_API(JSScript *)
        4831               2 : JS_CompileUCScript(JSContext *cx, JSObject *obj, const jschar *chars, size_t length,
        4832                 :                    const char *filename, unsigned lineno)
        4833                 : {
        4834               2 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4835               2 :     return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno);
        4836                 : }
        4837                 :
        4838                 : JS_PUBLIC_API(JSScript *)
        4839               0 : JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
        4840                 :                                      JSPrincipals *principals,
        4841                 :                                      const char *bytes, size_t length,
        4842                 :                                      const char *filename, unsigned lineno,
        4843                 :                                      JSVersion version)
        4844                 : {
        4845               0 :     AutoVersionAPI ava(cx, version);
        4846               0 :     return JS_CompileScriptForPrincipals(cx, obj, principals, bytes, length, filename, lineno);
        4847                 : }
        4848                 :
        4849                 : JS_PUBLIC_API(JSScript *)
        4850              10 : JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
        4851                 :                               JSPrincipals *principals,
        4852                 :                               const char *bytes, size_t length,
        4853                 :                               const char *filename, unsigned lineno)
        4854                 : {
        4855              10 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4856              10 :     AssertNoGC(cx);
        4857              20 :     CHECK_REQUEST(cx);
        4858                 :
        4859              10 :     jschar *chars = InflateString(cx, bytes, &length);
        4860              10 :     if (!chars)
        4861               0 :         return NULL;
        4862                 :     JSScript *script =
        4863              10 :         JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno);
        4864              10 :     cx->free_(chars);
        4865              10 :     return script;
        4866                 : }
        4867                 :
        4868                 : JS_PUBLIC_API(JSScript *)
        4869               9 : JS_CompileScript(JSContext *cx, JSObject *obj, const char *bytes, size_t length,
        4870                 :                  const char *filename, unsigned lineno)
        4871                 : {
        4872               9 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        4873               9 :     return JS_CompileScriptForPrincipals(cx, obj, NULL, bytes, length, filename, lineno);
        4874                 : }
        4875                 :
        4876                 : JS_PUBLIC_API(JSBool)
        4877               0 : JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *obj, const char *bytes, size_t length)
        4878                 : {
        4879                 :     jschar *chars;
        4880                 :     JSBool result;
        4881                 :     JSExceptionState *exnState;
        4882                 :     JSErrorReporter older;
        4883                 :
        4884               0 :     AssertNoGC(cx);
        4885               0 :     CHECK_REQUEST(cx);
        4886               0 :     assertSameCompartment(cx, obj);
        4887               0 :     if (bytes_are_utf8)
        4888               0 :         chars = InflateString(cx, bytes, &length, CESU8Encoding);
        4889                 :     else
        4890               0 :         chars = InflateString(cx, bytes, &length);
        4891               0 :     if (!chars)
        4892               0 :         return JS_TRUE;
        4893                 :
        4894                 :     /*
        4895                 :      * Return true on any out-of-memory error, so our caller doesn't try to
        4896                 :      * collect more buffered source.
        4897                 :      */
        4898               0 :     result = JS_TRUE;
        4899               0 :     exnState = JS_SaveExceptionState(cx);
        4900                 :     {
        4901               0 :         Parser parser(cx);
        4902               0 :         if (parser.init(chars, length, NULL, 1, cx->findVersion())) {
        4903               0 :             older = JS_SetErrorReporter(cx, NULL);
        4904               0 :             if (!parser.parse(obj) &&
        4905               0 :                 parser.tokenStream.isUnexpectedEOF()) {
        4906                 :                 /*
        4907                 :                  * We ran into an error. If it was because we ran out of
        4908                 :                  * source, we return false so our caller knows to try to
        4909                 :                  * collect more buffered source.
        4910                 :                  */
        4911               0 :                 result = JS_FALSE;
        4912                 :             }
        4913               0 :             JS_SetErrorReporter(cx, older);
        4914                 :         }
        4915                 :     }
        4916               0 :     cx->free_(chars);
        4917               0 :     JS_RestoreExceptionState(cx, exnState);
        4918               0 :     return result;
        4919                 : }
        4920                 :
        4921                 : /* Use the fastest available getc. */
        4922                 : #if defined(HAVE_GETC_UNLOCKED)
        4923                 : # define fast_getc getc_unlocked
        4924                 : #elif defined(HAVE__GETC_NOLOCK)
        4925                 : # define fast_getc _getc_nolock
        4926                 : #else
        4927                 : # define fast_getc getc
        4928                 : #endif
        4929                 :
        4930                 : static JSScript *
        4931           38282 : CompileUTF8FileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
        4932                 :                       const char* filename, FILE *fp)
        4933                 : {
        4934                 :     struct stat st;
        4935           38282 :     int ok = fstat(fileno(fp), &st);
        4936           38282 :     if (ok != 0)
        4937               0 :         return NULL;
        4938                 :
        4939           38282 :     char *buf = NULL;
        4940           38282 :     size_t len = st.st_size;
        4941           38282 :     size_t i = 0;
        4942                 :     JSScript *script;
        4943                 :
        4944                 :     /* Read in the whole file, then compile it. */
        4945           38282 :     if (fp == stdin) {
        4946               0 :         if (len == 0)
        4947               0 :             len = 8;  /* start with a small buffer, expand as necessary */
        4948                 :
        4949                 :         int c;
        4950               0 :         bool hitEOF = false;
        4951               0 :         while (!hitEOF) {
        4952               0 :             len *= 2;
        4953               0 :             char* tmpbuf = (char *) cx->realloc_(buf, len * sizeof(char));
        4954               0 :             if (!tmpbuf) {
        4955               0 :                 cx->free_(buf);
        4956               0 :                 return NULL;
        4957                 :             }
        4958               0 :             buf = tmpbuf;
        4959                 :
        4960               0 :             while (i < len) {
        4961               0 :                 c = fast_getc(fp);
        4962               0 :                 if (c == EOF) {
        4963               0 :                     hitEOF = true;
        4964               0 :                     break;
        4965                 :                 }
        4966               0 :                 buf[i++] = c;
        4967                 :             }
        4968                 :         }
        4969                 :     } else {
        4970           38282 :         buf = (char *) cx->malloc_(len * sizeof(char));
        4971           38282 :         if (!buf)
        4972               0 :             return NULL;
        4973                 :
        4974                 :         int c;
        4975                 :         // The |i < len| is necessary for files that lie about their length,
        4976                 :         // e.g. /dev/zero and /dev/random.  See bug 669434.
        4977        26390008 :         while (i < len && (c = fast_getc(fp)) != EOF)
        4978        26313444 :             buf[i++] = c;
        4979                 :     }
        4980                 :
        4981           38282 :     JS_ASSERT(i <= len);
        4982           38282 :     len = i;
        4983           38282 :     size_t decodelen = len;
        4984           38282 :     jschar *decodebuf = (jschar *)cx->malloc_(decodelen * sizeof(jschar));
        4985           38282 :     if (JS_DecodeUTF8(cx, buf, len, decodebuf, &decodelen)) {
        4986           38282 :         uint32_t tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_SCRIPT_GLOBAL;
        4987                 :         script = frontend::CompileScript(cx, obj, NULL, principals, NULL,
        4988                 :                                          tcflags, decodebuf, decodelen,
        4989           38282 :                                          filename, 1, cx->findVersion());
        4990                 :     } else {
        4991               0 :         script = NULL;
        4992                 :     }
        4993           38282 :     cx->free_(buf);
        4994           38282 :     cx->free_(decodebuf);
        4995           38282 :     return script;
        4996                 : }
        4997                 :
        4998                 : JS_PUBLIC_API(JSScript *)
        4999             947 : JS_CompileUTF8File(JSContext *cx, JSObject *obj, const char *filename)
        5000                 : {
        5001             947 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5002             947 :     AssertNoGC(cx);
        5003            1894 :     CHECK_REQUEST(cx);
        5004             947 :     assertSameCompartment(cx, obj);
        5005            1894 :     AutoLastFrameCheck lfc(cx);
        5006                 :
        5007                 :     FILE *fp;
        5008             947 :     if (!filename || strcmp(filename, "-") == 0) {
        5009               0 :         fp = stdin;
        5010                 :     } else {
        5011             947 :         fp = fopen(filename, "r");
        5012             947 :         if (!fp) {
        5013                 :             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
        5014               0 :                                  filename, "No such file or directory");
        5015               0 :             return NULL;
        5016                 :         }
        5017                 :     }
        5018                 :
        5019             947 :     JSScript *script = CompileUTF8FileHelper(cx, obj, NULL, filename, fp);
        5020             947 :     if (fp != stdin)
        5021             947 :         fclose(fp);
        5022             947 :     return script;
        5023                 : }
        5024                 :
        5025                 : JS_PUBLIC_API(JSScript *)
        5026           37335 : JS_CompileUTF8FileHandleForPrincipals(JSContext *cx, JSObject *obj, const char *filename,
        5027                 :                                       FILE *file, JSPrincipals *principals)
        5028                 : {
        5029           37335 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5030           37335 :     AssertNoGC(cx);
        5031           74670 :     CHECK_REQUEST(cx);
        5032           37335 :     assertSameCompartment(cx, obj, principals);
        5033           74670 :     AutoLastFrameCheck lfc(cx);
        5034                 :
        5035           37335 :     return CompileUTF8FileHelper(cx, obj, principals, filename, file);
        5036                 : }
        5037                 :
        5038                 : JS_PUBLIC_API(JSScript *)
        5039               0 : JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj, const char *filename,
        5040                 :                                              FILE *file, JSPrincipals *principals, JSVersion version)
        5041                 : {
        5042               0 :     AutoVersionAPI ava(cx, version);
        5043               0 :     return JS_CompileUTF8FileHandleForPrincipals(cx, obj, filename, file, principals);
        5044                 : }
        5045                 :
        5046                 : JS_PUBLIC_API(JSScript *)
        5047           37334 : JS_CompileUTF8FileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *file)
        5048                 : {
        5049           37334 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5050           37334 :     return JS_CompileUTF8FileHandleForPrincipals(cx, obj, filename, file, NULL);
        5051                 : }
        5052                 :
        5053                 : JS_PUBLIC_API(JSObject *)
        5054               0 : JS_GetGlobalFromScript(JSScript *script)
        5055                 : {
        5056               0 :     JS_ASSERT(!script->isCachedEval);
        5057               0 :     JS_ASSERT(script->globalObject);
        5058                 :
        5059               0 :     return script->globalObject;
        5060                 : }
        5061                 :
        5062                 : static JSFunction *
        5063               8 : CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
        5064                 :                                      JSPrincipals *principals, const char *name,
        5065                 :                                      unsigned nargs, const char **argnames,
        5066                 :                                      const jschar *chars, size_t length,
        5067                 :                                      const char *filename, unsigned lineno, JSVersion version)
        5068                 : {
        5069              16 :     RootObject objRoot(cx, &obj);
        5070                 :
        5071               8 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5072               8 :     AssertNoGC(cx);
        5073              16 :     CHECK_REQUEST(cx);
        5074               8 :     assertSameCompartment(cx, obj, principals);
        5075              16 :     AutoLastFrameCheck lfc(cx);
        5076                 :
        5077                 :     JSAtom *funAtom;
        5078               8 :     if (!name) {
        5079               0 :         funAtom = NULL;
        5080                 :     } else {
        5081               8 :         funAtom = js_Atomize(cx, name, strlen(name));
        5082               8 :         if (!funAtom)
        5083               0 :             return NULL;
        5084                 :     }
        5085                 :
        5086              16 :     Bindings bindings(cx);
        5087              14 :     for (unsigned i = 0; i < nargs; i++) {
        5088                 :         uint16_t dummy;
        5089               6 :         JSAtom *argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]));
        5090               6 :         if (!argAtom || !bindings.addArgument(cx, argAtom, &dummy))
        5091               0 :             return NULL;
        5092                 :     }
        5093                 :
        5094               8 :     JSFunction *fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, objRoot, funAtom);
        5095               8 :     if (!fun)
        5096               0 :         return NULL;
        5097                 :
        5098               8 :     if (!frontend::CompileFunctionBody(cx, fun, principals, NULL, &bindings,
        5099               8 :                                        chars, length, filename, lineno, version))
        5100                 :     {
        5101               0 :         return NULL;
        5102                 :     }
        5103                 :
        5104              16 :     if (obj && funAtom &&
        5105               8 :         !obj->defineGeneric(cx, ATOM_TO_JSID(funAtom), ObjectValue(*fun), NULL, NULL,
        5106               8 :                             JSPROP_ENUMERATE))
        5107                 :     {
        5108               0 :         return NULL;
        5109                 :     }
        5110                 :
        5111               8 :     return fun;
        5112                 : }
        5113                 :
        5114                 : JS_PUBLIC_API(JSFunction *)
        5115               0 : JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
        5116                 :                                          JSPrincipals *principals, const char *name,
        5117                 :                                          unsigned nargs, const char **argnames,
        5118                 :                                          const jschar *chars, size_t length,
        5119                 :                                          const char *filename, unsigned lineno,
        5120                 :                                          JSVersion version)
        5121                 : {
        5122               0 :     AutoVersionAPI avi(cx, version);
        5123                 :     return CompileUCFunctionForPrincipalsCommon(cx, obj, principals, name, nargs, argnames, chars,
        5124               0 :                                                 length, filename, lineno, avi.version());
        5125                 : }
        5126                 :
        5127                 : JS_PUBLIC_API(JSFunction *)
        5128               8 : JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
        5129                 :                                   JSPrincipals *principals, const char *name,
        5130                 :                                   unsigned nargs, const char **argnames,
        5131                 :                                   const jschar *chars, size_t length,
        5132                 :                                   const char *filename, unsigned lineno)
        5133                 : {
        5134                 :     return CompileUCFunctionForPrincipalsCommon(cx, obj, principals, name, nargs, argnames, chars,
        5135               8 :                                                 length, filename, lineno, cx->findVersion());
        5136                 : }
        5137                 :
        5138                 : JS_PUBLIC_API(JSFunction *)
        5139               0 : JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
        5140                 :                      unsigned nargs, const char **argnames,
        5141                 :                      const jschar *chars, size_t length,
        5142                 :                      const char *filename, unsigned lineno)
        5143                 : {
        5144               0 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5145                 :     return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames,
        5146               0 :                                              chars, length, filename, lineno);
        5147                 : }
        5148                 :
        5149                 : JS_PUBLIC_API(JSFunction *)
        5150               8 : JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
        5151                 :                                 JSPrincipals *principals, const char *name,
        5152                 :                                 unsigned nargs, const char **argnames,
        5153                 :                                 const char *bytes, size_t length,
        5154                 :                                 const char *filename, unsigned lineno)
        5155                 : {
        5156               8 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5157               8 :     jschar *chars = InflateString(cx, bytes, &length);
        5158               8 :     if (!chars)
        5159               0 :         return NULL;
        5160                 :     JSFunction *fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
        5161                 :                                                         nargs, argnames, chars, length,
        5162               8 :                                                         filename, lineno);
        5163               8 :     cx->free_(chars);
        5164               8 :     return fun;
        5165                 : }
        5166                 :
        5167                 : JS_PUBLIC_API(JSFunction *)
        5168               4 : JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
        5169                 :                    unsigned nargs, const char **argnames,
        5170                 :                    const char *bytes, size_t length,
        5171                 :                    const char *filename, unsigned lineno)
        5172                 : {
        5173               4 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5174                 :     return JS_CompileFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames, bytes, length,
        5175               4 :                                            filename, lineno);
        5176                 : }
        5177                 :
        5178                 : JS_PUBLIC_API(JSString *)
        5179               0 : JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent)
        5180                 : {
        5181               0 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5182                 :     JSPrinter *jp;
        5183                 :     JSString *str;
        5184                 :
        5185               0 :     AssertNoGC(cx);
        5186               0 :     CHECK_REQUEST(cx);
        5187                 : #ifdef DEBUG
        5188               0 :     if (cx->compartment != script->compartment())
        5189               0 :         CompartmentChecker::fail(cx->compartment, script->compartment());
        5190                 : #endif
        5191                 :     jp = js_NewPrinter(cx, name, NULL,
        5192                 :                        indent & ~JS_DONT_PRETTY_PRINT,
        5193                 :                        !(indent & JS_DONT_PRETTY_PRINT),
        5194               0 :                        false, false);
        5195               0 :     if (!jp)
        5196               0 :         return NULL;
        5197               0 :     if (js_DecompileScript(jp, script))
        5198               0 :         str = js_GetPrinterOutput(jp);
        5199                 :     else
        5200               0 :         str = NULL;
        5201               0 :     js_DestroyPrinter(jp);
        5202               0 :     return str;
        5203                 : }
        5204                 :
        5205                 : JS_PUBLIC_API(JSString *)
        5206           11538 : JS_DecompileFunction(JSContext *cx, JSFunction *fun, unsigned indent)
        5207                 : {
        5208           11538 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5209           11538 :     AssertNoGC(cx);
        5210           23076 :     CHECK_REQUEST(cx);
        5211           11538 :     assertSameCompartment(cx, fun);
        5212                 :     return js_DecompileToString(cx, "JS_DecompileFunction", fun,
        5213                 :                                 indent & ~JS_DONT_PRETTY_PRINT,
        5214                 :                                 !(indent & JS_DONT_PRETTY_PRINT),
        5215           11538 :                                 false, false, js_DecompileFunction);
        5216                 : }
        5217                 :
        5218                 : JS_PUBLIC_API(JSString *)
        5219               0 : JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, unsigned indent)
        5220                 : {
        5221               0 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5222               0 :     AssertNoGC(cx);
        5223               0 :     CHECK_REQUEST(cx);
        5224               0 :     assertSameCompartment(cx, fun);
        5225                 :     return js_DecompileToString(cx, "JS_DecompileFunctionBody", fun,
        5226                 :                                 indent & ~JS_DONT_PRETTY_PRINT,
        5227                 :                                 !(indent & JS_DONT_PRETTY_PRINT),
        5228               0 :                                 false, false, js_DecompileFunctionBody);
        5229                 : }
        5230                 :
        5231                 : JS_PUBLIC_API(JSBool)
        5232           38261 : JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *scriptArg, jsval *rval)
        5233                 : {
        5234           38261 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5235           38261 :     AssertNoGC(cx);
        5236           76522 :     CHECK_REQUEST(cx);
        5237           38261 :     assertSameCompartment(cx, obj);
        5238           76522 :     AutoLastFrameCheck lfc(cx);
        5239                 :
        5240           76522 :     JS::Anchor<JSScript *> script;
        5241                 :
        5242                 :     /*
        5243                 :      * Mozilla caches pre-compiled scripts (e.g., in the XUL prototype cache)
        5244                 :      * and runs them against multiple globals. With a compartment per global,
        5245                 :      * this requires cloning the pre-compiled script into each new global.
        5246                 :      * Since each script gets run once, there is no point in trying to cache
        5247                 :      * this clone. Ideally, this would be handled at some pinch point in
        5248                 :      * mozilla, but there doesn't seem to be one, so we handle it here.
        5249                 :      */
        5250           38261 :     if (scriptArg->compartment() != obj->compartment()) {
        5251               0 :         script = CloneScript(cx, scriptArg);
        5252               0 :         if (!script.get())
        5253               0 :             return false;
        5254                 :     } else {
        5255           38261 :         script = scriptArg;
        5256                 :     }
        5257                 :
        5258           38261 :     return Execute(cx, script.get(), *obj, rval);
        5259                 : }
        5260                 :
        5261                 : JS_PUBLIC_API(JSBool)
        5262               0 : JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval,
        5263                 :                         JSVersion version)
        5264                 : {
        5265               0 :     AutoVersionAPI ava(cx, version);
        5266               0 :     return JS_ExecuteScript(cx, obj, script, rval);
        5267                 : }
        5268                 :
        5269                 : bool
        5270           19357 : EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
        5271                 :                                     JSPrincipals *principals, JSPrincipals *originPrincipals,
        5272                 :                                     const jschar *chars, unsigned length,
        5273                 :                                     const char *filename, unsigned lineno,
        5274                 :                                     jsval *rval, JSVersion compileVersion)
        5275                 : {
        5276           19357 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5277                 :
        5278           19357 :     uint32_t flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL;
        5279           19357 :     if (!rval)
        5280               0 :         flags |= TCF_NO_SCRIPT_RVAL;
        5281                 :
        5282           38714 :     CHECK_REQUEST(cx);
        5283           38714 :     AutoLastFrameCheck lfc(cx);
        5284                 :     JSScript *script = frontend::CompileScript(cx, obj, NULL, principals, originPrincipals,
        5285                 :                                                flags, chars, length, filename, lineno,
        5286           19357 :                                                compileVersion);
        5287           19357 :     if (!script)
        5288               2 :         return false;
        5289                 :
        5290           19355 :     JS_ASSERT(script->getVersion() == compileVersion);
        5291                 :
        5292           19355 :     return Execute(cx, script, *obj, rval);
        5293                 : }
        5294                 :
        5295                 : JS_PUBLIC_API(JSBool)
        5296           19329 : JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
        5297                 :                                  JSPrincipals *principals,
        5298                 :                                  const jschar *chars, unsigned length,
        5299                 :                                  const char *filename, unsigned lineno,
        5300                 :                                  jsval *rval)
        5301                 : {
        5302                 :     return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
        5303           19329 :                                                filename, lineno, rval, cx->findVersion());
        5304                 : }
        5305                 :
        5306                 : JS_PUBLIC_API(JSBool)
        5307               2 : JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
        5308                 :                                         JSPrincipals *principals,
        5309                 :                                         const jschar *chars, unsigned length,
        5310                 :                                         const char *filename, unsigned lineno,
        5311                 :                                         jsval *rval, JSVersion version)
        5312                 : {
        5313               4 :     AutoVersionAPI avi(cx, version);
        5314                 :     return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
        5315               2 :                                                filename, lineno, rval, avi.version());
        5316                 : }
        5317                 :
        5318                 : extern JS_PUBLIC_API(JSBool)
        5319              26 : JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
        5320                 :                                               JSPrincipals *principals,
        5321                 :                                               JSPrincipals *originPrincipals,
        5322                 :                                               const jschar *chars, unsigned length,
        5323                 :                                               const char *filename, unsigned lineno,
        5324                 :                                               jsval *rval, JSVersion version)
        5325                 : {
        5326              52 :     AutoVersionAPI avi(cx, version);
        5327                 :     return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, originPrincipals,
        5328                 :                                                chars, length, filename, lineno, rval,
        5329              26 :                                                avi.version());
        5330                 : }
        5331                 :
        5332                 : JS_PUBLIC_API(JSBool)
        5333             486 : JS_EvaluateUCScript(JSContext *cx, JSObject *obj, const jschar *chars, unsigned length,
        5334                 :                     const char *filename, unsigned lineno, jsval *rval)
        5335                 : {
        5336             486 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5337             486 :     return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno, rval);
        5338                 : }
        5339                 :
        5340                 : /* Ancient unsigned nbytes is part of API/ABI, so use size_t length local. */
        5341                 : JS_PUBLIC_API(JSBool)
        5342           18843 : JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals,
        5343                 :                                const char *bytes, unsigned nbytes,
        5344                 :                                const char *filename, unsigned lineno, jsval *rval)
        5345                 : {
        5346           18843 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5347           18843 :     size_t length = nbytes;
        5348           18843 :     jschar *chars = InflateString(cx, bytes, &length);
        5349           18843 :     if (!chars)
        5350               0 :         return JS_FALSE;
        5351                 :     JSBool ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
        5352           18843 :                                                  filename, lineno, rval);
        5353           18843 :     cx->free_(chars);
        5354           18843 :     return ok;
        5355                 : }
        5356                 :
        5357                 : JS_PUBLIC_API(JSBool)
        5358               0 : JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *obj, JSPrincipals *principals,
        5359                 :                                       const char *bytes, unsigned nbytes,
        5360                 :                                       const char *filename, unsigned lineno, jsval *rval, JSVersion version)
        5361                 : {
        5362               0 :     AutoVersionAPI avi(cx, version);
        5363                 :     return JS_EvaluateScriptForPrincipals(cx, obj, principals, bytes, nbytes, filename, lineno,
        5364               0 :                                           rval);
        5365                 : }
        5366                 :
        5367                 : JS_PUBLIC_API(JSBool)
        5368           18843 : JS_EvaluateScript(JSContext *cx, JSObject *obj, const char *bytes, unsigned nbytes,
        5369                 :                   const char *filename, unsigned lineno, jsval *rval)
        5370                 : {
        5371           18843 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5372           18843 :     return JS_EvaluateScriptForPrincipals(cx, obj, NULL, bytes, nbytes, filename, lineno, rval);
        5373                 : }
        5374                 :
        5375                 : JS_PUBLIC_API(JSBool)
        5376               3 : JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, unsigned argc, jsval *argv,
        5377                 :                 jsval *rval)
        5378                 : {
        5379               3 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5380               3 :     AssertNoGC(cx);
        5381               6 :     CHECK_REQUEST(cx);
        5382               3 :     assertSameCompartment(cx, obj, fun, JSValueArray(argv, argc));
        5383               6 :     AutoLastFrameCheck lfc(cx);
        5384                 :
        5385               3 :     return Invoke(cx, ObjectOrNullValue(obj), ObjectValue(*fun), argc, argv, rval);
        5386                 : }
        5387                 :
        5388                 : JS_PUBLIC_API(JSBool)
        5389              21 : JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, unsigned argc, jsval *argv,
        5390                 :                     jsval *rval)
        5391                 : {
        5392              21 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5393              21 :     AssertNoGC(cx);
        5394              42 :     CHECK_REQUEST(cx);
        5395              21 :     assertSameCompartment(cx, obj, JSValueArray(argv, argc));
        5396              42 :     AutoLastFrameCheck lfc(cx);
        5397                 :
        5398                 :     Value v;
        5399              21 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
        5400                 :     return atom &&
        5401              21 :            js_GetMethod(cx, obj, ATOM_TO_JSID(atom), 0, &v) &&
        5402              42 :            Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval);
        5403                 : }
        5404                 :
        5405                 : JS_PUBLIC_API(JSBool)
        5406               3 : JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, unsigned argc, jsval *argv,
        5407                 :                      jsval *rval)
        5408                 : {
        5409               3 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
        5410               3 :     AssertNoGC(cx);
        5411               6 :     CHECK_REQUEST(cx);
        5412               3 :     assertSameCompartment(cx, obj, fval, JSValueArray(argv, argc));
        5413               6 :     AutoLastFrameCheck lfc(cx);
        5414                 :
        5415               3 :     return Invoke(cx, ObjectOrNullValue(obj), fval, argc, argv, rval);
        5416                 : }
        5417                 :
        5418                 : namespace JS {
        5419                 :
        5420                 : JS_PUBLIC_API(bool)
        5421               0 : Call(JSContext *cx, jsval thisv, jsval fval, unsigned argc, jsval *argv, jsval *rval)
        5422                 : {
        5423               0 :     AssertNoGC(cx);
        5424               0 :     CHECK_REQUEST(cx);
        5425               0 :     assertSameCompartment(cx, thisv, fval, JSValueArray(argv, argc));
        5426               0 :     AutoLastFrameCheck lfc(cx);
        5427                 :
        5428               0 :     return Invoke(cx, thisv, fval, argc, argv, rval);
        5429                 : }
        5430                 :
        5431                 : } // namespace JS
        5432                 :
        5433                 : JS_PUBLIC_API(JSObject *)
        5434               4 : JS_New(JSContext *cx, JSObject *ctor, unsigned argc, jsval *argv)
        5435                 : {
        5436               4 :     AssertNoGC(cx);
        5437               8 :     CHECK_REQUEST(cx);
        5438               4 :     assertSameCompartment(cx, ctor, JSValueArray(argv, argc));
        5439               8 :     AutoLastFrameCheck lfc(cx);
        5440                 :
        5441                 :     // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
        5442                 :     // is not a simple variation of JSOP_CALL. We have to determine what class
        5443                 :     // of object to create, create it, and clamp the return value to an object,
        5444                 :     // among other details. InvokeConstructor does the hard work.
        5445               8 :     InvokeArgsGuard args;
        5446               4 :     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
        5447               0 :         return NULL;
        5448                 :
        5449               4 :     args.calleev().setObject(*ctor);
        5450               4 :     args.thisv().setNull();
        5451               4 :     PodCopy(args.array(), argv, argc);
        5452                 :
        5453               4 :     if (!InvokeConstructor(cx, args))
        5454               0 :         return NULL;
        5455                 :
        5456               4 :     if (!args.rval().isObject()) {
        5457                 :         /*
        5458                 :          * Although constructors may return primitives (via proxies), this
        5459                 :          * API is asking for an object, so we report an error.
        5460                 :          */
        5461               0 :         JSAutoByteString bytes;
        5462               0 :         if (js_ValueToPrintable(cx, args.rval(), &bytes)) {
        5463                 :             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_NEW_RESULT,
        5464               0 :                                  bytes.ptr());
        5465                 :         }
        5466               0 :         return NULL;
        5467                 :     }
        5468                 :
        5469               4 :     return &args.rval().toObject();
        5470                 : }
        5471                 :
        5472                 : JS_PUBLIC_API(JSOperationCallback)
        5473           55998 : JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback)
        5474                 : {
        5475           55998 :     JSOperationCallback old = cx->operationCallback;
        5476           55998 :     cx->operationCallback = callback;
        5477           55998 :     return old;
        5478                 : }
        5479                 :
        5480                 : JS_PUBLIC_API(JSOperationCallback)
        5481               0 : JS_GetOperationCallback(JSContext *cx)
        5482                 : {
        5483               0 :     return cx->operationCallback;
        5484                 : }
        5485                 :
        5486                 : JS_PUBLIC_API(void)
        5487               0 : JS_TriggerOperationCallback(JSRuntime *rt)
        5488                 : {
        5489               0 :     rt->triggerOperationCallback();
        5490               0 : }
        5491                 :
        5492                 : JS_PUBLIC_API(JSBool)
        5493          475957 : JS_IsRunning(JSContext *cx)
        5494                 : {
        5495          475957 :     StackFrame *fp = cx->maybefp();
        5496          957959 :     while (fp && fp->isDummyFrame())
        5497            6045 :         fp = fp->prev();
        5498          475957 :     return fp != NULL;
        5499                 : }
        5500                 :
        5501                 : JS_PUBLIC_API(JSBool)
        5502             145 : JS_SaveFrameChain(JSContext *cx)
        5503                 : {
        5504             145 :     AssertNoGC(cx);
        5505             290 :     CHECK_REQUEST(cx);
        5506             145 :     return cx->stack.saveFrameChain();
        5507                 : }
        5508                 :
        5509                 : JS_PUBLIC_API(void)
        5510             145 : JS_RestoreFrameChain(JSContext *cx)
        5511                 : {
        5512             145 :     AssertNoGC(cx);
        5513             290 :     CHECK_REQUEST(cx);
        5514             145 :     cx->stack.restoreFrameChain();
        5515             145 : }
        5516                 :
        5517                 : #ifdef MOZ_TRACE_JSCALLS
        5518                 : JS_PUBLIC_API(void)
        5519                 : JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb)
        5520                 : {
        5521                 :     cx->functionCallback = fcb;
        5522                 : }
        5523                 :
        5524                 : JS_PUBLIC_API(JSFunctionCallback)
        5525                 : JS_GetFunctionCallback(JSContext *cx)
        5526                 : {
        5527                 :     return cx->functionCallback;
        5528                 : }
        5529                 : #endif
        5530                 :
        5531                 : /************************************************************************/
        5532                 : JS_PUBLIC_API(JSString *)
        5533               0 : JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
        5534                 : {
        5535               0 :     AssertNoGC(cx);
        5536               0 :     CHECK_REQUEST(cx);
        5537               0 :     return js_NewStringCopyN(cx, s, n);
        5538                 : }
        5539                 :
        5540                 : JS_PUBLIC_API(JSString *)
        5541          770602 : JS_NewStringCopyZ(JSContext *cx, const char *s)
        5542                 : {
        5543                 :     size_t n;
        5544                 :     jschar *js;
        5545                 :     JSString *str;
        5546                 :
        5547          770602 :     AssertNoGC(cx);
        5548         1541204 :     CHECK_REQUEST(cx);
        5549          770602 :     if (!s || !*s)
        5550              31 :         return cx->runtime->emptyString;
        5551          770571 :     n = strlen(s);
        5552          770571 :     js = InflateString(cx, s, &n);
        5553          770571 :     if (!js)
        5554               0 :         return NULL;
        5555          770571 :     str = js_NewString(cx, js, n);
        5556          770571 :     if (!str)
        5557               0 :         cx->free_(js);
        5558          770571 :     return str;
        5559                 : }
        5560                 :
        5561                 : JS_PUBLIC_API(JSBool)
        5562              18 : JS_StringHasBeenInterned(JSContext *cx, JSString *str)
        5563                 : {
        5564              18 :     AssertNoGC(cx);
        5565              36 :     CHECK_REQUEST(cx);
        5566                 :
        5567              18 :     if (!str->isAtom())
        5568               0 :         return false;
        5569                 :
        5570              18 :     return AtomIsInterned(cx, &str->asAtom());
        5571                 : }
        5572                 :
        5573                 : JS_PUBLIC_API(JSString *)
        5574               1 : JS_InternJSString(JSContext *cx, JSString *str)
        5575                 : {
        5576               1 :     AssertNoGC(cx);
        5577               2 :     CHECK_REQUEST(cx);
        5578               1 :     JSAtom *atom = js_AtomizeString(cx, str, InternAtom);
        5579               1 :     JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
        5580               1 :     return atom;
        5581                 : }
        5582                 :
        5583                 : JS_PUBLIC_API(JSString *)
        5584              10 : JS_InternString(JSContext *cx, const char *s)
        5585                 : {
        5586              10 :     AssertNoGC(cx);
        5587              20 :     CHECK_REQUEST(cx);
        5588              10 :     JSAtom *atom = js_Atomize(cx, s, strlen(s), InternAtom);
        5589              10 :     JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
        5590              10 :     return atom;
        5591                 : }
        5592                 :
        5593                 : JS_PUBLIC_API(JSString *)
        5594               0 : JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
        5595                 : {
        5596               0 :     AssertNoGC(cx);
        5597               0 :     CHECK_REQUEST(cx);
        5598               0 :     return js_NewString(cx, chars, length);
        5599                 : }
        5600                 :
        5601                 : JS_PUBLIC_API(JSString *)
        5602               1 : JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
        5603                 : {
        5604               1 :     AssertNoGC(cx);
        5605               2 :     CHECK_REQUEST(cx);
        5606               1 :     return js_NewStringCopyN(cx, s, n);
        5607                 : }
        5608                 :
        5609                 : JS_PUBLIC_API(JSString *)
        5610               0 : JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
        5611                 : {
        5612               0 :     AssertNoGC(cx);
        5613               0 :     CHECK_REQUEST(cx);
        5614               0 :     if (!s)
        5615               0 :         return cx->runtime->emptyString;
        5616               0 :     return js_NewStringCopyZ(cx, s);
        5617                 : }
        5618                 :
        5619                 : JS_PUBLIC_API(JSString *)
        5620               0 : JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
        5621                 : {
        5622               0 :     AssertNoGC(cx);
        5623               0 :     CHECK_REQUEST(cx);
        5624               0 :     JSAtom *atom = js_AtomizeChars(cx, s, length, InternAtom);
        5625               0 :     JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
        5626               0 :     return atom;
        5627                 : }
        5628                 :
        5629                 : JS_PUBLIC_API(JSString *)
        5630               0 : JS_InternUCString(JSContext *cx, const jschar *s)
        5631                 : {
        5632               0 :     return JS_InternUCStringN(cx, s, js_strlen(s));
        5633                 : }
        5634                 :
        5635                 : JS_PUBLIC_API(size_t)
        5636               0 : JS_GetStringLength(JSString *str)
        5637                 : {
        5638               0 :     return str->length();
        5639                 : }
        5640                 :
        5641                 : JS_PUBLIC_API(const jschar *)
        5642               2 : JS_GetStringCharsZ(JSContext *cx, JSString *str)
        5643                 : {
        5644               2 :     AssertNoGCOrFlatString(cx, str);
        5645               4 :     CHECK_REQUEST(cx);
        5646               2 :     assertSameCompartment(cx, str);
        5647               2 :     return str->getCharsZ(cx);
        5648                 : }
        5649                 :
        5650                 : JS_PUBLIC_API(const jschar *)
        5651               0 : JS_GetStringCharsZAndLength(JSContext *cx, JSString *str, size_t *plength)
        5652                 : {
        5653               0 :     AssertNoGCOrFlatString(cx, str);
        5654               0 :     CHECK_REQUEST(cx);
        5655               0 :     assertSameCompartment(cx, str);
        5656               0 :     *plength = str->length();
        5657               0 :     return str->getCharsZ(cx);
        5658                 : }
        5659                 :
        5660                 : JS_PUBLIC_API(const jschar *)
        5661            1647 : JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *plength)
        5662                 : {
        5663            1647 :     AssertNoGCOrFlatString(cx, str);
        5664            3294 :     CHECK_REQUEST(cx);
        5665            1647 :     assertSameCompartment(cx, str);
        5666            1647 :     *plength = str->length();
        5667            1647 :     return str->getChars(cx);
        5668                 : }
        5669                 :
        5670                 : JS_PUBLIC_API(const jschar *)
        5671               0 : JS_GetInternedStringChars(JSString *str)
        5672                 : {
        5673               0 :     return str->asAtom().chars();
        5674                 : }
        5675                 :
        5676                 : JS_PUBLIC_API(const jschar *)
        5677               0 : JS_GetInternedStringCharsAndLength(JSString *str, size_t *plength)
        5678                 : {
        5679               0 :     JSAtom &atom = str->asAtom();
        5680               0 :     *plength = atom.length();
        5681               0 :     return atom.chars();
        5682                 : }
        5683                 :
        5684                 : extern JS_PUBLIC_API(JSFlatString *)
        5685              43 : JS_FlattenString(JSContext *cx, JSString *str)
        5686                 : {
        5687              43 :     AssertNoGC(cx);
        5688              86 :     CHECK_REQUEST(cx);
        5689              43 :     assertSameCompartment(cx, str);
        5690              43 :     return str->getCharsZ(cx) ? (JSFlatString *)str : NULL;
        5691                 : }
        5692                 :
        5693                 : extern JS_PUBLIC_API(const jschar *)
        5694               8 : JS_GetFlatStringChars(JSFlatString *str)
        5695                 : {
        5696               8 :     return str->chars();
        5697                 : }
        5698                 :
        5699                 : JS_PUBLIC_API(JSBool)
        5700               0 : JS_CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *result)
        5701                 : {
        5702               0 :     AssertNoGC(cx);
        5703               0 :     CHECK_REQUEST(cx);
        5704                 :
        5705               0 :     return CompareStrings(cx, str1, str2, result);
        5706                 : }
        5707                 :
        5708                 : JS_PUBLIC_API(JSBool)
        5709            9360 : JS_StringEqualsAscii(JSContext *cx, JSString *str, const char *asciiBytes, JSBool *match)
        5710                 : {
        5711            9360 :     AssertNoGC(cx);
        5712           18720 :     CHECK_REQUEST(cx);
        5713                 :
        5714            9360 :     JSLinearString *linearStr = str->ensureLinear(cx);
        5715            9360 :     if (!linearStr)
        5716               0 :         return false;
        5717            9360 :     *match = StringEqualsAscii(linearStr, asciiBytes);
        5718            9360 :     return true;
        5719                 : }
        5720                 :
        5721                 : JS_PUBLIC_API(JSBool)
        5722              80 : JS_FlatStringEqualsAscii(JSFlatString *str, const char *asciiBytes)
        5723                 : {
        5724              80 :     return StringEqualsAscii(str, asciiBytes);
        5725                 : }
        5726                 :
        5727                 : JS_PUBLIC_API(size_t)
        5728               0 : JS_PutEscapedFlatString(char *buffer, size_t size, JSFlatString *str, char quote)
        5729                 : {
        5730               0 :     return PutEscapedString(buffer, size, str, quote);
        5731                 : }
        5732                 :
        5733                 : JS_PUBLIC_API(size_t)
        5734               0 : JS_PutEscapedString(JSContext *cx, char *buffer, size_t size, JSString *str, char quote)
        5735                 : {
        5736               0 :     AssertNoGC(cx);
        5737               0 :     JSLinearString *linearStr = str->ensureLinear(cx);
        5738               0 :     if (!linearStr)
        5739               0 :         return size_t(-1);
        5740               0 :     return PutEscapedString(buffer, size, linearStr, quote);
        5741                 : }
        5742                 :
        5743                 : JS_PUBLIC_API(JSBool)
        5744               0 : JS_FileEscapedString(FILE *fp, JSString *str, char quote)
        5745                 : {
        5746               0 :     JSLinearString *linearStr = str->ensureLinear(NULL);
        5747               0 :     return linearStr && FileEscapedString(fp, linearStr, quote);
        5748                 : }
        5749                 :
        5750                 : JS_PUBLIC_API(JSString *)
        5751               0 : JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
        5752                 : {
        5753               0 :     AssertNoGC(cx);
        5754               0 :     CHECK_REQUEST(cx);
        5755               0 :     return js_NewString(cx, chars, length);
        5756                 : }
        5757                 :
        5758                 : JS_PUBLIC_API(JSString *)
        5759               0 : JS_NewDependentString(JSContext *cx, JSString *str, size_t start, size_t length)
        5760                 : {
        5761               0 :     AssertNoGC(cx);
        5762               0 :     CHECK_REQUEST(cx);
        5763               0 :     return js_NewDependentString(cx, str, start, length);
        5764                 : }
        5765                 :
        5766                 : JS_PUBLIC_API(JSString *)
        5767              72 : JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
        5768                 : {
        5769              72 :     AssertNoGC(cx);
        5770             144 :     CHECK_REQUEST(cx);
        5771              72 :     return js_ConcatStrings(cx, left, right);
        5772                 : }
        5773                 :
        5774                 : JS_PUBLIC_API(const jschar *)
        5775               0 : JS_UndependString(JSContext *cx, JSString *str)
        5776                 : {
        5777               0 :     AssertNoGC(cx);
        5778               0 :     CHECK_REQUEST(cx);
        5779               0 :     return str->getCharsZ(cx);
        5780                 : }
        5781                 :
        5782                 : JS_PUBLIC_API(JSBool)
        5783               0 : JS_MakeStringImmutable(JSContext *cx, JSString *str)
        5784                 : {
        5785               0 :     AssertNoGC(cx);
        5786               0 :     CHECK_REQUEST(cx);
        5787               0 :     return !!str->ensureFixed(cx);
        5788                 : }
        5789                 :
        5790                 : JS_PUBLIC_API(JSBool)
        5791               2 : JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst, size_t *dstlenp)
        5792                 : {
        5793               2 :     AssertNoGC(cx);
        5794               4 :     CHECK_REQUEST(cx);
        5795                 :
        5796                 :     size_t n;
        5797               2 :     if (!dst) {
        5798               1 :         n = GetDeflatedStringLength(cx, src, srclen);
        5799               1 :         if (n == (size_t)-1) {
        5800               0 :             *dstlenp = 0;
        5801               0 :             return JS_FALSE;
        5802                 :         }
        5803               1 :         *dstlenp = n;
        5804               1 :         return JS_TRUE;
        5805                 :     }
        5806                 :
        5807               1 :     return DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
        5808                 : }
        5809                 :
        5810                 : JS_PUBLIC_API(JSBool)
        5811              36 : JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_t *dstlenp)
        5812                 : {
        5813              36 :     AssertNoGC(cx);
        5814              72 :     CHECK_REQUEST(cx);
        5815              36 :     return InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
        5816                 : }
        5817                 :
        5818                 : JS_PUBLIC_API(JSBool)
        5819           38282 : JS_DecodeUTF8(JSContext *cx, const char *src, size_t srclen, jschar *dst,
        5820                 :               size_t *dstlenp)
        5821                 : {
        5822           38282 :     AssertNoGC(cx);
        5823           76564 :     CHECK_REQUEST(cx);
        5824           38282 :     return InflateUTF8StringToBuffer(cx, src, srclen, dst, dstlenp);
        5825                 : }
        5826                 :
        5827                 : JS_PUBLIC_API(char *)
        5828           49486 : JS_EncodeString(JSContext *cx, JSString *str)
        5829                 : {
        5830           49486 :     AssertNoGC(cx);
        5831           98972 :     CHECK_REQUEST(cx);
        5832                 :
        5833           49486 :     const jschar *chars = str->getChars(cx);
        5834           49486 :     if (!chars)
        5835               0 :         return NULL;
        5836           49486 :     return DeflateString(cx, chars, str->length());
        5837                 : }
        5838                 :
        5839                 : JS_PUBLIC_API(size_t)
        5840               0 : JS_GetStringEncodingLength(JSContext *cx, JSString *str)
        5841                 : {
        5842                 :     /* jsd calls us with a NULL cx. Ugh. */
        5843               0 :     if (cx) {
        5844               0 :         AssertNoGC(cx);
        5845               0 :         CHECK_REQUEST(cx);
        5846                 :     }
        5847                 :
        5848               0 :     const jschar *chars = str->getChars(cx);
        5849               0 :     if (!chars)
        5850               0 :         return size_t(-1);
        5851               0 :     return GetDeflatedStringLength(cx, chars, str->length());
        5852                 : }
        5853                 :
        5854                 : JS_PUBLIC_API(size_t)
        5855               0 : JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length)
        5856                 : {
        5857                 :     /*
        5858                 :      * FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
        5859                 :      * would allow to distinguish between insufficient buffer and encoding
        5860                 :      * error.
        5861                 :      */
        5862               0 :     size_t writtenLength = length;
        5863               0 :     const jschar *chars = str->getChars(NULL);
        5864               0 :     if (!chars)
        5865               0 :         return size_t(-1);
        5866               0 :     if (DeflateStringToBuffer(NULL, chars, str->length(), buffer, &writtenLength)) {
        5867               0 :         JS_ASSERT(writtenLength <= length);
        5868               0 :         return writtenLength;
        5869                 :     }
        5870               0 :     JS_ASSERT(writtenLength <= length);
        5871               0 :     size_t necessaryLength = GetDeflatedStringLength(NULL, chars, str->length());
        5872               0 :     if (necessaryLength == size_t(-1))
        5873               0 :         return size_t(-1);
        5874               0 :     if (writtenLength != length) {
        5875                 :         /* Make sure that the buffer contains only valid UTF-8 sequences. */
        5876               0 :         JS_ASSERT(js_CStringsAreUTF8);
        5877               0 :         PodZero(buffer + writtenLength, length - writtenLength);
        5878                 :     }
        5879               0 :     return necessaryLength;
        5880                 : }
        5881                 :
        5882                 : JS_PUBLIC_API(JSBool)
        5883               0 : JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
        5884                 :              JSONWriteCallback callback, void *data)
        5885                 : {
        5886               0 :     AssertNoGC(cx);
        5887               0 :     CHECK_REQUEST(cx);
        5888               0 :     assertSameCompartment(cx, replacer, space);
        5889               0 :     StringBuffer sb(cx);
        5890               0 :     if (!js_Stringify(cx, vp, replacer, space, sb))
        5891               0 :         return false;
        5892               0 :     if (sb.empty()) {
        5893               0 :         JSAtom *nullAtom = cx->runtime->atomState.nullAtom;
        5894               0 :         return callback(nullAtom->chars(), nullAtom->length(), data);
        5895                 :     }
        5896               0 :     return callback(sb.begin(), sb.length(), data);
        5897                 : }
        5898                 :
        5899                 : JS_PUBLIC_API(JSBool)
        5900              30 : JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, jsval *vp)
        5901                 : {
        5902              30 :     AssertNoGC(cx);
        5903              60 :     CHECK_REQUEST(cx);
        5904                 :
        5905              30 :     return ParseJSONWithReviver(cx, chars, len, NullValue(), vp);
        5906                 : }
        5907                 :
        5908                 : JS_PUBLIC_API(JSBool)
        5909               8 : JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, jsval reviver, jsval *vp)
        5910                 : {
        5911               8 :     AssertNoGC(cx);
        5912              16 :     CHECK_REQUEST(cx);
        5913                 :
        5914               8 :     return ParseJSONWithReviver(cx, chars, len, reviver, vp);
        5915                 : }
        5916                 :
        5917                 : JS_PUBLIC_API(JSBool)
        5918               9 : JS_ReadStructuredClone(JSContext *cx, const uint64_t *buf, size_t nbytes,
        5919                 :                        uint32_t version, jsval *vp,
        5920                 :                        const JSStructuredCloneCallbacks *optionalCallbacks,
        5921                 :                        void *closure)
        5922                 : {
        5923               9 :     AssertNoGC(cx);
        5924              18 :     CHECK_REQUEST(cx);
        5925                 :
        5926               9 :     if (version > JS_STRUCTURED_CLONE_VERSION) {
        5927               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_VERSION);
        5928               0 :         return false;
        5929                 :     }
        5930                 :     const JSStructuredCloneCallbacks *callbacks =
        5931                 :         optionalCallbacks ?
        5932                 :         optionalCallbacks :
        5933               9 :         cx->runtime->structuredCloneCallbacks;
        5934               9 :     return ReadStructuredClone(cx, buf, nbytes, vp, callbacks, closure);
        5935                 : }
        5936                 :
        5937                 : JS_PUBLIC_API(JSBool)
        5938              54 : JS_WriteStructuredClone(JSContext *cx, jsval v, uint64_t **bufp, size_t *nbytesp,
        5939                 :                         const JSStructuredCloneCallbacks *optionalCallbacks,
        5940                 :                         void *closure)
        5941                 : {
        5942              54 :     AssertNoGC(cx);
        5943             108 :     CHECK_REQUEST(cx);
        5944              54 :     assertSameCompartment(cx, v);
        5945                 :
        5946                 :     const JSStructuredCloneCallbacks *callbacks =
        5947                 :         optionalCallbacks ?
        5948                 :         optionalCallbacks :
        5949              54 :         cx->runtime->structuredCloneCallbacks;
        5950              54 :     return WriteStructuredClone(cx, v, (uint64_t **) bufp, nbytesp, callbacks, closure);
        5951                 : }
        5952                 :
        5953                 : JS_PUBLIC_API(JSBool)
        5954               0 : JS_StructuredClone(JSContext *cx, jsval v, jsval *vp,
        5955                 :                    const JSStructuredCloneCallbacks *optionalCallbacks,
        5956                 :                    void *closure)
        5957                 : {
        5958               0 :     AssertNoGC(cx);
        5959               0 :     CHECK_REQUEST(cx);
        5960               0 :     assertSameCompartment(cx, v);
        5961                 :
        5962                 :     const JSStructuredCloneCallbacks *callbacks =
        5963                 :         optionalCallbacks ?
        5964                 :         optionalCallbacks :
        5965               0 :         cx->runtime->structuredCloneCallbacks;
        5966               0 :     JSAutoStructuredCloneBuffer buf;
        5967               0 :     return buf.write(cx, v, callbacks, closure) &&
        5968               0 :            buf.read(cx, vp, callbacks, closure);
        5969                 : }
        5970                 :
        5971                 : void
        5972               0 : JSAutoStructuredCloneBuffer::clear()
        5973                 : {
        5974               0 :     if (data_) {
        5975               0 :         Foreground::free_(data_);
        5976               0 :         data_ = NULL;
        5977               0 :         nbytes_ = 0;
        5978               0 :         version_ = 0;
        5979                 :     }
        5980               0 : }
        5981                 :
        5982                 : void
        5983               0 : JSAutoStructuredCloneBuffer::adopt(uint64_t *data, size_t nbytes, uint32_t version)
        5984                 : {
        5985               0 :     clear();
        5986               0 :     data_ = data;
        5987               0 :     nbytes_ = nbytes;
        5988               0 :     version_ = version;
        5989               0 : }
        5990                 :
        5991                 : bool
        5992               0 : JSAutoStructuredCloneBuffer::copy(const uint64_t *srcData, size_t nbytes, uint32_t version)
        5993                 : {
        5994               0 :     uint64_t *newData = static_cast<uint64_t *>(OffTheBooks::malloc_(nbytes));
        5995               0 :     if (!newData)
        5996               0 :         return false;
        5997                 :
        5998               0 :     js_memcpy(newData, srcData, nbytes);
        5999                 :
        6000               0 :     clear();
        6001               0 :     data_ = newData;
        6002               0 :     nbytes_ = nbytes;
        6003               0 :     version_ = version;
        6004               0 :     return true;
        6005                 : }
        6006                 : void
        6007               0 : JSAutoStructuredCloneBuffer::steal(uint64_t **datap, size_t *nbytesp, uint32_t *versionp)
        6008                 : {
        6009               0 :     *datap = data_;
        6010               0 :     *nbytesp = nbytes_;
        6011               0 :     if (versionp)
        6012               0 :         *versionp = version_;
        6013                 :
        6014               0 :     data_ = NULL;
        6015               0 :     nbytes_ = 0;
        6016               0 :     version_ = 0;
        6017               0 : }
        6018                 :
        6019                 : bool
        6020               0 : JSAutoStructuredCloneBuffer::read(JSContext *cx, jsval *vp,
        6021                 :                                   const JSStructuredCloneCallbacks *optionalCallbacks,
        6022                 :                                   void *closure) const
        6023                 : {
        6024               0 :     JS_ASSERT(cx);
        6025               0 :     JS_ASSERT(data_);
        6026                 :     return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp,
        6027               0 :                                     optionalCallbacks, closure);
        6028                 : }
        6029                 :
        6030                 : bool
        6031               0 : JSAutoStructuredCloneBuffer::write(JSContext *cx, jsval v,
        6032                 :                                    const JSStructuredCloneCallbacks *optionalCallbacks,
        6033                 :                                    void *closure)
        6034                 : {
        6035               0 :     clear();
        6036                 :     bool ok = !!JS_WriteStructuredClone(cx, v, &data_, &nbytes_,
        6037               0 :                                         optionalCallbacks, closure);
        6038               0 :     if (!ok) {
        6039               0 :         data_ = NULL;
        6040               0 :         nbytes_ = 0;
        6041               0 :         version_ = JS_STRUCTURED_CLONE_VERSION;
        6042                 :     }
        6043               0 :     return ok;
        6044                 : }
        6045                 :
        6046                 : void
        6047               0 : JSAutoStructuredCloneBuffer::swap(JSAutoStructuredCloneBuffer &other)
        6048                 : {
        6049               0 :     uint64_t *data = other.data_;
        6050               0 :     size_t nbytes = other.nbytes_;
        6051               0 :     uint32_t version = other.version_;
        6052                 :
        6053               0 :     other.data_ = this->data_;
        6054               0 :     other.nbytes_ = this->nbytes_;
        6055               0 :     other.version_ = this->version_;
        6056                 :
        6057               0 :     this->data_ = data;
        6058               0 :     this->nbytes_ = nbytes;
        6059               0 :     this->version_ = version;
        6060               0 : }
        6061                 :
        6062                 : JS_PUBLIC_API(void)
        6063               0 : JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks)
        6064                 : {
        6065               0 :     rt->structuredCloneCallbacks = callbacks;
        6066               0 : }
        6067                 :
        6068                 : JS_PUBLIC_API(JSBool)
        6069               0 : JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32_t *p1, uint32_t *p2)
        6070                 : {
        6071               0 :     return r->input().readPair((uint32_t *) p1, (uint32_t *) p2);
        6072                 : }
        6073                 :
        6074                 : JS_PUBLIC_API(JSBool)
        6075               0 : JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len)
        6076                 : {
        6077               0 :     return r->input().readBytes(p, len);
        6078                 : }
        6079                 :
        6080                 : JS_PUBLIC_API(JSBool)
        6081               0 : JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32_t tag, uint32_t data)
        6082                 : {
        6083               0 :     return w->output().writePair(tag, data);
        6084                 : }
        6085                 :
        6086                 : JS_PUBLIC_API(JSBool)
        6087               0 : JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len)
        6088                 : {
        6089               0 :     return w->output().writeBytes(p, len);
        6090                 : }
        6091                 :
        6092                 : /*
        6093                 :  * The following determines whether C Strings are to be treated as UTF-8
        6094                 :  * or ISO-8859-1.  For correct operation, it must be set prior to the
        6095                 :  * first call to JS_NewRuntime.
        6096                 :  */
        6097                 : #ifndef JS_C_STRINGS_ARE_UTF8
        6098                 : JSBool js_CStringsAreUTF8 = JS_FALSE;
        6099                 : #endif
        6100                 :
        6101                 : JS_PUBLIC_API(JSBool)
        6102               0 : JS_CStringsAreUTF8()
        6103                 : {
        6104               0 :     return js_CStringsAreUTF8;
        6105                 : }
        6106                 :
        6107                 : JS_PUBLIC_API(void)
        6108               1 : JS_SetCStringsAreUTF8()
        6109                 : {
        6110               1 :     JS_ASSERT(!js_NewRuntimeWasCalled);
        6111                 :
        6112                 : #ifndef JS_C_STRINGS_ARE_UTF8
        6113               1 :     js_CStringsAreUTF8 = JS_TRUE;
        6114                 : #endif
        6115               1 : }
        6116                 :
        6117                 : /************************************************************************/
        6118                 :
        6119                 : JS_PUBLIC_API(void)
        6120               0 : JS_ReportError(JSContext *cx, const char *format, ...)
        6121                 : {
        6122                 :     va_list ap;
        6123                 :
        6124               0 :     AssertNoGC(cx);
        6125               0 :     va_start(ap, format);
        6126               0 :     js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
        6127               0 :     va_end(ap);
        6128               0 : }
        6129                 :
        6130                 : JS_PUBLIC_API(void)
        6131          471361 : JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
        6132                 :                      void *userRef, const unsigned errorNumber, ...)
        6133                 : {
        6134                 :     va_list ap;
        6135                 :
        6136          471361 :     AssertNoGC(cx);
        6137          471361 :     va_start(ap, errorNumber);
        6138                 :     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
        6139          471361 :                            errorNumber, JS_TRUE, ap);
        6140          471361 :     va_end(ap);
        6141          471361 : }
        6142                 :
        6143                 : JS_PUBLIC_API(void)
        6144               0 : JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
        6145                 :                      void *userRef, const unsigned errorNumber, ...)
        6146                 : {
        6147                 :     va_list ap;
        6148                 :
        6149               0 :     AssertNoGC(cx);
        6150               0 :     va_start(ap, errorNumber);
        6151                 :     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
        6152               0 :                            errorNumber, JS_FALSE, ap);
        6153               0 :     va_end(ap);
        6154               0 : }
        6155                 :
        6156                 : JS_PUBLIC_API(JSBool)
        6157              63 : JS_ReportWarning(JSContext *cx, const char *format, ...)
        6158                 : {
        6159                 :     va_list ap;
        6160                 :     JSBool ok;
        6161                 :
        6162              63 :     AssertNoGC(cx);
        6163              63 :     va_start(ap, format);
        6164              63 :     ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
        6165              63 :     va_end(ap);
        6166              63 :     return ok;
        6167                 : }
        6168                 :
        6169                 : JS_PUBLIC_API(JSBool)
        6170            4087 : JS_ReportErrorFlagsAndNumber(JSContext *cx, unsigned flags,
        6171                 :                              JSErrorCallback errorCallback, void *userRef,
        6172                 :                              const unsigned errorNumber, ...)
        6173                 : {
        6174                 :     va_list ap;
        6175                 :     JSBool ok;
        6176                 :
        6177            4087 :     AssertNoGC(cx);
        6178            4087 :     va_start(ap, errorNumber);
        6179                 :     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
        6180            4087 :                                 errorNumber, JS_TRUE, ap);
        6181            4087 :     va_end(ap);
        6182            4087 :     return ok;
        6183                 : }
        6184                 :
        6185                 : JS_PUBLIC_API(JSBool)
        6186              81 : JS_ReportErrorFlagsAndNumberUC(JSContext *cx, unsigned flags,
        6187                 :                                JSErrorCallback errorCallback, void *userRef,
        6188                 :                                const unsigned errorNumber, ...)
        6189                 : {
        6190                 :     va_list ap;
        6191                 :     JSBool ok;
        6192                 :
        6193              81 :     AssertNoGC(cx);
        6194              81 :     va_start(ap, errorNumber);
        6195                 :     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
        6196              81 :                                 errorNumber, JS_FALSE, ap);
        6197              81 :     va_end(ap);
        6198              81 :     return ok;
        6199                 : }
        6200                 :
        6201                 : JS_PUBLIC_API(void)
        6202               0 : JS_ReportOutOfMemory(JSContext *cx)
        6203                 : {
        6204               0 :     js_ReportOutOfMemory(cx);
        6205               0 : }
        6206                 :
        6207                 : JS_PUBLIC_API(void)
        6208               0 : JS_ReportAllocationOverflow(JSContext *cx)
        6209                 : {
        6210               0 :     js_ReportAllocationOverflow(cx);
        6211               0 : }
        6212                 :
        6213                 : JS_PUBLIC_API(JSErrorReporter)
        6214               0 : JS_GetErrorReporter(JSContext *cx)
        6215                 : {
        6216               0 :     return cx->errorReporter;
        6217                 : }
        6218                 :
        6219                 : JS_PUBLIC_API(JSErrorReporter)
        6220           42273 : JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
        6221                 : {
        6222                 :     JSErrorReporter older;
        6223                 :
        6224           42273 :     older = cx->errorReporter;
        6225           42273 :     cx->errorReporter = er;
        6226           42273 :     return older;
        6227                 : }
        6228                 :
        6229                 : /************************************************************************/
        6230                 :
        6231                 : /*
        6232                 :  * Dates.
        6233                 :  */
        6234                 : JS_PUBLIC_API(JSObject *)
        6235               0 : JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec)
        6236                 : {
        6237               0 :     AssertNoGC(cx);
        6238               0 :     CHECK_REQUEST(cx);
        6239               0 :     return js_NewDateObject(cx, year, mon, mday, hour, min, sec);
        6240                 : }
        6241                 :
        6242                 : JS_PUBLIC_API(JSObject *)
        6243               0 : JS_NewDateObjectMsec(JSContext *cx, double msec)
        6244                 : {
        6245               0 :     AssertNoGC(cx);
        6246               0 :     CHECK_REQUEST(cx);
        6247               0 :     return js_NewDateObjectMsec(cx, msec);
        6248                 : }
        6249                 :
        6250                 : JS_PUBLIC_API(JSBool)
        6251               0 : JS_ObjectIsDate(JSContext *cx, JSObject *obj)
        6252                 : {
        6253               0 :     AssertNoGC(cx);
        6254               0 :     JS_ASSERT(obj);
        6255               0 :     return obj->isDate();
        6256                 : }
        6257                 :
        6258                 : /************************************************************************/
        6259                 :
        6260                 : /*
        6261                 :  * Regular Expressions.
        6262                 :  */
        6263                 : JS_PUBLIC_API(JSObject *)
        6264               0 : JS_NewRegExpObject(JSContext *cx, JSObject *obj, char *bytes, size_t length, unsigned flags)
        6265                 : {
        6266               0 :     AssertNoGC(cx);
        6267               0 :     CHECK_REQUEST(cx);
        6268               0 :     jschar *chars = InflateString(cx, bytes, &length);
        6269               0 :     if (!chars)
        6270               0 :         return NULL;
        6271                 :
        6272               0 :     RegExpStatics *res = obj->asGlobal().getRegExpStatics();
        6273               0 :     RegExpObject *reobj = RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
        6274               0 :     cx->free_(chars);
        6275               0 :     return reobj;
        6276                 : }
        6277                 :
        6278                 : JS_PUBLIC_API(JSObject *)
        6279               0 : JS_NewUCRegExpObject(JSContext *cx, JSObject *obj, jschar *chars, size_t length, unsigned flags)
        6280                 : {
        6281               0 :     AssertNoGC(cx);
        6282               0 :     CHECK_REQUEST(cx);
        6283               0 :     RegExpStatics *res = obj->asGlobal().getRegExpStatics();
        6284               0 :     return RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
        6285                 : }
        6286                 :
        6287                 : JS_PUBLIC_API(void)
        6288               0 : JS_SetRegExpInput(JSContext *cx, JSObject *obj, JSString *input, JSBool multiline)
        6289                 : {
        6290               0 :     AssertNoGC(cx);
        6291               0 :     CHECK_REQUEST(cx);
        6292               0 :     assertSameCompartment(cx, input);
        6293                 :
        6294               0 :     obj->asGlobal().getRegExpStatics()->reset(cx, input, !!multiline);
        6295               0 : }
        6296                 :
        6297                 : JS_PUBLIC_API(void)
        6298               0 : JS_ClearRegExpStatics(JSContext *cx, JSObject *obj)
        6299                 : {
        6300               0 :     AssertNoGC(cx);
        6301               0 :     CHECK_REQUEST(cx);
        6302               0 :     JS_ASSERT(obj);
        6303                 :
        6304               0 :     obj->asGlobal().getRegExpStatics()->clear();
        6305               0 : }
        6306                 :
        6307                 : JS_PUBLIC_API(JSBool)
        6308               0 : JS_ExecuteRegExp(JSContext *cx, JSObject *obj, JSObject *reobj, jschar *chars, size_t length,
        6309                 :                  size_t *indexp, JSBool test, jsval *rval)
        6310                 : {
        6311               0 :     AssertNoGC(cx);
        6312               0 :     CHECK_REQUEST(cx);
        6313                 :
        6314               0 :     RegExpStatics *res = obj->asGlobal().getRegExpStatics();
        6315               0 :     return ExecuteRegExp(cx, res, reobj->asRegExp(), NULL, chars, length,
        6316               0 :                          indexp, test ? RegExpTest : RegExpExec, rval);
        6317                 : }
        6318                 :
        6319                 : JS_PUBLIC_API(JSObject *)
        6320               0 : JS_NewRegExpObjectNoStatics(JSContext *cx, char *bytes, size_t length, unsigned flags)
        6321                 : {
        6322               0 :     AssertNoGC(cx);
        6323               0 :     CHECK_REQUEST(cx);
        6324               0 :     jschar *chars = InflateString(cx, bytes, &length);
        6325               0 :     if (!chars)
        6326               0 :         return NULL;
        6327               0 :     RegExpObject *reobj = RegExpObject::createNoStatics(cx, chars, length, RegExpFlag(flags), NULL);
        6328               0 :     cx->free_(chars);
        6329               0 :     return reobj;
        6330                 : }
        6331                 :
        6332                 : JS_PUBLIC_API(JSObject *)
        6333               0 : JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, unsigned flags)
        6334                 : {
        6335               0 :     AssertNoGC(cx);
        6336               0 :     CHECK_REQUEST(cx);
        6337               0 :     return RegExpObject::createNoStatics(cx, chars, length, RegExpFlag(flags), NULL);
        6338                 : }
        6339                 :
        6340                 : JS_PUBLIC_API(JSBool)
        6341               0 : JS_ExecuteRegExpNoStatics(JSContext *cx, JSObject *obj, jschar *chars, size_t length,
        6342                 :                           size_t *indexp, JSBool test, jsval *rval)
        6343                 : {
        6344               0 :     AssertNoGC(cx);
        6345               0 :     CHECK_REQUEST(cx);
        6346                 :
        6347               0 :     return ExecuteRegExp(cx, NULL, obj->asRegExp(), NULL, chars, length, indexp,
        6348               0 :                          test ? RegExpTest : RegExpExec, rval);
        6349                 : }
        6350                 :
        6351                 : JS_PUBLIC_API(JSBool)
        6352               2 : JS_ObjectIsRegExp(JSContext *cx, JSObject *obj)
        6353                 : {
        6354               2 :     AssertNoGC(cx);
        6355               2 :     JS_ASSERT(obj);
        6356               2 :     return obj->isRegExp();
        6357                 : }
        6358                 :
        6359                 : JS_PUBLIC_API(unsigned)
        6360               3 : JS_GetRegExpFlags(JSContext *cx, JSObject *obj)
        6361                 : {
        6362               3 :     AssertNoGC(cx);
        6363               6 :     CHECK_REQUEST(cx);
        6364                 :
        6365               3 :     return obj->asRegExp().getFlags();
        6366                 : }
        6367                 :
        6368                 : JS_PUBLIC_API(JSString *)
        6369               1 : JS_GetRegExpSource(JSContext *cx, JSObject *obj)
        6370                 : {
        6371               1 :     AssertNoGC(cx);
        6372               2 :     CHECK_REQUEST(cx);
        6373                 :
        6374               1 :     return obj->asRegExp().getSource();
        6375                 : }
        6376                 :
        6377                 : /************************************************************************/
        6378                 :
        6379                 : JS_PUBLIC_API(void)
        6380               0 : JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
        6381                 : {
        6382               0 :     AssertNoGC(cx);
        6383               0 :     cx->localeCallbacks = callbacks;
        6384               0 : }
        6385                 :
        6386                 : JS_PUBLIC_API(JSLocaleCallbacks *)
        6387               0 : JS_GetLocaleCallbacks(JSContext *cx)
        6388                 : {
        6389                 :     /* This function can be called by a finalizer. */
        6390               0 :     return cx->localeCallbacks;
        6391                 : }
        6392                 :
        6393                 : /************************************************************************/
        6394                 :
        6395                 : JS_PUBLIC_API(JSBool)
        6396            4051 : JS_IsExceptionPending(JSContext *cx)
        6397                 : {
        6398                 :     /* This function can be called by a finalizer. */
        6399            4051 :     return (JSBool) cx->isExceptionPending();
        6400                 : }
        6401                 :
        6402                 : JS_PUBLIC_API(JSBool)
        6403           12595 : JS_GetPendingException(JSContext *cx, jsval *vp)
        6404                 : {
        6405           12595 :     AssertNoGC(cx);
        6406           25190 :     CHECK_REQUEST(cx);
        6407           12595 :     if (!cx->isExceptionPending())
        6408           11721 :         return JS_FALSE;
        6409             874 :     *vp = cx->getPendingException();
        6410             874 :     assertSameCompartment(cx, *vp);
        6411             874 :     return JS_TRUE;
        6412                 : }
        6413                 :
        6414                 : JS_PUBLIC_API(void)
        6415           11636 : JS_SetPendingException(JSContext *cx, jsval v)
        6416                 : {
        6417           11636 :     AssertNoGC(cx);
        6418           23272 :     CHECK_REQUEST(cx);
        6419           11636 :     assertSameCompartment(cx, v);
        6420           11636 :     cx->setPendingException(v);
        6421           11636 : }
        6422                 :
        6423                 : JS_PUBLIC_API(void)
        6424           13295 : JS_ClearPendingException(JSContext *cx)
        6425                 : {
        6426           13295 :     AssertNoGC(cx);
        6427           13295 :     cx->clearPendingException();
        6428           13295 : }
        6429                 :
        6430                 : JS_PUBLIC_API(JSBool)
        6431              31 : JS_ReportPendingException(JSContext *cx)
        6432                 : {
        6433              31 :     AssertNoGC(cx);
        6434              62 :     CHECK_REQUEST(cx);
        6435                 :
        6436              31 :     return js_ReportUncaughtException(cx);
        6437                 : }
        6438                 :
        6439                 : struct JSExceptionState {
        6440                 :     JSBool throwing;
        6441                 :     jsval  exception;
        6442                 : };
        6443                 :
        6444                 : JS_PUBLIC_API(JSExceptionState *)
        6445           11745 : JS_SaveExceptionState(JSContext *cx)
        6446                 : {
        6447                 :     JSExceptionState *state;
        6448                 :
        6449           11745 :     AssertNoGC(cx);
        6450           23490 :     CHECK_REQUEST(cx);
        6451           11745 :     state = (JSExceptionState *) cx->malloc_(sizeof(JSExceptionState));
        6452           11745 :     if (state) {
        6453           11745 :         state->throwing = JS_GetPendingException(cx, &state->exception);
        6454           11745 :         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
        6455               0 :             js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
        6456                 :     }
        6457           11745 :     return state;
        6458                 : }
        6459                 :
        6460                 : JS_PUBLIC_API(void)
        6461           11745 : JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
        6462                 : {
        6463           11745 :     AssertNoGC(cx);
        6464           23490 :     CHECK_REQUEST(cx);
        6465           11745 :     if (state) {
        6466           11745 :         if (state->throwing)
        6467              24 :             JS_SetPendingException(cx, state->exception);
        6468                 :         else
        6469           11721 :             JS_ClearPendingException(cx);
        6470           11745 :         JS_DropExceptionState(cx, state);
        6471                 :     }
        6472           11745 : }
        6473                 :
        6474                 : JS_PUBLIC_API(void)
        6475           11745 : JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
        6476                 : {
        6477           11745 :     AssertNoGC(cx);
        6478           23490 :     CHECK_REQUEST(cx);
        6479           11745 :     if (state) {
        6480           11745 :         if (state->throwing && JSVAL_IS_GCTHING(state->exception)) {
        6481               0 :             assertSameCompartment(cx, state->exception);
        6482               0 :             JS_RemoveValueRoot(cx, &state->exception);
        6483                 :         }
        6484           11745 :         cx->free_(state);
        6485                 :     }
        6486           11745 : }
        6487                 :
        6488                 : JS_PUBLIC_API(JSErrorReport *)
        6489               0 : JS_ErrorFromException(JSContext *cx, jsval v)
        6490                 : {
        6491               0 :     AssertNoGC(cx);
        6492               0 :     CHECK_REQUEST(cx);
        6493               0 :     assertSameCompartment(cx, v);
        6494               0 :     return js_ErrorFromException(cx, v);
        6495                 : }
        6496                 :
        6497                 : JS_PUBLIC_API(JSBool)
        6498               0 : JS_ThrowReportedError(JSContext *cx, const char *message,
        6499                 :                       JSErrorReport *reportp)
        6500                 : {
        6501               0 :     AssertNoGC(cx);
        6502               0 :     return JS_IsRunning(cx) &&
        6503               0 :            js_ErrorToException(cx, message, reportp, NULL, NULL);
        6504                 : }
        6505                 :
        6506                 : JS_PUBLIC_API(JSBool)
        6507               1 : JS_ThrowStopIteration(JSContext *cx)
        6508                 : {
        6509               1 :     AssertNoGC(cx);
        6510               1 :     return js_ThrowStopIteration(cx);
        6511                 : }
        6512                 :
        6513                 : JS_PUBLIC_API(intptr_t)
        6514               0 : JS_GetCurrentThread()
        6515                 : {
        6516                 : #ifdef JS_THREADSAFE
        6517               0 :     return reinterpret_cast<intptr_t>(PR_GetCurrentThread());
        6518                 : #else
        6519                 :     return 0;
        6520                 : #endif
        6521                 : }
        6522                 :
        6523                 : extern JS_PUBLIC_API(void)
        6524               0 : JS_ClearRuntimeThread(JSRuntime *rt)
        6525                 : {
        6526               0 :     AssertNoGC(rt);
        6527                 : #ifdef JS_THREADSAFE
        6528               0 :     rt->clearOwnerThread();
        6529                 : #endif
        6530               0 : }
        6531                 :
        6532                 : extern JS_PUBLIC_API(void)
        6533               0 : JS_SetRuntimeThread(JSRuntime *rt)
        6534                 : {
        6535               0 :     AssertNoGC(rt);
        6536                 : #ifdef JS_THREADSAFE
        6537               0 :     rt->setOwnerThread();
        6538                 : #endif
        6539               0 : }
        6540                 :
        6541                 : extern JS_NEVER_INLINE JS_PUBLIC_API(void)
        6542           98547 : JS_AbortIfWrongThread(JSRuntime *rt)
        6543                 : {
        6544                 : #ifdef JS_THREADSAFE
        6545           98547 :     if (!rt->onOwnerThread())
        6546               0 :         MOZ_Assert("rt->onOwnerThread()", __FILE__, __LINE__);
        6547                 : #endif
        6548           98547 : }
        6549                 :
        6550                 : #ifdef JS_GC_ZEAL
        6551                 : JS_PUBLIC_API(void)
        6552            1647 : JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency)
        6553                 : {
        6554                 : #ifdef JS_GC_ZEAL
        6555            1647 :     const char *env = getenv("JS_GC_ZEAL");
        6556            1647 :     if (env) {
        6557               0 :         zeal = atoi(env);
        6558               0 :         frequency = 1;
        6559                 :     }
        6560                 : #endif
        6561                 :
        6562            1647 :     bool schedule = zeal >= js::gc::ZealAllocValue;
        6563            1647 :     cx->runtime->gcZeal_ = zeal;
        6564            1647 :     cx->runtime->gcZealFrequency = frequency;
        6565            1647 :     cx->runtime->gcNextScheduled = schedule ? frequency : 0;
        6566            1647 : }
        6567                 :
        6568                 : JS_PUBLIC_API(void)
        6569              54 : JS_ScheduleGC(JSContext *cx, uint32_t count)
        6570                 : {
        6571              54 :     cx->runtime->gcNextScheduled = count;
        6572              54 : }
        6573                 : #endif
        6574                 :
        6575                 : /************************************************************************/
        6576                 :
        6577                 : #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN)
        6578                 :
        6579                 : #include "jswin.h"
        6580                 :
        6581                 : /*
        6582                 :  * Initialization routine for the JS DLL.
        6583                 :  */
        6584                 : BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
        6585                 : {
        6586                 :     return TRUE;
        6587                 : }
        6588                 :
        6589                 : #endif
        6590                 :
        6591                 : JS_PUBLIC_API(JSBool)
        6592               0 : JS_IndexToId(JSContext *cx, uint32_t index, jsid *id)
        6593                 : {
        6594               0 :     return IndexToId(cx, index, id);
        6595                 : }
        6596                 :
        6597                 : JS_PUBLIC_API(JSBool)
        6598               0 : JS_IsIdentifier(JSContext *cx, JSString *str, JSBool *isIdentifier)
        6599                 : {
        6600               0 :     assertSameCompartment(cx, str);
        6601                 :
        6602               0 :     JSLinearString* linearStr = str->ensureLinear(cx);
        6603               0 :     if (!linearStr)
        6604               0 :         return false;
        6605                 :
        6606               0 :     *isIdentifier = js::IsIdentifier(linearStr);
        6607               0 :     return true;
        6608                 : }
        6609                 :
        6610                 : JS_PUBLIC_API(JSBool)
        6611             577 : JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno)
        6612                 : {
        6613             577 :     if (script)
        6614             577 :         *script = NULL;
        6615             577 :     if (lineno)
        6616             153 :         *lineno = 0;
        6617                 :
        6618             577 :     FrameRegsIter i(cx);
        6619             577 :     if (i.done())
        6620               0 :         return JS_FALSE;
        6621                 :
        6622             577 :     if (script)
        6623             577 :         *script = i.script();
        6624             577 :     if (lineno)
        6625             153 :         *lineno = js::PCToLineNumber(i.script(), i.pc());
        6626             577 :     return JS_TRUE;
        6627                 : }
        6628                 :
        6629                 : #ifdef JS_THREADSAFE
        6630                 : static PRStatus
        6631           18667 : CallOnce(void *func)
        6632                 : {
        6633           18667 :     JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
        6634           18667 :     return init() ? PR_SUCCESS : PR_FAILURE;
        6635                 : }
        6636                 : #endif
        6637                 :
        6638                 : JS_PUBLIC_API(JSBool)
        6639           18761 : JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
        6640                 : {
        6641                 : #ifdef JS_THREADSAFE
        6642           18761 :     return PR_CallOnceWithArg(once, CallOnce, JS_FUNC_TO_DATA_PTR(void *, func)) == PR_SUCCESS;
        6643                 : #else
        6644                 :     if (!*once) {
        6645                 :         *once = true;
        6646                 :         return func();
        6647                 :     } else {
        6648                 :         return JS_TRUE;
        6649                 :     }
        6650                 : #endif
        6651                 : }
        6652                 :
        6653                 : namespace JS {
        6654                 :
        6655        16498149 : AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
        6656        16498149 :   : down(cx->runtime->autoGCRooters), tag(tag), stackTop(&cx->runtime->autoGCRooters)
        6657                 : {
        6658        16498149 :     JS_ASSERT(this != *stackTop);
        6659        16498149 :     *stackTop = this;
        6660        16498149 : }
        6661                 :
        6662               0 : AutoEnumStateRooter::~AutoEnumStateRooter()
        6663                 : {
        6664               0 :     if (!stateValue.isNull())
        6665               0 :         MOZ_ALWAYS_TRUE(obj->enumerate(context, JSENUMERATE_DESTROY, &stateValue, 0));
        6666               0 : }
        6667                 :
        6668                 : #ifdef DEBUG
        6669                 : JS_PUBLIC_API(void)
        6670       187664031 : AssertArgumentsAreSane(JSContext *cx, const JS::Value &v)
        6671                 : {
        6672       187664031 :     AssertNoGC(cx);
        6673       375328062 :     CHECK_REQUEST(cx);
        6674       187664031 :     assertSameCompartment(cx, v);
        6675       187664031 : }
        6676                 : #endif /* DEBUG */
        6677                 :
        6678                 : } // namespace JS
        6679                 :
        6680                 : JS_PUBLIC_API(void *)
        6681              15 : JS_EncodeScript(JSContext *cx, JSScript *script, uint32_t *lengthp)
        6682                 : {
        6683              30 :     XDREncoder encoder(cx);
        6684              15 :     if (!encoder.codeScript(&script))
        6685               0 :         return NULL;
        6686              15 :     return encoder.forgetData(lengthp);
        6687                 : }
        6688                 :
        6689                 : JS_PUBLIC_API(void *)
        6690               6 : JS_EncodeInterpretedFunction(JSContext *cx, JSObject *funobj, uint32_t *lengthp)
        6691                 : {
        6692              12 :     XDREncoder encoder(cx);
        6693               6 :     if (!encoder.codeFunction(&funobj))
        6694               0 :         return NULL;
        6695               6 :     return encoder.forgetData(lengthp);
        6696                 : }
        6697                 :
        6698                 : JS_PUBLIC_API(JSScript *)
        6699              15 : JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
        6700                 :                 JSPrincipals *principals, JSPrincipals *originPrincipals)
        6701                 : {
        6702              15 :     XDRDecoder decoder(cx, data, length, principals, originPrincipals);
        6703                 :     JSScript *script;
        6704              15 :     if (!decoder.codeScript(&script))
        6705               0 :         return NULL;
        6706              15 :     return script;
        6707                 : }
        6708                 :
        6709                 : JS_PUBLIC_API(JSObject *)
        6710               6 : JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
        6711                 :                              JSPrincipals *principals, JSPrincipals *originPrincipals)
        6712                 : {
        6713               6 :     XDRDecoder decoder(cx, data, length, principals, originPrincipals);
        6714                 :     JSObject *funobj;
        6715               6 :     if (!decoder.codeFunction(&funobj))
        6716               0 :         return NULL;
        6717               6 :     return funobj;
        6718           56001 : }

Generated by: LCOV version 1.7