LCOV - code coverage report
Current view: directory - js/src - jsapi.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 3041 1872 61.6 %
Date: 2012-06-02 Functions: 463 321 69.3 %

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

Generated by: LCOV version 1.7