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: | 3041 | 1874 | 61.6 %
| Date: | 2012-04-21 | Functions: | 463 | 321 | 69.3 %

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

Generated by: LCOV version 1.7