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

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

Generated by: LCOV version 1.7