js/src/jsapi.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /*
     8  * JavaScript API.
     9  */
    11 #include "jsapi.h"
    13 #include "mozilla/FloatingPoint.h"
    14 #include "mozilla/PodOperations.h"
    16 #include <ctype.h>
    17 #include <stdarg.h>
    18 #include <string.h>
    19 #include <sys/stat.h>
    21 #include "jsarray.h"
    22 #include "jsatom.h"
    23 #include "jsbool.h"
    24 #include "jscntxt.h"
    25 #include "jsdate.h"
    26 #include "jsexn.h"
    27 #include "jsfun.h"
    28 #include "jsgc.h"
    29 #include "jsiter.h"
    30 #include "jslock.h"
    31 #include "jsmath.h"
    32 #include "jsnum.h"
    33 #include "jsobj.h"
    34 #include "json.h"
    35 #include "jsprf.h"
    36 #include "jsproxy.h"
    37 #include "jsscript.h"
    38 #include "jsstr.h"
    39 #include "jstypes.h"
    40 #include "jsutil.h"
    41 #include "jswatchpoint.h"
    42 #include "jsweakmap.h"
    43 #ifdef JS_THREADSAFE
    44 #include "jsworkers.h"
    45 #endif
    46 #include "jswrapper.h"
    47 #include "prmjtime.h"
    49 #if ENABLE_YARR_JIT
    50 #include "assembler/jit/ExecutableAllocator.h"
    51 #endif
    52 #include "builtin/Eval.h"
    53 #include "builtin/Intl.h"
    54 #include "builtin/MapObject.h"
    55 #include "builtin/RegExp.h"
    56 #ifdef ENABLE_BINARYDATA
    57 #include "builtin/SIMD.h"
    58 #include "builtin/TypedObject.h"
    59 #endif
    60 #include "frontend/BytecodeCompiler.h"
    61 #include "frontend/FullParseHandler.h"  // for JS_BufferIsCompileableUnit
    62 #include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
    63 #include "gc/Marking.h"
    64 #include "jit/AsmJSLink.h"
    65 #include "jit/JitCommon.h"
    66 #include "js/CharacterEncoding.h"
    67 #include "js/SliceBudget.h"
    68 #include "js/StructuredClone.h"
    69 #if ENABLE_INTL_API
    70 #include "unicode/uclean.h"
    71 #include "unicode/utypes.h"
    72 #endif // ENABLE_INTL_API
    73 #include "vm/DateObject.h"
    74 #include "vm/Debugger.h"
    75 #include "vm/ErrorObject.h"
    76 #include "vm/Interpreter.h"
    77 #include "vm/NumericConversions.h"
    78 #include "vm/RegExpStatics.h"
    79 #include "vm/Runtime.h"
    80 #include "vm/Shape.h"
    81 #include "vm/SharedArrayObject.h"
    82 #include "vm/StopIterationObject.h"
    83 #include "vm/StringBuffer.h"
    84 #include "vm/TypedArrayObject.h"
    85 #include "vm/WeakMapObject.h"
    86 #include "vm/WrapperObject.h"
    87 #include "vm/Xdr.h"
    88 #include "yarr/BumpPointerAllocator.h"
    90 #include "jsatominlines.h"
    91 #include "jsfuninlines.h"
    92 #include "jsinferinlines.h"
    93 #include "jsscriptinlines.h"
    95 #include "vm/Interpreter-inl.h"
    96 #include "vm/ObjectImpl-inl.h"
    97 #include "vm/String-inl.h"
    99 using namespace js;
   100 using namespace js::gc;
   101 using namespace js::types;
   103 using mozilla::Maybe;
   104 using mozilla::PodCopy;
   105 using mozilla::PodZero;
   107 using js::frontend::Parser;
   109 #ifdef HAVE_VA_LIST_AS_ARRAY
   110 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
   111 #else
   112 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
   113 #endif
   115 /* Make sure that jschar is two bytes unsigned integer */
   116 JS_STATIC_ASSERT((jschar)-1 > 0);
   117 JS_STATIC_ASSERT(sizeof(jschar) == 2);
   119 JS_PUBLIC_API(int64_t)
   120 JS_Now()
   121 {
   122     return PRMJ_Now();
   123 }
   125 JS_PUBLIC_API(jsval)
   126 JS_GetNaNValue(JSContext *cx)
   127 {
   128     return cx->runtime()->NaNValue;
   129 }
   131 JS_PUBLIC_API(jsval)
   132 JS_GetNegativeInfinityValue(JSContext *cx)
   133 {
   134     return cx->runtime()->negativeInfinityValue;
   135 }
   137 JS_PUBLIC_API(jsval)
   138 JS_GetPositiveInfinityValue(JSContext *cx)
   139 {
   140     return cx->runtime()->positiveInfinityValue;
   141 }
   143 JS_PUBLIC_API(jsval)
   144 JS_GetEmptyStringValue(JSContext *cx)
   145 {
   146     return STRING_TO_JSVAL(cx->runtime()->emptyString);
   147 }
   149 JS_PUBLIC_API(JSString *)
   150 JS_GetEmptyString(JSRuntime *rt)
   151 {
   152     JS_ASSERT(rt->hasContexts());
   153     return rt->emptyString;
   154 }
   156 namespace js {
   158 void
   159 AssertHeapIsIdle(JSRuntime *rt)
   160 {
   161     JS_ASSERT(rt->heapState == js::Idle);
   162 }
   164 void
   165 AssertHeapIsIdle(JSContext *cx)
   166 {
   167     AssertHeapIsIdle(cx->runtime());
   168 }
   170 }
   172 static void
   173 AssertHeapIsIdleOrIterating(JSRuntime *rt)
   174 {
   175     JS_ASSERT(!rt->isHeapCollecting());
   176 }
   178 static void
   179 AssertHeapIsIdleOrIterating(JSContext *cx)
   180 {
   181     AssertHeapIsIdleOrIterating(cx->runtime());
   182 }
   184 static void
   185 AssertHeapIsIdleOrStringIsFlat(JSContext *cx, JSString *str)
   186 {
   187     /*
   188      * We allow some functions to be called during a GC as long as the argument
   189      * is a flat string, since that will not cause allocation.
   190      */
   191     JS_ASSERT_IF(cx->runtime()->isHeapBusy(), str->isFlat());
   192 }
   194 JS_PUBLIC_API(bool)
   195 JS_ConvertArguments(JSContext *cx, const CallArgs &args, const char *format, ...)
   196 {
   197     va_list ap;
   198     bool ok;
   200     AssertHeapIsIdle(cx);
   202     va_start(ap, format);
   203     ok = JS_ConvertArgumentsVA(cx, args, format, ap);
   204     va_end(ap);
   205     return ok;
   206 }
   208 JS_PUBLIC_API(bool)
   209 JS_ConvertArgumentsVA(JSContext *cx, const CallArgs &args, const char *format, va_list ap)
   210 {
   211     unsigned index = 0;
   212     bool required;
   213     char c;
   214     double d;
   215     JSString *str;
   216     RootedObject obj(cx);
   217     RootedValue val(cx);
   219     AssertHeapIsIdle(cx);
   220     CHECK_REQUEST(cx);
   221     assertSameCompartment(cx, args);
   222     required = true;
   223     while ((c = *format++) != '\0') {
   224         if (isspace(c))
   225             continue;
   226         if (c == '/') {
   227             required = false;
   228             continue;
   229         }
   230         if (index == args.length()) {
   231             if (required) {
   232                 if (JSFunction *fun = ReportIfNotFunction(cx, args.calleev())) {
   233                     char numBuf[12];
   234                     JS_snprintf(numBuf, sizeof numBuf, "%u", args.length());
   235                     JSAutoByteString funNameBytes;
   236                     if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
   237                         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
   238                                              JSMSG_MORE_ARGS_NEEDED,
   239                                              name, numBuf, (args.length() == 1) ? "" : "s");
   240                     }
   241                 }
   242                 return false;
   243             }
   244             break;
   245         }
   246         MutableHandleValue arg = args[index++];
   247         switch (c) {
   248           case 'b':
   249             *va_arg(ap, bool *) = ToBoolean(arg);
   250             break;
   251           case 'c':
   252             if (!ToUint16(cx, arg, va_arg(ap, uint16_t *)))
   253                 return false;
   254             break;
   255           case 'i':
   256           case 'j': // "j" was broken, you should not use it.
   257             if (!ToInt32(cx, arg, va_arg(ap, int32_t *)))
   258                 return false;
   259             break;
   260           case 'u':
   261             if (!ToUint32(cx, arg, va_arg(ap, uint32_t *)))
   262                 return false;
   263             break;
   264           case 'd':
   265             if (!ToNumber(cx, arg, va_arg(ap, double *)))
   266                 return false;
   267             break;
   268           case 'I':
   269             if (!ToNumber(cx, arg, &d))
   270                 return false;
   271             *va_arg(ap, double *) = ToInteger(d);
   272             break;
   273           case 'S':
   274           case 'W':
   275             str = ToString<CanGC>(cx, arg);
   276             if (!str)
   277                 return false;
   278             arg.setString(str);
   279             if (c == 'W') {
   280                 JSFlatString *flat = str->ensureFlat(cx);
   281                 if (!flat)
   282                     return false;
   283                 *va_arg(ap, const jschar **) = flat->chars();
   284             } else {
   285                 *va_arg(ap, JSString **) = str;
   286             }
   287             break;
   288           case 'o':
   289             if (arg.isNullOrUndefined()) {
   290                 obj = nullptr;
   291             } else {
   292                 obj = ToObject(cx, arg);
   293                 if (!obj)
   294                     return false;
   295             }
   296             arg.setObjectOrNull(obj);
   297             *va_arg(ap, JSObject **) = obj;
   298             break;
   299           case 'f':
   300             obj = ReportIfNotFunction(cx, arg);
   301             if (!obj)
   302                 return false;
   303             arg.setObject(*obj);
   304             *va_arg(ap, JSFunction **) = &obj->as<JSFunction>();
   305             break;
   306           case 'v':
   307             *va_arg(ap, jsval *) = arg;
   308             break;
   309           case '*':
   310             break;
   311           default:
   312             JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_CHAR, format);
   313             return false;
   314         }
   315     }
   316     return true;
   317 }
   319 JS_PUBLIC_API(bool)
   320 JS_ConvertValue(JSContext *cx, HandleValue value, JSType type, MutableHandleValue vp)
   321 {
   322     bool ok;
   323     RootedObject obj(cx);
   324     JSString *str;
   325     double d;
   327     AssertHeapIsIdle(cx);
   328     CHECK_REQUEST(cx);
   329     assertSameCompartment(cx, value);
   330     switch (type) {
   331       case JSTYPE_VOID:
   332         vp.setUndefined();
   333         ok = true;
   334         break;
   335       case JSTYPE_OBJECT:
   336         if (value.isNullOrUndefined()) {
   337             obj.set(nullptr);
   338         } else {
   339             obj = ToObject(cx, value);
   340             if (!obj)
   341                 return false;
   342         }
   343         ok = true;
   344         break;
   345       case JSTYPE_FUNCTION:
   346         vp.set(value);
   347         obj = ReportIfNotFunction(cx, vp);
   348         ok = (obj != nullptr);
   349         break;
   350       case JSTYPE_STRING:
   351         str = ToString<CanGC>(cx, value);
   352         ok = (str != nullptr);
   353         if (ok)
   354             vp.setString(str);
   355         break;
   356       case JSTYPE_NUMBER:
   357         ok = ToNumber(cx, value, &d);
   358         if (ok)
   359             vp.setDouble(d);
   360         break;
   361       case JSTYPE_BOOLEAN:
   362         vp.setBoolean(ToBoolean(value));
   363         return true;
   364       default: {
   365         char numBuf[12];
   366         JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
   367         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_TYPE, numBuf);
   368         ok = false;
   369         break;
   370       }
   371     }
   372     return ok;
   373 }
   375 JS_PUBLIC_API(bool)
   376 JS_ValueToObject(JSContext *cx, HandleValue value, MutableHandleObject objp)
   377 {
   378     AssertHeapIsIdle(cx);
   379     CHECK_REQUEST(cx);
   380     assertSameCompartment(cx, value);
   381     if (value.isNullOrUndefined()) {
   382         objp.set(nullptr);
   383         return true;
   384     }
   385     JSObject *obj = ToObject(cx, value);
   386     if (!obj)
   387         return false;
   388     objp.set(obj);
   389     return true;
   390 }
   392 JS_PUBLIC_API(JSFunction *)
   393 JS_ValueToFunction(JSContext *cx, HandleValue value)
   394 {
   395     AssertHeapIsIdle(cx);
   396     CHECK_REQUEST(cx);
   397     assertSameCompartment(cx, value);
   398     return ReportIfNotFunction(cx, value);
   399 }
   401 JS_PUBLIC_API(JSFunction *)
   402 JS_ValueToConstructor(JSContext *cx, HandleValue value)
   403 {
   404     AssertHeapIsIdle(cx);
   405     CHECK_REQUEST(cx);
   406     assertSameCompartment(cx, value);
   407     return ReportIfNotFunction(cx, value);
   408 }
   410 JS_PUBLIC_API(JSString *)
   411 JS_ValueToSource(JSContext *cx, HandleValue value)
   412 {
   413     AssertHeapIsIdle(cx);
   414     CHECK_REQUEST(cx);
   415     assertSameCompartment(cx, value);
   416     return ValueToSource(cx, value);
   417 }
   419 JS_PUBLIC_API(bool)
   420 JS_DoubleIsInt32(double d, int32_t *ip)
   421 {
   422     return mozilla::NumberIsInt32(d, ip);
   423 }
   425 JS_PUBLIC_API(int32_t)
   426 JS_DoubleToInt32(double d)
   427 {
   428     return ToInt32(d);
   429 }
   431 JS_PUBLIC_API(uint32_t)
   432 JS_DoubleToUint32(double d)
   433 {
   434     return ToUint32(d);
   435 }
   437 JS_PUBLIC_API(JSType)
   438 JS_TypeOfValue(JSContext *cx, HandleValue value)
   439 {
   440     AssertHeapIsIdle(cx);
   441     CHECK_REQUEST(cx);
   442     assertSameCompartment(cx, value);
   443     return TypeOfValue(value);
   444 }
   446 JS_PUBLIC_API(const char *)
   447 JS_GetTypeName(JSContext *cx, JSType type)
   448 {
   449     if ((unsigned)type >= (unsigned)JSTYPE_LIMIT)
   450         return nullptr;
   451     return TypeStrings[type];
   452 }
   454 JS_PUBLIC_API(bool)
   455 JS_StrictlyEqual(JSContext *cx, jsval value1, jsval value2, bool *equal)
   456 {
   457     AssertHeapIsIdle(cx);
   458     CHECK_REQUEST(cx);
   459     assertSameCompartment(cx, value1, value2);
   460     bool eq;
   461     if (!StrictlyEqual(cx, value1, value2, &eq))
   462         return false;
   463     *equal = eq;
   464     return true;
   465 }
   467 JS_PUBLIC_API(bool)
   468 JS_LooselyEqual(JSContext *cx, HandleValue value1, HandleValue value2, bool *equal)
   469 {
   470     AssertHeapIsIdle(cx);
   471     CHECK_REQUEST(cx);
   472     assertSameCompartment(cx, value1, value2);
   473     JS_ASSERT(equal);
   474     return LooselyEqual(cx, value1, value2, equal);
   475 }
   477 JS_PUBLIC_API(bool)
   478 JS_SameValue(JSContext *cx, jsval value1, jsval value2, bool *same)
   479 {
   480     AssertHeapIsIdle(cx);
   481     CHECK_REQUEST(cx);
   482     assertSameCompartment(cx, value1, value2);
   483     bool s;
   484     if (!SameValue(cx, value1, value2, &s))
   485         return false;
   486     *same = s;
   487     return true;
   488 }
   490 JS_PUBLIC_API(bool)
   491 JS_IsBuiltinEvalFunction(JSFunction *fun)
   492 {
   493     return IsAnyBuiltinEval(fun);
   494 }
   496 JS_PUBLIC_API(bool)
   497 JS_IsBuiltinFunctionConstructor(JSFunction *fun)
   498 {
   499     return fun->isBuiltinFunctionConstructor();
   500 }
   502 /************************************************************************/
   504 /*
   505  * SpiderMonkey's initialization status is tracked here, and it controls things
   506  * that should happen only once across all runtimes.  It's an API requirement
   507  * that JS_Init (and JS_ShutDown, if called) be called in a thread-aware
   508  * manner, so this variable doesn't need to be atomic.
   509  *
   510  * The only reason at present for the restriction that you can't call
   511  * JS_Init/stuff/JS_ShutDown multiple times is the Windows PRMJ NowInit
   512  * initialization code, which uses PR_CallOnce to initialize the PRMJ_Now
   513  * subsystem.  (For reinitialization to be permitted, we'd need to "reset" the
   514  * called-once status -- doable, but more trouble than it's worth now.)
   515  * Initializing that subsystem from JS_Init eliminates the problem, but
   516  * initialization can take a comparatively long time (15ms or so), so we
   517  * really don't want to do it in JS_Init, and we really do want to do it only
   518  * when PRMJ_Now is eventually called.
   519  */
   520 enum InitState { Uninitialized, Running, ShutDown };
   521 static InitState jsInitState = Uninitialized;
   523 #ifdef DEBUG
   524 static void
   525 CheckMessageNumbering()
   526 {
   527     // Assert that the numbers associated with the error names in js.msg are
   528     // monotonically increasing.  It's not a compile-time check, but it's
   529     // better than nothing.
   530     int errorNumber = 0;
   531 # define MSG_DEF(name, number, count, exception, format)                      \
   532     JS_ASSERT(name == errorNumber++);
   533 # include "js.msg"
   534 # undef MSG_DEF
   535 }
   537 static unsigned
   538 MessageParameterCount(const char *format)
   539 {
   540     unsigned numfmtspecs = 0;
   541     for (const char *fmt = format; *fmt != '\0'; fmt++) {
   542         if (*fmt == '{' && isdigit(fmt[1]))
   543             ++numfmtspecs;
   544     }
   545     return numfmtspecs;
   546 }
   548 static void
   549 CheckMessageParameterCounts()
   550 {
   551     // Assert that each message format has the correct number of braced
   552     // parameters.
   553 # define MSG_DEF(name, number, count, exception, format)                      \
   554     JS_BEGIN_MACRO                                                            \
   555         JS_ASSERT(MessageParameterCount(format) == count);                    \
   556     JS_END_MACRO;
   557 # include "js.msg"
   558 # undef MSG_DEF
   559 }
   560 #endif /* DEBUG */
   562 JS_PUBLIC_API(bool)
   563 JS_Init(void)
   564 {
   565     MOZ_ASSERT(jsInitState == Uninitialized,
   566                "must call JS_Init once before any JSAPI operation except "
   567                "JS_SetICUMemoryFunctions");
   568     MOZ_ASSERT(!JSRuntime::hasLiveRuntimes(),
   569                "how do we have live runtimes before JS_Init?");
   571 #ifdef DEBUG
   572     CheckMessageNumbering();
   573     CheckMessageParameterCounts();
   574 #endif
   576     using js::TlsPerThreadData;
   577     if (!TlsPerThreadData.initialized() && !TlsPerThreadData.init())
   578         return false;
   580 #if defined(JS_ION)
   581     if (!jit::InitializeIon())
   582         return false;
   583 #endif
   585     if (!ForkJoinContext::initialize())
   586         return false;
   588 #if EXPOSE_INTL_API
   589     UErrorCode err = U_ZERO_ERROR;
   590     u_init(&err);
   591     if (U_FAILURE(err))
   592         return false;
   593 #endif // EXPOSE_INTL_API
   595     jsInitState = Running;
   596     return true;
   597 }
   599 JS_PUBLIC_API(void)
   600 JS_ShutDown(void)
   601 {
   602     MOZ_ASSERT(jsInitState == Running,
   603                "JS_ShutDown must only be called after JS_Init and can't race with it");
   604 #ifdef DEBUG
   605     if (JSRuntime::hasLiveRuntimes()) {
   606         // Gecko is too buggy to assert this just yet.
   607         fprintf(stderr,
   608                 "WARNING: YOU ARE LEAKING THE WORLD (at least one JSRuntime "
   609                 "and everything alive inside it, that is) AT JS_ShutDown "
   610                 "TIME.  FIX THIS!\n");
   611     }
   612 #endif
   614 #ifdef JS_THREADSAFE
   615     WorkerThreadState().finish();
   616 #endif
   618     PRMJ_NowShutdown();
   620 #if EXPOSE_INTL_API
   621     u_cleanup();
   622 #endif // EXPOSE_INTL_API
   624     jsInitState = ShutDown;
   625 }
   627 #ifdef DEBUG
   628 JS_FRIEND_API(bool)
   629 JS::isGCEnabled()
   630 {
   631     return !TlsPerThreadData.get()->suppressGC;
   632 }
   633 #else
   634 JS_FRIEND_API(bool) JS::isGCEnabled() { return true; }
   635 #endif
   637 JS_PUBLIC_API(JSRuntime *)
   638 JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads, JSRuntime *parentRuntime)
   639 {
   640     MOZ_ASSERT(jsInitState == Running,
   641                "must call JS_Init prior to creating any JSRuntimes");
   643     // Any parent runtime should be the topmost parent. This assert
   644     // isn't required for correctness, but ensuring that the parent
   645     // runtime is not destroyed before this one is more easily done
   646     // for the main runtime in the process.
   647     JS_ASSERT_IF(parentRuntime, !parentRuntime->parentRuntime);
   649     JSRuntime *rt = js_new<JSRuntime>(parentRuntime, useHelperThreads);
   650     if (!rt)
   651         return nullptr;
   653     if (!rt->init(maxbytes)) {
   654         JS_DestroyRuntime(rt);
   655         return nullptr;
   656     }
   658     return rt;
   659 }
   661 JS_PUBLIC_API(void)
   662 JS_DestroyRuntime(JSRuntime *rt)
   663 {
   664     js_delete(rt);
   665 }
   667 JS_PUBLIC_API(bool)
   668 JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn)
   669 {
   670     MOZ_ASSERT(jsInitState == Uninitialized,
   671                "must call JS_SetICUMemoryFunctions before any other JSAPI "
   672                "operation (including JS_Init)");
   674 #if EXPOSE_INTL_API
   675     UErrorCode status = U_ZERO_ERROR;
   676     u_setMemoryFunctions(/* context = */ nullptr, allocFn, reallocFn, freeFn, &status);
   677     return U_SUCCESS(status);
   678 #else
   679     return true;
   680 #endif
   681 }
   683 JS_PUBLIC_API(void *)
   684 JS_GetRuntimePrivate(JSRuntime *rt)
   685 {
   686     return rt->data;
   687 }
   689 JS_PUBLIC_API(void)
   690 JS_SetRuntimePrivate(JSRuntime *rt, void *data)
   691 {
   692     rt->data = data;
   693 }
   695 #ifdef JS_THREADSAFE
   696 static void
   697 StartRequest(JSContext *cx)
   698 {
   699     JSRuntime *rt = cx->runtime();
   700     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
   702     if (rt->requestDepth) {
   703         rt->requestDepth++;
   704     } else {
   705         /* Indicate that a request is running. */
   706         rt->requestDepth = 1;
   707         rt->triggerActivityCallback(true);
   708     }
   709 }
   711 static void
   712 StopRequest(JSContext *cx)
   713 {
   714     JSRuntime *rt = cx->runtime();
   715     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
   717     JS_ASSERT(rt->requestDepth != 0);
   718     if (rt->requestDepth != 1) {
   719         rt->requestDepth--;
   720     } else {
   721         rt->conservativeGC.updateForRequestEnd();
   722         rt->requestDepth = 0;
   723         rt->triggerActivityCallback(false);
   724     }
   725 }
   726 #endif /* JS_THREADSAFE */
   728 JS_PUBLIC_API(void)
   729 JS_BeginRequest(JSContext *cx)
   730 {
   731 #ifdef JS_THREADSAFE
   732     cx->outstandingRequests++;
   733     StartRequest(cx);
   734 #endif
   735 }
   737 JS_PUBLIC_API(void)
   738 JS_EndRequest(JSContext *cx)
   739 {
   740 #ifdef JS_THREADSAFE
   741     JS_ASSERT(cx->outstandingRequests != 0);
   742     cx->outstandingRequests--;
   743     StopRequest(cx);
   744 #endif
   745 }
   747 JS_PUBLIC_API(bool)
   748 JS_IsInRequest(JSRuntime *rt)
   749 {
   750 #ifdef JS_THREADSAFE
   751     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
   752     return rt->requestDepth != 0;
   753 #else
   754     return false;
   755 #endif
   756 }
   758 JS_PUBLIC_API(void)
   759 JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback, void *data)
   760 {
   761     rt->cxCallback = cxCallback;
   762     rt->cxCallbackData = data;
   763 }
   765 JS_PUBLIC_API(JSContext *)
   766 JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
   767 {
   768     return NewContext(rt, stackChunkSize);
   769 }
   771 JS_PUBLIC_API(void)
   772 JS_DestroyContext(JSContext *cx)
   773 {
   774     JS_ASSERT(!cx->compartment());
   775     DestroyContext(cx, DCM_FORCE_GC);
   776 }
   778 JS_PUBLIC_API(void)
   779 JS_DestroyContextNoGC(JSContext *cx)
   780 {
   781     JS_ASSERT(!cx->compartment());
   782     DestroyContext(cx, DCM_NO_GC);
   783 }
   785 JS_PUBLIC_API(void *)
   786 JS_GetContextPrivate(JSContext *cx)
   787 {
   788     return cx->data;
   789 }
   791 JS_PUBLIC_API(void)
   792 JS_SetContextPrivate(JSContext *cx, void *data)
   793 {
   794     cx->data = data;
   795 }
   797 JS_PUBLIC_API(void *)
   798 JS_GetSecondContextPrivate(JSContext *cx)
   799 {
   800     return cx->data2;
   801 }
   803 JS_PUBLIC_API(void)
   804 JS_SetSecondContextPrivate(JSContext *cx, void *data)
   805 {
   806     cx->data2 = data;
   807 }
   809 JS_PUBLIC_API(JSRuntime *)
   810 JS_GetRuntime(JSContext *cx)
   811 {
   812     return cx->runtime();
   813 }
   815 JS_PUBLIC_API(JSRuntime *)
   816 JS_GetParentRuntime(JSContext *cx)
   817 {
   818     JSRuntime *rt = cx->runtime();
   819     return rt->parentRuntime ? rt->parentRuntime : rt;
   820 }
   822 JS_PUBLIC_API(JSContext *)
   823 JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
   824 {
   825     JSContext *cx = *iterp;
   826     cx = cx ? cx->getNext() : rt->contextList.getFirst();
   827     *iterp = cx;
   828     return cx;
   829 }
   831 JS_PUBLIC_API(JSVersion)
   832 JS_GetVersion(JSContext *cx)
   833 {
   834     return VersionNumber(cx->findVersion());
   835 }
   837 JS_PUBLIC_API(void)
   838 JS_SetVersionForCompartment(JSCompartment *compartment, JSVersion version)
   839 {
   840     compartment->options().setVersion(version);
   841 }
   843 static const struct v2smap {
   844     JSVersion   version;
   845     const char  *string;
   846 } v2smap[] = {
   847     {JSVERSION_ECMA_3,  "ECMAv3"},
   848     {JSVERSION_1_6,     "1.6"},
   849     {JSVERSION_1_7,     "1.7"},
   850     {JSVERSION_1_8,     "1.8"},
   851     {JSVERSION_ECMA_5,  "ECMAv5"},
   852     {JSVERSION_DEFAULT, js_default_str},
   853     {JSVERSION_DEFAULT, "1.0"},
   854     {JSVERSION_DEFAULT, "1.1"},
   855     {JSVERSION_DEFAULT, "1.2"},
   856     {JSVERSION_DEFAULT, "1.3"},
   857     {JSVERSION_DEFAULT, "1.4"},
   858     {JSVERSION_DEFAULT, "1.5"},
   859     {JSVERSION_UNKNOWN, nullptr},          /* must be last, nullptr is sentinel */
   860 };
   862 JS_PUBLIC_API(const char *)
   863 JS_VersionToString(JSVersion version)
   864 {
   865     int i;
   867     for (i = 0; v2smap[i].string; i++)
   868         if (v2smap[i].version == version)
   869             return v2smap[i].string;
   870     return "unknown";
   871 }
   873 JS_PUBLIC_API(JSVersion)
   874 JS_StringToVersion(const char *string)
   875 {
   876     int i;
   878     for (i = 0; v2smap[i].string; i++)
   879         if (strcmp(v2smap[i].string, string) == 0)
   880             return v2smap[i].version;
   881     return JSVERSION_UNKNOWN;
   882 }
   884 JS_PUBLIC_API(JS::RuntimeOptions &)
   885 JS::RuntimeOptionsRef(JSRuntime *rt)
   886 {
   887     return rt->options();
   888 }
   890 JS_PUBLIC_API(JS::RuntimeOptions &)
   891 JS::RuntimeOptionsRef(JSContext *cx)
   892 {
   893     return cx->runtime()->options();
   894 }
   896 JS_PUBLIC_API(JS::ContextOptions &)
   897 JS::ContextOptionsRef(JSContext *cx)
   898 {
   899     return cx->options();
   900 }
   902 JS_PUBLIC_API(const char *)
   903 JS_GetImplementationVersion(void)
   904 {
   905     return "JavaScript-C" MOZILLA_VERSION;
   906 }
   908 JS_PUBLIC_API(void)
   909 JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback callback)
   910 {
   911     rt->destroyCompartmentCallback = callback;
   912 }
   914 JS_PUBLIC_API(void)
   915 JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback)
   916 {
   917     rt->destroyZoneCallback = callback;
   918 }
   920 JS_PUBLIC_API(void)
   921 JS_SetSweepZoneCallback(JSRuntime *rt, JSZoneCallback callback)
   922 {
   923     rt->sweepZoneCallback = callback;
   924 }
   926 JS_PUBLIC_API(void)
   927 JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback)
   928 {
   929     rt->compartmentNameCallback = callback;
   930 }
   932 JS_PUBLIC_API(void)
   933 JS_SetWrapObjectCallbacks(JSRuntime *rt, const JSWrapObjectCallbacks *callbacks)
   934 {
   935     rt->wrapObjectCallbacks = callbacks;
   936 }
   938 JS_PUBLIC_API(JSCompartment *)
   939 JS_EnterCompartment(JSContext *cx, JSObject *target)
   940 {
   941     AssertHeapIsIdle(cx);
   942     CHECK_REQUEST(cx);
   944     JSCompartment *oldCompartment = cx->compartment();
   945     cx->enterCompartment(target->compartment());
   946     return oldCompartment;
   947 }
   949 JS_PUBLIC_API(JSCompartment *)
   950 JS_EnterCompartmentOfScript(JSContext *cx, JSScript *target)
   951 {
   952     AssertHeapIsIdle(cx);
   953     CHECK_REQUEST(cx);
   954     GlobalObject &global = target->global();
   955     return JS_EnterCompartment(cx, &global);
   956 }
   958 JS_PUBLIC_API(void)
   959 JS_LeaveCompartment(JSContext *cx, JSCompartment *oldCompartment)
   960 {
   961     AssertHeapIsIdle(cx);
   962     CHECK_REQUEST(cx);
   963     cx->leaveCompartment(oldCompartment);
   964 }
   966 JSAutoCompartment::JSAutoCompartment(JSContext *cx, JSObject *target)
   967   : cx_(cx),
   968     oldCompartment_(cx->compartment())
   969 {
   970     AssertHeapIsIdleOrIterating(cx_);
   971     cx_->enterCompartment(target->compartment());
   972 }
   974 JSAutoCompartment::JSAutoCompartment(JSContext *cx, JSScript *target)
   975   : cx_(cx),
   976     oldCompartment_(cx->compartment())
   977 {
   978     AssertHeapIsIdleOrIterating(cx_);
   979     cx_->enterCompartment(target->compartment());
   980 }
   982 JSAutoCompartment::~JSAutoCompartment()
   983 {
   984     cx_->leaveCompartment(oldCompartment_);
   985 }
   987 JSAutoNullCompartment::JSAutoNullCompartment(JSContext *cx)
   988   : cx_(cx),
   989     oldCompartment_(cx->compartment())
   990 {
   991     AssertHeapIsIdleOrIterating(cx_);
   992     cx_->enterNullCompartment();
   993 }
   995 JSAutoNullCompartment::~JSAutoNullCompartment()
   996 {
   997     cx_->leaveCompartment(oldCompartment_);
   998 }
  1000 JS_PUBLIC_API(void)
  1001 JS_SetCompartmentPrivate(JSCompartment *compartment, void *data)
  1003     compartment->data = data;
  1006 JS_PUBLIC_API(void *)
  1007 JS_GetCompartmentPrivate(JSCompartment *compartment)
  1009     return compartment->data;
  1012 JS_PUBLIC_API(void)
  1013 JS_SetZoneUserData(JS::Zone *zone, void *data)
  1015     zone->data = data;
  1018 JS_PUBLIC_API(void *)
  1019 JS_GetZoneUserData(JS::Zone *zone)
  1021     return zone->data;
  1024 JS_PUBLIC_API(bool)
  1025 JS_WrapObject(JSContext *cx, MutableHandleObject objp)
  1027     AssertHeapIsIdle(cx);
  1028     CHECK_REQUEST(cx);
  1029     if (objp)
  1030         JS::ExposeGCThingToActiveJS(objp, JSTRACE_OBJECT);
  1031     return cx->compartment()->wrap(cx, objp);
  1034 JS_PUBLIC_API(bool)
  1035 JS_WrapValue(JSContext *cx, MutableHandleValue vp)
  1037     AssertHeapIsIdle(cx);
  1038     CHECK_REQUEST(cx);
  1039     JS::ExposeValueToActiveJS(vp);
  1040     return cx->compartment()->wrap(cx, vp);
  1043 JS_PUBLIC_API(bool)
  1044 JS_WrapId(JSContext *cx, JS::MutableHandleId idp)
  1046   AssertHeapIsIdle(cx);
  1047   CHECK_REQUEST(cx);
  1048   jsid id = idp.get();
  1049   if (JSID_IS_STRING(id))
  1050       JS::ExposeGCThingToActiveJS(JSID_TO_STRING(id), JSTRACE_STRING);
  1051   else if (JSID_IS_OBJECT(id))
  1052       JS::ExposeGCThingToActiveJS(JSID_TO_OBJECT(id), JSTRACE_OBJECT);
  1053   return cx->compartment()->wrapId(cx, idp.address());
  1056 /*
  1057  * Identity remapping. Not for casual consumers.
  1059  * Normally, an object's contents and its identity are inextricably linked.
  1060  * Identity is determined by the address of the JSObject* in the heap, and
  1061  * the contents are what is located at that address. Transplanting allows these
  1062  * concepts to be separated through a combination of swapping (exchanging the
  1063  * contents of two same-compartment objects) and remapping cross-compartment
  1064  * identities by altering wrappers.
  1066  * The |origobj| argument should be the object whose identity needs to be
  1067  * remapped, usually to another compartment. The contents of |origobj| are
  1068  * destroyed.
  1070  * The |target| argument serves two purposes:
  1072  * First, |target| serves as a hint for the new identity of the object. The new
  1073  * identity object will always be in the same compartment as |target|, but
  1074  * if that compartment already had an object representing |origobj| (either a
  1075  * cross-compartment wrapper for it, or |origobj| itself if the two arguments
  1076  * are same-compartment), the existing object is used. Otherwise, |target|
  1077  * itself is used. To avoid ambiguity, JS_TransplantObject always returns the
  1078  * new identity.
  1080  * Second, the new identity object's contents will be those of |target|. A swap()
  1081  * is used to make this happen if an object other than |target| is used.
  1083  * We don't have a good way to recover from failure in this function, so
  1084  * we intentionally crash instead.
  1085  */
  1087 JS_PUBLIC_API(JSObject *)
  1088 JS_TransplantObject(JSContext *cx, HandleObject origobj, HandleObject target)
  1090     AssertHeapIsIdle(cx);
  1091     JS_ASSERT(origobj != target);
  1092     JS_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
  1093     JS_ASSERT(!target->is<CrossCompartmentWrapperObject>());
  1095     RootedValue origv(cx, ObjectValue(*origobj));
  1096     RootedObject newIdentity(cx);
  1099         // Scope to make ~AutoMaybeTouchDeadZones do its GC before the return value is on the stack.
  1100         AutoMaybeTouchDeadZones agc(cx);
  1101         AutoDisableProxyCheck adpc(cx->runtime());
  1103         JSCompartment *destination = target->compartment();
  1105         if (origobj->compartment() == destination) {
  1106             // If the original object is in the same compartment as the
  1107             // destination, then we know that we won't find a wrapper in the
  1108             // destination's cross compartment map and that the same
  1109             // object will continue to work.
  1110             if (!JSObject::swap(cx, origobj, target))
  1111                 MOZ_CRASH();
  1112             newIdentity = origobj;
  1113         } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
  1114             // There might already be a wrapper for the original object in
  1115             // the new compartment. If there is, we use its identity and swap
  1116             // in the contents of |target|.
  1117         newIdentity = &p->value().toObject();
  1119             // When we remove origv from the wrapper map, its wrapper, newIdentity,
  1120             // must immediately cease to be a cross-compartment wrapper. Neuter it.
  1121             destination->removeWrapper(p);
  1122             NukeCrossCompartmentWrapper(cx, newIdentity);
  1124             if (!JSObject::swap(cx, newIdentity, target))
  1125                 MOZ_CRASH();
  1126         } else {
  1127             // Otherwise, we use |target| for the new identity object.
  1128             newIdentity = target;
  1131         // Now, iterate through other scopes looking for references to the
  1132         // old object, and update the relevant cross-compartment wrappers.
  1133         if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
  1134             MOZ_CRASH();
  1136         // Lastly, update the original object to point to the new one.
  1137         if (origobj->compartment() != destination) {
  1138             RootedObject newIdentityWrapper(cx, newIdentity);
  1139             AutoCompartment ac(cx, origobj);
  1140             if (!JS_WrapObject(cx, &newIdentityWrapper))
  1141                 MOZ_CRASH();
  1142             JS_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
  1143             if (!JSObject::swap(cx, origobj, newIdentityWrapper))
  1144                 MOZ_CRASH();
  1145         origobj->compartment()->putWrapper(cx, ObjectValue(*newIdentity), origv);
  1149     // The new identity object might be one of several things. Return it to avoid
  1150     // ambiguity.
  1151     return newIdentity;
  1154 /*
  1155  * Recompute all cross-compartment wrappers for an object, resetting state.
  1156  * Gecko uses this to clear Xray wrappers when doing a navigation that reuses
  1157  * the inner window and global object.
  1158  */
  1159 JS_PUBLIC_API(bool)
  1160 JS_RefreshCrossCompartmentWrappers(JSContext *cx, HandleObject obj)
  1162     return RemapAllWrappersForObject(cx, obj, obj);
  1165 JS_PUBLIC_API(bool)
  1166 JS_InitStandardClasses(JSContext *cx, HandleObject obj)
  1168     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1169     AssertHeapIsIdle(cx);
  1170     CHECK_REQUEST(cx);
  1172     cx->setDefaultCompartmentObjectIfUnset(obj);
  1173     assertSameCompartment(cx, obj);
  1175     Rooted<GlobalObject*> global(cx, &obj->global());
  1176     return GlobalObject::initStandardClasses(cx, global);
  1179 #define CLASP(name)                 (&name##Class)
  1180 #define OCLASP(name)                (&name##Object::class_)
  1181 #define TYPED_ARRAY_CLASP(type)     (&TypedArrayObject::classes[ScalarTypeDescr::type])
  1182 #define EAGER_ATOM(name)            NAME_OFFSET(name)
  1183 #define EAGER_CLASS_ATOM(name)      NAME_OFFSET(name)
  1185 static js::Class DummyClass;
  1186 static js::Class SentinelClass;
  1188 typedef struct JSStdName {
  1189     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
  1190     const Class *clasp;
  1191     bool isDummy() const { return clasp == &DummyClass; };
  1192     bool isSentinel() const { return clasp == &SentinelClass; };
  1193 } JSStdName;
  1195 static const JSStdName*
  1196 LookupStdName(JSRuntime *rt, HandleString name, const JSStdName *table)
  1198     MOZ_ASSERT(name->isAtom());
  1199     for (unsigned i = 0; !table[i].isSentinel(); i++) {
  1200         if (table[i].isDummy())
  1201             continue;
  1202         JSAtom *atom = AtomStateOffsetToName(*rt->commonNames, table[i].atomOffset);
  1203         MOZ_ASSERT(atom);
  1204         if (name == atom)
  1205             return &table[i];
  1208     return nullptr;
  1211 /*
  1212  * Table of standard classes, indexed by JSProtoKey. For entries where the
  1213  * JSProtoKey does not correspond to a class with a meaningful constructor, we
  1214  * insert a null entry into the table.
  1215  */
  1216 #define STD_NAME_ENTRY(name, code, init, clasp) { EAGER_CLASS_ATOM(name), clasp },
  1217 #define STD_DUMMY_ENTRY(name, code, init, dummy) { 0, &DummyClass },
  1218 static const JSStdName standard_class_names[] = {
  1219   JS_FOR_PROTOTYPES(STD_NAME_ENTRY, STD_DUMMY_ENTRY)
  1220   { 0, &SentinelClass }
  1221 };
  1223 /*
  1224  * Table of top-level function and constant names and the init function of the
  1225  * corresponding standard class that sets them up.
  1226  */
  1227 static const JSStdName builtin_property_names[] = {
  1228     { EAGER_ATOM(eval), &JSObject::class_ },
  1230     /* Global properties and functions defined by the Number class. */
  1231     { EAGER_ATOM(NaN), OCLASP(Number) },
  1232     { EAGER_ATOM(Infinity), OCLASP(Number) },
  1233     { EAGER_ATOM(isNaN), OCLASP(Number) },
  1234     { EAGER_ATOM(isFinite), OCLASP(Number) },
  1235     { EAGER_ATOM(parseFloat), OCLASP(Number) },
  1236     { EAGER_ATOM(parseInt), OCLASP(Number) },
  1238     /* String global functions. */
  1239     { EAGER_ATOM(escape), OCLASP(String) },
  1240     { EAGER_ATOM(unescape), OCLASP(String) },
  1241     { EAGER_ATOM(decodeURI), OCLASP(String) },
  1242     { EAGER_ATOM(encodeURI), OCLASP(String) },
  1243     { EAGER_ATOM(decodeURIComponent), OCLASP(String) },
  1244     { EAGER_ATOM(encodeURIComponent), OCLASP(String) },
  1245 #if JS_HAS_UNEVAL
  1246     { EAGER_ATOM(uneval), OCLASP(String) },
  1247 #endif
  1248 #ifdef ENABLE_BINARYDATA
  1249     { EAGER_ATOM(SIMD), OCLASP(SIMD) },
  1250     { EAGER_ATOM(TypedObject), OCLASP(TypedObjectModule) },
  1251 #endif
  1253     { 0, &SentinelClass }
  1254 };
  1256 #undef CLASP
  1257 #undef TYPED_ARRAY_CLASP
  1258 #undef EAGER_ATOM
  1259 #undef EAGER_CLASS_ATOM
  1260 #undef EAGER_ATOM_CLASP
  1262 JS_PUBLIC_API(bool)
  1263 JS_ResolveStandardClass(JSContext *cx, HandleObject obj, HandleId id, bool *resolved)
  1265     JSRuntime *rt;
  1266     const JSStdName *stdnm;
  1268     AssertHeapIsIdle(cx);
  1269     CHECK_REQUEST(cx);
  1270     assertSameCompartment(cx, obj, id);
  1272     Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
  1273     *resolved = false;
  1275     rt = cx->runtime();
  1276     if (!rt->hasContexts() || !JSID_IS_ATOM(id))
  1277         return true;
  1279     RootedString idstr(cx, JSID_TO_STRING(id));
  1281     /* Check whether we're resolving 'undefined', and define it if so. */
  1282     JSAtom *undefinedAtom = cx->names().undefined;
  1283     if (idstr == undefinedAtom) {
  1284         *resolved = true;
  1285         return JSObject::defineProperty(cx, obj, undefinedAtom->asPropertyName(),
  1286                                         UndefinedHandleValue,
  1287                                         JS_PropertyStub, JS_StrictPropertyStub,
  1288                                         JSPROP_PERMANENT | JSPROP_READONLY);
  1291     /* Try for class constructors/prototypes named by well-known atoms. */
  1292     stdnm = LookupStdName(rt, idstr, standard_class_names);
  1294     /* Try less frequently used top-level functions and constants. */
  1295     if (!stdnm)
  1296         stdnm = LookupStdName(rt, idstr, builtin_property_names);
  1298     // If this class is anonymous, then it doesn't exist as a global
  1299     // property, so we won't resolve anything.
  1300     if (stdnm && !(stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS)) {
  1301         JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(stdnm->clasp);
  1302         if (!GlobalObject::ensureConstructor(cx, global, key))
  1303             return false;
  1305         *resolved = true;
  1306         return true;
  1309     // There is no such property to resolve. An ordinary resolve hook would
  1310     // just return true at this point. But the global object is special in one
  1311     // more way: its prototype chain is lazily initialized. That is,
  1312     // global->getProto() might be null right now because we haven't created
  1313     // Object.prototype yet. Force it now.
  1314     if (!global->getOrCreateObjectPrototype(cx))
  1315         return false;
  1317     return true;
  1320 JS_PUBLIC_API(bool)
  1321 JS_EnumerateStandardClasses(JSContext *cx, HandleObject obj)
  1323     AssertHeapIsIdle(cx);
  1324     CHECK_REQUEST(cx);
  1325     assertSameCompartment(cx, obj);
  1326     MOZ_ASSERT(obj->is<GlobalObject>());
  1327     Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
  1328     return GlobalObject::initStandardClasses(cx, global);
  1331 JS_PUBLIC_API(bool)
  1332 JS_GetClassObject(JSContext *cx, JSProtoKey key, MutableHandleObject objp)
  1334     AssertHeapIsIdle(cx);
  1335     CHECK_REQUEST(cx);
  1336     return GetBuiltinConstructor(cx, key, objp);
  1339 JS_PUBLIC_API(bool)
  1340 JS_GetClassPrototype(JSContext *cx, JSProtoKey key, MutableHandleObject objp)
  1342     AssertHeapIsIdle(cx);
  1343     CHECK_REQUEST(cx);
  1344     return GetBuiltinPrototype(cx, key, objp);
  1347 JS_PUBLIC_API(JSProtoKey)
  1348 JS_IdToProtoKey(JSContext *cx, HandleId id)
  1350     AssertHeapIsIdle(cx);
  1351     CHECK_REQUEST(cx);
  1353     if (!JSID_IS_ATOM(id))
  1354         return JSProto_Null;
  1355     RootedString idstr(cx, JSID_TO_STRING(id));
  1356     const JSStdName *stdnm = LookupStdName(cx->runtime(), idstr, standard_class_names);
  1357     if (!stdnm)
  1358         return JSProto_Null;
  1360     MOZ_ASSERT(MOZ_ARRAY_LENGTH(standard_class_names) == JSProto_LIMIT + 1);
  1361     return static_cast<JSProtoKey>(stdnm - standard_class_names);
  1364 JS_PUBLIC_API(JSObject *)
  1365 JS_GetObjectPrototype(JSContext *cx, HandleObject forObj)
  1367     CHECK_REQUEST(cx);
  1368     assertSameCompartment(cx, forObj);
  1369     return forObj->global().getOrCreateObjectPrototype(cx);
  1372 JS_PUBLIC_API(JSObject *)
  1373 JS_GetFunctionPrototype(JSContext *cx, HandleObject forObj)
  1375     CHECK_REQUEST(cx);
  1376     assertSameCompartment(cx, forObj);
  1377     return forObj->global().getOrCreateFunctionPrototype(cx);
  1380 JS_PUBLIC_API(JSObject *)
  1381 JS_GetArrayPrototype(JSContext *cx, HandleObject forObj)
  1383     CHECK_REQUEST(cx);
  1384     assertSameCompartment(cx, forObj);
  1385     Rooted<GlobalObject*> global(cx, &forObj->global());
  1386     return GlobalObject::getOrCreateArrayPrototype(cx, global);
  1389 JS_PUBLIC_API(JSObject *)
  1390 JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
  1392     AssertHeapIsIdle(cx);
  1393     assertSameCompartment(cx, obj);
  1394     return &obj->global();
  1397 extern JS_PUBLIC_API(bool)
  1398 JS_IsGlobalObject(JSObject *obj)
  1400     return obj->is<GlobalObject>();
  1403 JS_PUBLIC_API(JSObject *)
  1404 JS_GetGlobalForCompartmentOrNull(JSContext *cx, JSCompartment *c)
  1406     AssertHeapIsIdleOrIterating(cx);
  1407     assertSameCompartment(cx, c);
  1408     return c->maybeGlobal();
  1411 JS_PUBLIC_API(JSObject *)
  1412 JS::CurrentGlobalOrNull(JSContext *cx)
  1414     AssertHeapIsIdleOrIterating(cx);
  1415     CHECK_REQUEST(cx);
  1416     if (!cx->compartment())
  1417         return nullptr;
  1418     return cx->global();
  1421 JS_PUBLIC_API(jsval)
  1422 JS_ComputeThis(JSContext *cx, jsval *vp)
  1424     AssertHeapIsIdle(cx);
  1425     assertSameCompartment(cx, JSValueArray(vp, 2));
  1426     CallReceiver call = CallReceiverFromVp(vp);
  1427     if (!BoxNonStrictThis(cx, call))
  1428         return JSVAL_NULL;
  1429     return call.thisv();
  1432 JS_PUBLIC_API(void *)
  1433 JS_malloc(JSContext *cx, size_t nbytes)
  1435     AssertHeapIsIdle(cx);
  1436     CHECK_REQUEST(cx);
  1437     return cx->malloc_(nbytes);
  1440 JS_PUBLIC_API(void *)
  1441 JS_realloc(JSContext *cx, void *p, size_t nbytes)
  1443     AssertHeapIsIdle(cx);
  1444     CHECK_REQUEST(cx);
  1445     return cx->realloc_(p, nbytes);
  1448 JS_PUBLIC_API(void)
  1449 JS_free(JSContext *cx, void *p)
  1451     return js_free(p);
  1454 JS_PUBLIC_API(void)
  1455 JS_freeop(JSFreeOp *fop, void *p)
  1457     return FreeOp::get(fop)->free_(p);
  1460 JS_PUBLIC_API(JSFreeOp *)
  1461 JS_GetDefaultFreeOp(JSRuntime *rt)
  1463     return rt->defaultFreeOp();
  1466 JS_PUBLIC_API(void)
  1467 JS_updateMallocCounter(JSContext *cx, size_t nbytes)
  1469     return cx->runtime()->updateMallocCounter(cx->zone(), nbytes);
  1472 JS_PUBLIC_API(char *)
  1473 JS_strdup(JSContext *cx, const char *s)
  1475     AssertHeapIsIdle(cx);
  1476     return js_strdup(cx, s);
  1479 JS_PUBLIC_API(char *)
  1480 JS_strdup(JSRuntime *rt, const char *s)
  1482     AssertHeapIsIdle(rt);
  1483     size_t n = strlen(s) + 1;
  1484     void *p = rt->malloc_(n);
  1485     if (!p)
  1486         return nullptr;
  1487     return static_cast<char*>(js_memcpy(p, s, n));
  1490 #undef JS_AddRoot
  1492 JS_PUBLIC_API(bool)
  1493 JS::AddValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp)
  1495     AssertHeapIsIdle(cx);
  1496     CHECK_REQUEST(cx);
  1497     return AddValueRoot(cx, vp->unsafeGet(), nullptr);
  1500 JS_PUBLIC_API(bool)
  1501 JS::AddStringRoot(JSContext *cx, JS::Heap<JSString *> *rp)
  1503     AssertHeapIsIdle(cx);
  1504     CHECK_REQUEST(cx);
  1505     return AddStringRoot(cx, rp->unsafeGet(), nullptr);
  1508 JS_PUBLIC_API(bool)
  1509 JS::AddObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp)
  1511     AssertHeapIsIdle(cx);
  1512     CHECK_REQUEST(cx);
  1513     return AddObjectRoot(cx, rp->unsafeGet(), nullptr);
  1516 JS_PUBLIC_API(bool)
  1517 JS::AddNamedValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp, const char *name)
  1519     AssertHeapIsIdle(cx);
  1520     CHECK_REQUEST(cx);
  1521     return AddValueRoot(cx, vp->unsafeGet(), name);
  1524 JS_PUBLIC_API(bool)
  1525 JS::AddNamedValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp, const char *name)
  1527     return AddValueRootRT(rt, vp->unsafeGet(), name);
  1530 JS_PUBLIC_API(bool)
  1531 JS::AddNamedStringRoot(JSContext *cx, JS::Heap<JSString *> *rp, const char *name)
  1533     AssertHeapIsIdle(cx);
  1534     CHECK_REQUEST(cx);
  1535     return AddStringRoot(cx, rp->unsafeGet(), name);
  1538 JS_PUBLIC_API(bool)
  1539 JS::AddNamedObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp, const char *name)
  1541     AssertHeapIsIdle(cx);
  1542     CHECK_REQUEST(cx);
  1543     return AddObjectRoot(cx, rp->unsafeGet(), name);
  1546 JS_PUBLIC_API(bool)
  1547 JS::AddNamedScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp, const char *name)
  1549     AssertHeapIsIdle(cx);
  1550     CHECK_REQUEST(cx);
  1551     return AddScriptRoot(cx, rp->unsafeGet(), name);
  1554 /* We allow unrooting from finalizers within the GC */
  1556 JS_PUBLIC_API(void)
  1557 JS::RemoveValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp)
  1559     CHECK_REQUEST(cx);
  1560     RemoveRoot(cx->runtime(), (void *)vp);
  1561     *vp = UndefinedValue();
  1564 JS_PUBLIC_API(void)
  1565 JS::RemoveStringRoot(JSContext *cx, JS::Heap<JSString *> *rp)
  1567     CHECK_REQUEST(cx);
  1568     RemoveRoot(cx->runtime(), (void *)rp);
  1569     *rp = nullptr;
  1572 JS_PUBLIC_API(void)
  1573 JS::RemoveObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp)
  1575     CHECK_REQUEST(cx);
  1576     RemoveRoot(cx->runtime(), (void *)rp);
  1577     *rp = nullptr;
  1580 JS_PUBLIC_API(void)
  1581 JS::RemoveScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp)
  1583     CHECK_REQUEST(cx);
  1584     RemoveRoot(cx->runtime(), (void *)rp);
  1585     *rp = nullptr;
  1588 JS_PUBLIC_API(void)
  1589 JS::RemoveValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp)
  1591     RemoveRoot(rt, (void *)vp);
  1592     *vp = UndefinedValue();
  1595 JS_PUBLIC_API(void)
  1596 JS::RemoveStringRootRT(JSRuntime *rt, JS::Heap<JSString *> *rp)
  1598     RemoveRoot(rt, (void *)rp);
  1599     *rp = nullptr;
  1602 JS_PUBLIC_API(void)
  1603 JS::RemoveObjectRootRT(JSRuntime *rt, JS::Heap<JSObject *> *rp)
  1605     RemoveRoot(rt, (void *)rp);
  1606     *rp = nullptr;
  1609 JS_PUBLIC_API(void)
  1610 JS::RemoveScriptRootRT(JSRuntime *rt, JS::Heap<JSScript *> *rp)
  1612     RemoveRoot(rt, (void *)rp);
  1613     *rp = nullptr;
  1616 JS_PUBLIC_API(bool)
  1617 JS_AddExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
  1619     AssertHeapIsIdle(rt);
  1620     return !!rt->gcBlackRootTracers.append(JSRuntime::ExtraTracer(traceOp, data));
  1623 JS_PUBLIC_API(void)
  1624 JS_RemoveExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
  1626     AssertHeapIsIdle(rt);
  1627     for (size_t i = 0; i < rt->gcBlackRootTracers.length(); i++) {
  1628         JSRuntime::ExtraTracer *e = &rt->gcBlackRootTracers[i];
  1629         if (e->op == traceOp && e->data == data) {
  1630             rt->gcBlackRootTracers.erase(e);
  1631             break;
  1636 #ifdef DEBUG
  1638 typedef struct JSHeapDumpNode JSHeapDumpNode;
  1640 struct JSHeapDumpNode {
  1641     void            *thing;
  1642     JSGCTraceKind   kind;
  1643     JSHeapDumpNode  *next;          /* next sibling */
  1644     JSHeapDumpNode  *parent;        /* node with the thing that refer to thing
  1645                                        from this node */
  1646     char            edgeName[1];    /* name of the edge from parent->thing
  1647                                        into thing */
  1648 };
  1650 typedef HashSet<void *, PointerHasher<void *, 3>, SystemAllocPolicy> VisitedSet;
  1652 class DumpingTracer
  1654   public:
  1655     DumpingTracer(JSRuntime *rt, JSTraceCallback callback)
  1656       : base(rt, callback)
  1657     {}
  1659     JSTracer            base;
  1660     VisitedSet          visited;
  1661     bool                ok;
  1662     void                *startThing;
  1663     void                *thingToFind;
  1664     void                *thingToIgnore;
  1665     JSHeapDumpNode      *parentNode;
  1666     JSHeapDumpNode      **lastNodep;
  1667     char                buffer[200];
  1668 };
  1670 static void
  1671 DumpNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
  1673     JS_ASSERT(trc->callback == DumpNotify);
  1675     DumpingTracer *dtrc = (DumpingTracer *)trc;
  1676     void *thing = *thingp;
  1678     if (!dtrc->ok || thing == dtrc->thingToIgnore)
  1679         return;
  1681     /*
  1682      * Check if we have already seen thing unless it is thingToFind to include
  1683      * it to the graph each time we reach it and print all live things that
  1684      * refer to thingToFind.
  1686      * This does not print all possible paths leading to thingToFind since
  1687      * when a thing A refers directly or indirectly to thingToFind and A is
  1688      * present several times in the graph, we will print only the first path
  1689      * leading to A and thingToFind, other ways to reach A will be ignored.
  1690      */
  1691     if (dtrc->thingToFind != thing) {
  1692         /*
  1693          * The startThing check allows to avoid putting startThing into the
  1694          * hash table before tracing startThing in JS_DumpHeap.
  1695          */
  1696         if (thing == dtrc->startThing)
  1697             return;
  1698         VisitedSet::AddPtr p = dtrc->visited.lookupForAdd(thing);
  1699         if (p)
  1700             return;
  1701         if (!dtrc->visited.add(p, thing)) {
  1702             dtrc->ok = false;
  1703             return;
  1707     const char *edgeName = dtrc->base.getTracingEdgeName(dtrc->buffer, sizeof(dtrc->buffer));
  1708     size_t edgeNameSize = strlen(edgeName) + 1;
  1709     size_t bytes = offsetof(JSHeapDumpNode, edgeName) + edgeNameSize;
  1710     JSHeapDumpNode *node = (JSHeapDumpNode *) js_malloc(bytes);
  1711     if (!node) {
  1712         dtrc->ok = false;
  1713         return;
  1716     node->thing = thing;
  1717     node->kind = kind;
  1718     node->next = nullptr;
  1719     node->parent = dtrc->parentNode;
  1720     js_memcpy(node->edgeName, edgeName, edgeNameSize);
  1722     JS_ASSERT(!*dtrc->lastNodep);
  1723     *dtrc->lastNodep = node;
  1724     dtrc->lastNodep = &node->next;
  1727 /* Dump node and the chain that leads to thing it contains. */
  1728 static bool
  1729 DumpNode(DumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
  1731     JSHeapDumpNode *prev, *following;
  1732     size_t chainLimit;
  1733     enum { MAX_PARENTS_TO_PRINT = 10 };
  1735     JS_GetTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
  1736                          &dtrc->base, node->thing, node->kind, true);
  1737     if (fprintf(fp, "%p %-22s via ", node->thing, dtrc->buffer) < 0)
  1738         return false;
  1740     /*
  1741      * We need to print the parent chain in the reverse order. To do it in
  1742      * O(N) time where N is the chain length we first reverse the chain while
  1743      * searching for the top and then print each node while restoring the
  1744      * chain order.
  1745      */
  1746     chainLimit = MAX_PARENTS_TO_PRINT;
  1747     prev = nullptr;
  1748     for (;;) {
  1749         following = node->parent;
  1750         node->parent = prev;
  1751         prev = node;
  1752         node = following;
  1753         if (!node)
  1754             break;
  1755         if (chainLimit == 0) {
  1756             if (fputs("...", fp) < 0)
  1757                 return false;
  1758             break;
  1760         --chainLimit;
  1763     node = prev;
  1764     prev = following;
  1765     bool ok = true;
  1766     do {
  1767         /* Loop must continue even when !ok to restore the parent chain. */
  1768         if (ok) {
  1769             if (!prev) {
  1770                 /* Print edge from some runtime root or startThing. */
  1771                 if (fputs(node->edgeName, fp) < 0)
  1772                     ok = false;
  1773             } else {
  1774                 JS_GetTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
  1775                                      &dtrc->base, prev->thing, prev->kind,
  1776                                      false);
  1777                 if (fprintf(fp, "(%p %s).%s",
  1778                            prev->thing, dtrc->buffer, node->edgeName) < 0) {
  1779                     ok = false;
  1783         following = node->parent;
  1784         node->parent = prev;
  1785         prev = node;
  1786         node = following;
  1787     } while (node);
  1789     return ok && putc('\n', fp) >= 0;
  1792 JS_PUBLIC_API(bool)
  1793 JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind startKind,
  1794             void *thingToFind, size_t maxDepth, void *thingToIgnore)
  1796     if (maxDepth == 0)
  1797         return true;
  1799     DumpingTracer dtrc(rt, DumpNotify);
  1800     if (!dtrc.visited.init())
  1801         return false;
  1802     dtrc.ok = true;
  1803     dtrc.startThing = startThing;
  1804     dtrc.thingToFind = thingToFind;
  1805     dtrc.thingToIgnore = thingToIgnore;
  1806     dtrc.parentNode = nullptr;
  1807     JSHeapDumpNode *node = nullptr;
  1808     dtrc.lastNodep = &node;
  1809     if (!startThing) {
  1810         JS_ASSERT(startKind == JSTRACE_OBJECT);
  1811         TraceRuntime(&dtrc.base);
  1812     } else {
  1813         JS_TraceChildren(&dtrc.base, startThing, startKind);
  1816     if (!node)
  1817         return dtrc.ok;
  1819     size_t depth = 1;
  1820     JSHeapDumpNode *children, *next, *parent;
  1821     bool thingToFindWasTraced = thingToFind && thingToFind == startThing;
  1822     for (;;) {
  1823         /*
  1824          * Loop must continue even when !dtrc.ok to free all nodes allocated
  1825          * so far.
  1826          */
  1827         if (dtrc.ok) {
  1828             if (thingToFind == nullptr || thingToFind == node->thing)
  1829                 dtrc.ok = DumpNode(&dtrc, fp, node);
  1831             /* Descend into children. */
  1832             if (dtrc.ok &&
  1833                 depth < maxDepth &&
  1834                 (thingToFind != node->thing || !thingToFindWasTraced)) {
  1835                 dtrc.parentNode = node;
  1836                 children = nullptr;
  1837                 dtrc.lastNodep = &children;
  1838                 JS_TraceChildren(&dtrc.base, node->thing, node->kind);
  1839                 if (thingToFind == node->thing)
  1840                     thingToFindWasTraced = true;
  1841                 if (children != nullptr) {
  1842                     ++depth;
  1843                     node = children;
  1844                     continue;
  1849         /* Move to next or parents next and free the node. */
  1850         for (;;) {
  1851             next = node->next;
  1852             parent = node->parent;
  1853             js_free(node);
  1854             node = next;
  1855             if (node)
  1856                 break;
  1857             if (!parent)
  1858                 return dtrc.ok;
  1859             JS_ASSERT(depth > 1);
  1860             --depth;
  1861             node = parent;
  1865     JS_ASSERT(depth == 1);
  1866     return dtrc.ok;
  1869 #endif /* DEBUG */
  1871 extern JS_PUBLIC_API(bool)
  1872 JS_IsGCMarkingTracer(JSTracer *trc)
  1874     return IS_GC_MARKING_TRACER(trc);
  1877 #ifdef DEBUG
  1878 extern JS_PUBLIC_API(bool)
  1879 JS_IsMarkingGray(JSTracer *trc)
  1881     JS_ASSERT(JS_IsGCMarkingTracer(trc));
  1882     return trc->callback == GCMarker::GrayCallback;
  1884 #endif
  1886 JS_PUBLIC_API(void)
  1887 JS_GC(JSRuntime *rt)
  1889     AssertHeapIsIdle(rt);
  1890     JS::PrepareForFullGC(rt);
  1891     GC(rt, GC_NORMAL, JS::gcreason::API);
  1894 JS_PUBLIC_API(void)
  1895 JS_MaybeGC(JSContext *cx)
  1897     MaybeGC(cx);
  1900 JS_PUBLIC_API(void)
  1901 JS_SetGCCallback(JSRuntime *rt, JSGCCallback cb, void *data)
  1903     AssertHeapIsIdle(rt);
  1904     rt->gcCallback = cb;
  1905     rt->gcCallbackData = data;
  1908 JS_PUBLIC_API(void)
  1909 JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb)
  1911     AssertHeapIsIdle(rt);
  1912     rt->gcFinalizeCallback = cb;
  1915 JS_PUBLIC_API(bool)
  1916 JS_IsAboutToBeFinalized(JS::Heap<JSObject *> *objp)
  1918     return IsObjectAboutToBeFinalized(objp->unsafeGet());
  1921 JS_PUBLIC_API(bool)
  1922 JS_IsAboutToBeFinalizedUnbarriered(JSObject **objp)
  1924     return IsObjectAboutToBeFinalized(objp);
  1927 JS_PUBLIC_API(void)
  1928 JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32_t value)
  1930     switch (key) {
  1931       case JSGC_MAX_BYTES: {
  1932         JS_ASSERT(value >= rt->gcBytes);
  1933         rt->gcMaxBytes = value;
  1934         break;
  1936       case JSGC_MAX_MALLOC_BYTES:
  1937         rt->setGCMaxMallocBytes(value);
  1938         break;
  1939       case JSGC_SLICE_TIME_BUDGET:
  1940         rt->gcSliceBudget = SliceBudget::TimeBudget(value);
  1941         break;
  1942       case JSGC_MARK_STACK_LIMIT:
  1943         js::SetMarkStackLimit(rt, value);
  1944         break;
  1945       case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
  1946         rt->gcHighFrequencyTimeThreshold = value;
  1947         break;
  1948       case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
  1949         rt->gcHighFrequencyLowLimitBytes = value * 1024 * 1024;
  1950         break;
  1951       case JSGC_HIGH_FREQUENCY_HIGH_LIMIT:
  1952         rt->gcHighFrequencyHighLimitBytes = value * 1024 * 1024;
  1953         break;
  1954       case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX:
  1955         rt->gcHighFrequencyHeapGrowthMax = value / 100.0;
  1956         MOZ_ASSERT(rt->gcHighFrequencyHeapGrowthMax / 0.85 > 1.0);
  1957         break;
  1958       case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN:
  1959         rt->gcHighFrequencyHeapGrowthMin = value / 100.0;
  1960         MOZ_ASSERT(rt->gcHighFrequencyHeapGrowthMin / 0.85 > 1.0);
  1961         break;
  1962       case JSGC_LOW_FREQUENCY_HEAP_GROWTH:
  1963         rt->gcLowFrequencyHeapGrowth = value / 100.0;
  1964         MOZ_ASSERT(rt->gcLowFrequencyHeapGrowth / 0.9 > 1.0);
  1965         break;
  1966       case JSGC_DYNAMIC_HEAP_GROWTH:
  1967         rt->gcDynamicHeapGrowth = value;
  1968         break;
  1969       case JSGC_DYNAMIC_MARK_SLICE:
  1970         rt->gcDynamicMarkSlice = value;
  1971         break;
  1972       case JSGC_ALLOCATION_THRESHOLD:
  1973         rt->gcAllocationThreshold = value * 1024 * 1024;
  1974         break;
  1975       case JSGC_DECOMMIT_THRESHOLD:
  1976         rt->gcDecommitThreshold = value * 1024 * 1024;
  1977         break;
  1978       default:
  1979         JS_ASSERT(key == JSGC_MODE);
  1980         rt->setGCMode(JSGCMode(value));
  1981         JS_ASSERT(rt->gcMode() == JSGC_MODE_GLOBAL ||
  1982                   rt->gcMode() == JSGC_MODE_COMPARTMENT ||
  1983                   rt->gcMode() == JSGC_MODE_INCREMENTAL);
  1984         return;
  1988 JS_PUBLIC_API(uint32_t)
  1989 JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
  1991     switch (key) {
  1992       case JSGC_MAX_BYTES:
  1993         return uint32_t(rt->gcMaxBytes);
  1994       case JSGC_MAX_MALLOC_BYTES:
  1995         return rt->gcMaxMallocBytes;
  1996       case JSGC_BYTES:
  1997         return uint32_t(rt->gcBytes);
  1998       case JSGC_MODE:
  1999         return uint32_t(rt->gcMode());
  2000       case JSGC_UNUSED_CHUNKS:
  2001         return uint32_t(rt->gcChunkPool.getEmptyCount());
  2002       case JSGC_TOTAL_CHUNKS:
  2003         return uint32_t(rt->gcChunkSet.count() + rt->gcChunkPool.getEmptyCount());
  2004       case JSGC_SLICE_TIME_BUDGET:
  2005         return uint32_t(rt->gcSliceBudget > 0 ? rt->gcSliceBudget / PRMJ_USEC_PER_MSEC : 0);
  2006       case JSGC_MARK_STACK_LIMIT:
  2007         return rt->gcMarker.maxCapacity();
  2008       case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
  2009         return rt->gcHighFrequencyTimeThreshold;
  2010       case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
  2011         return rt->gcHighFrequencyLowLimitBytes / 1024 / 1024;
  2012       case JSGC_HIGH_FREQUENCY_HIGH_LIMIT:
  2013         return rt->gcHighFrequencyHighLimitBytes / 1024 / 1024;
  2014       case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX:
  2015         return uint32_t(rt->gcHighFrequencyHeapGrowthMax * 100);
  2016       case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN:
  2017         return uint32_t(rt->gcHighFrequencyHeapGrowthMin * 100);
  2018       case JSGC_LOW_FREQUENCY_HEAP_GROWTH:
  2019         return uint32_t(rt->gcLowFrequencyHeapGrowth * 100);
  2020       case JSGC_DYNAMIC_HEAP_GROWTH:
  2021         return rt->gcDynamicHeapGrowth;
  2022       case JSGC_DYNAMIC_MARK_SLICE:
  2023         return rt->gcDynamicMarkSlice;
  2024       case JSGC_ALLOCATION_THRESHOLD:
  2025         return rt->gcAllocationThreshold / 1024 / 1024;
  2026       default:
  2027         JS_ASSERT(key == JSGC_NUMBER);
  2028         return uint32_t(rt->gcNumber);
  2032 JS_PUBLIC_API(void)
  2033 JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value)
  2035     JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
  2038 JS_PUBLIC_API(uint32_t)
  2039 JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
  2041     JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
  2042     return 0;
  2045 static const size_t NumGCConfigs = 14;
  2046 struct JSGCConfig {
  2047     JSGCParamKey key;
  2048     uint32_t value;
  2049 };
  2051 JS_PUBLIC_API(void)
  2052 JS_SetGCParametersBasedOnAvailableMemory(JSRuntime *rt, uint32_t availMem)
  2054     static const JSGCConfig minimal[NumGCConfigs] = {
  2055         {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
  2056         {JSGC_SLICE_TIME_BUDGET, 30},
  2057         {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  2058         {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 40},
  2059         {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 0},
  2060         {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300},
  2061         {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 120},
  2062         {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 120},
  2063         {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  2064         {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  2065         {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  2066         {JSGC_ALLOCATION_THRESHOLD, 1},
  2067         {JSGC_DECOMMIT_THRESHOLD, 1},
  2068         {JSGC_MODE, JSGC_MODE_INCREMENTAL}
  2069     };
  2071     const JSGCConfig *config = minimal;
  2072     if (availMem > 512) {
  2073         static const JSGCConfig nominal[NumGCConfigs] = {
  2074             {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
  2075             {JSGC_SLICE_TIME_BUDGET, 30},
  2076             {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000},
  2077             {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500},
  2078             {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 100},
  2079             {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300},
  2080             {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 150},
  2081             {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 150},
  2082             {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  2083             {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  2084             {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  2085             {JSGC_ALLOCATION_THRESHOLD, 30},
  2086             {JSGC_DECOMMIT_THRESHOLD, 32},
  2087             {JSGC_MODE, JSGC_MODE_COMPARTMENT}
  2088         };
  2090         config = nominal;
  2093     for (size_t i = 0; i < NumGCConfigs; i++)
  2094         JS_SetGCParameter(rt, config[i].key, config[i].value);
  2098 JS_PUBLIC_API(JSString *)
  2099 JS_NewExternalString(JSContext *cx, const jschar *chars, size_t length,
  2100                      const JSStringFinalizer *fin)
  2102     AssertHeapIsIdle(cx);
  2103     CHECK_REQUEST(cx);
  2104     JSString *s = JSExternalString::new_(cx, chars, length, fin);
  2105     return s;
  2108 extern JS_PUBLIC_API(bool)
  2109 JS_IsExternalString(JSString *str)
  2111     return str->isExternal();
  2114 extern JS_PUBLIC_API(const JSStringFinalizer *)
  2115 JS_GetExternalStringFinalizer(JSString *str)
  2117     return str->asExternal().externalFinalizer();
  2120 static void
  2121 SetNativeStackQuota(JSRuntime *rt, StackKind kind, size_t stackSize)
  2123     rt->nativeStackQuota[kind] = stackSize;
  2124     if (rt->nativeStackBase)
  2125         RecomputeStackLimit(rt, kind);
  2128 void
  2129 js::RecomputeStackLimit(JSRuntime *rt, StackKind kind)
  2131     size_t stackSize = rt->nativeStackQuota[kind];
  2132 #if JS_STACK_GROWTH_DIRECTION > 0
  2133     if (stackSize == 0) {
  2134         rt->mainThread.nativeStackLimit[kind] = UINTPTR_MAX;
  2135     } else {
  2136         JS_ASSERT(rt->nativeStackBase <= size_t(-1) - stackSize);
  2137         rt->mainThread.nativeStackLimit[kind] =
  2138           rt->nativeStackBase + stackSize - 1;
  2140 #else
  2141     if (stackSize == 0) {
  2142         rt->mainThread.nativeStackLimit[kind] = 0;
  2143     } else {
  2144         JS_ASSERT(rt->nativeStackBase >= stackSize);
  2145         rt->mainThread.nativeStackLimit[kind] =
  2146           rt->nativeStackBase - (stackSize - 1);
  2148 #endif
  2150     // If there's no pending interrupt request set on the runtime's main thread's
  2151     // jitStackLimit, then update it so that it reflects the new nativeStacklimit.
  2152     //
  2153     // Note that, for now, we use the untrusted limit for ion. This is fine,
  2154     // because it's the most conservative limit, and if we hit it, we'll bail
  2155     // out of ion into the interpeter, which will do a proper recursion check.
  2156 #ifdef JS_ION
  2157     if (kind == StackForUntrustedScript) {
  2158         JSRuntime::AutoLockForInterrupt lock(rt);
  2159         if (rt->mainThread.jitStackLimit != uintptr_t(-1)) {
  2160             rt->mainThread.jitStackLimit = rt->mainThread.nativeStackLimit[kind];
  2161 #ifdef JS_ARM_SIMULATOR
  2162             rt->mainThread.jitStackLimit = jit::Simulator::StackLimit();
  2163 #endif
  2166 #endif
  2169 JS_PUBLIC_API(void)
  2170 JS_SetNativeStackQuota(JSRuntime *rt, size_t systemCodeStackSize,
  2171                        size_t trustedScriptStackSize,
  2172                        size_t untrustedScriptStackSize)
  2174     JS_ASSERT_IF(trustedScriptStackSize,
  2175                  trustedScriptStackSize < systemCodeStackSize);
  2176     if (!trustedScriptStackSize)
  2177         trustedScriptStackSize = systemCodeStackSize;
  2178     JS_ASSERT_IF(untrustedScriptStackSize,
  2179                  untrustedScriptStackSize < trustedScriptStackSize);
  2180     if (!untrustedScriptStackSize)
  2181         untrustedScriptStackSize = trustedScriptStackSize;
  2182     SetNativeStackQuota(rt, StackForSystemCode, systemCodeStackSize);
  2183     SetNativeStackQuota(rt, StackForTrustedScript, trustedScriptStackSize);
  2184     SetNativeStackQuota(rt, StackForUntrustedScript, untrustedScriptStackSize);
  2187 /************************************************************************/
  2189 JS_PUBLIC_API(int)
  2190 JS_IdArrayLength(JSContext *cx, JSIdArray *ida)
  2192     return ida->length;
  2195 JS_PUBLIC_API(jsid)
  2196 JS_IdArrayGet(JSContext *cx, JSIdArray *ida, int index)
  2198     JS_ASSERT(index >= 0 && index < ida->length);
  2199     return ida->vector[index];
  2202 JS_PUBLIC_API(void)
  2203 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
  2205     cx->runtime()->defaultFreeOp()->free_(ida);
  2208 JS_PUBLIC_API(bool)
  2209 JS_ValueToId(JSContext *cx, HandleValue value, MutableHandleId idp)
  2211     AssertHeapIsIdle(cx);
  2212     CHECK_REQUEST(cx);
  2213     assertSameCompartment(cx, value);
  2214     return ValueToId<CanGC>(cx, value, idp);
  2217 JS_PUBLIC_API(bool)
  2218 JS_StringToId(JSContext *cx, HandleString string, MutableHandleId idp)
  2220     AssertHeapIsIdle(cx);
  2221     CHECK_REQUEST(cx);
  2222     assertSameCompartment(cx, string);
  2223     RootedValue value(cx, StringValue(string));
  2224     return ValueToId<CanGC>(cx, value, idp);
  2227 JS_PUBLIC_API(bool)
  2228 JS_IdToValue(JSContext *cx, jsid id, MutableHandleValue vp)
  2230     AssertHeapIsIdle(cx);
  2231     CHECK_REQUEST(cx);
  2232     vp.set(IdToValue(id));
  2233     assertSameCompartment(cx, vp);
  2234     return true;
  2237 JS_PUBLIC_API(bool)
  2238 JS_DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp)
  2240     AssertHeapIsIdle(cx);
  2241     CHECK_REQUEST(cx);
  2242     JS_ASSERT(obj != nullptr);
  2243     JS_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
  2244     return JSObject::defaultValue(cx, obj, hint, vp);
  2247 JS_PUBLIC_API(bool)
  2248 JS_PropertyStub(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
  2250     return true;
  2253 JS_PUBLIC_API(bool)
  2254 JS_StrictPropertyStub(JSContext *cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
  2256     return true;
  2259 JS_PUBLIC_API(bool)
  2260 JS_DeletePropertyStub(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
  2262     *succeeded = true;
  2263     return true;
  2266 JS_PUBLIC_API(bool)
  2267 JS_EnumerateStub(JSContext *cx, HandleObject obj)
  2269     return true;
  2272 JS_PUBLIC_API(bool)
  2273 JS_ResolveStub(JSContext *cx, HandleObject obj, HandleId id)
  2275     return true;
  2278 JS_PUBLIC_API(bool)
  2279 JS_ConvertStub(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue vp)
  2281     JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
  2282     JS_ASSERT(obj);
  2283     return DefaultValue(cx, obj, type, vp);
  2286 JS_PUBLIC_API(JSObject *)
  2287 JS_InitClass(JSContext *cx, HandleObject obj, HandleObject parent_proto,
  2288              const JSClass *clasp, JSNative constructor, unsigned nargs,
  2289              const JSPropertySpec *ps, const JSFunctionSpec *fs,
  2290              const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs)
  2292     AssertHeapIsIdle(cx);
  2293     CHECK_REQUEST(cx);
  2294     assertSameCompartment(cx, obj, parent_proto);
  2295     return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
  2296                         nargs, ps, fs, static_ps, static_fs);
  2299 JS_PUBLIC_API(bool)
  2300 JS_LinkConstructorAndPrototype(JSContext *cx, HandleObject ctor, HandleObject proto)
  2302     return LinkConstructorAndPrototype(cx, ctor, proto);
  2305 JS_PUBLIC_API(const JSClass *)
  2306 JS_GetClass(JSObject *obj)
  2308     return obj->getJSClass();
  2311 JS_PUBLIC_API(bool)
  2312 JS_InstanceOf(JSContext *cx, HandleObject obj, const JSClass *clasp, CallArgs *args)
  2314     AssertHeapIsIdle(cx);
  2315     CHECK_REQUEST(cx);
  2316 #ifdef DEBUG
  2317     if (args) {
  2318         assertSameCompartment(cx, obj);
  2319         assertSameCompartment(cx, args->thisv(), args->calleev());
  2321 #endif
  2322     if (!obj || obj->getJSClass() != clasp) {
  2323         if (args)
  2324             ReportIncompatibleMethod(cx, *args, Valueify(clasp));
  2325         return false;
  2327     return true;
  2330 JS_PUBLIC_API(bool)
  2331 JS_HasInstance(JSContext *cx, HandleObject obj, HandleValue value, bool *bp)
  2333     AssertHeapIsIdle(cx);
  2334     assertSameCompartment(cx, obj, value);
  2335     return HasInstance(cx, obj, value, bp);
  2338 JS_PUBLIC_API(void *)
  2339 JS_GetPrivate(JSObject *obj)
  2341     /* This function can be called by a finalizer. */
  2342     return obj->getPrivate();
  2345 JS_PUBLIC_API(void)
  2346 JS_SetPrivate(JSObject *obj, void *data)
  2348     /* This function can be called by a finalizer. */
  2349     obj->setPrivate(data);
  2352 JS_PUBLIC_API(void *)
  2353 JS_GetInstancePrivate(JSContext *cx, HandleObject obj, const JSClass *clasp, CallArgs *args)
  2355     if (!JS_InstanceOf(cx, obj, clasp, args))
  2356         return nullptr;
  2357     return obj->getPrivate();
  2360 JS_PUBLIC_API(bool)
  2361 JS_GetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> protop)
  2363     return JSObject::getProto(cx, obj, protop);
  2366 JS_PUBLIC_API(bool)
  2367 JS_SetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<JSObject*> proto)
  2369     AssertHeapIsIdle(cx);
  2370     CHECK_REQUEST(cx);
  2371     assertSameCompartment(cx, obj, proto);
  2373     bool succeeded;
  2374     if (!JSObject::setProto(cx, obj, proto, &succeeded))
  2375         return false;
  2377     if (!succeeded) {
  2378         RootedValue val(cx, ObjectValue(*obj));
  2379         js_ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, val, js::NullPtr());
  2380         return false;
  2383     return true;
  2386 JS_PUBLIC_API(JSObject *)
  2387 JS_GetParent(JSObject *obj)
  2389     JS_ASSERT(!obj->is<ScopeObject>());
  2390     return obj->getParent();
  2393 JS_PUBLIC_API(bool)
  2394 JS_SetParent(JSContext *cx, HandleObject obj, HandleObject parent)
  2396     AssertHeapIsIdle(cx);
  2397     CHECK_REQUEST(cx);
  2398     JS_ASSERT(!obj->is<ScopeObject>());
  2399     JS_ASSERT(parent || !obj->getParent());
  2400     assertSameCompartment(cx, obj, parent);
  2402     return JSObject::setParent(cx, obj, parent);
  2405 JS_PUBLIC_API(JSObject *)
  2406 JS_GetConstructor(JSContext *cx, HandleObject proto)
  2408     AssertHeapIsIdle(cx);
  2409     CHECK_REQUEST(cx);
  2410     assertSameCompartment(cx, proto);
  2412     RootedValue cval(cx);
  2413     if (!JSObject::getProperty(cx, proto, proto, cx->names().constructor, &cval))
  2414         return nullptr;
  2415     if (!IsFunctionObject(cval)) {
  2416         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
  2417                              proto->getClass()->name);
  2418         return nullptr;
  2420     return &cval.toObject();
  2423 namespace {
  2425 class AutoCompartmentRooter : private JS::CustomAutoRooter
  2427   public:
  2428     explicit AutoCompartmentRooter(JSContext *cx, JSCompartment *comp
  2429                                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  2430       : CustomAutoRooter(cx), compartment(comp)
  2432         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  2435     operator JSCompartment *() {
  2436         return compartment;
  2439     JSCompartment *operator->() {
  2440         return compartment;
  2443   protected:
  2444     virtual void trace(JSTracer *trc)
  2446         compartment->mark();
  2449   private:
  2450     JSCompartment *compartment;
  2451     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  2452 };
  2454 } /* anonymous namespace */
  2456 bool
  2457 JS::CompartmentOptions::cloneSingletons(JSContext *cx) const
  2459     return cloneSingletonsOverride_.get(cx->options().cloneSingletons());
  2462 JS::CompartmentOptions &
  2463 JS::CompartmentOptions::setZone(ZoneSpecifier spec)
  2465     zone_.spec = spec;
  2466     return *this;
  2469 JS::CompartmentOptions &
  2470 JS::CompartmentOptions::setSameZoneAs(JSObject *obj)
  2472     zone_.pointer = static_cast<void *>(obj->zone());
  2473     return *this;
  2476 JS::CompartmentOptions &
  2477 JS::CompartmentOptionsRef(JSCompartment *compartment)
  2479     return compartment->options();
  2482 JS::CompartmentOptions &
  2483 JS::CompartmentOptionsRef(JSObject *obj)
  2485     return obj->compartment()->options();
  2488 JS::CompartmentOptions &
  2489 JS::CompartmentOptionsRef(JSContext *cx)
  2491     return cx->compartment()->options();
  2494 JS_PUBLIC_API(JSObject *)
  2495 JS_NewGlobalObject(JSContext *cx, const JSClass *clasp, JSPrincipals *principals,
  2496                    JS::OnNewGlobalHookOption hookOption,
  2497                    const JS::CompartmentOptions &options /* = JS::CompartmentOptions() */)
  2499     AssertHeapIsIdle(cx);
  2500     CHECK_REQUEST(cx);
  2501     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  2502     JS_ASSERT(!cx->isExceptionPending());
  2504     JSRuntime *rt = cx->runtime();
  2506     Zone *zone;
  2507     if (options.zoneSpecifier() == JS::SystemZone)
  2508         zone = rt->systemZone;
  2509     else if (options.zoneSpecifier() == JS::FreshZone)
  2510         zone = nullptr;
  2511     else
  2512         zone = static_cast<Zone *>(options.zonePointer());
  2514     AutoCompartmentRooter compartment(cx, NewCompartment(cx, zone, principals, options));
  2515     if (!compartment)
  2516         return nullptr;
  2518     // Lazily create the system zone.
  2519     if (!rt->systemZone && options.zoneSpecifier() == JS::SystemZone) {
  2520         rt->systemZone = compartment->zone();
  2521         rt->systemZone->isSystem = true;
  2524     Rooted<GlobalObject *> global(cx);
  2526         AutoCompartment ac(cx, compartment);
  2527         global = GlobalObject::create(cx, Valueify(clasp));
  2530     if (!global)
  2531         return nullptr;
  2533     if (hookOption == JS::FireOnNewGlobalHook)
  2534         JS_FireOnNewGlobalObject(cx, global);
  2536     return global;
  2539 JS_PUBLIC_API(void)
  2540 JS_GlobalObjectTraceHook(JSTracer *trc, JSObject *global)
  2542     JS_ASSERT(global->is<GlobalObject>());
  2544     // Off thread parsing and compilation tasks create a dummy global which is then
  2545     // merged back into the host compartment. Since it used to be a global, it will still
  2546     // have this trace hook, but it does not have a meaning relative to its new compartment.
  2547     // We can safely skip it.
  2548     if (!global->isOwnGlobal())
  2549         return;
  2551     // Trace the compartment for any GC things that should only stick around if we know the
  2552     // compartment is live.
  2553     global->compartment()->trace(trc);
  2555     JSTraceOp trace = global->compartment()->options().getTrace();
  2556     if (trace)
  2557         trace(trc, global);
  2560 JS_PUBLIC_API(void)
  2561 JS_FireOnNewGlobalObject(JSContext *cx, JS::HandleObject global)
  2563     // This hook is infallible, because we don't really want arbitrary script
  2564     // to be able to throw errors during delicate global creation routines.
  2565     // This infallibility will eat OOM and slow script, but if that happens
  2566     // we'll likely run up into them again soon in a fallible context.
  2567     Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>());
  2568     Debugger::onNewGlobalObject(cx, globalObject);
  2571 JS_PUBLIC_API(JSObject *)
  2572 JS_NewObject(JSContext *cx, const JSClass *jsclasp, HandleObject proto, HandleObject parent)
  2574     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  2575     AssertHeapIsIdle(cx);
  2576     CHECK_REQUEST(cx);
  2577     assertSameCompartment(cx, proto, parent);
  2579     const Class *clasp = Valueify(jsclasp);
  2580     if (!clasp)
  2581         clasp = &JSObject::class_;    /* default class is Object */
  2583     JS_ASSERT(clasp != &JSFunction::class_);
  2584     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
  2586     JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
  2587     JS_ASSERT_IF(obj, obj->getParent());
  2588     return obj;
  2591 JS_PUBLIC_API(JSObject *)
  2592 JS_NewObjectWithGivenProto(JSContext *cx, const JSClass *jsclasp, HandleObject proto, HandleObject parent)
  2594     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  2595     AssertHeapIsIdle(cx);
  2596     CHECK_REQUEST(cx);
  2597     assertSameCompartment(cx, proto, parent);
  2599     const Class *clasp = Valueify(jsclasp);
  2600     if (!clasp)
  2601         clasp = &JSObject::class_;    /* default class is Object */
  2603     JS_ASSERT(clasp != &JSFunction::class_);
  2604     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
  2606     JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
  2607     if (obj)
  2608         MarkTypeObjectUnknownProperties(cx, obj->type());
  2609     return obj;
  2612 JS_PUBLIC_API(JSObject *)
  2613 JS_NewObjectForConstructor(JSContext *cx, const JSClass *clasp, const CallArgs& args)
  2615     AssertHeapIsIdle(cx);
  2616     CHECK_REQUEST(cx);
  2618     Value callee = args.calleev();
  2619     assertSameCompartment(cx, callee);
  2620     RootedObject obj(cx, &callee.toObject());
  2621     return CreateThis(cx, Valueify(clasp), obj);
  2624 JS_PUBLIC_API(bool)
  2625 JS_IsExtensible(JSContext *cx, HandleObject obj, bool *extensible)
  2627     return JSObject::isExtensible(cx, obj, extensible);
  2630 JS_PUBLIC_API(bool)
  2631 JS_IsNative(JSObject *obj)
  2633     return obj->isNative();
  2636 JS_PUBLIC_API(JSRuntime *)
  2637 JS_GetObjectRuntime(JSObject *obj)
  2639     return obj->compartment()->runtimeFromMainThread();
  2642 JS_PUBLIC_API(bool)
  2643 JS_FreezeObject(JSContext *cx, HandleObject obj)
  2645     AssertHeapIsIdle(cx);
  2646     CHECK_REQUEST(cx);
  2647     assertSameCompartment(cx, obj);
  2648     return JSObject::freeze(cx, obj);
  2651 JS_PUBLIC_API(bool)
  2652 JS_DeepFreezeObject(JSContext *cx, HandleObject obj)
  2654     AssertHeapIsIdle(cx);
  2655     CHECK_REQUEST(cx);
  2656     assertSameCompartment(cx, obj);
  2658     /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
  2659     bool extensible;
  2660     if (!JSObject::isExtensible(cx, obj, &extensible))
  2661         return false;
  2662     if (!extensible)
  2663         return true;
  2665     if (!JSObject::freeze(cx, obj))
  2666         return false;
  2668     /* Walk slots in obj and if any value is a non-null object, seal it. */
  2669     for (uint32_t i = 0, n = obj->slotSpan(); i < n; ++i) {
  2670         const Value &v = obj->getSlot(i);
  2671         if (v.isPrimitive())
  2672             continue;
  2673         RootedObject obj(cx, &v.toObject());
  2674         if (!JS_DeepFreezeObject(cx, obj))
  2675             return false;
  2678     return true;
  2681 static bool
  2682 LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id,
  2683                    MutableHandleObject objp, MutableHandleShape propp)
  2685     AssertHeapIsIdle(cx);
  2686     CHECK_REQUEST(cx);
  2687     assertSameCompartment(cx, obj, id);
  2689     return JSObject::lookupGeneric(cx, obj, id, objp, propp);
  2692 #define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
  2694 static bool
  2695 LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, HandleId id,
  2696              HandleShape shape, MutableHandleValue vp)
  2698     if (!shape) {
  2699         /* XXX bad API: no way to tell "not defined" from "void value" */
  2700         vp.setUndefined();
  2701         return true;
  2704     if (!obj2->isNative()) {
  2705         if (obj2->is<ProxyObject>()) {
  2706             Rooted<PropertyDescriptor> desc(cx);
  2707             if (!Proxy::getPropertyDescriptor(cx, obj2, id, &desc))
  2708                 return false;
  2709             if (!desc.isShared()) {
  2710                 vp.set(desc.value());
  2711                 return true;
  2714     } else if (IsImplicitDenseOrTypedArrayElement(shape)) {
  2715         vp.set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
  2716         return true;
  2717     } else {
  2718         /* Peek at the native property's slot value, without doing a Get. */
  2719         if (shape->hasSlot()) {
  2720             vp.set(obj2->nativeGetSlot(shape->slot()));
  2721             return true;
  2725     /* XXX bad API: no way to return "defined but value unknown" */
  2726     vp.setBoolean(true);
  2727     return true;
  2730 JS_PUBLIC_API(bool)
  2731 JS_LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
  2733     RootedObject obj2(cx);
  2734     RootedShape prop(cx);
  2736     return LookupPropertyById(cx, obj, id, &obj2, &prop) &&
  2737            LookupResult(cx, obj, obj2, id, prop, vp);
  2740 JS_PUBLIC_API(bool)
  2741 JS_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
  2743     CHECK_REQUEST(cx);
  2744     RootedId id(cx);
  2745     if (!IndexToId(cx, index, &id))
  2746         return false;
  2747     return JS_LookupPropertyById(cx, obj, id, vp);
  2750 JS_PUBLIC_API(bool)
  2751 JS_LookupProperty(JSContext *cx, HandleObject objArg, const char *name, MutableHandleValue vp)
  2753     RootedObject obj(cx, objArg);
  2754     JSAtom *atom = Atomize(cx, name, strlen(name));
  2755     if (!atom)
  2756         return false;
  2758     RootedId id(cx, AtomToId(atom));
  2759     return JS_LookupPropertyById(cx, obj, id, vp);
  2762 JS_PUBLIC_API(bool)
  2763 JS_LookupUCProperty(JSContext *cx, HandleObject objArg, const jschar *name, size_t namelen,
  2764                     MutableHandleValue vp)
  2766     RootedObject obj(cx, objArg);
  2767     JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  2768     if (!atom)
  2769         return false;
  2771     RootedId id(cx, AtomToId(atom));
  2772     return JS_LookupPropertyById(cx, obj, id, vp);
  2775 JS_PUBLIC_API(bool)
  2776 JS_HasPropertyById(JSContext *cx, HandleObject obj, HandleId id, bool *foundp)
  2778     RootedObject obj2(cx);
  2779     RootedShape prop(cx);
  2780     bool ok = LookupPropertyById(cx, obj, id, &obj2, &prop);
  2781     *foundp = (prop != nullptr);
  2782     return ok;
  2785 JS_PUBLIC_API(bool)
  2786 JS_HasElement(JSContext *cx, HandleObject obj, uint32_t index, bool *foundp)
  2788     AssertHeapIsIdle(cx);
  2789     CHECK_REQUEST(cx);
  2790     RootedId id(cx);
  2791     if (!IndexToId(cx, index, &id))
  2792         return false;
  2793     return JS_HasPropertyById(cx, obj, id, foundp);
  2796 JS_PUBLIC_API(bool)
  2797 JS_HasProperty(JSContext *cx, HandleObject obj, const char *name, bool *foundp)
  2799     JSAtom *atom = Atomize(cx, name, strlen(name));
  2800     if (!atom)
  2801         return false;
  2802     RootedId id(cx, AtomToId(atom));
  2803     return JS_HasPropertyById(cx, obj, id, foundp);
  2806 JS_PUBLIC_API(bool)
  2807 JS_HasUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen, bool *foundp)
  2809     JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  2810     if (!atom)
  2811         return false;
  2812     RootedId id(cx, AtomToId(atom));
  2813     return JS_HasPropertyById(cx, obj, id, foundp);
  2816 JS_PUBLIC_API(bool)
  2817 JS_AlreadyHasOwnPropertyById(JSContext *cx, HandleObject obj, HandleId id, bool *foundp)
  2819     AssertHeapIsIdle(cx);
  2820     CHECK_REQUEST(cx);
  2821     assertSameCompartment(cx, obj, id);
  2823     if (!obj->isNative()) {
  2824         RootedObject obj2(cx);
  2825         RootedShape prop(cx);
  2827         if (!LookupPropertyById(cx, obj, id, &obj2, &prop))
  2828             return false;
  2829         *foundp = (obj == obj2);
  2830         return true;
  2833     // Check for an existing native property on the objct. Be careful not to
  2834     // call any lookup or resolve hooks.
  2836     if (JSID_IS_INT(id)) {
  2837         uint32_t index = JSID_TO_INT(id);
  2839         if (obj->containsDenseElement(index)) {
  2840             *foundp = true;
  2841             return true;
  2844         if (obj->is<TypedArrayObject>() && index < obj->as<TypedArrayObject>().length()) {
  2845             *foundp = true;
  2846             return true;
  2850     *foundp = obj->nativeContains(cx, id);
  2851     return true;
  2854 JS_PUBLIC_API(bool)
  2855 JS_AlreadyHasOwnElement(JSContext *cx, HandleObject obj, uint32_t index, bool *foundp)
  2857     AssertHeapIsIdle(cx);
  2858     CHECK_REQUEST(cx);
  2859     RootedId id(cx);
  2860     if (!IndexToId(cx, index, &id))
  2861         return false;
  2862     return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
  2865 JS_PUBLIC_API(bool)
  2866 JS_AlreadyHasOwnProperty(JSContext *cx, HandleObject obj, const char *name, bool *foundp)
  2868     JSAtom *atom = Atomize(cx, name, strlen(name));
  2869     if (!atom)
  2870         return false;
  2871     RootedId id(cx, AtomToId(atom));
  2872     return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
  2875 JS_PUBLIC_API(bool)
  2876 JS_AlreadyHasOwnUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  2877                            bool *foundp)
  2879     JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  2880     if (!atom)
  2881         return false;
  2882     RootedId id(cx, AtomToId(atom));
  2883     return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
  2886 /* Wrapper functions to create wrappers with no corresponding JSJitInfo from API
  2887  * function arguments.
  2888  */
  2889 static JSPropertyOpWrapper
  2890 GetterWrapper(JSPropertyOp getter)
  2892     JSPropertyOpWrapper ret;
  2893     ret.op = getter;
  2894     ret.info = nullptr;
  2895     return ret;
  2898 static JSStrictPropertyOpWrapper
  2899 SetterWrapper(JSStrictPropertyOp setter)
  2901     JSStrictPropertyOpWrapper ret;
  2902     ret.op = setter;
  2903     ret.info = nullptr;
  2904     return ret;
  2907 static bool
  2908 DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
  2909                    const JSPropertyOpWrapper &get, const JSStrictPropertyOpWrapper &set,
  2910                    unsigned attrs, unsigned flags)
  2912     PropertyOp getter = get.op;
  2913     StrictPropertyOp setter = set.op;
  2914     /*
  2915      * JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
  2916      * throw if this happens, but we've accepted it for long enough that it's
  2917      * not worth trying to make callers change their ways. Just flip it off on
  2918      * its way through the API layer so that we can enforce this internally.
  2919      */
  2920     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
  2921         attrs &= ~JSPROP_READONLY;
  2923     /*
  2924      * When we use DefineProperty, we need full scriptable Function objects rather
  2925      * than JSNatives. However, we might be pulling this property descriptor off
  2926      * of something with JSNative property descriptors. If we are, wrap them in
  2927      * JS Function objects.
  2928      */
  2929     if (attrs & JSPROP_NATIVE_ACCESSORS) {
  2930         JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
  2931         JSFunction::Flags zeroFlags = JSAPIToJSFunctionFlags(0);
  2932         // We can't just use JS_NewFunctionById here because it
  2933         // assumes a string id.
  2934         RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : nullptr);
  2935         attrs &= ~JSPROP_NATIVE_ACCESSORS;
  2936         if (getter) {
  2937             RootedObject global(cx, (JSObject*) &obj->global());
  2938             JSFunction *getobj = NewFunction(cx, NullPtr(), (Native) getter, 0,
  2939                                              zeroFlags, global, atom);
  2940             if (!getobj)
  2941                 return false;
  2943             if (get.info)
  2944                 getobj->setJitInfo(get.info);
  2946             getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj);
  2947             attrs |= JSPROP_GETTER;
  2949         if (setter) {
  2950             // Root just the getter, since the setter is not yet a JSObject.
  2951             AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, nullptr);
  2952             RootedObject global(cx, (JSObject*) &obj->global());
  2953             JSFunction *setobj = NewFunction(cx, NullPtr(), (Native) setter, 1,
  2954                                              zeroFlags, global, atom);
  2955             if (!setobj)
  2956                 return false;
  2958             if (set.info)
  2959                 setobj->setJitInfo(set.info);
  2961             setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj);
  2962             attrs |= JSPROP_SETTER;
  2967     AssertHeapIsIdle(cx);
  2968     CHECK_REQUEST(cx);
  2969     assertSameCompartment(cx, obj, id, value,
  2970                             (attrs & JSPROP_GETTER)
  2971                             ? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
  2972                             : nullptr,
  2973                             (attrs & JSPROP_SETTER)
  2974                             ? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
  2975                             : nullptr);
  2977     return JSObject::defineGeneric(cx, obj, id, value, getter, setter, attrs);
  2980 JS_PUBLIC_API(bool)
  2981 JS_DefinePropertyById(JSContext *cx, JSObject *objArg, jsid idArg, jsval valueArg,
  2982                       JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
  2984     RootedObject obj(cx, objArg);
  2985     RootedId id(cx, idArg);
  2986     RootedValue value(cx, valueArg);
  2987     return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), SetterWrapper(setter),
  2988                               attrs, 0);
  2991 JS_PUBLIC_API(bool)
  2992 JS_DefineElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval valueArg,
  2993                  JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
  2995     RootedObject obj(cx, objArg);
  2996     RootedValue value(cx, valueArg);
  2997     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
  2998     AssertHeapIsIdle(cx);
  2999     CHECK_REQUEST(cx);
  3000     RootedId id(cx);
  3001     if (!IndexToId(cx, index, &id))
  3002         return false;
  3003     return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), SetterWrapper(setter),
  3004                               attrs, 0);
  3007 static bool
  3008 DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleValue value,
  3009                const JSPropertyOpWrapper &getter, const JSStrictPropertyOpWrapper &setter,
  3010                unsigned attrs, unsigned flags)
  3012     AutoRooterGetterSetter gsRoot(cx, attrs, const_cast<JSPropertyOp *>(&getter.op),
  3013                                   const_cast<JSStrictPropertyOp *>(&setter.op));
  3015     RootedId id(cx);
  3016     if (attrs & JSPROP_INDEX) {
  3017         id.set(INT_TO_JSID(intptr_t(name)));
  3018         attrs &= ~JSPROP_INDEX;
  3019     } else {
  3020         JSAtom *atom = Atomize(cx, name, strlen(name));
  3021         if (!atom)
  3022             return false;
  3023         id = AtomToId(atom);
  3026     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags);
  3030 static bool
  3031 DefineSelfHostedProperty(JSContext *cx,
  3032                          HandleObject obj,
  3033                          const char *name,
  3034                          const char *getterName,
  3035                          const char *setterName,
  3036                          unsigned attrs,
  3037                          unsigned flags)
  3039     RootedAtom nameAtom(cx, Atomize(cx, name, strlen(name)));
  3040     if (!nameAtom)
  3041         return false;
  3043     RootedAtom getterNameAtom(cx, Atomize(cx, getterName, strlen(getterName)));
  3044     if (!getterNameAtom)
  3045         return false;
  3047     RootedValue getterValue(cx);
  3048     if (!cx->global()->getSelfHostedFunction(cx, getterNameAtom, nameAtom,
  3049                                              0, &getterValue))
  3051         return false;
  3053     JS_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>());
  3054     RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>());
  3055     JSPropertyOp getterOp = JS_DATA_TO_FUNC_PTR(PropertyOp, getterFunc.get());
  3057     RootedFunction setterFunc(cx);
  3058     if (setterName) {
  3059         RootedAtom setterNameAtom(cx, Atomize(cx, setterName, strlen(setterName)));
  3060         if (!setterNameAtom)
  3061             return false;
  3063         RootedValue setterValue(cx);
  3064         if (!cx->global()->getSelfHostedFunction(cx, setterNameAtom, nameAtom,
  3065                                                  0, &setterValue))
  3067             return false;
  3069         JS_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>());
  3070         setterFunc = &getterValue.toObject().as<JSFunction>();
  3072     JSStrictPropertyOp setterOp = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setterFunc.get());
  3074     return DefineProperty(cx, obj, name, JS::UndefinedHandleValue,
  3075                           GetterWrapper(getterOp), SetterWrapper(setterOp),
  3076                           attrs, flags);
  3079 JS_PUBLIC_API(bool)
  3080 JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleValue value,
  3081                   unsigned attrs,
  3082                   PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  3084     return DefineProperty(cx, obj, name, value, GetterWrapper(getter), SetterWrapper(setter),
  3085                           attrs, 0);
  3088 JS_PUBLIC_API(bool)
  3089 JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleObject valueArg,
  3090                   unsigned attrs,
  3091                   PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  3093     RootedValue value(cx, ObjectValue(*valueArg));
  3094     return DefineProperty(cx, obj, name, value, GetterWrapper(getter), SetterWrapper(setter),
  3095                           attrs, 0);
  3098 JS_PUBLIC_API(bool)
  3099 JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleString valueArg,
  3100                   unsigned attrs,
  3101                   PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  3103     RootedValue value(cx, StringValue(valueArg));
  3104     return DefineProperty(cx, obj, name, value, GetterWrapper(getter), SetterWrapper(setter),
  3105                           attrs, 0);
  3108 JS_PUBLIC_API(bool)
  3109 JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, int32_t valueArg,
  3110                   unsigned attrs,
  3111                   PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  3113     Value value = Int32Value(valueArg);
  3114     return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
  3115                           GetterWrapper(getter), SetterWrapper(setter), attrs, 0);
  3118 JS_PUBLIC_API(bool)
  3119 JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, uint32_t valueArg,
  3120                   unsigned attrs,
  3121                   PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  3123     Value value = UINT_TO_JSVAL(valueArg);
  3124     return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
  3125                           GetterWrapper(getter), SetterWrapper(setter), attrs, 0);
  3128 JS_PUBLIC_API(bool)
  3129 JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, double valueArg,
  3130                   unsigned attrs,
  3131                   PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  3133     Value value = NumberValue(valueArg);
  3134     return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
  3135                           GetterWrapper(getter), SetterWrapper(setter), attrs, 0);
  3138 static bool
  3139 DefineUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  3140                  const Value &value_, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
  3141                  unsigned flags)
  3143     RootedValue value(cx, value_);
  3144     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
  3145     JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  3146     if (!atom)
  3147         return false;
  3148     RootedId id(cx, AtomToId(atom));
  3149     return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), SetterWrapper(setter),
  3150                               attrs, flags);
  3153 JS_PUBLIC_API(bool)
  3154 JS_DefineUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
  3155                     jsval valueArg, JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
  3157     RootedObject obj(cx, objArg);
  3158     RootedValue value(cx, valueArg);
  3159     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0);
  3162 JS_PUBLIC_API(bool)
  3163 JS_DefineOwnProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue descriptor, bool *bp)
  3165     AssertHeapIsIdle(cx);
  3166     CHECK_REQUEST(cx);
  3167     assertSameCompartment(cx, obj, id, descriptor);
  3169     return DefineOwnProperty(cx, obj, id, descriptor, bp);
  3172 JS_PUBLIC_API(JSObject *)
  3173 JS_DefineObject(JSContext *cx, JSObject *objArg, const char *name, const JSClass *jsclasp,
  3174                 JSObject *protoArg, unsigned attrs)
  3176     RootedObject obj(cx, objArg);
  3177     RootedObject proto(cx, protoArg);
  3178     AssertHeapIsIdle(cx);
  3179     CHECK_REQUEST(cx);
  3180     assertSameCompartment(cx, obj, proto);
  3182     const Class *clasp = Valueify(jsclasp);
  3183     if (!clasp)
  3184         clasp = &JSObject::class_;    /* default class is Object */
  3186     RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, proto, obj));
  3187     if (!nobj)
  3188         return nullptr;
  3190     RootedValue nobjValue(cx, ObjectValue(*nobj));
  3191     if (!DefineProperty(cx, obj, name, nobjValue, GetterWrapper(nullptr), SetterWrapper(nullptr),
  3192                         attrs, 0)) {
  3193         return nullptr;
  3196     return nobj;
  3199 JS_PUBLIC_API(bool)
  3200 JS_DefineConstDoubles(JSContext *cx, HandleObject obj, const JSConstDoubleSpec *cds)
  3202     bool ok;
  3203     unsigned attrs;
  3205     AssertHeapIsIdle(cx);
  3206     CHECK_REQUEST(cx);
  3207     JSPropertyOpWrapper noget = GetterWrapper(nullptr);
  3208     JSStrictPropertyOpWrapper noset = SetterWrapper(nullptr);
  3209     for (ok = true; cds->name; cds++) {
  3210         RootedValue value(cx, DoubleValue(cds->dval));
  3211         attrs = cds->flags;
  3212         if (!attrs)
  3213             attrs = JSPROP_READONLY | JSPROP_PERMANENT;
  3214         ok = DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0);
  3215         if (!ok)
  3216             break;
  3218     return ok;
  3221 JS_PUBLIC_API(bool)
  3222 JS_DefineProperties(JSContext *cx, HandleObject obj, const JSPropertySpec *ps)
  3224     bool ok;
  3225     for (ok = true; ps->name; ps++) {
  3226         if (ps->flags & JSPROP_NATIVE_ACCESSORS) {
  3227             // If you declare native accessors, then you should have a native
  3228             // getter.
  3229             JS_ASSERT(ps->getter.propertyOp.op);
  3230             // If you do not have a self-hosted getter, you should not have a
  3231             // self-hosted setter. This is the closest approximation to that
  3232             // assertion we can have with our setup.
  3233             JS_ASSERT_IF(ps->setter.propertyOp.info, ps->setter.propertyOp.op);
  3235             ok = DefineProperty(cx, obj, ps->name, JS::UndefinedHandleValue,
  3236                                 ps->getter.propertyOp, ps->setter.propertyOp, ps->flags, 0);
  3237         } else {
  3238             // If you have self-hosted getter/setter, you can't have a
  3239             // native one.
  3240             JS_ASSERT(!ps->getter.propertyOp.op && !ps->setter.propertyOp.op);
  3241             JS_ASSERT(ps->flags & JSPROP_GETTER);
  3242             /*
  3243              * During creation of the self-hosting global, we ignore all
  3244              * self-hosted properties, as that means we're currently setting up
  3245              * the global object that the self-hosted code is then compiled
  3246              * in. That means that Self-hosted properties can't be used in the
  3247              * self-hosting global itself, right now.
  3248              */
  3249             if (cx->runtime()->isSelfHostingGlobal(cx->global()))
  3250                 continue;
  3252             ok = DefineSelfHostedProperty(cx, obj, ps->name,
  3253                                           ps->getter.selfHosted.funname,
  3254                                           ps->setter.selfHosted.funname,
  3255                                           ps->flags, 0);
  3257         if (!ok)
  3258             break;
  3260     return ok;
  3263 static bool
  3264 GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id,
  3265                           MutableHandle<PropertyDescriptor> desc)
  3267     RootedObject obj2(cx);
  3268     RootedShape shape(cx);
  3270     if (!LookupPropertyById(cx, obj, id, &obj2, &shape))
  3271         return false;
  3273     desc.clear();
  3274     if (!shape)
  3275         return true;
  3277     desc.object().set(obj2);
  3278     if (obj2->isNative()) {
  3279         if (IsImplicitDenseOrTypedArrayElement(shape)) {
  3280             desc.setEnumerable();
  3281             desc.value().set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
  3282         } else {
  3283             desc.setAttributes(shape->attributes());
  3284             desc.setGetter(shape->getter());
  3285             desc.setSetter(shape->setter());
  3286             JS_ASSERT(desc.value().isUndefined());
  3287             if (shape->hasSlot())
  3288                 desc.value().set(obj2->nativeGetSlot(shape->slot()));
  3290     } else {
  3291         if (obj2->is<ProxyObject>())
  3292             return Proxy::getPropertyDescriptor(cx, obj2, id, desc);
  3293         if (!JSObject::getGenericAttributes(cx, obj2, id, &desc.attributesRef()))
  3294             return false;
  3295         JS_ASSERT(desc.getter() == nullptr);
  3296         JS_ASSERT(desc.setter() == nullptr);
  3297         JS_ASSERT(desc.value().isUndefined());
  3299     return true;
  3302 JS_PUBLIC_API(bool)
  3303 JS_GetOwnPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id,
  3304                                 MutableHandle<JSPropertyDescriptor> desc)
  3306     AssertHeapIsIdle(cx);
  3307     CHECK_REQUEST(cx);
  3309     return GetOwnPropertyDescriptor(cx, obj, id, desc);
  3312 JS_PUBLIC_API(bool)
  3313 JS_GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, const char *name,
  3314                             MutableHandle<JSPropertyDescriptor> desc)
  3316     JSAtom *atom = Atomize(cx, name, strlen(name));
  3317     if (!atom)
  3318         return false;
  3319     RootedId id(cx, AtomToId(atom));
  3320     return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc);
  3323 JS_PUBLIC_API(bool)
  3324 JS_GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id,
  3325                              MutableHandle<JSPropertyDescriptor> desc)
  3327     return GetPropertyDescriptorById(cx, obj, id, desc);
  3330 JS_PUBLIC_API(bool)
  3331 JS_GetPropertyDescriptor(JSContext *cx, HandleObject obj, const char *name,
  3332                          MutableHandle<JSPropertyDescriptor> desc)
  3334     JSAtom *atom = Atomize(cx, name, strlen(name));
  3335     if (!atom)
  3336         return false;
  3337     RootedId id(cx, AtomToId(atom));
  3338     return atom && JS_GetPropertyDescriptorById(cx, obj, id, desc);
  3341 JS_PUBLIC_API(bool)
  3342 JS_GetPropertyById(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
  3344     return JS_ForwardGetPropertyTo(cx, obj, id, obj, vp);
  3347 JS_PUBLIC_API(bool)
  3348 JS_ForwardGetPropertyTo(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject onBehalfOf,
  3349                         JS::MutableHandleValue vp)
  3351     AssertHeapIsIdle(cx);
  3352     CHECK_REQUEST(cx);
  3353     assertSameCompartment(cx, obj, id);
  3354     assertSameCompartment(cx, onBehalfOf);
  3356     return JSObject::getGeneric(cx, obj, onBehalfOf, id, vp);
  3359 JS_PUBLIC_API(bool)
  3360 JS_GetElement(JSContext *cx, HandleObject objArg, uint32_t index, MutableHandleValue vp)
  3362     return JS_ForwardGetElementTo(cx, objArg, index, objArg, vp);
  3365 JS_PUBLIC_API(bool)
  3366 JS_ForwardGetElementTo(JSContext *cx, HandleObject obj, uint32_t index, HandleObject onBehalfOf,
  3367                        MutableHandleValue vp)
  3369     AssertHeapIsIdle(cx);
  3370     CHECK_REQUEST(cx);
  3371     assertSameCompartment(cx, obj);
  3373     return JSObject::getElement(cx, obj, onBehalfOf, index, vp);
  3376 JS_PUBLIC_API(bool)
  3377 JS_GetProperty(JSContext *cx, HandleObject obj, const char *name, MutableHandleValue vp)
  3379     JSAtom *atom = Atomize(cx, name, strlen(name));
  3380     if (!atom)
  3381         return false;
  3382     RootedId id(cx, AtomToId(atom));
  3383     return JS_GetPropertyById(cx, obj, id, vp);
  3386 JS_PUBLIC_API(bool)
  3387 JS_GetUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  3388                  MutableHandleValue vp)
  3390     JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  3391     if (!atom)
  3392         return false;
  3393     RootedId id(cx, AtomToId(atom));
  3394     return JS_GetPropertyById(cx, obj, id, vp);
  3397 JS_PUBLIC_API(bool)
  3398 JS_SetPropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue v)
  3400     RootedValue value(cx, v);
  3401     AssertHeapIsIdle(cx);
  3402     CHECK_REQUEST(cx);
  3403     assertSameCompartment(cx, obj, id);
  3405     return JSObject::setGeneric(cx, obj, obj, id, &value, false);
  3408 static bool
  3409 SetElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
  3411     AssertHeapIsIdle(cx);
  3412     CHECK_REQUEST(cx);
  3413     assertSameCompartment(cx, obj, vp);
  3415     return JSObject::setElement(cx, obj, obj, index, vp, false);
  3418 JS_PUBLIC_API(bool)
  3419 JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v)
  3421     RootedValue value(cx, v);
  3422     return SetElement(cx, obj, index, &value);
  3425 JS_PUBLIC_API(bool)
  3426 JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleObject v)
  3428     RootedValue value(cx, ObjectOrNullValue(v));
  3429     return SetElement(cx, obj, index, &value);
  3432 JS_PUBLIC_API(bool)
  3433 JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleString v)
  3435     RootedValue value(cx, StringValue(v));
  3436     return SetElement(cx, obj, index, &value);
  3439 JS_PUBLIC_API(bool)
  3440 JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, int32_t v)
  3442     RootedValue value(cx, NumberValue(v));
  3443     return SetElement(cx, obj, index, &value);
  3446 JS_PUBLIC_API(bool)
  3447 JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, uint32_t v)
  3449     RootedValue value(cx, NumberValue(v));
  3450     return SetElement(cx, obj, index, &value);
  3453 JS_PUBLIC_API(bool)
  3454 JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, double v)
  3456     RootedValue value(cx, NumberValue(v));
  3457     return SetElement(cx, obj, index, &value);
  3460 JS_PUBLIC_API(bool)
  3461 JS_SetProperty(JSContext *cx, HandleObject obj, const char *name, HandleValue v)
  3463     JSAtom *atom = Atomize(cx, name, strlen(name));
  3464     if (!atom)
  3465         return false;
  3466     RootedId id(cx, AtomToId(atom));
  3467     return JS_SetPropertyById(cx, obj, id, v);
  3470 JS_PUBLIC_API(bool)
  3471 JS_SetUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  3472                  HandleValue v)
  3474     JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  3475     if (!atom)
  3476         return false;
  3477     RootedId id(cx, AtomToId(atom));
  3478     return JS_SetPropertyById(cx, obj, id, v);
  3481 JS_PUBLIC_API(bool)
  3482 JS_DeletePropertyById2(JSContext *cx, HandleObject obj, HandleId id, bool *result)
  3484     AssertHeapIsIdle(cx);
  3485     CHECK_REQUEST(cx);
  3486     assertSameCompartment(cx, obj, id);
  3488     return JSObject::deleteByValue(cx, obj, IdToValue(id), result);
  3491 JS_PUBLIC_API(bool)
  3492 JS_DeleteElement2(JSContext *cx, HandleObject obj, uint32_t index, bool *result)
  3494     AssertHeapIsIdle(cx);
  3495     CHECK_REQUEST(cx);
  3496     assertSameCompartment(cx, obj);
  3498     return JSObject::deleteElement(cx, obj, index, result);
  3501 JS_PUBLIC_API(bool)
  3502 JS_DeleteProperty2(JSContext *cx, HandleObject obj, const char *name, bool *result)
  3504     CHECK_REQUEST(cx);
  3505     assertSameCompartment(cx, obj);
  3507     JSAtom *atom = Atomize(cx, name, strlen(name));
  3508     if (!atom)
  3509         return false;
  3510     return JSObject::deleteByValue(cx, obj, StringValue(atom), result);
  3513 JS_PUBLIC_API(bool)
  3514 JS_DeleteUCProperty2(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  3515                      bool *result)
  3517     CHECK_REQUEST(cx);
  3518     assertSameCompartment(cx, obj);
  3520     JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  3521     if (!atom)
  3522         return false;
  3523     return JSObject::deleteByValue(cx, obj, StringValue(atom), result);
  3526 JS_PUBLIC_API(bool)
  3527 JS_DeletePropertyById(JSContext *cx, HandleObject obj, HandleId id)
  3529     bool junk;
  3530     return JS_DeletePropertyById2(cx, obj, id, &junk);
  3533 JS_PUBLIC_API(bool)
  3534 JS_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index)
  3536     bool junk;
  3537     return JS_DeleteElement2(cx, obj, index, &junk);
  3540 JS_PUBLIC_API(bool)
  3541 JS_DeleteProperty(JSContext *cx, HandleObject obj, const char *name)
  3543     bool junk;
  3544     return JS_DeleteProperty2(cx, obj, name, &junk);
  3547 static Shape *
  3548 LastConfigurableShape(JSObject *obj)
  3550     for (Shape::Range<NoGC> r(obj->lastProperty()); !r.empty(); r.popFront()) {
  3551         Shape *shape = &r.front();
  3552         if (shape->configurable())
  3553             return shape;
  3555     return nullptr;
  3558 JS_PUBLIC_API(void)
  3559 JS_ClearNonGlobalObject(JSContext *cx, HandleObject obj)
  3561     AssertHeapIsIdle(cx);
  3562     CHECK_REQUEST(cx);
  3563     assertSameCompartment(cx, obj);
  3565     JS_ASSERT(!obj->is<GlobalObject>());
  3567     if (!obj->isNative())
  3568         return;
  3570     /* Remove all configurable properties from obj. */
  3571     RootedShape shape(cx);
  3572     while ((shape = LastConfigurableShape(obj))) {
  3573         if (!obj->removeProperty(cx, shape->propid()))
  3574             return;
  3577     /* Set all remaining writable plain data properties to undefined. */
  3578     for (Shape::Range<NoGC> r(obj->lastProperty()); !r.empty(); r.popFront()) {
  3579         Shape *shape = &r.front();
  3580         if (shape->isDataDescriptor() &&
  3581             shape->writable() &&
  3582             shape->hasDefaultSetter() &&
  3583             shape->hasSlot())
  3585             obj->nativeSetSlot(shape->slot(), UndefinedValue());
  3590 JS_PUBLIC_API(void)
  3591 JS_SetAllNonReservedSlotsToUndefined(JSContext *cx, JSObject *objArg)
  3593     RootedObject obj(cx, objArg);
  3594     AssertHeapIsIdle(cx);
  3595     CHECK_REQUEST(cx);
  3596     assertSameCompartment(cx, obj);
  3598     if (!obj->isNative())
  3599         return;
  3601     const Class *clasp = obj->getClass();
  3602     unsigned numReserved = JSCLASS_RESERVED_SLOTS(clasp);
  3603     unsigned numSlots = obj->slotSpan();
  3604     for (unsigned i = numReserved; i < numSlots; i++)
  3605         obj->setSlot(i, UndefinedValue());
  3608 JS_PUBLIC_API(JSIdArray *)
  3609 JS_Enumerate(JSContext *cx, HandleObject obj)
  3611     AssertHeapIsIdle(cx);
  3612     CHECK_REQUEST(cx);
  3613     assertSameCompartment(cx, obj);
  3615     AutoIdVector props(cx);
  3616     JSIdArray *ida;
  3617     if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
  3618         return nullptr;
  3619     return ida;
  3622 /*
  3623  * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
  3624  *     prop_iterator_class somehow...
  3625  * + preserve the obj->enumerate API while optimizing the native object case
  3626  * + native case here uses a JSShape *, but that iterates in reverse!
  3627  * + so we make non-native match, by reverse-iterating after JS_Enumerating
  3628  */
  3629 static const uint32_t JSSLOT_ITER_INDEX = 0;
  3631 static void
  3632 prop_iter_finalize(FreeOp *fop, JSObject *obj)
  3634     void *pdata = obj->getPrivate();
  3635     if (!pdata)
  3636         return;
  3638     if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
  3639         /* Non-native case: destroy the ida enumerated when obj was created. */
  3640         JSIdArray *ida = (JSIdArray *) pdata;
  3641         fop->free_(ida);
  3645 static void
  3646 prop_iter_trace(JSTracer *trc, JSObject *obj)
  3648     void *pdata = obj->getPrivate();
  3649     if (!pdata)
  3650         return;
  3652     if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) {
  3653         /*
  3654          * Native case: just mark the next property to visit. We don't need a
  3655          * barrier here because the pointer is updated via setPrivate, which
  3656          * always takes a barrier.
  3657          */
  3658         Shape *tmp = static_cast<Shape *>(pdata);
  3659         MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
  3660         obj->setPrivateUnbarriered(tmp);
  3661     } else {
  3662         /* Non-native case: mark each id in the JSIdArray private. */
  3663         JSIdArray *ida = (JSIdArray *) pdata;
  3664         MarkIdRange(trc, ida->length, ida->vector, "prop iter");
  3668 static const Class prop_iter_class = {
  3669     "PropertyIterator",
  3670     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1),
  3671     JS_PropertyStub,         /* addProperty */
  3672     JS_DeletePropertyStub,   /* delProperty */
  3673     JS_PropertyStub,         /* getProperty */
  3674     JS_StrictPropertyStub,   /* setProperty */
  3675     JS_EnumerateStub,
  3676     JS_ResolveStub,
  3677     JS_ConvertStub,
  3678     prop_iter_finalize,
  3679     nullptr,        /* call        */
  3680     nullptr,        /* hasInstance */
  3681     nullptr,        /* construct   */
  3682     prop_iter_trace
  3683 };
  3685 JS_PUBLIC_API(JSObject *)
  3686 JS_NewPropertyIterator(JSContext *cx, HandleObject obj)
  3688     AssertHeapIsIdle(cx);
  3689     CHECK_REQUEST(cx);
  3690     assertSameCompartment(cx, obj);
  3692     RootedObject iterobj(cx, NewObjectWithClassProto(cx, &prop_iter_class, nullptr, obj));
  3693     if (!iterobj)
  3694         return nullptr;
  3696     int index;
  3697     if (obj->isNative()) {
  3698         /* Native case: start with the last property in obj. */
  3699         iterobj->setPrivateGCThing(obj->lastProperty());
  3700         index = -1;
  3701     } else {
  3702         /* Non-native case: enumerate a JSIdArray and keep it via private. */
  3703         JSIdArray *ida = JS_Enumerate(cx, obj);
  3704         if (!ida)
  3705             return nullptr;
  3706         iterobj->setPrivate((void *)ida);
  3707         index = ida->length;
  3710     /* iterobj cannot escape to other threads here. */
  3711     iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
  3712     return iterobj;
  3715 JS_PUBLIC_API(bool)
  3716 JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp)
  3718     AssertHeapIsIdle(cx);
  3719     CHECK_REQUEST(cx);
  3720     assertSameCompartment(cx, iterobj);
  3721     int32_t i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
  3722     if (i < 0) {
  3723         /* Native case: private data is a property tree node pointer. */
  3724         JS_ASSERT(iterobj->getParent()->isNative());
  3725         Shape *shape = static_cast<Shape *>(iterobj->getPrivate());
  3727         while (shape->previous() && !shape->enumerable())
  3728             shape = shape->previous();
  3730         if (!shape->previous()) {
  3731             JS_ASSERT(shape->isEmptyShape());
  3732             *idp = JSID_VOID;
  3733         } else {
  3734             iterobj->setPrivateGCThing(const_cast<Shape *>(shape->previous().get()));
  3735             *idp = shape->propid();
  3737     } else {
  3738         /* Non-native case: use the ida enumerated when iterobj was created. */
  3739         JSIdArray *ida = (JSIdArray *) iterobj->getPrivate();
  3740         JS_ASSERT(i <= ida->length);
  3741         STATIC_ASSUME(i <= ida->length);
  3742         if (i == 0) {
  3743             *idp = JSID_VOID;
  3744         } else {
  3745             *idp = ida->vector[--i];
  3746             iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(i));
  3749     return true;
  3752 JS_PUBLIC_API(jsval)
  3753 JS_GetReservedSlot(JSObject *obj, uint32_t index)
  3755     return obj->getReservedSlot(index);
  3758 JS_PUBLIC_API(void)
  3759 JS_SetReservedSlot(JSObject *obj, uint32_t index, Value value)
  3761     obj->setReservedSlot(index, value);
  3764 JS_PUBLIC_API(JSObject *)
  3765 JS_NewArrayObject(JSContext *cx, const JS::HandleValueArray& contents)
  3767     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  3768     AssertHeapIsIdle(cx);
  3769     CHECK_REQUEST(cx);
  3771     assertSameCompartment(cx, contents);
  3772     return NewDenseCopiedArray(cx, contents.length(), contents.begin());
  3775 JS_PUBLIC_API(JSObject *)
  3776 JS_NewArrayObject(JSContext *cx, size_t length)
  3778     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  3779     AssertHeapIsIdle(cx);
  3780     CHECK_REQUEST(cx);
  3782     return NewDenseAllocatedArray(cx, length);
  3785 JS_PUBLIC_API(bool)
  3786 JS_IsArrayObject(JSContext *cx, JS::HandleObject obj)
  3788     assertSameCompartment(cx, obj);
  3789     return ObjectClassIs(obj, ESClass_Array, cx);
  3792 JS_PUBLIC_API(bool)
  3793 JS_IsArrayObject(JSContext *cx, JS::HandleValue value)
  3795     if (!value.isObject())
  3796         return false;
  3797     RootedObject obj(cx, &value.toObject());
  3798     return JS_IsArrayObject(cx, obj);
  3801 JS_PUBLIC_API(bool)
  3802 JS_GetArrayLength(JSContext *cx, HandleObject obj, uint32_t *lengthp)
  3804     AssertHeapIsIdle(cx);
  3805     CHECK_REQUEST(cx);
  3806     assertSameCompartment(cx, obj);
  3807     return GetLengthProperty(cx, obj, lengthp);
  3810 JS_PUBLIC_API(bool)
  3811 JS_SetArrayLength(JSContext *cx, HandleObject obj, uint32_t length)
  3813     AssertHeapIsIdle(cx);
  3814     CHECK_REQUEST(cx);
  3815     assertSameCompartment(cx, obj);
  3816     return SetLengthProperty(cx, obj, length);
  3819 JS_PUBLIC_API(void)
  3820 JS_HoldPrincipals(JSPrincipals *principals)
  3822     ++principals->refcount;
  3825 JS_PUBLIC_API(void)
  3826 JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals)
  3828     int rc = --principals->refcount;
  3829     if (rc == 0)
  3830         rt->destroyPrincipals(principals);
  3833 JS_PUBLIC_API(void)
  3834 JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *scb)
  3836     JS_ASSERT(scb != &NullSecurityCallbacks);
  3837     rt->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
  3840 JS_PUBLIC_API(const JSSecurityCallbacks *)
  3841 JS_GetSecurityCallbacks(JSRuntime *rt)
  3843     return (rt->securityCallbacks != &NullSecurityCallbacks) ? rt->securityCallbacks : nullptr;
  3846 JS_PUBLIC_API(void)
  3847 JS_SetTrustedPrincipals(JSRuntime *rt, const JSPrincipals *prin)
  3849     rt->setTrustedPrincipals(prin);
  3852 extern JS_PUBLIC_API(void)
  3853 JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals)
  3855     JS_ASSERT(destroyPrincipals);
  3856     JS_ASSERT(!rt->destroyPrincipals);
  3857     rt->destroyPrincipals = destroyPrincipals;
  3860 JS_PUBLIC_API(JSFunction *)
  3861 JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
  3862                HandleObject parent, const char *name)
  3864     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  3866     AssertHeapIsIdle(cx);
  3867     CHECK_REQUEST(cx);
  3868     assertSameCompartment(cx, parent);
  3870     RootedAtom atom(cx);
  3871     if (name) {
  3872         atom = Atomize(cx, name, strlen(name));
  3873         if (!atom)
  3874             return nullptr;
  3877     JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
  3878     return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
  3881 JS_PUBLIC_API(JSFunction *)
  3882 JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
  3883                    HandleObject parent, HandleId id)
  3885     JS_ASSERT(JSID_IS_STRING(id));
  3886     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  3887     JS_ASSERT(native);
  3888     AssertHeapIsIdle(cx);
  3889     CHECK_REQUEST(cx);
  3890     assertSameCompartment(cx, parent);
  3892     RootedAtom name(cx, JSID_TO_ATOM(id));
  3893     JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
  3894     return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, name);
  3897 JS_PUBLIC_API(JSFunction *)
  3898 JS::GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, HandleId id, unsigned nargs)
  3900     JS_ASSERT(JSID_IS_STRING(id));
  3901     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  3902     AssertHeapIsIdle(cx);
  3903     CHECK_REQUEST(cx);
  3905     RootedAtom name(cx, JSID_TO_ATOM(id));
  3906     RootedAtom shName(cx, Atomize(cx, selfHostedName, strlen(selfHostedName)));
  3907     if (!shName)
  3908         return nullptr;
  3909     RootedValue funVal(cx);
  3910     if (!cx->global()->getSelfHostedFunction(cx, shName, name, nargs, &funVal))
  3911         return nullptr;
  3912     return &funVal.toObject().as<JSFunction>();
  3915 JS_PUBLIC_API(JSObject *)
  3916 JS_CloneFunctionObject(JSContext *cx, HandleObject funobj, HandleObject parentArg)
  3918     RootedObject parent(cx, parentArg);
  3920     AssertHeapIsIdle(cx);
  3921     CHECK_REQUEST(cx);
  3922     assertSameCompartment(cx, parent);
  3923     // Note that funobj can be in a different compartment.
  3925     if (!parent)
  3926         parent = cx->global();
  3928     if (!funobj->is<JSFunction>()) {
  3929         AutoCompartment ac(cx, funobj);
  3930         RootedValue v(cx, ObjectValue(*funobj));
  3931         ReportIsNotFunction(cx, v);
  3932         return nullptr;
  3935     RootedFunction fun(cx, &funobj->as<JSFunction>());
  3936     if (fun->isInterpretedLazy()) {
  3937         AutoCompartment ac(cx, funobj);
  3938         if (!fun->getOrCreateScript(cx))
  3939             return nullptr;
  3941     /*
  3942      * If a function was compiled to be lexically nested inside some other
  3943      * script, we cannot clone it without breaking the compiler's assumptions.
  3944      */
  3945     if (fun->isInterpreted() && (fun->nonLazyScript()->enclosingStaticScope() ||
  3946         (fun->nonLazyScript()->compileAndGo() && !parent->is<GlobalObject>())))
  3948         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
  3949         return nullptr;
  3952     if (fun->isBoundFunction()) {
  3953         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
  3954         return nullptr;
  3957     if (fun->isNative() && IsAsmJSModuleNative(fun->native())) {
  3958         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
  3959         return nullptr;
  3962     return CloneFunctionObject(cx, fun, parent, fun->getAllocKind());
  3965 JS_PUBLIC_API(JSObject *)
  3966 JS_GetFunctionObject(JSFunction *fun)
  3968     return fun;
  3971 JS_PUBLIC_API(JSString *)
  3972 JS_GetFunctionId(JSFunction *fun)
  3974     return fun->atom();
  3977 JS_PUBLIC_API(JSString *)
  3978 JS_GetFunctionDisplayId(JSFunction *fun)
  3980     return fun->displayAtom();
  3983 JS_PUBLIC_API(uint16_t)
  3984 JS_GetFunctionArity(JSFunction *fun)
  3986     return fun->nargs();
  3989 JS_PUBLIC_API(bool)
  3990 JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
  3992     return obj->is<JSFunction>();
  3995 JS_PUBLIC_API(bool)
  3996 JS_ObjectIsCallable(JSContext *cx, JSObject *obj)
  3998     return obj->isCallable();
  4001 JS_PUBLIC_API(bool)
  4002 JS_IsNativeFunction(JSObject *funobj, JSNative call)
  4004     if (!funobj->is<JSFunction>())
  4005         return false;
  4006     JSFunction *fun = &funobj->as<JSFunction>();
  4007     return fun->isNative() && fun->native() == call;
  4010 extern JS_PUBLIC_API(bool)
  4011 JS_IsConstructor(JSFunction *fun)
  4013     return fun->isNativeConstructor() || fun->isInterpretedConstructor();
  4016 JS_PUBLIC_API(JSObject*)
  4017 JS_BindCallable(JSContext *cx, HandleObject target, HandleObject newThis)
  4019     RootedValue thisArg(cx, ObjectValue(*newThis));
  4020     return js_fun_bind(cx, target, thisArg, nullptr, 0);
  4023 static bool
  4024 js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp)
  4026     CallArgs args = CallArgsFromVp(argc, vp);
  4028     const JSFunctionSpec *fs = (JSFunctionSpec *)
  4029         args.callee().as<JSFunction>().getExtendedSlot(0).toPrivate();
  4030     JS_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0);
  4032     if (argc < 1) {
  4033         js_ReportMissingArg(cx, args.calleev(), 0);
  4034         return false;
  4037     /*
  4038      * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
  4039      * which is almost always the class constructor object, e.g. Array.  Then
  4040      * call the corresponding prototype native method with our first argument
  4041      * passed as |this|.
  4042      */
  4043     memmove(vp + 1, vp + 2, argc * sizeof(jsval));
  4045     /* Clear the last parameter in case too few arguments were passed. */
  4046     vp[2 + --argc].setUndefined();
  4048     return fs->call.op(cx, argc, vp);
  4051 JS_PUBLIC_API(bool)
  4052 JS_DefineFunctions(JSContext *cx, HandleObject obj, const JSFunctionSpec *fs)
  4054     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4055     AssertHeapIsIdle(cx);
  4056     CHECK_REQUEST(cx);
  4057     assertSameCompartment(cx, obj);
  4059     RootedObject ctor(cx);
  4061     for (; fs->name; fs++) {
  4062         RootedAtom atom(cx);
  4063         // If the name starts with "@@", it must be a well-known symbol.
  4064         if (fs->name[0] != '@' || fs->name[1] != '@')
  4065             atom = Atomize(cx, fs->name, strlen(fs->name));
  4066         else if (strcmp(fs->name, "@@iterator") == 0)
  4067             // FIXME: This atom should be a symbol: bug 918828.
  4068             atom = cx->names().std_iterator;
  4069         else
  4070             JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_SYMBOL, fs->name);
  4071         if (!atom)
  4072             return false;
  4074         Rooted<jsid> id(cx, AtomToId(atom));
  4076         /*
  4077          * Define a generic arity N+1 static method for the arity N prototype
  4078          * method if flags contains JSFUN_GENERIC_NATIVE.
  4079          */
  4080         unsigned flags = fs->flags;
  4081         if (flags & JSFUN_GENERIC_NATIVE) {
  4082             if (!ctor) {
  4083                 ctor = JS_GetConstructor(cx, obj);
  4084                 if (!ctor)
  4085                     return false;
  4088             flags &= ~JSFUN_GENERIC_NATIVE;
  4089             JSFunction *fun = DefineFunction(cx, ctor, id,
  4090                                              js_generic_native_method_dispatcher,
  4091                                              fs->nargs + 1, flags,
  4092                                              JSFunction::ExtendedFinalizeKind);
  4093             if (!fun)
  4094                 return false;
  4096             /*
  4097              * As jsapi.h notes, fs must point to storage that lives as long
  4098              * as fun->object lives.
  4099              */
  4100             fun->setExtendedSlot(0, PrivateValue(const_cast<JSFunctionSpec*>(fs)));
  4103         /*
  4104          * Delay cloning self-hosted functions until they are called. This is
  4105          * achieved by passing DefineFunction a nullptr JSNative which
  4106          * produces an interpreted JSFunction where !hasScript. Interpreted
  4107          * call paths then call InitializeLazyFunctionScript if !hasScript.
  4108          */
  4109         if (fs->selfHostedName) {
  4110             JS_ASSERT(!fs->call.op);
  4111             JS_ASSERT(!fs->call.info);
  4112             /*
  4113              * During creation of the self-hosting global, we ignore all
  4114              * self-hosted functions, as that means we're currently setting up
  4115              * the global object that the self-hosted code is then compiled
  4116              * in. Self-hosted functions can access each other via their names,
  4117              * but not via the builtin classes they get installed into.
  4118              */
  4119             if (cx->runtime()->isSelfHostingGlobal(cx->global()))
  4120                 continue;
  4122             RootedAtom shName(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
  4123             if (!shName)
  4124                 return false;
  4125             RootedValue funVal(cx);
  4126             if (!cx->global()->getSelfHostedFunction(cx, shName, atom, fs->nargs, &funVal))
  4127                 return false;
  4128             if (!JSObject::defineGeneric(cx, obj, id, funVal, nullptr, nullptr, flags))
  4129                 return false;
  4130         } else {
  4131             JSFunction *fun = DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags);
  4132             if (!fun)
  4133                 return false;
  4134             if (fs->call.info)
  4135                 fun->setJitInfo(fs->call.info);
  4138     return true;
  4141 JS_PUBLIC_API(JSFunction *)
  4142 JS_DefineFunction(JSContext *cx, HandleObject obj, const char *name, JSNative call,
  4143                   unsigned nargs, unsigned attrs)
  4145     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4146     AssertHeapIsIdle(cx);
  4147     CHECK_REQUEST(cx);
  4148     assertSameCompartment(cx, obj);
  4149     JSAtom *atom = Atomize(cx, name, strlen(name));
  4150     if (!atom)
  4151         return nullptr;
  4152     Rooted<jsid> id(cx, AtomToId(atom));
  4153     return DefineFunction(cx, obj, id, call, nargs, attrs);
  4156 JS_PUBLIC_API(JSFunction *)
  4157 JS_DefineUCFunction(JSContext *cx, HandleObject obj,
  4158                     const jschar *name, size_t namelen, JSNative call,
  4159                     unsigned nargs, unsigned attrs)
  4161     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4162     AssertHeapIsIdle(cx);
  4163     CHECK_REQUEST(cx);
  4164     assertSameCompartment(cx, obj);
  4165     JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  4166     if (!atom)
  4167         return nullptr;
  4168     Rooted<jsid> id(cx, AtomToId(atom));
  4169     return DefineFunction(cx, obj, id, call, nargs, attrs);
  4172 extern JS_PUBLIC_API(JSFunction *)
  4173 JS_DefineFunctionById(JSContext *cx, HandleObject obj, HandleId id, JSNative call,
  4174                       unsigned nargs, unsigned attrs)
  4176     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4177     AssertHeapIsIdle(cx);
  4178     CHECK_REQUEST(cx);
  4179     assertSameCompartment(cx, obj);
  4180     return DefineFunction(cx, obj, id, call, nargs, attrs);
  4183 struct AutoLastFrameCheck
  4185     AutoLastFrameCheck(JSContext *cx
  4186                        MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  4187       : cx(cx)
  4189         JS_ASSERT(cx);
  4190         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  4193     ~AutoLastFrameCheck() {
  4194         if (cx->isExceptionPending() &&
  4195             !JS_IsRunning(cx) &&
  4196             !cx->options().dontReportUncaught()) {
  4197             js_ReportUncaughtException(cx);
  4201   private:
  4202     JSContext *cx;
  4203     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  4204 };
  4206 /* Use the fastest available getc. */
  4207 #if defined(HAVE_GETC_UNLOCKED)
  4208 # define fast_getc getc_unlocked
  4209 #elif defined(HAVE__GETC_NOLOCK)
  4210 # define fast_getc _getc_nolock
  4211 #else
  4212 # define fast_getc getc
  4213 #endif
  4215 typedef js::Vector<char, 8, TempAllocPolicy> FileContents;
  4217 static bool
  4218 ReadCompleteFile(JSContext *cx, FILE *fp, FileContents &buffer)
  4220     /* Get the complete length of the file, if possible. */
  4221     struct stat st;
  4222     int ok = fstat(fileno(fp), &st);
  4223     if (ok != 0)
  4224         return false;
  4225     if (st.st_size > 0) {
  4226         if (!buffer.reserve(st.st_size))
  4227             return false;
  4230     // Read in the whole file. Note that we can't assume the data's length
  4231     // is actually st.st_size, because 1) some files lie about their size
  4232     // (/dev/zero and /dev/random), and 2) reading files in text mode on
  4233     // Windows collapses "\r\n" pairs to single \n characters.
  4234     for (;;) {
  4235         int c = fast_getc(fp);
  4236         if (c == EOF)
  4237             break;
  4238         if (!buffer.append(c))
  4239             return false;
  4242     return true;
  4245 namespace {
  4247 class AutoFile
  4249     FILE *fp_;
  4250   public:
  4251     AutoFile()
  4252       : fp_(nullptr)
  4253     {}
  4254     ~AutoFile()
  4256         if (fp_ && fp_ != stdin)
  4257             fclose(fp_);
  4259     FILE *fp() const { return fp_; }
  4260     bool open(JSContext *cx, const char *filename);
  4261     bool readAll(JSContext *cx, FileContents &buffer)
  4263         JS_ASSERT(fp_);
  4264         return ReadCompleteFile(cx, fp_, buffer);
  4266 };
  4268 } /* anonymous namespace */
  4270 /*
  4271  * Open a source file for reading. Supports "-" and nullptr to mean stdin. The
  4272  * return value must be fclosed unless it is stdin.
  4273  */
  4274 bool
  4275 AutoFile::open(JSContext *cx, const char *filename)
  4277     if (!filename || strcmp(filename, "-") == 0) {
  4278         fp_ = stdin;
  4279     } else {
  4280         fp_ = fopen(filename, "r");
  4281         if (!fp_) {
  4282             JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_OPEN,
  4283                                  filename, "No such file or directory");
  4284             return false;
  4287     return true;
  4290 JSObject * const JS::ReadOnlyCompileOptions::nullObjectPtr = nullptr;
  4292 void
  4293 JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions &rhs)
  4295     version = rhs.version;
  4296     versionSet = rhs.versionSet;
  4297     utf8 = rhs.utf8;
  4298     lineno = rhs.lineno;
  4299     column = rhs.column;
  4300     compileAndGo = rhs.compileAndGo;
  4301     forEval = rhs.forEval;
  4302     noScriptRval = rhs.noScriptRval;
  4303     selfHostingMode = rhs.selfHostingMode;
  4304     canLazilyParse = rhs.canLazilyParse;
  4305     strictOption = rhs.strictOption;
  4306     extraWarningsOption = rhs.extraWarningsOption;
  4307     werrorOption = rhs.werrorOption;
  4308     asmJSOption = rhs.asmJSOption;
  4309     forceAsync = rhs.forceAsync;
  4310     installedFile = rhs.installedFile;
  4311     sourceIsLazy = rhs.sourceIsLazy;
  4312     introductionType = rhs.introductionType;
  4313     introductionLineno = rhs.introductionLineno;
  4314     introductionOffset = rhs.introductionOffset;
  4315     hasIntroductionInfo = rhs.hasIntroductionInfo;
  4318 JSPrincipals *
  4319 JS::ReadOnlyCompileOptions::originPrincipals(ExclusiveContext *cx) const
  4321     return NormalizeOriginPrincipals(cx->compartment()->principals, originPrincipals_);
  4324 JS::OwningCompileOptions::OwningCompileOptions(JSContext *cx)
  4325     : ReadOnlyCompileOptions(),
  4326       runtime(GetRuntime(cx)),
  4327       elementRoot(cx),
  4328       elementAttributeNameRoot(cx),
  4329       introductionScriptRoot(cx)
  4333 JS::OwningCompileOptions::~OwningCompileOptions()
  4335     if (originPrincipals_)
  4336         JS_DropPrincipals(runtime, originPrincipals_);
  4338     // OwningCompileOptions always owns these, so these casts are okay.
  4339     js_free(const_cast<char *>(filename_));
  4340     js_free(const_cast<jschar *>(sourceMapURL_));
  4341     js_free(const_cast<char *>(introducerFilename_));
  4344 bool
  4345 JS::OwningCompileOptions::copy(JSContext *cx, const ReadOnlyCompileOptions &rhs)
  4347     copyPODOptions(rhs);
  4349     setOriginPrincipals(rhs.originPrincipals(cx));
  4350     setElement(rhs.element());
  4351     setElementAttributeName(rhs.elementAttributeName());
  4352     setIntroductionScript(rhs.introductionScript());
  4354     return (setFileAndLine(cx, rhs.filename(), rhs.lineno) &&
  4355             setSourceMapURL(cx, rhs.sourceMapURL()) &&
  4356             setIntroducerFilename(cx, rhs.introducerFilename()));
  4359 bool
  4360 JS::OwningCompileOptions::setFile(JSContext *cx, const char *f)
  4362     char *copy = nullptr;
  4363     if (f) {
  4364         copy = JS_strdup(cx, f);
  4365         if (!copy)
  4366             return false;
  4369     // OwningCompileOptions always owns filename_, so this cast is okay.
  4370     js_free(const_cast<char *>(filename_));
  4372     filename_ = copy;
  4373     return true;
  4376 bool
  4377 JS::OwningCompileOptions::setFileAndLine(JSContext *cx, const char *f, unsigned l)
  4379     if (!setFile(cx, f))
  4380         return false;
  4382     lineno = l;
  4383     return true;
  4386 bool
  4387 JS::OwningCompileOptions::setSourceMapURL(JSContext *cx, const jschar *s)
  4389     jschar *copy = nullptr;
  4390     if (s) {
  4391         copy = js_strdup(cx, s);
  4392         if (!copy)
  4393             return false;
  4396     // OwningCompileOptions always owns sourceMapURL_, so this cast is okay.
  4397     js_free(const_cast<jschar *>(sourceMapURL_));
  4399     sourceMapURL_ = copy;
  4400     return true;
  4403 bool
  4404 JS::OwningCompileOptions::setIntroducerFilename(JSContext *cx, const char *s)
  4406     char *copy = nullptr;
  4407     if (s) {
  4408         copy = JS_strdup(cx, s);
  4409         if (!copy)
  4410             return false;
  4413     // OwningCompileOptions always owns introducerFilename_, so this cast is okay.
  4414     js_free(const_cast<char *>(introducerFilename_));
  4416     introducerFilename_ = copy;
  4417     return true;
  4420 bool
  4421 JS::OwningCompileOptions::wrap(JSContext *cx, JSCompartment *compartment)
  4423     if (!compartment->wrap(cx, &elementRoot))
  4424         return false;
  4425     if (elementAttributeNameRoot) {
  4426         if (!compartment->wrap(cx, elementAttributeNameRoot.address()))
  4427             return false;
  4430     // There is no equivalent of cross-compartment wrappers for scripts. If
  4431     // the introduction script would be in a different compartment from the
  4432     // compiled code, we would be creating a cross-compartment script
  4433     // reference, which would be bogus. In that case, just don't bother to
  4434     // retain the introduction script.
  4435     if (introductionScriptRoot) {
  4436         if (introductionScriptRoot->compartment() != compartment)
  4437             introductionScriptRoot = nullptr;
  4440     return true;
  4443 JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version)
  4444     : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
  4445       introductionScriptRoot(cx)
  4447     this->version = (version != JSVERSION_UNKNOWN) ? version : cx->findVersion();
  4449     compileAndGo = false;
  4450     noScriptRval = cx->options().noScriptRval();
  4451     strictOption = cx->options().strictMode();
  4452     extraWarningsOption = cx->options().extraWarnings();
  4453     werrorOption = cx->options().werror();
  4454     asmJSOption = cx->runtime()->options().asmJS();
  4457 bool
  4458 JS::CompileOptions::wrap(JSContext *cx, JSCompartment *compartment)
  4460     if (!compartment->wrap(cx, &elementRoot))
  4461         return false;
  4462     if (elementAttributeNameRoot) {
  4463         if (!compartment->wrap(cx, elementAttributeNameRoot.address()))
  4464             return false;
  4467     // There is no equivalent of cross-compartment wrappers for scripts. If
  4468     // the introduction script would be in a different compartment from the
  4469     // compiled code, we would be creating a cross-compartment script
  4470     // reference, which would be bogus. In that case, just don't bother to
  4471     // retain the introduction script.
  4472     if (introductionScriptRoot) {
  4473         if (introductionScriptRoot->compartment() != compartment)
  4474             introductionScriptRoot = nullptr;
  4477     return true;
  4480 bool
  4481 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4482             SourceBufferHolder &srcBuf, MutableHandleScript script)
  4484     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4485     AssertHeapIsIdle(cx);
  4486     CHECK_REQUEST(cx);
  4487     assertSameCompartment(cx, obj);
  4488     AutoLastFrameCheck lfc(cx);
  4490     script.set(frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, srcBuf));
  4491     return !!script;
  4494 JSScript *
  4495 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4496             const jschar *chars, size_t length)
  4498     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
  4499     RootedScript script(cx);
  4500     if (!Compile(cx, obj, options, srcBuf, &script))
  4501         return nullptr;
  4502     return script;
  4505 JSScript *
  4506 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4507             const char *bytes, size_t length)
  4509     jschar *chars;
  4510     if (options.utf8)
  4511         chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
  4512     else
  4513         chars = InflateString(cx, bytes, &length);
  4514     if (!chars)
  4515         return nullptr;
  4517     JSScript *script = Compile(cx, obj, options, chars, length);
  4518     js_free(chars);
  4519     return script;
  4522 JSScript *
  4523 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options, FILE *fp)
  4525     FileContents buffer(cx);
  4526     if (!ReadCompleteFile(cx, fp, buffer))
  4527         return nullptr;
  4529     JSScript *script = Compile(cx, obj, options, buffer.begin(), buffer.length());
  4530     return script;
  4533 JSScript *
  4534 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg, const char *filename)
  4536     AutoFile file;
  4537     if (!file.open(cx, filename))
  4538         return nullptr;
  4539     CompileOptions options(cx, optionsArg);
  4540     options.setFileAndLine(filename, 1);
  4541     return Compile(cx, obj, options, file.fp());
  4544 JS_PUBLIC_API(bool)
  4545 JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length)
  4547     static const size_t TINY_LENGTH = 1000;
  4548     static const size_t HUGE_LENGTH = 100 * 1000;
  4550     // These are heuristics which the caller may choose to ignore (e.g., for
  4551     // testing purposes).
  4552     if (!options.forceAsync) {
  4553         // Compiling off the main thread inolves creating a new Zone and other
  4554         // significant overheads.  Don't bother if the script is tiny.
  4555         if (length < TINY_LENGTH)
  4556             return false;
  4558 #ifdef JS_THREADSAFE
  4559         // If the parsing task would have to wait for GC to complete, it'll probably
  4560         // be faster to just start it synchronously on the main thread unless the
  4561         // script is huge.
  4562         if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH)
  4563             return false;
  4564 #endif // JS_THREADSAFE
  4567     return cx->runtime()->canUseParallelParsing();
  4570 JS_PUBLIC_API(bool)
  4571 JS::CompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options,
  4572                      const jschar *chars, size_t length,
  4573                      OffThreadCompileCallback callback, void *callbackData)
  4575     JS_ASSERT(CanCompileOffThread(cx, options, length));
  4576     return StartOffThreadParseScript(cx, options, chars, length, callback, callbackData);
  4579 JS_PUBLIC_API(JSScript *)
  4580 JS::FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token)
  4582 #ifdef JS_THREADSAFE
  4583     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
  4585     if (maybecx) {
  4586         RootedScript script(maybecx);
  4588             AutoLastFrameCheck lfc(maybecx);
  4589             script = WorkerThreadState().finishParseTask(maybecx, rt, token);
  4591         return script;
  4592     } else {
  4593         return WorkerThreadState().finishParseTask(maybecx, rt, token);
  4595 #else
  4596     MOZ_ASSUME_UNREACHABLE("Off thread compilation is not available.");
  4597 #endif
  4600 JS_PUBLIC_API(JSScript *)
  4601 JS_CompileScript(JSContext *cx, JS::HandleObject obj, const char *ascii,
  4602                  size_t length, const JS::CompileOptions &options)
  4604     return Compile(cx, obj, options, ascii, length);
  4607 JS_PUBLIC_API(JSScript *)
  4608 JS_CompileUCScript(JSContext *cx, JS::HandleObject obj, const jschar *chars,
  4609                    size_t length, const JS::CompileOptions &options)
  4611     return Compile(cx, obj, options, chars, length);
  4614 JS_PUBLIC_API(bool)
  4615 JS_BufferIsCompilableUnit(JSContext *cx, HandleObject obj, const char *utf8, size_t length)
  4617     AssertHeapIsIdle(cx);
  4618     CHECK_REQUEST(cx);
  4619     assertSameCompartment(cx, obj);
  4621     cx->clearPendingException();
  4623     jschar *chars = JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get();
  4624     if (!chars)
  4625         return true;
  4627     // Return true on any out-of-memory error or non-EOF-related syntax error, so our
  4628     // caller doesn't try to collect more buffered source.
  4629     bool result = true;
  4631     CompileOptions options(cx);
  4632     options.setCompileAndGo(false);
  4633     Parser<frontend::FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
  4634                                               options, chars, length,
  4635                                               /* foldConstants = */ true, nullptr, nullptr);
  4636     JSErrorReporter older = JS_SetErrorReporter(cx, nullptr);
  4637     if (!parser.parse(obj)) {
  4638         // We ran into an error. If it was because we ran out of source, we
  4639         // return false so our caller knows to try to collect more buffered
  4640         // source.
  4641         if (parser.isUnexpectedEOF())
  4642             result = false;
  4644         cx->clearPendingException();
  4646     JS_SetErrorReporter(cx, older);
  4648     js_free(chars);
  4649     return result;
  4652 JS_PUBLIC_API(JSObject *)
  4653 JS_GetGlobalFromScript(JSScript *script)
  4655     JS_ASSERT(!script->isCachedEval());
  4656     return &script->global();
  4659 JS_PUBLIC_API(bool)
  4660 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4661                     const char *name, unsigned nargs, const char *const *argnames,
  4662                     SourceBufferHolder &srcBuf, MutableHandleFunction fun)
  4664     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4665     AssertHeapIsIdle(cx);
  4666     CHECK_REQUEST(cx);
  4667     assertSameCompartment(cx, obj);
  4668     RootedAtom funAtom(cx);
  4669     AutoLastFrameCheck lfc(cx);
  4671     if (name) {
  4672         funAtom = Atomize(cx, name, strlen(name));
  4673         if (!funAtom)
  4674             return false;
  4677     AutoNameVector formals(cx);
  4678     for (unsigned i = 0; i < nargs; i++) {
  4679         RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
  4680         if (!argAtom || !formals.append(argAtom->asPropertyName()))
  4681             return false;
  4684     fun.set(NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED, obj,
  4685                         funAtom, JSFunction::FinalizeKind, TenuredObject));
  4686     if (!fun)
  4687         return false;
  4689     if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf))
  4690         return false;
  4692     if (obj && funAtom && options.defineOnScope) {
  4693         Rooted<jsid> id(cx, AtomToId(funAtom));
  4694         RootedValue value(cx, ObjectValue(*fun));
  4695         if (!JSObject::defineGeneric(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE))
  4696             return false;
  4699     return true;
  4702 JS_PUBLIC_API(JSFunction *)
  4703 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4704                     const char *name, unsigned nargs, const char *const *argnames,
  4705                     const jschar *chars, size_t length)
  4707     RootedFunction fun(cx);
  4708     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
  4709     if (!JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf, &fun))
  4710         return nullptr;
  4711     return fun;
  4714 JS_PUBLIC_API(JSFunction *)
  4715 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4716                     const char *name, unsigned nargs, const char *const *argnames,
  4717                     const char *bytes, size_t length)
  4719     jschar *chars;
  4720     if (options.utf8)
  4721         chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
  4722     else
  4723         chars = InflateString(cx, bytes, &length);
  4724     if (!chars)
  4725         return nullptr;
  4727     JSFunction *fun = CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
  4728     js_free(chars);
  4729     return fun;
  4732 JS_PUBLIC_API(JSFunction *)
  4733 JS_CompileUCFunction(JSContext *cx, JS::HandleObject obj, const char *name,
  4734                      unsigned nargs, const char *const *argnames,
  4735                      const jschar *chars, size_t length,
  4736                      const CompileOptions &options)
  4738     return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
  4741 JS_PUBLIC_API(JSFunction *)
  4742 JS_CompileFunction(JSContext *cx, JS::HandleObject obj, const char *name,
  4743                    unsigned nargs, const char *const *argnames,
  4744                    const char *ascii, size_t length,
  4745                    const JS::CompileOptions &options)
  4747     return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
  4750 JS_PUBLIC_API(JSString *)
  4751 JS_DecompileScript(JSContext *cx, HandleScript script, const char *name, unsigned indent)
  4753     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4755     AssertHeapIsIdle(cx);
  4756     CHECK_REQUEST(cx);
  4757     script->ensureNonLazyCanonicalFunction(cx);
  4758     RootedFunction fun(cx, script->functionNonDelazifying());
  4759     if (fun)
  4760         return JS_DecompileFunction(cx, fun, indent);
  4761     bool haveSource = script->scriptSource()->hasSourceData();
  4762     if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
  4763         return nullptr;
  4764     return haveSource ? script->sourceData(cx) : js_NewStringCopyZ<CanGC>(cx, "[no source]");
  4767 JS_PUBLIC_API(JSString *)
  4768 JS_DecompileFunction(JSContext *cx, HandleFunction fun, unsigned indent)
  4770     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4771     AssertHeapIsIdle(cx);
  4772     CHECK_REQUEST(cx);
  4773     assertSameCompartment(cx, fun);
  4774     return FunctionToString(cx, fun, false, !(indent & JS_DONT_PRETTY_PRINT));
  4777 JS_PUBLIC_API(JSString *)
  4778 JS_DecompileFunctionBody(JSContext *cx, HandleFunction fun, unsigned indent)
  4780     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4781     AssertHeapIsIdle(cx);
  4782     CHECK_REQUEST(cx);
  4783     assertSameCompartment(cx, fun);
  4784     return FunctionToString(cx, fun, true, !(indent & JS_DONT_PRETTY_PRINT));
  4787 MOZ_NEVER_INLINE static bool
  4788 ExecuteScript(JSContext *cx, HandleObject obj, HandleScript scriptArg, jsval *rval)
  4790     RootedScript script(cx, scriptArg);
  4792     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4793     AssertHeapIsIdle(cx);
  4794     CHECK_REQUEST(cx);
  4795     assertSameCompartment(cx, obj, scriptArg);
  4796     AutoLastFrameCheck lfc(cx);
  4797     return Execute(cx, script, *obj, rval);
  4800 MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
  4801 JS_ExecuteScript(JSContext *cx, HandleObject obj, HandleScript scriptArg, MutableHandleValue rval)
  4803     return ExecuteScript(cx, obj, scriptArg, rval.address());
  4806 MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
  4807 JS_ExecuteScript(JSContext *cx, HandleObject obj, HandleScript scriptArg)
  4809     return ExecuteScript(cx, obj, scriptArg, nullptr);
  4812 JS_PUBLIC_API(bool)
  4813 JS::CloneAndExecuteScript(JSContext *cx, HandleObject obj, HandleScript scriptArg)
  4815     CHECK_REQUEST(cx);
  4816     assertSameCompartment(cx, obj);
  4817     RootedScript script(cx, scriptArg);
  4818     if (script->compartment() != cx->compartment()) {
  4819         script = CloneScript(cx, NullPtr(), NullPtr(), script);
  4820         if (!script)
  4821             return false;
  4823     return ExecuteScript(cx, obj, script, nullptr);
  4826 JS_PUBLIC_API(bool)
  4827 JS_ExecuteScriptVersion(JSContext *cx, HandleObject obj, HandleScript script,
  4828                         MutableHandleValue rval, JSVersion version)
  4830     return ExecuteScript(cx, obj, script, rval.address());
  4833 JS_PUBLIC_API(bool)
  4834 JS_ExecuteScriptVersion(JSContext *cx, HandleObject obj, HandleScript script, JSVersion version)
  4836     return ExecuteScript(cx, obj, script, nullptr);
  4839 static const unsigned LARGE_SCRIPT_LENGTH = 500*1024;
  4841 static bool
  4842 Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4843          SourceBufferHolder &srcBuf, JS::Value *rval)
  4845     CompileOptions options(cx, optionsArg);
  4846     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  4847     AssertHeapIsIdle(cx);
  4848     CHECK_REQUEST(cx);
  4849     assertSameCompartment(cx, obj);
  4851     AutoLastFrameCheck lfc(cx);
  4853     options.setCompileAndGo(obj->is<GlobalObject>());
  4854     options.setNoScriptRval(!rval);
  4855     SourceCompressionTask sct(cx);
  4856     RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(),
  4857                                                     obj, NullPtr(), options,
  4858                                                     srcBuf, nullptr, 0, &sct));
  4859     if (!script)
  4860         return false;
  4862     JS_ASSERT(script->getVersion() == options.version);
  4864     bool result = Execute(cx, script, *obj, rval);
  4865     if (!sct.complete())
  4866         result = false;
  4868     // After evaluation, the compiled script will not be run again.
  4869     // script->ensureRanAnalysis allocated 1 analyze::Bytecode for every opcode
  4870     // which for large scripts means significant memory. Perform a GC eagerly
  4871     // to clear out this analysis data before anything happens to inhibit the
  4872     // flushing of this memory (such as setting requestAnimationFrame).
  4873     if (script->length() > LARGE_SCRIPT_LENGTH) {
  4874         script = nullptr;
  4875         PrepareZoneForGC(cx->zone());
  4876         GC(cx->runtime(), GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUTE);
  4879     return result;
  4882 static bool
  4883 Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4884          const jschar *chars, size_t length, JS::Value *rval)
  4886   SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
  4887   return ::Evaluate(cx, obj, optionsArg, srcBuf, rval);
  4890 static bool
  4891 Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4892          const char *bytes, size_t length, JS::Value *rval)
  4894     jschar *chars;
  4895     if (options.utf8)
  4896         chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
  4897     else
  4898         chars = InflateString(cx, bytes, &length);
  4899     if (!chars)
  4900         return false;
  4902     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
  4903     bool ok = ::Evaluate(cx, obj, options, srcBuf, rval);
  4904     return ok;
  4907 static bool
  4908 Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4909          const char *filename, JS::Value *rval)
  4911     FileContents buffer(cx);
  4913         AutoFile file;
  4914         if (!file.open(cx, filename) || !file.readAll(cx, buffer))
  4915             return false;
  4918     CompileOptions options(cx, optionsArg);
  4919     options.setFileAndLine(filename, 1);
  4920     return Evaluate(cx, obj, options, buffer.begin(), buffer.length(), rval);
  4923 extern JS_PUBLIC_API(bool)
  4924 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4925              SourceBufferHolder &srcBuf, MutableHandleValue rval)
  4927     return ::Evaluate(cx, obj, optionsArg, srcBuf, rval.address());
  4930 extern JS_PUBLIC_API(bool)
  4931 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4932              const jschar *chars, size_t length, MutableHandleValue rval)
  4934     return ::Evaluate(cx, obj, optionsArg, chars, length, rval.address());
  4937 extern JS_PUBLIC_API(bool)
  4938 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4939              const char *bytes, size_t length, MutableHandleValue rval)
  4941     return ::Evaluate(cx, obj, options, bytes, length, rval.address());
  4944 extern JS_PUBLIC_API(bool)
  4945 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4946              const char *filename, MutableHandleValue rval)
  4948     return ::Evaluate(cx, obj, optionsArg, filename, rval.address());
  4951 extern JS_PUBLIC_API(bool)
  4952 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4953              SourceBufferHolder &srcBuf)
  4955     return ::Evaluate(cx, obj, optionsArg, srcBuf, nullptr);
  4958 extern JS_PUBLIC_API(bool)
  4959 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4960              const jschar *chars, size_t length)
  4962     return ::Evaluate(cx, obj, optionsArg, chars, length, nullptr);
  4965 extern JS_PUBLIC_API(bool)
  4966 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  4967              const char *bytes, size_t length)
  4969     return ::Evaluate(cx, obj, options, bytes, length, nullptr);
  4972 extern JS_PUBLIC_API(bool)
  4973 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  4974              const char *filename)
  4976     return ::Evaluate(cx, obj, optionsArg, filename, nullptr);
  4979 JS_PUBLIC_API(bool)
  4980 JS_EvaluateUCScript(JSContext *cx, HandleObject obj, const jschar *chars, unsigned length,
  4981                     const char *filename, unsigned lineno, MutableHandleValue rval)
  4983     CompileOptions options(cx);
  4984     options.setFileAndLine(filename, lineno);
  4986     return ::Evaluate(cx, obj, options, chars, length, rval.address());
  4989 JS_PUBLIC_API(bool)
  4990 JS_EvaluateUCScript(JSContext *cx, HandleObject obj, SourceBufferHolder &srcBuf,
  4991                     const char *filename, unsigned lineno, MutableHandleValue rval)
  4993     CompileOptions options(cx);
  4994     options.setFileAndLine(filename, lineno);
  4996     return ::Evaluate(cx, obj, options, srcBuf, rval.address());
  4999 JS_PUBLIC_API(bool)
  5000 JS_EvaluateScript(JSContext *cx, HandleObject obj, const char *bytes, unsigned nbytes,
  5001                   const char *filename, unsigned lineno, MutableHandleValue rval)
  5003     CompileOptions options(cx);
  5004     options.setFileAndLine(filename, lineno);
  5006     return ::Evaluate(cx, obj, options, bytes, nbytes, rval.address());
  5009 JS_PUBLIC_API(bool)
  5010 JS_EvaluateScript(JSContext *cx, HandleObject obj, const char *bytes, unsigned nbytes,
  5011                   const char *filename, unsigned lineno)
  5013     CompileOptions options(cx);
  5014     options.setFileAndLine(filename, lineno);
  5016     return ::Evaluate(cx, obj, options, bytes, nbytes, nullptr);
  5019 JS_PUBLIC_API(bool)
  5020 JS_CallFunction(JSContext *cx, HandleObject obj, HandleFunction fun, const HandleValueArray& args,
  5021                 MutableHandleValue rval)
  5023     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  5024     AssertHeapIsIdle(cx);
  5025     CHECK_REQUEST(cx);
  5026     assertSameCompartment(cx, obj, fun, args);
  5027     AutoLastFrameCheck lfc(cx);
  5029     return Invoke(cx, ObjectOrNullValue(obj), ObjectValue(*fun), args.length(), args.begin(), rval);
  5032 JS_PUBLIC_API(bool)
  5033 JS_CallFunctionName(JSContext *cx, HandleObject obj, const char *name, const HandleValueArray& args,
  5034                     MutableHandleValue rval)
  5036     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  5037     AssertHeapIsIdle(cx);
  5038     CHECK_REQUEST(cx);
  5039     assertSameCompartment(cx, obj, args);
  5040     AutoLastFrameCheck lfc(cx);
  5042     JSAtom *atom = Atomize(cx, name, strlen(name));
  5043     if (!atom)
  5044         return false;
  5046     RootedValue v(cx);
  5047     RootedId id(cx, AtomToId(atom));
  5048     if (!JSObject::getGeneric(cx, obj, obj, id, &v))
  5049         return false;
  5051     return Invoke(cx, ObjectOrNullValue(obj), v, args.length(), args.begin(), rval);
  5054 JS_PUBLIC_API(bool)
  5055 JS_CallFunctionValue(JSContext *cx, HandleObject obj, HandleValue fval, const HandleValueArray& args,
  5056                      MutableHandleValue rval)
  5058     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  5059     AssertHeapIsIdle(cx);
  5060     CHECK_REQUEST(cx);
  5061     assertSameCompartment(cx, obj, fval, args);
  5062     AutoLastFrameCheck lfc(cx);
  5064     return Invoke(cx, ObjectOrNullValue(obj), fval, args.length(), args.begin(), rval);
  5067 JS_PUBLIC_API(bool)
  5068 JS::Call(JSContext *cx, HandleValue thisv, HandleValue fval, const JS::HandleValueArray& args,
  5069          MutableHandleValue rval)
  5071     AssertHeapIsIdle(cx);
  5072     CHECK_REQUEST(cx);
  5073     assertSameCompartment(cx, thisv, fval, args);
  5074     AutoLastFrameCheck lfc(cx);
  5076     return Invoke(cx, thisv, fval, args.length(), args.begin(), rval);
  5079 static JSObject *
  5080 JS_NewHelper(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
  5082     AssertHeapIsIdle(cx);
  5083     CHECK_REQUEST(cx);
  5084     assertSameCompartment(cx, ctor, inputArgs);
  5086     // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
  5087     // is not a simple variation of JSOP_CALL. We have to determine what class
  5088     // of object to create, create it, and clamp the return value to an object,
  5089     // among other details. InvokeConstructor does the hard work.
  5090     InvokeArgs args(cx);
  5091     if (!args.init(inputArgs.length()))
  5092         return nullptr;
  5094     args.setCallee(ObjectValue(*ctor));
  5095     args.setThis(NullValue());
  5096     PodCopy(args.array(), inputArgs.begin(), inputArgs.length());
  5098     if (!InvokeConstructor(cx, args))
  5099         return nullptr;
  5101     if (!args.rval().isObject()) {
  5102         /*
  5103          * Although constructors may return primitives (via proxies), this
  5104          * API is asking for an object, so we report an error.
  5105          */
  5106         JSAutoByteString bytes;
  5107         if (js_ValueToPrintable(cx, args.rval(), &bytes)) {
  5108             JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_NEW_RESULT,
  5109                                  bytes.ptr());
  5111         return nullptr;
  5114     return &args.rval().toObject();
  5117 JS_PUBLIC_API(JSObject *)
  5118 JS_New(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
  5120     RootedObject obj(cx);
  5122         AutoLastFrameCheck lfc(cx);
  5123         obj = JS_NewHelper(cx, ctor, inputArgs);
  5125     return obj;
  5128 JS_PUBLIC_API(JSInterruptCallback)
  5129 JS_SetInterruptCallback(JSRuntime *rt, JSInterruptCallback callback)
  5131     JSInterruptCallback old = rt->interruptCallback;
  5132     rt->interruptCallback = callback;
  5133     return old;
  5136 JS_PUBLIC_API(JSInterruptCallback)
  5137 JS_GetInterruptCallback(JSRuntime *rt)
  5139     return rt->interruptCallback;
  5142 JS_PUBLIC_API(void)
  5143 JS_RequestInterruptCallback(JSRuntime *rt)
  5145     rt->requestInterrupt(JSRuntime::RequestInterruptAnyThread);
  5148 JS_PUBLIC_API(bool)
  5149 JS_IsRunning(JSContext *cx)
  5151     return cx->currentlyRunning();
  5154 JS_PUBLIC_API(bool)
  5155 JS_SaveFrameChain(JSContext *cx)
  5157     AssertHeapIsIdleOrIterating(cx);
  5158     CHECK_REQUEST(cx);
  5159     return cx->saveFrameChain();
  5162 JS_PUBLIC_API(void)
  5163 JS_RestoreFrameChain(JSContext *cx)
  5165     AssertHeapIsIdleOrIterating(cx);
  5166     CHECK_REQUEST(cx);
  5167     cx->restoreFrameChain();
  5170 #ifdef MOZ_TRACE_JSCALLS
  5171 JS_PUBLIC_API(void)
  5172 JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb)
  5174     cx->functionCallback = fcb;
  5177 JS_PUBLIC_API(JSFunctionCallback)
  5178 JS_GetFunctionCallback(JSContext *cx)
  5180     return cx->functionCallback;
  5182 #endif
  5184 /************************************************************************/
  5185 JS_PUBLIC_API(JSString *)
  5186 JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
  5188     AssertHeapIsIdle(cx);
  5189     CHECK_REQUEST(cx);
  5190     if (!n)
  5191         return cx->names().empty;
  5192     return js_NewStringCopyN<CanGC>(cx, s, n);
  5195 JS_PUBLIC_API(JSString *)
  5196 JS_NewStringCopyZ(JSContext *cx, const char *s)
  5198     size_t n;
  5199     jschar *js;
  5200     JSString *str;
  5202     AssertHeapIsIdle(cx);
  5203     CHECK_REQUEST(cx);
  5204     if (!s || !*s)
  5205         return cx->runtime()->emptyString;
  5206     n = strlen(s);
  5207     js = InflateString(cx, s, &n);
  5208     if (!js)
  5209         return nullptr;
  5210     str = js_NewString<CanGC>(cx, js, n);
  5211     if (!str)
  5212         js_free(js);
  5213     return str;
  5216 JS_PUBLIC_API(bool)
  5217 JS_StringHasBeenInterned(JSContext *cx, JSString *str)
  5219     AssertHeapIsIdle(cx);
  5220     CHECK_REQUEST(cx);
  5222     if (!str->isAtom())
  5223         return false;
  5225     return AtomIsInterned(cx, &str->asAtom());
  5228 JS_PUBLIC_API(jsid)
  5229 INTERNED_STRING_TO_JSID(JSContext *cx, JSString *str)
  5231     JS_ASSERT(str);
  5232     JS_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
  5233     JS_ASSERT_IF(cx, JS_StringHasBeenInterned(cx, str));
  5234     return AtomToId(&str->asAtom());
  5237 JS_PUBLIC_API(JSString *)
  5238 JS_InternJSString(JSContext *cx, HandleString str)
  5240     AssertHeapIsIdle(cx);
  5241     CHECK_REQUEST(cx);
  5242     JSAtom *atom = AtomizeString(cx, str, InternAtom);
  5243     JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
  5244     return atom;
  5247 JS_PUBLIC_API(JSString *)
  5248 JS_InternString(JSContext *cx, const char *s)
  5250     return JS_InternStringN(cx, s, strlen(s));
  5253 JS_PUBLIC_API(JSString *)
  5254 JS_InternStringN(JSContext *cx, const char *s, size_t length)
  5256     AssertHeapIsIdle(cx);
  5257     CHECK_REQUEST(cx);
  5258     JSAtom *atom = Atomize(cx, s, length, InternAtom);
  5259     JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
  5260     return atom;
  5263 JS_PUBLIC_API(JSString *)
  5264 JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
  5266     AssertHeapIsIdle(cx);
  5267     CHECK_REQUEST(cx);
  5268     return js_NewString<CanGC>(cx, chars, length);
  5271 JS_PUBLIC_API(JSString *)
  5272 JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
  5274     AssertHeapIsIdle(cx);
  5275     CHECK_REQUEST(cx);
  5276     if (!n)
  5277         return cx->names().empty;
  5278     return js_NewStringCopyN<CanGC>(cx, s, n);
  5281 JS_PUBLIC_API(JSString *)
  5282 JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
  5284     AssertHeapIsIdle(cx);
  5285     CHECK_REQUEST(cx);
  5286     if (!s)
  5287         return cx->runtime()->emptyString;
  5288     return js_NewStringCopyZ<CanGC>(cx, s);
  5291 JS_PUBLIC_API(JSString *)
  5292 JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
  5294     AssertHeapIsIdle(cx);
  5295     CHECK_REQUEST(cx);
  5296     JSAtom *atom = AtomizeChars(cx, s, length, InternAtom);
  5297     JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
  5298     return atom;
  5301 JS_PUBLIC_API(JSString *)
  5302 JS_InternUCString(JSContext *cx, const jschar *s)
  5304     return JS_InternUCStringN(cx, s, js_strlen(s));
  5307 JS_PUBLIC_API(size_t)
  5308 JS_GetStringLength(JSString *str)
  5310     return str->length();
  5313 JS_PUBLIC_API(const jschar *)
  5314 JS_GetStringCharsZ(JSContext *cx, JSString *str)
  5316     size_t dummy;
  5317     return JS_GetStringCharsZAndLength(cx, str, &dummy);
  5320 JS_PUBLIC_API(const jschar *)
  5321 JS_GetStringCharsZAndLength(JSContext *cx, JSString *str, size_t *plength)
  5323     /*
  5324      * Don't require |cx->compartment()| to be |str|'s compartment. We don't need
  5325      * it, and it's annoying for callers.
  5326      */
  5327     JS_ASSERT(plength);
  5328     AssertHeapIsIdleOrStringIsFlat(cx, str);
  5329     CHECK_REQUEST(cx);
  5330     JSFlatString *flat = str->ensureFlat(cx);
  5331     if (!flat)
  5332         return nullptr;
  5333     *plength = flat->length();
  5334     return flat->chars();
  5337 JS_PUBLIC_API(const jschar *)
  5338 JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *plength)
  5340     JS_ASSERT(plength);
  5341     AssertHeapIsIdleOrStringIsFlat(cx, str);
  5342     CHECK_REQUEST(cx);
  5343     assertSameCompartment(cx, str);
  5344     JSLinearString *linear = str->ensureLinear(cx);
  5345     if (!linear)
  5346         return nullptr;
  5347     *plength = linear->length();
  5348     return linear->chars();
  5351 JS_PUBLIC_API(const jschar *)
  5352 JS_GetInternedStringChars(JSString *str)
  5354     JS_ASSERT(str->isAtom());
  5355     JSFlatString *flat = str->ensureFlat(nullptr);
  5356     if (!flat)
  5357         return nullptr;
  5358     return flat->chars();
  5361 JS_PUBLIC_API(const jschar *)
  5362 JS_GetInternedStringCharsAndLength(JSString *str, size_t *plength)
  5364     JS_ASSERT(str->isAtom());
  5365     JS_ASSERT(plength);
  5366     JSFlatString *flat = str->ensureFlat(nullptr);
  5367     if (!flat)
  5368         return nullptr;
  5369     *plength = flat->length();
  5370     return flat->chars();
  5373 extern JS_PUBLIC_API(JSFlatString *)
  5374 JS_FlattenString(JSContext *cx, JSString *str)
  5376     AssertHeapIsIdle(cx);
  5377     CHECK_REQUEST(cx);
  5378     assertSameCompartment(cx, str);
  5379     JSFlatString *flat = str->ensureFlat(cx);
  5380     if (!flat)
  5381         return nullptr;
  5382     return flat;
  5385 extern JS_PUBLIC_API(const jschar *)
  5386 JS_GetFlatStringChars(JSFlatString *str)
  5388     return str->chars();
  5391 JS_PUBLIC_API(bool)
  5392 JS_CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *result)
  5394     AssertHeapIsIdle(cx);
  5395     CHECK_REQUEST(cx);
  5397     return CompareStrings(cx, str1, str2, result);
  5400 JS_PUBLIC_API(bool)
  5401 JS_StringEqualsAscii(JSContext *cx, JSString *str, const char *asciiBytes, bool *match)
  5403     AssertHeapIsIdle(cx);
  5404     CHECK_REQUEST(cx);
  5406     JSLinearString *linearStr = str->ensureLinear(cx);
  5407     if (!linearStr)
  5408         return false;
  5409     *match = StringEqualsAscii(linearStr, asciiBytes);
  5410     return true;
  5413 JS_PUBLIC_API(bool)
  5414 JS_FlatStringEqualsAscii(JSFlatString *str, const char *asciiBytes)
  5416     return StringEqualsAscii(str, asciiBytes);
  5419 JS_PUBLIC_API(size_t)
  5420 JS_PutEscapedFlatString(char *buffer, size_t size, JSFlatString *str, char quote)
  5422     return PutEscapedString(buffer, size, str, quote);
  5425 JS_PUBLIC_API(size_t)
  5426 JS_PutEscapedString(JSContext *cx, char *buffer, size_t size, JSString *str, char quote)
  5428     AssertHeapIsIdle(cx);
  5429     JSLinearString *linearStr = str->ensureLinear(cx);
  5430     if (!linearStr)
  5431         return size_t(-1);
  5432     return PutEscapedString(buffer, size, linearStr, quote);
  5435 JS_PUBLIC_API(bool)
  5436 JS_FileEscapedString(FILE *fp, JSString *str, char quote)
  5438     JSLinearString *linearStr = str->ensureLinear(nullptr);
  5439     return linearStr && FileEscapedString(fp, linearStr, quote);
  5442 JS_PUBLIC_API(JSString *)
  5443 JS_NewDependentString(JSContext *cx, HandleString str, size_t start, size_t length)
  5445     AssertHeapIsIdle(cx);
  5446     CHECK_REQUEST(cx);
  5447     return js_NewDependentString(cx, str, start, length);
  5450 JS_PUBLIC_API(JSString *)
  5451 JS_ConcatStrings(JSContext *cx, HandleString left, HandleString right)
  5453     AssertHeapIsIdle(cx);
  5454     CHECK_REQUEST(cx);
  5455     return ConcatStrings<CanGC>(cx, left, right);
  5458 JS_PUBLIC_API(bool)
  5459 JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_t *dstlenp)
  5461     AssertHeapIsIdle(cx);
  5462     CHECK_REQUEST(cx);
  5464     if (!dst) {
  5465         *dstlenp = srclen;
  5466         return true;
  5469     size_t dstlen = *dstlenp;
  5471     if (srclen > dstlen) {
  5472         InflateStringToBuffer(src, dstlen, dst);
  5474         AutoSuppressGC suppress(cx);
  5475         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BUFFER_TOO_SMALL);
  5476         return false;
  5479     InflateStringToBuffer(src, srclen, dst);
  5480     *dstlenp = srclen;
  5481     return true;
  5484 JS_PUBLIC_API(char *)
  5485 JS_EncodeString(JSContext *cx, JSString *str)
  5487     AssertHeapIsIdle(cx);
  5488     CHECK_REQUEST(cx);
  5490     JSLinearString *linear = str->ensureLinear(cx);
  5491     if (!linear)
  5492         return nullptr;
  5494     return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
  5497 JS_PUBLIC_API(char *)
  5498 JS_EncodeStringToUTF8(JSContext *cx, HandleString str)
  5500     AssertHeapIsIdle(cx);
  5501     CHECK_REQUEST(cx);
  5503     JSLinearString *linear = str->ensureLinear(cx);
  5504     if (!linear)
  5505         return nullptr;
  5507     return TwoByteCharsToNewUTF8CharsZ(cx, linear->range()).c_str();
  5510 JS_PUBLIC_API(size_t)
  5511 JS_GetStringEncodingLength(JSContext *cx, JSString *str)
  5513     AssertHeapIsIdle(cx);
  5514     CHECK_REQUEST(cx);
  5516     const jschar *chars = str->getChars(cx);
  5517     if (!chars)
  5518         return size_t(-1);
  5519     return str->length();
  5522 JS_PUBLIC_API(size_t)
  5523 JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t length)
  5525     AssertHeapIsIdle(cx);
  5526     CHECK_REQUEST(cx);
  5528     /*
  5529      * FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
  5530      * would allow to distinguish between insufficient buffer and encoding
  5531      * error.
  5532      */
  5533     size_t writtenLength = length;
  5534     const jschar *chars = str->getChars(nullptr);
  5535     if (!chars)
  5536         return size_t(-1);
  5537     if (DeflateStringToBuffer(nullptr, chars, str->length(), buffer, &writtenLength)) {
  5538         JS_ASSERT(writtenLength <= length);
  5539         return writtenLength;
  5541     JS_ASSERT(writtenLength <= length);
  5542     size_t necessaryLength = str->length();
  5543     if (necessaryLength == size_t(-1))
  5544         return size_t(-1);
  5545     JS_ASSERT(writtenLength == length); // C strings are NOT encoded.
  5546     return necessaryLength;
  5549 JS_PUBLIC_API(bool)
  5550 JS_Stringify(JSContext *cx, MutableHandleValue vp, HandleObject replacer,
  5551              HandleValue space, JSONWriteCallback callback, void *data)
  5553     AssertHeapIsIdle(cx);
  5554     CHECK_REQUEST(cx);
  5555     assertSameCompartment(cx, replacer, space);
  5556     StringBuffer sb(cx);
  5557     if (!js_Stringify(cx, vp, replacer, space, sb))
  5558         return false;
  5559     if (sb.empty()) {
  5560         HandlePropertyName null = cx->names().null;
  5561         return callback(null->chars(), null->length(), data);
  5563     return callback(sb.begin(), sb.length(), data);
  5566 JS_PUBLIC_API(bool)
  5567 JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, JS::MutableHandleValue vp)
  5569     AssertHeapIsIdle(cx);
  5570     CHECK_REQUEST(cx);
  5572     RootedValue reviver(cx, NullValue());
  5573     return ParseJSONWithReviver(cx, ConstTwoByteChars(chars, len), len, reviver, vp);
  5576 JS_PUBLIC_API(bool)
  5577 JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, HandleValue reviver, MutableHandleValue vp)
  5579     AssertHeapIsIdle(cx);
  5580     CHECK_REQUEST(cx);
  5581     return ParseJSONWithReviver(cx, ConstTwoByteChars(chars, len), len, reviver, vp);
  5584 /************************************************************************/
  5586 JS_PUBLIC_API(void)
  5587 JS_ReportError(JSContext *cx, const char *format, ...)
  5589     va_list ap;
  5591     AssertHeapIsIdle(cx);
  5592     va_start(ap, format);
  5593     js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
  5594     va_end(ap);
  5597 JS_PUBLIC_API(void)
  5598 JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
  5599                      void *userRef, const unsigned errorNumber, ...)
  5601     va_list ap;
  5602     va_start(ap, errorNumber);
  5603     JS_ReportErrorNumberVA(cx, errorCallback, userRef, errorNumber, ap);
  5604     va_end(ap);
  5607 JS_PUBLIC_API(void)
  5608 JS_ReportErrorNumberVA(JSContext *cx, JSErrorCallback errorCallback,
  5609                        void *userRef, const unsigned errorNumber,
  5610                        va_list ap)
  5612     AssertHeapIsIdle(cx);
  5613     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
  5614                            errorNumber, ArgumentsAreASCII, ap);
  5617 JS_PUBLIC_API(void)
  5618 JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
  5619                        void *userRef, const unsigned errorNumber, ...)
  5621     va_list ap;
  5623     AssertHeapIsIdle(cx);
  5624     va_start(ap, errorNumber);
  5625     js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
  5626                            errorNumber, ArgumentsAreUnicode, ap);
  5627     va_end(ap);
  5630 JS_PUBLIC_API(void)
  5631 JS_ReportErrorNumberUCArray(JSContext *cx, JSErrorCallback errorCallback,
  5632                             void *userRef, const unsigned errorNumber,
  5633                             const jschar **args)
  5635     AssertHeapIsIdle(cx);
  5636     js_ReportErrorNumberUCArray(cx, JSREPORT_ERROR, errorCallback, userRef,
  5637                                 errorNumber, args);
  5640 JS_PUBLIC_API(bool)
  5641 JS_ReportWarning(JSContext *cx, const char *format, ...)
  5643     va_list ap;
  5644     bool ok;
  5646     AssertHeapIsIdle(cx);
  5647     va_start(ap, format);
  5648     ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
  5649     va_end(ap);
  5650     return ok;
  5653 JS_PUBLIC_API(bool)
  5654 JS_ReportErrorFlagsAndNumber(JSContext *cx, unsigned flags,
  5655                              JSErrorCallback errorCallback, void *userRef,
  5656                              const unsigned errorNumber, ...)
  5658     va_list ap;
  5659     bool ok;
  5661     AssertHeapIsIdle(cx);
  5662     va_start(ap, errorNumber);
  5663     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
  5664                                 errorNumber, ArgumentsAreASCII, ap);
  5665     va_end(ap);
  5666     return ok;
  5669 JS_PUBLIC_API(bool)
  5670 JS_ReportErrorFlagsAndNumberUC(JSContext *cx, unsigned flags,
  5671                                JSErrorCallback errorCallback, void *userRef,
  5672                                const unsigned errorNumber, ...)
  5674     va_list ap;
  5675     bool ok;
  5677     AssertHeapIsIdle(cx);
  5678     va_start(ap, errorNumber);
  5679     ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
  5680                                 errorNumber, ArgumentsAreUnicode, ap);
  5681     va_end(ap);
  5682     return ok;
  5685 JS_PUBLIC_API(void)
  5686 JS_ReportOutOfMemory(JSContext *cx)
  5688     js_ReportOutOfMemory(cx);
  5691 JS_PUBLIC_API(void)
  5692 JS_ReportAllocationOverflow(JSContext *cx)
  5694     js_ReportAllocationOverflow(cx);
  5697 JS_PUBLIC_API(JSErrorReporter)
  5698 JS_GetErrorReporter(JSContext *cx)
  5700     return cx->errorReporter;
  5703 JS_PUBLIC_API(JSErrorReporter)
  5704 JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
  5706     JSErrorReporter older;
  5708     older = cx->errorReporter;
  5709     cx->errorReporter = er;
  5710     return older;
  5713 /************************************************************************/
  5715 /*
  5716  * Dates.
  5717  */
  5718 JS_PUBLIC_API(JSObject *)
  5719 JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec)
  5721     AssertHeapIsIdle(cx);
  5722     CHECK_REQUEST(cx);
  5723     return js_NewDateObject(cx, year, mon, mday, hour, min, sec);
  5726 JS_PUBLIC_API(JSObject *)
  5727 JS_NewDateObjectMsec(JSContext *cx, double msec)
  5729     AssertHeapIsIdle(cx);
  5730     CHECK_REQUEST(cx);
  5731     return js_NewDateObjectMsec(cx, msec);
  5734 JS_PUBLIC_API(bool)
  5735 JS_ObjectIsDate(JSContext *cx, HandleObject obj)
  5737     assertSameCompartment(cx, obj);
  5738     return ObjectClassIs(obj, ESClass_Date, cx);
  5741 JS_PUBLIC_API(void)
  5742 JS_ClearDateCaches(JSContext *cx)
  5744     AssertHeapIsIdle(cx);
  5745     CHECK_REQUEST(cx);
  5746     cx->runtime()->dateTimeInfo.updateTimeZoneAdjustment();
  5749 /************************************************************************/
  5751 /*
  5752  * Regular Expressions.
  5753  */
  5754 JS_PUBLIC_API(JSObject *)
  5755 JS_NewRegExpObject(JSContext *cx, HandleObject obj, char *bytes, size_t length, unsigned flags)
  5757     AssertHeapIsIdle(cx);
  5758     CHECK_REQUEST(cx);
  5759     jschar *chars = InflateString(cx, bytes, &length);
  5760     if (!chars)
  5761         return nullptr;
  5763     RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
  5764     RegExpObject *reobj = RegExpObject::create(cx, res, chars, length,
  5765                                                RegExpFlag(flags), nullptr);
  5766     js_free(chars);
  5767     return reobj;
  5770 JS_PUBLIC_API(JSObject *)
  5771 JS_NewUCRegExpObject(JSContext *cx, HandleObject obj, jschar *chars, size_t length,
  5772                      unsigned flags)
  5774     AssertHeapIsIdle(cx);
  5775     CHECK_REQUEST(cx);
  5776     RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
  5777     return RegExpObject::create(cx, res, chars, length,
  5778                                 RegExpFlag(flags), nullptr);
  5781 JS_PUBLIC_API(void)
  5782 JS_SetRegExpInput(JSContext *cx, HandleObject obj, HandleString input, bool multiline)
  5784     AssertHeapIsIdle(cx);
  5785     CHECK_REQUEST(cx);
  5786     assertSameCompartment(cx, input);
  5788     obj->as<GlobalObject>().getRegExpStatics()->reset(cx, input, !!multiline);
  5791 JS_PUBLIC_API(void)
  5792 JS_ClearRegExpStatics(JSContext *cx, HandleObject obj)
  5794     AssertHeapIsIdle(cx);
  5795     CHECK_REQUEST(cx);
  5796     JS_ASSERT(obj);
  5798     obj->as<GlobalObject>().getRegExpStatics()->clear();
  5801 JS_PUBLIC_API(bool)
  5802 JS_ExecuteRegExp(JSContext *cx, HandleObject obj, HandleObject reobj, jschar *chars,
  5803                  size_t length, size_t *indexp, bool test, MutableHandleValue rval)
  5805     AssertHeapIsIdle(cx);
  5806     CHECK_REQUEST(cx);
  5808     RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
  5810     return ExecuteRegExpLegacy(cx, res, reobj->as<RegExpObject>(), NullPtr(), chars, length, indexp,
  5811                                test, rval);
  5814 JS_PUBLIC_API(JSObject *)
  5815 JS_NewRegExpObjectNoStatics(JSContext *cx, char *bytes, size_t length, unsigned flags)
  5817     AssertHeapIsIdle(cx);
  5818     CHECK_REQUEST(cx);
  5819     jschar *chars = InflateString(cx, bytes, &length);
  5820     if (!chars)
  5821         return nullptr;
  5822     RegExpObject *reobj = RegExpObject::createNoStatics(cx, chars, length,
  5823                                                         RegExpFlag(flags), nullptr);
  5824     js_free(chars);
  5825     return reobj;
  5828 JS_PUBLIC_API(JSObject *)
  5829 JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, unsigned flags)
  5831     AssertHeapIsIdle(cx);
  5832     CHECK_REQUEST(cx);
  5833     return RegExpObject::createNoStatics(cx, chars, length,
  5834                                          RegExpFlag(flags), nullptr);
  5837 JS_PUBLIC_API(bool)
  5838 JS_ExecuteRegExpNoStatics(JSContext *cx, HandleObject obj, jschar *chars, size_t length,
  5839                           size_t *indexp, bool test, MutableHandleValue rval)
  5841     AssertHeapIsIdle(cx);
  5842     CHECK_REQUEST(cx);
  5844     return ExecuteRegExpLegacy(cx, nullptr, obj->as<RegExpObject>(), NullPtr(), chars, length,
  5845                                indexp, test, rval);
  5848 JS_PUBLIC_API(bool)
  5849 JS_ObjectIsRegExp(JSContext *cx, HandleObject obj)
  5851     assertSameCompartment(cx, obj);
  5852     return ObjectClassIs(obj, ESClass_RegExp, cx);
  5855 JS_PUBLIC_API(unsigned)
  5856 JS_GetRegExpFlags(JSContext *cx, HandleObject obj)
  5858     AssertHeapIsIdle(cx);
  5859     CHECK_REQUEST(cx);
  5861     return obj->as<RegExpObject>().getFlags();
  5864 JS_PUBLIC_API(JSString *)
  5865 JS_GetRegExpSource(JSContext *cx, HandleObject obj)
  5867     AssertHeapIsIdle(cx);
  5868     CHECK_REQUEST(cx);
  5870     return obj->as<RegExpObject>().getSource();
  5873 /************************************************************************/
  5875 JS_PUBLIC_API(bool)
  5876 JS_SetDefaultLocale(JSRuntime *rt, const char *locale)
  5878     AssertHeapIsIdle(rt);
  5879     return rt->setDefaultLocale(locale);
  5882 JS_PUBLIC_API(const char*)
  5883 JS_GetDefaultLocale(JSRuntime *rt)
  5885     AssertHeapIsIdle(rt);
  5886     return rt->getDefaultLocale();
  5889 JS_PUBLIC_API(void)
  5890 JS_ResetDefaultLocale(JSRuntime *rt)
  5892     AssertHeapIsIdle(rt);
  5893     rt->resetDefaultLocale();
  5896 JS_PUBLIC_API(void)
  5897 JS_SetLocaleCallbacks(JSRuntime *rt, JSLocaleCallbacks *callbacks)
  5899     AssertHeapIsIdle(rt);
  5900     rt->localeCallbacks = callbacks;
  5903 JS_PUBLIC_API(JSLocaleCallbacks *)
  5904 JS_GetLocaleCallbacks(JSRuntime *rt)
  5906     /* This function can be called by a finalizer. */
  5907     return rt->localeCallbacks;
  5910 /************************************************************************/
  5912 JS_PUBLIC_API(bool)
  5913 JS_IsExceptionPending(JSContext *cx)
  5915     /* This function can be called by a finalizer. */
  5916     return (bool) cx->isExceptionPending();
  5919 JS_PUBLIC_API(bool)
  5920 JS_GetPendingException(JSContext *cx, MutableHandleValue vp)
  5922     AssertHeapIsIdle(cx);
  5923     CHECK_REQUEST(cx);
  5924     if (!cx->isExceptionPending())
  5925         return false;
  5926     return cx->getPendingException(vp);
  5929 JS_PUBLIC_API(void)
  5930 JS_SetPendingException(JSContext *cx, HandleValue value)
  5932     AssertHeapIsIdle(cx);
  5933     CHECK_REQUEST(cx);
  5934     assertSameCompartment(cx, value);
  5935     cx->setPendingException(value);
  5938 JS_PUBLIC_API(void)
  5939 JS_ClearPendingException(JSContext *cx)
  5941     AssertHeapIsIdle(cx);
  5942     cx->clearPendingException();
  5945 JS_PUBLIC_API(bool)
  5946 JS_ReportPendingException(JSContext *cx)
  5948     AssertHeapIsIdle(cx);
  5949     CHECK_REQUEST(cx);
  5951     // This can only fail due to oom.
  5952     bool ok = js_ReportUncaughtException(cx);
  5953     JS_ASSERT(!cx->isExceptionPending());
  5954     return ok;
  5957 JS::AutoSaveExceptionState::AutoSaveExceptionState(JSContext *cx)
  5958     : context(cx), wasThrowing(cx->throwing), exceptionValue(cx)
  5960     AssertHeapIsIdle(cx);
  5961     CHECK_REQUEST(cx);
  5962     if (wasThrowing) {
  5963         exceptionValue = cx->unwrappedException_;
  5964         cx->clearPendingException();
  5968 void
  5969 JS::AutoSaveExceptionState::restore()
  5971     context->throwing = wasThrowing;
  5972     context->unwrappedException_ = exceptionValue;
  5973     drop();
  5976 JS::AutoSaveExceptionState::~AutoSaveExceptionState()
  5978     if (wasThrowing && !context->isExceptionPending()) {
  5979         context->throwing = true;
  5980         context->unwrappedException_ = exceptionValue;
  5984 struct JSExceptionState {
  5985     bool throwing;
  5986     jsval exception;
  5987 };
  5989 JS_PUBLIC_API(JSExceptionState *)
  5990 JS_SaveExceptionState(JSContext *cx)
  5992     JSExceptionState *state;
  5994     AssertHeapIsIdle(cx);
  5995     CHECK_REQUEST(cx);
  5996     state = cx->pod_malloc<JSExceptionState>();
  5997     if (state) {
  5998         state->throwing =
  5999             JS_GetPendingException(cx, MutableHandleValue::fromMarkedLocation(&state->exception));
  6000         if (state->throwing && JSVAL_IS_GCTHING(state->exception))
  6001             AddValueRoot(cx, &state->exception, "JSExceptionState.exception");
  6003     return state;
  6006 JS_PUBLIC_API(void)
  6007 JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
  6009     AssertHeapIsIdle(cx);
  6010     CHECK_REQUEST(cx);
  6011     if (state) {
  6012         if (state->throwing)
  6013             JS_SetPendingException(cx, HandleValue::fromMarkedLocation(&state->exception));
  6014         else
  6015             JS_ClearPendingException(cx);
  6016         JS_DropExceptionState(cx, state);
  6020 JS_PUBLIC_API(void)
  6021 JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
  6023     AssertHeapIsIdle(cx);
  6024     CHECK_REQUEST(cx);
  6025     if (state) {
  6026         if (state->throwing && JSVAL_IS_GCTHING(state->exception)) {
  6027             assertSameCompartment(cx, state->exception);
  6028             RemoveRoot(cx->runtime(), &state->exception);
  6030         js_free(state);
  6034 JS_PUBLIC_API(JSErrorReport *)
  6035 JS_ErrorFromException(JSContext *cx, HandleObject obj)
  6037     AssertHeapIsIdle(cx);
  6038     CHECK_REQUEST(cx);
  6039     assertSameCompartment(cx, obj);
  6040     return js_ErrorFromException(cx, obj);
  6043 JS_PUBLIC_API(bool)
  6044 JS_ThrowStopIteration(JSContext *cx)
  6046     AssertHeapIsIdle(cx);
  6047     return js_ThrowStopIteration(cx);
  6050 JS_PUBLIC_API(bool)
  6051 JS_IsStopIteration(jsval v)
  6053     return v.isObject() && v.toObject().is<StopIterationObject>();
  6056 JS_PUBLIC_API(intptr_t)
  6057 JS_GetCurrentThread()
  6059 #ifdef JS_THREADSAFE
  6060     return reinterpret_cast<intptr_t>(PR_GetCurrentThread());
  6061 #else
  6062     return 0;
  6063 #endif
  6066 extern MOZ_NEVER_INLINE JS_PUBLIC_API(void)
  6067 JS_AbortIfWrongThread(JSRuntime *rt)
  6069     if (!CurrentThreadCanAccessRuntime(rt))
  6070         MOZ_CRASH();
  6071     if (!js::TlsPerThreadData.get()->associatedWith(rt))
  6072         MOZ_CRASH();
  6075 #ifdef JS_GC_ZEAL
  6076 JS_PUBLIC_API(void)
  6077 JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency)
  6079     SetGCZeal(cx->runtime(), zeal, frequency);
  6082 JS_PUBLIC_API(void)
  6083 JS_ScheduleGC(JSContext *cx, uint32_t count)
  6085     cx->runtime()->gcNextScheduled = count;
  6087 #endif
  6089 JS_PUBLIC_API(void)
  6090 JS_SetParallelParsingEnabled(JSRuntime *rt, bool enabled)
  6092 #ifdef JS_ION
  6093     rt->setParallelParsingEnabled(enabled);
  6094 #endif
  6097 JS_PUBLIC_API(void)
  6098 JS_SetParallelIonCompilationEnabled(JSRuntime *rt, bool enabled)
  6100 #ifdef JS_ION
  6101     rt->setParallelIonCompilationEnabled(enabled);
  6102 #endif
  6105 JS_PUBLIC_API(void)
  6106 JS_SetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt, uint32_t value)
  6108 #ifdef JS_ION
  6110     switch (opt) {
  6111       case JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER:
  6112         if (value == uint32_t(-1)) {
  6113             jit::JitOptions defaultValues;
  6114             value = defaultValues.baselineUsesBeforeCompile;
  6116         jit::js_JitOptions.baselineUsesBeforeCompile = value;
  6117         break;
  6118       case JSJITCOMPILER_ION_USECOUNT_TRIGGER:
  6119         if (value == uint32_t(-1)) {
  6120             jit::js_JitOptions.resetUsesBeforeCompile();
  6121             break;
  6123         jit::js_JitOptions.setUsesBeforeCompile(value);
  6124         if (value == 0)
  6125             jit::js_JitOptions.setEagerCompilation();
  6126         break;
  6127       case JSJITCOMPILER_ION_ENABLE:
  6128         if (value == 1) {
  6129             JS::RuntimeOptionsRef(rt).setIon(true);
  6130             IonSpew(js::jit::IonSpew_Scripts, "Enable ion");
  6131         } else if (value == 0) {
  6132             JS::RuntimeOptionsRef(rt).setIon(false);
  6133             IonSpew(js::jit::IonSpew_Scripts, "Disable ion");
  6135         break;
  6136       case JSJITCOMPILER_BASELINE_ENABLE:
  6137         if (value == 1) {
  6138             JS::RuntimeOptionsRef(rt).setBaseline(true);
  6139             IonSpew(js::jit::IonSpew_BaselineScripts, "Enable baseline");
  6140         } else if (value == 0) {
  6141             JS::RuntimeOptionsRef(rt).setBaseline(false);
  6142             IonSpew(js::jit::IonSpew_BaselineScripts, "Disable baseline");
  6144         break;
  6145       case JSJITCOMPILER_PARALLEL_COMPILATION_ENABLE:
  6146         if (value == 1) {
  6147             rt->setParallelIonCompilationEnabled(true);
  6148             IonSpew(js::jit::IonSpew_Scripts, "Enable parallel compilation");
  6149         } else if (value == 0) {
  6150             rt->setParallelIonCompilationEnabled(false);
  6151             IonSpew(js::jit::IonSpew_Scripts, "Disable parallel compilation");
  6153         break;
  6154       default:
  6155         break;
  6157 #endif
  6160 JS_PUBLIC_API(int)
  6161 JS_GetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt)
  6163 #ifdef JS_ION
  6164     switch (opt) {
  6165       case JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER:
  6166         return jit::js_JitOptions.baselineUsesBeforeCompile;
  6167       case JSJITCOMPILER_ION_USECOUNT_TRIGGER:
  6168         return jit::js_JitOptions.forcedDefaultIonUsesBeforeCompile;
  6169       case JSJITCOMPILER_ION_ENABLE:
  6170         return JS::RuntimeOptionsRef(rt).ion();
  6171       case JSJITCOMPILER_BASELINE_ENABLE:
  6172         return JS::RuntimeOptionsRef(rt).baseline();
  6173       case JSJITCOMPILER_PARALLEL_COMPILATION_ENABLE:
  6174         return rt->canUseParallelIonCompilation();
  6175       default:
  6176         break;
  6178 #endif
  6179     return 0;
  6182 /************************************************************************/
  6184 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN)
  6186 #include "jswin.h"
  6188 /*
  6189  * Initialization routine for the JS DLL.
  6190  */
  6191 BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
  6193     return TRUE;
  6196 #endif
  6198 JS_PUBLIC_API(bool)
  6199 JS_IndexToId(JSContext *cx, uint32_t index, MutableHandleId id)
  6201     return IndexToId(cx, index, id);
  6204 JS_PUBLIC_API(bool)
  6205 JS_CharsToId(JSContext* cx, JS::TwoByteChars chars, MutableHandleId idp)
  6207     RootedAtom atom(cx, AtomizeChars(cx, chars.start().get(), chars.length()));
  6208     if (!atom)
  6209         return false;
  6210 #ifdef DEBUG
  6211     uint32_t dummy;
  6212     MOZ_ASSERT(!atom->isIndex(&dummy), "API misuse: |chars| must not encode an index");
  6213 #endif
  6214     idp.set(AtomToId(atom));
  6215     return true;
  6218 JS_PUBLIC_API(bool)
  6219 JS_IsIdentifier(JSContext *cx, HandleString str, bool *isIdentifier)
  6221     assertSameCompartment(cx, str);
  6223     JSLinearString* linearStr = str->ensureLinear(cx);
  6224     if (!linearStr)
  6225         return false;
  6227     *isIdentifier = js::frontend::IsIdentifier(linearStr);
  6228     return true;
  6231 namespace JS {
  6233 void
  6234 AutoFilename::reset(void *newScriptSource)
  6236     if (newScriptSource)
  6237         reinterpret_cast<ScriptSource*>(newScriptSource)->incref();
  6238     if (scriptSource_)
  6239         reinterpret_cast<ScriptSource*>(scriptSource_)->decref();
  6240     scriptSource_ = newScriptSource;
  6243 const char *
  6244 AutoFilename::get() const
  6246     JS_ASSERT(scriptSource_);
  6247     return reinterpret_cast<ScriptSource*>(scriptSource_)->filename();
  6250 JS_PUBLIC_API(bool)
  6251 DescribeScriptedCaller(JSContext *cx, AutoFilename *filename, unsigned *lineno)
  6253     if (lineno)
  6254         *lineno = 0;
  6256     NonBuiltinFrameIter i(cx);
  6257     if (i.done())
  6258         return false;
  6260     // If the caller is hidden, the embedding wants us to return false here so
  6261     // that it can check its own stack (see HideScriptedCaller).
  6262     if (i.activation()->scriptedCallerIsHidden())
  6263         return false;
  6265     if (filename)
  6266         filename->reset(i.scriptSource());
  6267     if (lineno)
  6268         *lineno = i.computeLine();
  6269     return true;
  6272 JS_PUBLIC_API(JSObject *)
  6273 GetScriptedCallerGlobal(JSContext *cx)
  6275     NonBuiltinFrameIter i(cx);
  6276     if (i.done())
  6277         return nullptr;
  6279     // If the caller is hidden, the embedding wants us to return null here so
  6280     // that it can check its own stack (see HideScriptedCaller).
  6281     if (i.activation()->scriptedCallerIsHidden())
  6282         return nullptr;
  6284     GlobalObject *global = i.activation()->compartment()->maybeGlobal();
  6286     // Noone should be running code in the atoms compartment or running code in
  6287     // a compartment without any live objects, so there should definitely be a
  6288     // live global.
  6289     JS_ASSERT(global);
  6291     return global;
  6294 JS_PUBLIC_API(void)
  6295 HideScriptedCaller(JSContext *cx)
  6297     MOZ_ASSERT(cx);
  6299     // If there's no accessible activation on the stack, we'll return null from
  6300     // DescribeScriptedCaller anyway, so there's no need to annotate anything.
  6301     Activation *act = cx->runtime()->mainThread.activation();
  6302     if (!act)
  6303         return;
  6304     act->hideScriptedCaller();
  6307 JS_PUBLIC_API(void)
  6308 UnhideScriptedCaller(JSContext *cx)
  6310     Activation *act = cx->runtime()->mainThread.activation();
  6311     if (!act)
  6312         return;
  6313     act->unhideScriptedCaller();
  6316 } /* namespace JS */
  6318 #ifdef JS_THREADSAFE
  6319 static PRStatus
  6320 CallOnce(void *func)
  6322     JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
  6323     return init() ? PR_SUCCESS : PR_FAILURE;
  6325 #endif
  6327 JS_PUBLIC_API(bool)
  6328 JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
  6330 #ifdef JS_THREADSAFE
  6331     return PR_CallOnceWithArg(once, CallOnce, JS_FUNC_TO_DATA_PTR(void *, func)) == PR_SUCCESS;
  6332 #else
  6333     if (!*once) {
  6334         *once = true;
  6335         return func();
  6336     } else {
  6337         return true;
  6339 #endif
  6342 AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
  6343   : down(ContextFriendFields::get(cx)->autoGCRooters),
  6344     tag_(tag),
  6345     stackTop(&ContextFriendFields::get(cx)->autoGCRooters)
  6347     JS_ASSERT(this != *stackTop);
  6348     *stackTop = this;
  6351 AutoGCRooter::AutoGCRooter(ContextFriendFields *cx, ptrdiff_t tag)
  6352   : down(cx->autoGCRooters),
  6353     tag_(tag),
  6354     stackTop(&cx->autoGCRooters)
  6356     JS_ASSERT(this != *stackTop);
  6357     *stackTop = this;
  6360 #ifdef DEBUG
  6361 JS_PUBLIC_API(void)
  6362 JS::AssertArgumentsAreSane(JSContext *cx, HandleValue value)
  6364     AssertHeapIsIdle(cx);
  6365     CHECK_REQUEST(cx);
  6366     assertSameCompartment(cx, value);
  6368 #endif /* DEBUG */
  6370 JS_PUBLIC_API(void *)
  6371 JS_EncodeScript(JSContext *cx, HandleScript scriptArg, uint32_t *lengthp)
  6373     XDREncoder encoder(cx);
  6374     RootedScript script(cx, scriptArg);
  6375     if (!encoder.codeScript(&script))
  6376         return nullptr;
  6377     return encoder.forgetData(lengthp);
  6380 JS_PUBLIC_API(void *)
  6381 JS_EncodeInterpretedFunction(JSContext *cx, HandleObject funobjArg, uint32_t *lengthp)
  6383     XDREncoder encoder(cx);
  6384     RootedObject funobj(cx, funobjArg);
  6385     if (!encoder.codeFunction(&funobj))
  6386         return nullptr;
  6387     return encoder.forgetData(lengthp);
  6390 JS_PUBLIC_API(JSScript *)
  6391 JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
  6392                 JSPrincipals *originPrincipals)
  6394     XDRDecoder decoder(cx, data, length, originPrincipals);
  6395     RootedScript script(cx);
  6396     if (!decoder.codeScript(&script))
  6397         return nullptr;
  6398     return script;
  6401 JS_PUBLIC_API(JSObject *)
  6402 JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
  6403                              JSPrincipals *originPrincipals)
  6405     XDRDecoder decoder(cx, data, length, originPrincipals);
  6406     RootedObject funobj(cx);
  6407     if (!decoder.codeFunction(&funobj))
  6408         return nullptr;
  6409     return funobj;
  6412 JS_PUBLIC_API(bool)
  6413 JS_PreventExtensions(JSContext *cx, JS::HandleObject obj)
  6415     bool extensible;
  6416     if (!JSObject::isExtensible(cx, obj, &extensible))
  6417         return false;
  6418     if (!extensible)
  6419         return true;
  6420     return JSObject::preventExtensions(cx, obj);
  6423 JS_PUBLIC_API(void)
  6424 JS::SetAsmJSCacheOps(JSRuntime *rt, const JS::AsmJSCacheOps *ops)
  6426     rt->asmJSCacheOps = *ops;
  6429 char *
  6430 JSAutoByteString::encodeLatin1(ExclusiveContext *cx, JSString *str)
  6432     JSLinearString *linear = str->ensureLinear(cx);
  6433     if (!linear)
  6434         return nullptr;
  6436     mBytes = LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
  6437     return mBytes;
  6440 JS_PUBLIC_API(void)
  6441 JS::SetLargeAllocationFailureCallback(JSRuntime *rt, JS::LargeAllocationFailureCallback lafc)
  6443     rt->largeAllocationFailureCallback = lafc;
  6446 JS_PUBLIC_API(void)
  6447 JS::SetOutOfMemoryCallback(JSRuntime *rt, OutOfMemoryCallback cb)
  6449     rt->oomCallback = cb;

mercurial